input_stream: return allocated input_stream objects
Major API redesign: don't let the caller allocate the input_stream object. Let each input plugin allocate its own (derived/extended) input_stream pointer. The "data" attribute can now be removed, and all input plugins simply cast the input_stream pointer to their own structure (with an "struct input_stream base" as the first attribute).
This commit is contained in:
parent
816b6ad4a7
commit
d3b763a48c
@ -45,10 +45,12 @@ struct bz2_archive_file {
|
|||||||
|
|
||||||
char *name;
|
char *name;
|
||||||
bool reset;
|
bool reset;
|
||||||
struct input_stream istream;
|
struct input_stream *istream;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bz2_input_stream {
|
struct bz2_input_stream {
|
||||||
|
struct input_stream base;
|
||||||
|
|
||||||
struct bz2_archive_file *archive;
|
struct bz2_archive_file *archive;
|
||||||
|
|
||||||
bool eof;
|
bool eof;
|
||||||
@ -111,7 +113,8 @@ bz2_open(const char *pathname, GError **error_r)
|
|||||||
refcount_init(&context->ref);
|
refcount_init(&context->ref);
|
||||||
|
|
||||||
//open archive
|
//open archive
|
||||||
if (!input_stream_open(&context->istream, pathname, error_r)) {
|
context->istream = input_stream_open(pathname, error_r);
|
||||||
|
if (context->istream == NULL) {
|
||||||
g_free(context);
|
g_free(context);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -158,44 +161,42 @@ bz2_close(struct archive_file *file)
|
|||||||
|
|
||||||
g_free(context->name);
|
g_free(context->name);
|
||||||
|
|
||||||
input_stream_close(&context->istream);
|
input_stream_close(context->istream);
|
||||||
g_free(context);
|
g_free(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* single archive handling */
|
/* single archive handling */
|
||||||
|
|
||||||
static bool
|
static struct input_stream *
|
||||||
bz2_open_stream(struct archive_file *file, struct input_stream *is,
|
bz2_open_stream(struct archive_file *file,
|
||||||
G_GNUC_UNUSED const char *path, GError **error_r)
|
G_GNUC_UNUSED const char *path, GError **error_r)
|
||||||
{
|
{
|
||||||
struct bz2_archive_file *context = (struct bz2_archive_file *) file;
|
struct bz2_archive_file *context = (struct bz2_archive_file *) file;
|
||||||
struct bz2_input_stream *bis = g_new(struct bz2_input_stream, 1);
|
struct bz2_input_stream *bis = g_new(struct bz2_input_stream, 1);
|
||||||
|
|
||||||
|
input_stream_init(&bis->base, &bz2_inputplugin);
|
||||||
|
|
||||||
bis->archive = context;
|
bis->archive = context;
|
||||||
|
|
||||||
//setup file ops
|
bis->base.ready = true;
|
||||||
is->plugin = &bz2_inputplugin;
|
bis->base.seekable = false;
|
||||||
//insert back reference
|
|
||||||
is->data = bis;
|
|
||||||
is->ready = true;
|
|
||||||
is->seekable = false;
|
|
||||||
|
|
||||||
if (!bz2_alloc(bis, error_r)) {
|
if (!bz2_alloc(bis, error_r)) {
|
||||||
g_free(bis);
|
g_free(bis);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bis->eof = false;
|
bis->eof = false;
|
||||||
|
|
||||||
refcount_inc(&context->ref);
|
refcount_inc(&context->ref);
|
||||||
|
|
||||||
return true;
|
return &bis->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bz2_is_close(struct input_stream *is)
|
bz2_is_close(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct bz2_input_stream *bis = (struct bz2_input_stream *)is->data;
|
struct bz2_input_stream *bis = (struct bz2_input_stream *)is;
|
||||||
|
|
||||||
bz2_destroy(bis);
|
bz2_destroy(bis);
|
||||||
|
|
||||||
@ -215,7 +216,7 @@ bz2_fillbuffer(struct bz2_input_stream *bis, GError **error_r)
|
|||||||
if (bzstream->avail_in > 0)
|
if (bzstream->avail_in > 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
count = input_stream_read(&bis->archive->istream,
|
count = input_stream_read(bis->archive->istream,
|
||||||
bis->buffer, sizeof(bis->buffer),
|
bis->buffer, sizeof(bis->buffer),
|
||||||
error_r);
|
error_r);
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
@ -230,7 +231,7 @@ static size_t
|
|||||||
bz2_is_read(struct input_stream *is, void *ptr, size_t length,
|
bz2_is_read(struct input_stream *is, void *ptr, size_t length,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
struct bz2_input_stream *bis = (struct bz2_input_stream *)is->data;
|
struct bz2_input_stream *bis = (struct bz2_input_stream *)is;
|
||||||
bz_stream *bzstream;
|
bz_stream *bzstream;
|
||||||
int bz_result;
|
int bz_result;
|
||||||
size_t nbytes = 0;
|
size_t nbytes = 0;
|
||||||
@ -269,7 +270,7 @@ bz2_is_read(struct input_stream *is, void *ptr, size_t length,
|
|||||||
static bool
|
static bool
|
||||||
bz2_is_eof(struct input_stream *is)
|
bz2_is_eof(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct bz2_input_stream *bis = (struct bz2_input_stream *)is->data;
|
struct bz2_input_stream *bis = (struct bz2_input_stream *)is;
|
||||||
|
|
||||||
return bis->eof;
|
return bis->eof;
|
||||||
}
|
}
|
||||||
|
@ -163,14 +163,16 @@ iso9660_archive_close(struct archive_file *file)
|
|||||||
/* single archive handling */
|
/* single archive handling */
|
||||||
|
|
||||||
struct iso9660_input_stream {
|
struct iso9660_input_stream {
|
||||||
|
struct input_stream base;
|
||||||
|
|
||||||
struct iso9660_archive_file *archive;
|
struct iso9660_archive_file *archive;
|
||||||
|
|
||||||
iso9660_stat_t *statbuf;
|
iso9660_stat_t *statbuf;
|
||||||
size_t max_blocks;
|
size_t max_blocks;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
static struct input_stream *
|
||||||
iso9660_archive_open_stream(struct archive_file *file, struct input_stream *is,
|
iso9660_archive_open_stream(struct archive_file *file,
|
||||||
const char *pathname, GError **error_r)
|
const char *pathname, GError **error_r)
|
||||||
{
|
{
|
||||||
struct iso9660_archive_file *context =
|
struct iso9660_archive_file *context =
|
||||||
@ -178,6 +180,7 @@ iso9660_archive_open_stream(struct archive_file *file, struct input_stream *is,
|
|||||||
struct iso9660_input_stream *iis;
|
struct iso9660_input_stream *iis;
|
||||||
|
|
||||||
iis = g_new(struct iso9660_input_stream, 1);
|
iis = g_new(struct iso9660_input_stream, 1);
|
||||||
|
input_stream_init(&iis->base, &iso9660_input_plugin);
|
||||||
|
|
||||||
iis->archive = context;
|
iis->archive = context;
|
||||||
iis->statbuf = iso9660_ifs_stat_translate(context->iso, pathname);
|
iis->statbuf = iso9660_ifs_stat_translate(context->iso, pathname);
|
||||||
@ -185,31 +188,26 @@ iso9660_archive_open_stream(struct archive_file *file, struct input_stream *is,
|
|||||||
g_free(iis);
|
g_free(iis);
|
||||||
g_set_error(error_r, iso9660_quark(), 0,
|
g_set_error(error_r, iso9660_quark(), 0,
|
||||||
"not found in the ISO file: %s", pathname);
|
"not found in the ISO file: %s", pathname);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//setup file ops
|
iis->base.ready = true;
|
||||||
is->plugin = &iso9660_input_plugin;
|
|
||||||
//insert back reference
|
|
||||||
is->data = iis;
|
|
||||||
is->ready = true;
|
|
||||||
//we are not seekable
|
//we are not seekable
|
||||||
is->seekable = false;
|
iis->base.seekable = false;
|
||||||
|
|
||||||
is->size = iis->statbuf->size;
|
iis->base.size = iis->statbuf->size;
|
||||||
|
|
||||||
iis->max_blocks = CEILING(iis->statbuf->size, ISO_BLOCKSIZE);
|
iis->max_blocks = CEILING(iis->statbuf->size, ISO_BLOCKSIZE);
|
||||||
|
|
||||||
refcount_inc(&context->ref);
|
refcount_inc(&context->ref);
|
||||||
|
|
||||||
return true;
|
return &iis->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
iso9660_input_close(struct input_stream *is)
|
iso9660_input_close(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct iso9660_input_stream *iis =
|
struct iso9660_input_stream *iis = (struct iso9660_input_stream *)is;
|
||||||
(struct iso9660_input_stream *)is->data;
|
|
||||||
|
|
||||||
g_free(iis->statbuf);
|
g_free(iis->statbuf);
|
||||||
|
|
||||||
@ -220,8 +218,7 @@ iso9660_input_close(struct input_stream *is)
|
|||||||
static size_t
|
static size_t
|
||||||
iso9660_input_read(struct input_stream *is, void *ptr, size_t size, GError **error_r)
|
iso9660_input_read(struct input_stream *is, void *ptr, size_t size, GError **error_r)
|
||||||
{
|
{
|
||||||
struct iso9660_input_stream *iis =
|
struct iso9660_input_stream *iis = (struct iso9660_input_stream *)is;
|
||||||
(struct iso9660_input_stream *)is->data;
|
|
||||||
int toread, readed = 0;
|
int toread, readed = 0;
|
||||||
int no_blocks, cur_block;
|
int no_blocks, cur_block;
|
||||||
size_t left_bytes = iis->statbuf->size - is->offset;
|
size_t left_bytes = iis->statbuf->size - is->offset;
|
||||||
|
@ -125,13 +125,15 @@ zzip_archive_close(struct archive_file *file)
|
|||||||
/* single archive handling */
|
/* single archive handling */
|
||||||
|
|
||||||
struct zzip_input_stream {
|
struct zzip_input_stream {
|
||||||
|
struct input_stream base;
|
||||||
|
|
||||||
struct zzip_archive *archive;
|
struct zzip_archive *archive;
|
||||||
|
|
||||||
ZZIP_FILE *file;
|
ZZIP_FILE *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
static struct input_stream *
|
||||||
zzip_archive_open_stream(struct archive_file *file, struct input_stream *is,
|
zzip_archive_open_stream(struct archive_file *file,
|
||||||
const char *pathname, GError **error_r)
|
const char *pathname, GError **error_r)
|
||||||
{
|
{
|
||||||
struct zzip_archive *context = (struct zzip_archive *) file;
|
struct zzip_archive *context = (struct zzip_archive *) file;
|
||||||
@ -139,6 +141,7 @@ zzip_archive_open_stream(struct archive_file *file, struct input_stream *is,
|
|||||||
ZZIP_STAT z_stat;
|
ZZIP_STAT z_stat;
|
||||||
|
|
||||||
zis = g_new(struct zzip_input_stream, 1);
|
zis = g_new(struct zzip_input_stream, 1);
|
||||||
|
input_stream_init(&zis->base, &zzip_input_plugin);
|
||||||
|
|
||||||
zis->archive = context;
|
zis->archive = context;
|
||||||
zis->file = zzip_file_open(context->dir, pathname, 0);
|
zis->file = zzip_file_open(context->dir, pathname, 0);
|
||||||
@ -146,29 +149,25 @@ zzip_archive_open_stream(struct archive_file *file, struct input_stream *is,
|
|||||||
g_free(zis);
|
g_free(zis);
|
||||||
g_set_error(error_r, zzip_quark(), 0,
|
g_set_error(error_r, zzip_quark(), 0,
|
||||||
"not found in the ZIP file: %s", pathname);
|
"not found in the ZIP file: %s", pathname);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//setup file ops
|
zis->base.ready = true;
|
||||||
is->plugin = &zzip_input_plugin;
|
|
||||||
//insert back reference
|
|
||||||
is->data = zis;
|
|
||||||
is->ready = true;
|
|
||||||
//we are seekable (but its not recommendent to do so)
|
//we are seekable (but its not recommendent to do so)
|
||||||
is->seekable = true;
|
zis->base.seekable = true;
|
||||||
|
|
||||||
zzip_file_stat(zis->file, &z_stat);
|
zzip_file_stat(zis->file, &z_stat);
|
||||||
is->size = z_stat.st_size;
|
zis->base.size = z_stat.st_size;
|
||||||
|
|
||||||
refcount_inc(&context->ref);
|
refcount_inc(&context->ref);
|
||||||
|
|
||||||
return true;
|
return &zis->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
zzip_input_close(struct input_stream *is)
|
zzip_input_close(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct zzip_input_stream *zis = (struct zzip_input_stream *)is->data;
|
struct zzip_input_stream *zis = (struct zzip_input_stream *)is;
|
||||||
|
|
||||||
zzip_file_close(zis->file);
|
zzip_file_close(zis->file);
|
||||||
zzip_archive_close(&zis->archive->base);
|
zzip_archive_close(&zis->archive->base);
|
||||||
@ -179,7 +178,7 @@ static size_t
|
|||||||
zzip_input_read(struct input_stream *is, void *ptr, size_t size,
|
zzip_input_read(struct input_stream *is, void *ptr, size_t size,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
struct zzip_input_stream *zis = (struct zzip_input_stream *)is->data;
|
struct zzip_input_stream *zis = (struct zzip_input_stream *)is;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = zzip_file_read(zis->file, ptr, size);
|
ret = zzip_file_read(zis->file, ptr, size);
|
||||||
@ -197,7 +196,7 @@ zzip_input_read(struct input_stream *is, void *ptr, size_t size,
|
|||||||
static bool
|
static bool
|
||||||
zzip_input_eof(struct input_stream *is)
|
zzip_input_eof(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct zzip_input_stream *zis = (struct zzip_input_stream *)is->data;
|
struct zzip_input_stream *zis = (struct zzip_input_stream *)is;
|
||||||
|
|
||||||
return (goffset)zzip_tell(zis->file) == is->size;
|
return (goffset)zzip_tell(zis->file) == is->size;
|
||||||
}
|
}
|
||||||
@ -206,7 +205,7 @@ static bool
|
|||||||
zzip_input_seek(struct input_stream *is,
|
zzip_input_seek(struct input_stream *is,
|
||||||
goffset offset, int whence, GError **error_r)
|
goffset offset, int whence, GError **error_r)
|
||||||
{
|
{
|
||||||
struct zzip_input_stream *zis = (struct zzip_input_stream *)is->data;
|
struct zzip_input_stream *zis = (struct zzip_input_stream *)is;
|
||||||
zzip_off_t ofs = zzip_seek(zis->file, offset, whence);
|
zzip_off_t ofs = zzip_seek(zis->file, offset, whence);
|
||||||
if (ofs != -1) {
|
if (ofs != -1) {
|
||||||
g_set_error(error_r, zzip_quark(), ofs,
|
g_set_error(error_r, zzip_quark(), ofs,
|
||||||
|
@ -80,13 +80,13 @@ archive_file_scan_next(struct archive_file *file)
|
|||||||
return file->plugin->scan_next(file);
|
return file->plugin->scan_next(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
struct input_stream *
|
||||||
archive_file_open_stream(struct archive_file *file, struct input_stream *is,
|
archive_file_open_stream(struct archive_file *file,
|
||||||
const char *path, GError **error_r)
|
const char *path, GError **error_r)
|
||||||
{
|
{
|
||||||
assert(file != NULL);
|
assert(file != NULL);
|
||||||
assert(file->plugin != NULL);
|
assert(file->plugin != NULL);
|
||||||
assert(file->plugin->open_stream != NULL);
|
assert(file->plugin->open_stream != NULL);
|
||||||
|
|
||||||
return file->plugin->open_stream(file, is, path, error_r);
|
return file->plugin->open_stream(file, path, error_r);
|
||||||
}
|
}
|
||||||
|
@ -71,8 +71,9 @@ struct archive_plugin {
|
|||||||
* @param error_r location to store the error occuring, or
|
* @param error_r location to store the error occuring, or
|
||||||
* NULL to ignore errors
|
* NULL to ignore errors
|
||||||
*/
|
*/
|
||||||
bool (*open_stream)(struct archive_file *, struct input_stream *is,
|
struct input_stream *(*open_stream)(struct archive_file *af,
|
||||||
const char *path, GError **error_r);
|
const char *path,
|
||||||
|
GError **error_r);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* closes archive file.
|
* closes archive file.
|
||||||
@ -99,8 +100,8 @@ archive_file_scan_reset(struct archive_file *file);
|
|||||||
char *
|
char *
|
||||||
archive_file_scan_next(struct archive_file *file);
|
archive_file_scan_next(struct archive_file *file);
|
||||||
|
|
||||||
bool
|
struct input_stream *
|
||||||
archive_file_open_stream(struct archive_file *file, struct input_stream *is,
|
archive_file_open_stream(struct archive_file *file,
|
||||||
const char *path, GError **error_r);
|
const char *path, GError **error_r);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -464,13 +464,12 @@ wavpack_input_init(struct wavpack_input *isp, struct decoder *decoder,
|
|||||||
isp->last_byte = EOF;
|
isp->last_byte = EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static struct input_stream *
|
||||||
wavpack_open_wvc(struct decoder *decoder, struct input_stream *is_wvc,
|
wavpack_open_wvc(struct decoder *decoder, struct wavpack_input *wpi)
|
||||||
struct wavpack_input *wpi)
|
|
||||||
{
|
{
|
||||||
|
struct input_stream *is_wvc;
|
||||||
char *utf8url;
|
char *utf8url;
|
||||||
char *wvc_url = NULL;
|
char *wvc_url = NULL;
|
||||||
bool ret;
|
|
||||||
char first_byte;
|
char first_byte;
|
||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
|
|
||||||
@ -486,12 +485,11 @@ wavpack_open_wvc(struct decoder *decoder, struct input_stream *is_wvc,
|
|||||||
wvc_url = g_strconcat(utf8url, "c", NULL);
|
wvc_url = g_strconcat(utf8url, "c", NULL);
|
||||||
g_free(utf8url);
|
g_free(utf8url);
|
||||||
|
|
||||||
ret = input_stream_open(is_wvc, wvc_url, NULL);
|
is_wvc = input_stream_open(wvc_url, NULL);
|
||||||
g_free(wvc_url);
|
g_free(wvc_url);
|
||||||
|
|
||||||
if (!ret) {
|
if (is_wvc == NULL)
|
||||||
return false;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* And we try to buffer in order to get know
|
* And we try to buffer in order to get know
|
||||||
@ -502,13 +500,13 @@ wavpack_open_wvc(struct decoder *decoder, struct input_stream *is_wvc,
|
|||||||
);
|
);
|
||||||
if (nbytes == 0) {
|
if (nbytes == 0) {
|
||||||
input_stream_close(is_wvc);
|
input_stream_close(is_wvc);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push it back */
|
/* push it back */
|
||||||
wavpack_input_init(wpi, decoder, is_wvc);
|
wavpack_input_init(wpi, decoder, is_wvc);
|
||||||
wpi->last_byte = first_byte;
|
wpi->last_byte = first_byte;
|
||||||
return true;
|
return is_wvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -519,14 +517,15 @@ wavpack_streamdecode(struct decoder * decoder, struct input_stream *is)
|
|||||||
{
|
{
|
||||||
char error[ERRORLEN];
|
char error[ERRORLEN];
|
||||||
WavpackContext *wpc;
|
WavpackContext *wpc;
|
||||||
struct input_stream is_wvc;
|
struct input_stream *is_wvc;
|
||||||
int open_flags = OPEN_NORMALIZE;
|
int open_flags = OPEN_NORMALIZE;
|
||||||
struct wavpack_input isp, isp_wvc;
|
struct wavpack_input isp, isp_wvc;
|
||||||
bool can_seek = is->seekable;
|
bool can_seek = is->seekable;
|
||||||
|
|
||||||
if (wavpack_open_wvc(decoder, &is_wvc, &isp_wvc)) {
|
is_wvc = wavpack_open_wvc(decoder, &isp_wvc);
|
||||||
|
if (is_wvc != NULL) {
|
||||||
open_flags |= OPEN_WVC;
|
open_flags |= OPEN_WVC;
|
||||||
can_seek &= is_wvc.seekable;
|
can_seek &= is_wvc->seekable;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!can_seek) {
|
if (!can_seek) {
|
||||||
@ -549,7 +548,7 @@ wavpack_streamdecode(struct decoder * decoder, struct input_stream *is)
|
|||||||
|
|
||||||
WavpackCloseFile(wpc);
|
WavpackCloseFile(wpc);
|
||||||
if (open_flags & OPEN_WVC) {
|
if (open_flags & OPEN_WVC) {
|
||||||
input_stream_close(&is_wvc);
|
input_stream_close(is_wvc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,22 +56,23 @@ decoder_lock_get_command(struct decoder_control *dc)
|
|||||||
*
|
*
|
||||||
* Unlock the decoder before calling this function.
|
* Unlock the decoder before calling this function.
|
||||||
*
|
*
|
||||||
* @return true on success of if #DECODE_COMMAND_STOP is received,
|
* @return an input_stream on success or if #DECODE_COMMAND_STOP is
|
||||||
* false on error
|
* received, NULL on error
|
||||||
*/
|
*/
|
||||||
static bool
|
static struct input_stream *
|
||||||
decoder_input_stream_open(struct decoder_control *dc,
|
decoder_input_stream_open(struct decoder_control *dc, const char *uri)
|
||||||
struct input_stream *is, const char *uri)
|
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
struct input_stream *is;
|
||||||
|
|
||||||
if (!input_stream_open(is, uri, &error)) {
|
is = input_stream_open(uri, &error);
|
||||||
|
if (is == NULL) {
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wait for the input stream to become ready; its metadata
|
/* wait for the input stream to become ready; its metadata
|
||||||
@ -86,11 +87,11 @@ decoder_input_stream_open(struct decoder_control *dc,
|
|||||||
input_stream_close(is);
|
input_stream_close(is);
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return is;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -215,12 +216,13 @@ static bool
|
|||||||
decoder_run_stream(struct decoder *decoder, const char *uri)
|
decoder_run_stream(struct decoder *decoder, const char *uri)
|
||||||
{
|
{
|
||||||
struct decoder_control *dc = decoder->dc;
|
struct decoder_control *dc = decoder->dc;
|
||||||
struct input_stream input_stream;
|
struct input_stream *input_stream;
|
||||||
bool success;
|
bool success;
|
||||||
|
|
||||||
decoder_unlock(dc);
|
decoder_unlock(dc);
|
||||||
|
|
||||||
if (!decoder_input_stream_open(dc, &input_stream, uri)) {
|
input_stream = decoder_input_stream_open(dc, uri);
|
||||||
|
if (input_stream == NULL) {
|
||||||
decoder_lock(dc);
|
decoder_lock(dc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -229,15 +231,15 @@ decoder_run_stream(struct decoder *decoder, const char *uri)
|
|||||||
|
|
||||||
success = dc->command == DECODE_COMMAND_STOP ||
|
success = dc->command == DECODE_COMMAND_STOP ||
|
||||||
/* first we try mime types: */
|
/* first we try mime types: */
|
||||||
decoder_run_stream_mime_type(decoder, &input_stream) ||
|
decoder_run_stream_mime_type(decoder, input_stream) ||
|
||||||
/* if that fails, try suffix matching the URL: */
|
/* if that fails, try suffix matching the URL: */
|
||||||
decoder_run_stream_suffix(decoder, &input_stream, uri) ||
|
decoder_run_stream_suffix(decoder, input_stream, uri) ||
|
||||||
/* fallback to mp3: this is needed for bastard streams
|
/* fallback to mp3: this is needed for bastard streams
|
||||||
that don't have a suffix or set the mimeType */
|
that don't have a suffix or set the mimeType */
|
||||||
decoder_run_stream_fallback(decoder, &input_stream);
|
decoder_run_stream_fallback(decoder, input_stream);
|
||||||
|
|
||||||
decoder_unlock(dc);
|
decoder_unlock(dc);
|
||||||
input_stream_close(&input_stream);
|
input_stream_close(input_stream);
|
||||||
decoder_lock(dc);
|
decoder_lock(dc);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
@ -267,21 +269,21 @@ decoder_run_file(struct decoder *decoder, const char *path_fs)
|
|||||||
|
|
||||||
decoder_unlock(dc);
|
decoder_unlock(dc);
|
||||||
} else if (plugin->stream_decode != NULL) {
|
} else if (plugin->stream_decode != NULL) {
|
||||||
struct input_stream input_stream;
|
struct input_stream *input_stream;
|
||||||
bool success;
|
bool success;
|
||||||
|
|
||||||
if (!decoder_input_stream_open(dc, &input_stream,
|
input_stream = decoder_input_stream_open(dc, path_fs);
|
||||||
path_fs))
|
if (input_stream == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
decoder_lock(dc);
|
decoder_lock(dc);
|
||||||
|
|
||||||
success = decoder_stream_decode(plugin, decoder,
|
success = decoder_stream_decode(plugin, decoder,
|
||||||
&input_stream);
|
input_stream);
|
||||||
|
|
||||||
decoder_unlock(dc);
|
decoder_unlock(dc);
|
||||||
|
|
||||||
input_stream_close(&input_stream);
|
input_stream_close(input_stream);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
decoder_lock(dc);
|
decoder_lock(dc);
|
||||||
|
@ -33,24 +33,23 @@
|
|||||||
* parent_stream so tar plugin fetches file data from gzip
|
* parent_stream so tar plugin fetches file data from gzip
|
||||||
* plugin and gzip fetches file from disk
|
* plugin and gzip fetches file from disk
|
||||||
*/
|
*/
|
||||||
static bool
|
static struct input_stream *
|
||||||
input_archive_open(struct input_stream *is, const char *pathname,
|
input_archive_open(const char *pathname, GError **error_r)
|
||||||
GError **error_r)
|
|
||||||
{
|
{
|
||||||
const struct archive_plugin *arplug;
|
const struct archive_plugin *arplug;
|
||||||
struct archive_file *file;
|
struct archive_file *file;
|
||||||
char *archive, *filename, *suffix, *pname;
|
char *archive, *filename, *suffix, *pname;
|
||||||
bool opened;
|
struct input_stream *is;
|
||||||
|
|
||||||
if (!g_path_is_absolute(pathname))
|
if (!g_path_is_absolute(pathname))
|
||||||
return false;
|
return NULL;
|
||||||
|
|
||||||
pname = g_strdup(pathname);
|
pname = g_strdup(pathname);
|
||||||
// archive_lookup will modify pname when true is returned
|
// archive_lookup will modify pname when true is returned
|
||||||
if (!archive_lookup(pname, &archive, &filename, &suffix)) {
|
if (!archive_lookup(pname, &archive, &filename, &suffix)) {
|
||||||
g_debug("not an archive, lookup %s failed\n", pname);
|
g_debug("not an archive, lookup %s failed\n", pname);
|
||||||
g_free(pname);
|
g_free(pname);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check which archive plugin to use (by ext)
|
//check which archive plugin to use (by ext)
|
||||||
@ -58,19 +57,19 @@ input_archive_open(struct input_stream *is, const char *pathname,
|
|||||||
if (!arplug) {
|
if (!arplug) {
|
||||||
g_warning("can't handle archive %s\n",archive);
|
g_warning("can't handle archive %s\n",archive);
|
||||||
g_free(pname);
|
g_free(pname);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = archive_file_open(arplug, archive, error_r);
|
file = archive_file_open(arplug, archive, error_r);
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return false;
|
return NULL;
|
||||||
|
|
||||||
//setup fileops
|
//setup fileops
|
||||||
opened = archive_file_open_stream(file, is, filename, error_r);
|
is = archive_file_open_stream(file, filename, error_r);
|
||||||
archive_file_close(file);
|
archive_file_close(file);
|
||||||
g_free(pname);
|
g_free(pname);
|
||||||
|
|
||||||
return opened;
|
return is;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct input_plugin input_plugin_archive = {
|
const struct input_plugin input_plugin_archive = {
|
||||||
|
@ -57,6 +57,8 @@ struct buffer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct input_curl {
|
struct input_curl {
|
||||||
|
struct input_stream base;
|
||||||
|
|
||||||
/* some buffers which were passed to libcurl, which we have
|
/* some buffers which were passed to libcurl, which we have
|
||||||
too free */
|
too free */
|
||||||
char *url, *range;
|
char *url, *range;
|
||||||
@ -179,10 +181,8 @@ input_curl_easy_free(struct input_curl *c)
|
|||||||
* Frees this stream (but not the input_stream struct itself).
|
* Frees this stream (but not the input_stream struct itself).
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
input_curl_free(struct input_stream *is)
|
input_curl_free(struct input_curl *c)
|
||||||
{
|
{
|
||||||
struct input_curl *c = is->data;
|
|
||||||
|
|
||||||
if (c->tag != NULL)
|
if (c->tag != NULL)
|
||||||
tag_free(c->tag);
|
tag_free(c->tag);
|
||||||
g_free(c->meta_name);
|
g_free(c->meta_name);
|
||||||
@ -201,7 +201,7 @@ input_curl_free(struct input_stream *is)
|
|||||||
static struct tag *
|
static struct tag *
|
||||||
input_curl_tag(struct input_stream *is)
|
input_curl_tag(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct input_curl *c = is->data;
|
struct input_curl *c = (struct input_curl *)is;
|
||||||
struct tag *tag = c->tag;
|
struct tag *tag = c->tag;
|
||||||
|
|
||||||
c->tag = NULL;
|
c->tag = NULL;
|
||||||
@ -209,9 +209,8 @@ input_curl_tag(struct input_stream *is)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
input_curl_multi_info_read(struct input_stream *is, GError **error_r)
|
input_curl_multi_info_read(struct input_curl *c, GError **error_r)
|
||||||
{
|
{
|
||||||
struct input_curl *c = is->data;
|
|
||||||
CURLMsg *msg;
|
CURLMsg *msg;
|
||||||
int msgs_in_queue;
|
int msgs_in_queue;
|
||||||
|
|
||||||
@ -219,7 +218,7 @@ input_curl_multi_info_read(struct input_stream *is, GError **error_r)
|
|||||||
&msgs_in_queue)) != NULL) {
|
&msgs_in_queue)) != NULL) {
|
||||||
if (msg->msg == CURLMSG_DONE) {
|
if (msg->msg == CURLMSG_DONE) {
|
||||||
c->eof = true;
|
c->eof = true;
|
||||||
is->ready = true;
|
c->base.ready = true;
|
||||||
|
|
||||||
if (msg->data.result != CURLE_OK) {
|
if (msg->data.result != CURLE_OK) {
|
||||||
g_set_error(error_r, curl_quark(),
|
g_set_error(error_r, curl_quark(),
|
||||||
@ -279,7 +278,7 @@ input_curl_select(struct input_curl *c, GError **error_r)
|
|||||||
static bool
|
static bool
|
||||||
fill_buffer(struct input_stream *is, GError **error_r)
|
fill_buffer(struct input_stream *is, GError **error_r)
|
||||||
{
|
{
|
||||||
struct input_curl *c = is->data;
|
struct input_curl *c = (struct input_curl *)is;
|
||||||
CURLMcode mcode = CURLM_CALL_MULTI_PERFORM;
|
CURLMcode mcode = CURLM_CALL_MULTI_PERFORM;
|
||||||
|
|
||||||
while (!c->eof && g_queue_is_empty(c->buffers)) {
|
while (!c->eof && g_queue_is_empty(c->buffers)) {
|
||||||
@ -305,7 +304,7 @@ fill_buffer(struct input_stream *is, GError **error_r)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bret = input_curl_multi_info_read(is, error_r);
|
bret = input_curl_multi_info_read(c, error_r);
|
||||||
if (!bret)
|
if (!bret)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -407,7 +406,7 @@ static size_t
|
|||||||
input_curl_read(struct input_stream *is, void *ptr, size_t size,
|
input_curl_read(struct input_stream *is, void *ptr, size_t size,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
struct input_curl *c = is->data;
|
struct input_curl *c = (struct input_curl *)is;
|
||||||
bool success;
|
bool success;
|
||||||
size_t nbytes = 0;
|
size_t nbytes = 0;
|
||||||
char *dest = ptr;
|
char *dest = ptr;
|
||||||
@ -441,13 +440,15 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size,
|
|||||||
static void
|
static void
|
||||||
input_curl_close(struct input_stream *is)
|
input_curl_close(struct input_stream *is)
|
||||||
{
|
{
|
||||||
input_curl_free(is);
|
struct input_curl *c = (struct input_curl *)is;
|
||||||
|
|
||||||
|
input_curl_free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
input_curl_eof(G_GNUC_UNUSED struct input_stream *is)
|
input_curl_eof(G_GNUC_UNUSED struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct input_curl *c = is->data;
|
struct input_curl *c = (struct input_curl *)is;
|
||||||
|
|
||||||
return c->eof && g_queue_is_empty(c->buffers);
|
return c->eof && g_queue_is_empty(c->buffers);
|
||||||
}
|
}
|
||||||
@ -455,7 +456,7 @@ input_curl_eof(G_GNUC_UNUSED struct input_stream *is)
|
|||||||
static int
|
static int
|
||||||
input_curl_buffer(struct input_stream *is, GError **error_r)
|
input_curl_buffer(struct input_stream *is, GError **error_r)
|
||||||
{
|
{
|
||||||
struct input_curl *c = is->data;
|
struct input_curl *c = (struct input_curl *)is;
|
||||||
CURLMcode mcode;
|
CURLMcode mcode;
|
||||||
int running_handles;
|
int running_handles;
|
||||||
bool ret;
|
bool ret;
|
||||||
@ -483,7 +484,7 @@ input_curl_buffer(struct input_stream *is, GError **error_r)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = input_curl_multi_info_read(is, error_r);
|
ret = input_curl_multi_info_read(c, error_r);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -494,8 +495,7 @@ input_curl_buffer(struct input_stream *is, GError **error_r)
|
|||||||
static size_t
|
static size_t
|
||||||
input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
|
input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||||
{
|
{
|
||||||
struct input_stream *is = stream;
|
struct input_curl *c = (struct input_curl *)stream;
|
||||||
struct input_curl *c = is->data;
|
|
||||||
const char *header = ptr, *end, *value;
|
const char *header = ptr, *end, *value;
|
||||||
char name[64];
|
char name[64];
|
||||||
|
|
||||||
@ -524,7 +524,7 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
|
|||||||
if (g_ascii_strcasecmp(name, "accept-ranges") == 0) {
|
if (g_ascii_strcasecmp(name, "accept-ranges") == 0) {
|
||||||
/* a stream with icy-metadata is not seekable */
|
/* a stream with icy-metadata is not seekable */
|
||||||
if (!icy_defined(&c->icy_metadata))
|
if (!icy_defined(&c->icy_metadata))
|
||||||
is->seekable = true;
|
c->base.seekable = true;
|
||||||
} else if (g_ascii_strcasecmp(name, "content-length") == 0) {
|
} else if (g_ascii_strcasecmp(name, "content-length") == 0) {
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
|
|
||||||
@ -534,10 +534,10 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
|
|||||||
memcpy(buffer, value, end - value);
|
memcpy(buffer, value, end - value);
|
||||||
buffer[end - value] = 0;
|
buffer[end - value] = 0;
|
||||||
|
|
||||||
is->size = is->offset + g_ascii_strtoull(buffer, NULL, 10);
|
c->base.size = c->base.offset + g_ascii_strtoull(buffer, NULL, 10);
|
||||||
} else if (g_ascii_strcasecmp(name, "content-type") == 0) {
|
} else if (g_ascii_strcasecmp(name, "content-type") == 0) {
|
||||||
g_free(is->mime);
|
g_free(c->base.mime);
|
||||||
is->mime = g_strndup(value, end - value);
|
c->base.mime = g_strndup(value, end - value);
|
||||||
} else if (g_ascii_strcasecmp(name, "icy-name") == 0 ||
|
} else if (g_ascii_strcasecmp(name, "icy-name") == 0 ||
|
||||||
g_ascii_strcasecmp(name, "ice-name") == 0 ||
|
g_ascii_strcasecmp(name, "ice-name") == 0 ||
|
||||||
g_ascii_strcasecmp(name, "x-audiocast-name") == 0) {
|
g_ascii_strcasecmp(name, "x-audiocast-name") == 0) {
|
||||||
@ -568,7 +568,7 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
|
|||||||
|
|
||||||
/* a stream with icy-metadata is not
|
/* a stream with icy-metadata is not
|
||||||
seekable */
|
seekable */
|
||||||
is->seekable = false;
|
c->base.seekable = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,8 +579,7 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
|
|||||||
static size_t
|
static size_t
|
||||||
input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream)
|
input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||||
{
|
{
|
||||||
struct input_stream *is = stream;
|
struct input_curl *c = (struct input_curl *)stream;
|
||||||
struct input_curl *c = is->data;
|
|
||||||
struct buffer *buffer;
|
struct buffer *buffer;
|
||||||
|
|
||||||
size *= nmemb;
|
size *= nmemb;
|
||||||
@ -594,15 +593,14 @@ input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream)
|
|||||||
g_queue_push_tail(c->buffers, buffer);
|
g_queue_push_tail(c->buffers, buffer);
|
||||||
|
|
||||||
c->buffered = true;
|
c->buffered = true;
|
||||||
is->ready = true;
|
c->base.ready = true;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
input_curl_easy_init(struct input_stream *is, GError **error_r)
|
input_curl_easy_init(struct input_curl *c, GError **error_r)
|
||||||
{
|
{
|
||||||
struct input_curl *c = is->data;
|
|
||||||
CURLcode code;
|
CURLcode code;
|
||||||
CURLMcode mcode;
|
CURLMcode mcode;
|
||||||
|
|
||||||
@ -627,10 +625,10 @@ input_curl_easy_init(struct input_stream *is, GError **error_r)
|
|||||||
"Music Player Daemon " VERSION);
|
"Music Player Daemon " VERSION);
|
||||||
curl_easy_setopt(c->easy, CURLOPT_HEADERFUNCTION,
|
curl_easy_setopt(c->easy, CURLOPT_HEADERFUNCTION,
|
||||||
input_curl_headerfunction);
|
input_curl_headerfunction);
|
||||||
curl_easy_setopt(c->easy, CURLOPT_WRITEHEADER, is);
|
curl_easy_setopt(c->easy, CURLOPT_WRITEHEADER, c);
|
||||||
curl_easy_setopt(c->easy, CURLOPT_WRITEFUNCTION,
|
curl_easy_setopt(c->easy, CURLOPT_WRITEFUNCTION,
|
||||||
input_curl_writefunction);
|
input_curl_writefunction);
|
||||||
curl_easy_setopt(c->easy, CURLOPT_WRITEDATA, is);
|
curl_easy_setopt(c->easy, CURLOPT_WRITEDATA, c);
|
||||||
curl_easy_setopt(c->easy, CURLOPT_HTTP200ALIASES, http_200_aliases);
|
curl_easy_setopt(c->easy, CURLOPT_HTTP200ALIASES, http_200_aliases);
|
||||||
curl_easy_setopt(c->easy, CURLOPT_FOLLOWLOCATION, 1);
|
curl_easy_setopt(c->easy, CURLOPT_FOLLOWLOCATION, 1);
|
||||||
curl_easy_setopt(c->easy, CURLOPT_MAXREDIRS, 5);
|
curl_easy_setopt(c->easy, CURLOPT_MAXREDIRS, 5);
|
||||||
@ -669,9 +667,9 @@ input_curl_easy_init(struct input_stream *is, GError **error_r)
|
|||||||
void
|
void
|
||||||
input_curl_reinit(struct input_stream *is)
|
input_curl_reinit(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct input_curl *c = is->data;
|
struct input_curl *c = (struct input_curl *)is;
|
||||||
|
|
||||||
assert(is->plugin == &input_plugin_curl);
|
assert(c->base.plugin == &input_plugin_curl);
|
||||||
assert(c->easy != NULL);
|
assert(c->easy != NULL);
|
||||||
|
|
||||||
curl_easy_setopt(c->easy, CURLOPT_WRITEHEADER, is);
|
curl_easy_setopt(c->easy, CURLOPT_WRITEHEADER, is);
|
||||||
@ -702,7 +700,7 @@ static bool
|
|||||||
input_curl_seek(struct input_stream *is, goffset offset, int whence,
|
input_curl_seek(struct input_stream *is, goffset offset, int whence,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
struct input_curl *c = is->data;
|
struct input_curl *c = (struct input_curl *)is;
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
assert(is->ready);
|
assert(is->ready);
|
||||||
@ -774,7 +772,7 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = input_curl_easy_init(is, error_r);
|
ret = input_curl_easy_init(c, error_r);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -789,55 +787,54 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence,
|
|||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return input_curl_multi_info_read(is, error_r);
|
return input_curl_multi_info_read(c, error_r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static struct input_stream *
|
||||||
input_curl_open(struct input_stream *is, const char *url, GError **error_r)
|
input_curl_open(const char *url, GError **error_r)
|
||||||
{
|
{
|
||||||
struct input_curl *c;
|
struct input_curl *c;
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
if (strncmp(url, "http://", 7) != 0)
|
if (strncmp(url, "http://", 7) != 0)
|
||||||
return false;
|
return NULL;
|
||||||
|
|
||||||
c = g_new0(struct input_curl, 1);
|
c = g_new0(struct input_curl, 1);
|
||||||
|
input_stream_init(&c->base, &input_plugin_curl);
|
||||||
|
|
||||||
c->url = g_strdup(url);
|
c->url = g_strdup(url);
|
||||||
c->buffers = g_queue_new();
|
c->buffers = g_queue_new();
|
||||||
|
|
||||||
is->plugin = &input_plugin_curl;
|
|
||||||
is->data = c;
|
|
||||||
|
|
||||||
c->multi = curl_multi_init();
|
c->multi = curl_multi_init();
|
||||||
if (c->multi == NULL) {
|
if (c->multi == NULL) {
|
||||||
g_set_error(error_r, curl_quark(), 0,
|
g_set_error(error_r, curl_quark(), 0,
|
||||||
"curl_multi_init() failed");
|
"curl_multi_init() failed");
|
||||||
input_curl_free(is);
|
input_curl_free(c);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
icy_clear(&c->icy_metadata);
|
icy_clear(&c->icy_metadata);
|
||||||
c->tag = NULL;
|
c->tag = NULL;
|
||||||
|
|
||||||
ret = input_curl_easy_init(is, error_r);
|
ret = input_curl_easy_init(c, error_r);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
input_curl_free(is);
|
input_curl_free(c);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = input_curl_send_request(c, error_r);
|
ret = input_curl_send_request(c, error_r);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
input_curl_free(is);
|
input_curl_free(c);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = input_curl_multi_info_read(is, error_r);
|
ret = input_curl_multi_info_read(c, error_r);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
input_curl_free(is);
|
input_curl_free(c);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return &c->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct input_plugin input_plugin_curl = {
|
const struct input_plugin input_plugin_curl = {
|
||||||
|
@ -32,18 +32,24 @@
|
|||||||
#undef G_LOG_DOMAIN
|
#undef G_LOG_DOMAIN
|
||||||
#define G_LOG_DOMAIN "input_file"
|
#define G_LOG_DOMAIN "input_file"
|
||||||
|
|
||||||
|
struct file_input_stream {
|
||||||
|
struct input_stream base;
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
static inline GQuark
|
static inline GQuark
|
||||||
file_quark(void)
|
file_quark(void)
|
||||||
{
|
{
|
||||||
return g_quark_from_static_string("file");
|
return g_quark_from_static_string("file");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static struct input_stream *
|
||||||
input_file_open(struct input_stream *is, const char *filename,
|
input_file_open(const char *filename, GError **error_r)
|
||||||
GError **error_r)
|
|
||||||
{
|
{
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
struct file_input_stream *fis;
|
||||||
|
|
||||||
if (!g_path_is_absolute(filename))
|
if (!g_path_is_absolute(filename))
|
||||||
return false;
|
return false;
|
||||||
@ -57,8 +63,6 @@ input_file_open(struct input_stream *is, const char *filename,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
is->seekable = true;
|
|
||||||
|
|
||||||
ret = fstat(fd, &st);
|
ret = fstat(fd, &st);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
g_set_error(error_r, file_quark(), errno,
|
g_set_error(error_r, file_quark(), errno,
|
||||||
@ -75,26 +79,29 @@ input_file_open(struct input_stream *is, const char *filename,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
is->size = st.st_size;
|
|
||||||
|
|
||||||
#ifdef POSIX_FADV_SEQUENTIAL
|
#ifdef POSIX_FADV_SEQUENTIAL
|
||||||
posix_fadvise(fd, (off_t)0, is->size, POSIX_FADV_SEQUENTIAL);
|
posix_fadvise(fd, (off_t)0, st.st_size, POSIX_FADV_SEQUENTIAL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
is->plugin = &input_plugin_file;
|
fis = g_new(struct file_input_stream, 1);
|
||||||
is->data = GINT_TO_POINTER(fd);
|
input_stream_init(&fis->base, &input_plugin_file);
|
||||||
is->ready = true;
|
|
||||||
|
|
||||||
return true;
|
fis->base.size = st.st_size;
|
||||||
|
fis->base.seekable = true;
|
||||||
|
fis->base.ready = true;
|
||||||
|
|
||||||
|
fis->fd = fd;
|
||||||
|
|
||||||
|
return &fis->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
input_file_seek(struct input_stream *is, goffset offset, int whence,
|
input_file_seek(struct input_stream *is, goffset offset, int whence,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
int fd = GPOINTER_TO_INT(is->data);
|
struct file_input_stream *fis = (struct file_input_stream *)is;
|
||||||
|
|
||||||
offset = (goffset)lseek(fd, (off_t)offset, whence);
|
offset = (goffset)lseek(fis->fd, (off_t)offset, whence);
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
g_set_error(error_r, file_quark(), errno,
|
g_set_error(error_r, file_quark(), errno,
|
||||||
"Failed to seek: %s", g_strerror(errno));
|
"Failed to seek: %s", g_strerror(errno));
|
||||||
@ -109,10 +116,10 @@ static size_t
|
|||||||
input_file_read(struct input_stream *is, void *ptr, size_t size,
|
input_file_read(struct input_stream *is, void *ptr, size_t size,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
int fd = GPOINTER_TO_INT(is->data);
|
struct file_input_stream *fis = (struct file_input_stream *)is;
|
||||||
ssize_t nbytes;
|
ssize_t nbytes;
|
||||||
|
|
||||||
nbytes = read(fd, ptr, size);
|
nbytes = read(fis->fd, ptr, size);
|
||||||
if (nbytes < 0) {
|
if (nbytes < 0) {
|
||||||
g_set_error(error_r, file_quark(), errno,
|
g_set_error(error_r, file_quark(), errno,
|
||||||
"Failed to read: %s", g_strerror(errno));
|
"Failed to read: %s", g_strerror(errno));
|
||||||
@ -126,9 +133,10 @@ input_file_read(struct input_stream *is, void *ptr, size_t size,
|
|||||||
static void
|
static void
|
||||||
input_file_close(struct input_stream *is)
|
input_file_close(struct input_stream *is)
|
||||||
{
|
{
|
||||||
int fd = GPOINTER_TO_INT(is->data);
|
struct file_input_stream *fis = (struct file_input_stream *)is;
|
||||||
|
|
||||||
close(fd);
|
close(fis->fd);
|
||||||
|
g_free(fis);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#define G_LOG_DOMAIN "input_mms"
|
#define G_LOG_DOMAIN "input_mms"
|
||||||
|
|
||||||
struct input_mms {
|
struct input_mms {
|
||||||
|
struct input_stream base;
|
||||||
|
|
||||||
mmsx_t *mms;
|
mmsx_t *mms;
|
||||||
|
|
||||||
bool eof;
|
bool eof;
|
||||||
@ -42,8 +44,8 @@ mms_quark(void)
|
|||||||
return g_quark_from_static_string("mms");
|
return g_quark_from_static_string("mms");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static struct input_stream *
|
||||||
input_mms_open(struct input_stream *is, const char *url, GError **error_r)
|
input_mms_open(const char *url, GError **error_r)
|
||||||
{
|
{
|
||||||
struct input_mms *m;
|
struct input_mms *m;
|
||||||
|
|
||||||
@ -51,30 +53,31 @@ input_mms_open(struct input_stream *is, const char *url, GError **error_r)
|
|||||||
!g_str_has_prefix(url, "mmsh://") &&
|
!g_str_has_prefix(url, "mmsh://") &&
|
||||||
!g_str_has_prefix(url, "mmst://") &&
|
!g_str_has_prefix(url, "mmst://") &&
|
||||||
!g_str_has_prefix(url, "mmsu://"))
|
!g_str_has_prefix(url, "mmsu://"))
|
||||||
return false;
|
return NULL;
|
||||||
|
|
||||||
m = g_new(struct input_mms, 1);
|
m = g_new(struct input_mms, 1);
|
||||||
|
input_stream_init(&m->base, &input_plugin_mms);
|
||||||
|
|
||||||
m->mms = mmsx_connect(NULL, NULL, url, 128 * 1024);
|
m->mms = mmsx_connect(NULL, NULL, url, 128 * 1024);
|
||||||
if (m->mms == NULL) {
|
if (m->mms == NULL) {
|
||||||
g_set_error(error_r, mms_quark(), 0, "mmsx_connect() failed");
|
g_set_error(error_r, mms_quark(), 0, "mmsx_connect() failed");
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XX is this correct? at least this selects the ffmpeg
|
/* XX is this correct? at least this selects the ffmpeg
|
||||||
decoder, which seems to work fine*/
|
decoder, which seems to work fine*/
|
||||||
is->mime = g_strdup("audio/x-ms-wma");
|
m->base.mime = g_strdup("audio/x-ms-wma");
|
||||||
|
|
||||||
is->plugin = &input_plugin_mms;
|
m->base.ready = true;
|
||||||
is->data = m;
|
|
||||||
is->ready = true;
|
return &m->base;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
input_mms_read(struct input_stream *is, void *ptr, size_t size,
|
input_mms_read(struct input_stream *is, void *ptr, size_t size,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
struct input_mms *m = is->data;
|
struct input_mms *m = (struct input_mms *)is;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = mmsx_read(NULL, m->mms, ptr, size);
|
ret = mmsx_read(NULL, m->mms, ptr, size);
|
||||||
@ -97,7 +100,7 @@ input_mms_read(struct input_stream *is, void *ptr, size_t size,
|
|||||||
static void
|
static void
|
||||||
input_mms_close(struct input_stream *is)
|
input_mms_close(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct input_mms *m = is->data;
|
struct input_mms *m = (struct input_mms *)is;
|
||||||
|
|
||||||
mmsx_close(m->mms);
|
mmsx_close(m->mms);
|
||||||
g_free(m);
|
g_free(m);
|
||||||
@ -106,7 +109,7 @@ input_mms_close(struct input_stream *is)
|
|||||||
static bool
|
static bool
|
||||||
input_mms_eof(struct input_stream *is)
|
input_mms_eof(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct input_mms *m = is->data;
|
struct input_mms *m = (struct input_mms *)is;
|
||||||
|
|
||||||
return m->eof;
|
return m->eof;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,9 @@
|
|||||||
#define G_LOG_DOMAIN "input_rewind"
|
#define G_LOG_DOMAIN "input_rewind"
|
||||||
|
|
||||||
struct input_rewind {
|
struct input_rewind {
|
||||||
struct input_stream input;
|
struct input_stream base;
|
||||||
|
|
||||||
|
struct input_stream *input;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The read position within the buffer. Undefined as long as
|
* The read position within the buffer. Undefined as long as
|
||||||
@ -61,11 +63,9 @@ struct input_rewind {
|
|||||||
* contain more data for the next read operation?
|
* contain more data for the next read operation?
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
reading_from_buffer(const struct input_stream *is)
|
reading_from_buffer(const struct input_rewind *r)
|
||||||
{
|
{
|
||||||
const struct input_rewind *r = is->data;
|
return r->tail > 0 && r->base.offset < r->input->offset;
|
||||||
|
|
||||||
return r->tail > 0 && is->offset < r->input.offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,10 +75,10 @@ reading_from_buffer(const struct input_stream *is)
|
|||||||
* attributes.
|
* attributes.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
copy_attributes(struct input_stream *dest)
|
copy_attributes(struct input_rewind *r)
|
||||||
{
|
{
|
||||||
const struct input_rewind *r = dest->data;
|
struct input_stream *dest = &r->base;
|
||||||
const struct input_stream *src = &r->input;
|
const struct input_stream *src = r->input;
|
||||||
|
|
||||||
dest->ready = src->ready;
|
dest->ready = src->ready;
|
||||||
dest->seekable = src->seekable;
|
dest->seekable = src->seekable;
|
||||||
@ -94,9 +94,9 @@ copy_attributes(struct input_stream *dest)
|
|||||||
static void
|
static void
|
||||||
input_rewind_close(struct input_stream *is)
|
input_rewind_close(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct input_rewind *r = is->data;
|
struct input_rewind *r = (struct input_rewind *)is;
|
||||||
|
|
||||||
input_stream_close(&r->input);
|
input_stream_close(r->input);
|
||||||
|
|
||||||
g_free(r);
|
g_free(r);
|
||||||
}
|
}
|
||||||
@ -104,19 +104,19 @@ input_rewind_close(struct input_stream *is)
|
|||||||
static struct tag *
|
static struct tag *
|
||||||
input_rewind_tag(struct input_stream *is)
|
input_rewind_tag(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct input_rewind *r = is->data;
|
struct input_rewind *r = (struct input_rewind *)is;
|
||||||
|
|
||||||
return input_stream_tag(&r->input);
|
return input_stream_tag(r->input);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
input_rewind_buffer(struct input_stream *is, GError **error_r)
|
input_rewind_buffer(struct input_stream *is, GError **error_r)
|
||||||
{
|
{
|
||||||
struct input_rewind *r = is->data;
|
struct input_rewind *r = (struct input_rewind *)is;
|
||||||
|
|
||||||
int ret = input_stream_buffer(&r->input, error_r);
|
int ret = input_stream_buffer(r->input, error_r);
|
||||||
if (ret < 0 || !reading_from_buffer(is))
|
if (ret < 0 || !reading_from_buffer(r))
|
||||||
copy_attributes(is);
|
copy_attributes(r);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -125,13 +125,13 @@ static size_t
|
|||||||
input_rewind_read(struct input_stream *is, void *ptr, size_t size,
|
input_rewind_read(struct input_stream *is, void *ptr, size_t size,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
struct input_rewind *r = is->data;
|
struct input_rewind *r = (struct input_rewind *)is;
|
||||||
|
|
||||||
if (reading_from_buffer(is)) {
|
if (reading_from_buffer(r)) {
|
||||||
/* buffered read */
|
/* buffered read */
|
||||||
|
|
||||||
assert(r->head == (size_t)is->offset);
|
assert(r->head == (size_t)is->offset);
|
||||||
assert(r->tail == (size_t)r->input.offset);
|
assert(r->tail == (size_t)r->input->offset);
|
||||||
|
|
||||||
if (size > r->tail - r->head)
|
if (size > r->tail - r->head)
|
||||||
size = r->tail - r->head;
|
size = r->tail - r->head;
|
||||||
@ -144,9 +144,9 @@ input_rewind_read(struct input_stream *is, void *ptr, size_t size,
|
|||||||
} else {
|
} else {
|
||||||
/* pass method call to underlying stream */
|
/* pass method call to underlying stream */
|
||||||
|
|
||||||
size_t nbytes = input_stream_read(&r->input, ptr, size, error_r);
|
size_t nbytes = input_stream_read(r->input, ptr, size, error_r);
|
||||||
|
|
||||||
if (r->input.offset > (goffset)sizeof(r->buffer))
|
if (r->input->offset > (goffset)sizeof(r->buffer))
|
||||||
/* disable buffering */
|
/* disable buffering */
|
||||||
r->tail = 0;
|
r->tail = 0;
|
||||||
else if (r->tail == (size_t)is->offset) {
|
else if (r->tail == (size_t)is->offset) {
|
||||||
@ -155,46 +155,46 @@ input_rewind_read(struct input_stream *is, void *ptr, size_t size,
|
|||||||
memcpy(r->buffer + r->tail, ptr, nbytes);
|
memcpy(r->buffer + r->tail, ptr, nbytes);
|
||||||
r->tail += nbytes;
|
r->tail += nbytes;
|
||||||
|
|
||||||
assert(r->tail == (size_t)r->input.offset);
|
assert(r->tail == (size_t)r->input->offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_attributes(is);
|
copy_attributes(r);
|
||||||
|
|
||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
input_rewind_eof(G_GNUC_UNUSED struct input_stream *is)
|
input_rewind_eof(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct input_rewind *r = is->data;
|
struct input_rewind *r = (struct input_rewind *)is;
|
||||||
|
|
||||||
return !reading_from_buffer(is) && input_stream_eof(&r->input);
|
return !reading_from_buffer(r) && input_stream_eof(r->input);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
input_rewind_seek(struct input_stream *is, goffset offset, int whence,
|
input_rewind_seek(struct input_stream *is, goffset offset, int whence,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
struct input_rewind *r = is->data;
|
struct input_rewind *r = (struct input_rewind *)is;
|
||||||
|
|
||||||
assert(is->ready);
|
assert(is->ready);
|
||||||
|
|
||||||
if (whence == SEEK_SET && r->tail > 0 && offset <= (goffset)r->tail) {
|
if (whence == SEEK_SET && r->tail > 0 && offset <= (goffset)r->tail) {
|
||||||
/* buffered seek */
|
/* buffered seek */
|
||||||
|
|
||||||
assert(!reading_from_buffer(is) ||
|
assert(!reading_from_buffer(r) ||
|
||||||
r->head == (size_t)is->offset);
|
r->head == (size_t)is->offset);
|
||||||
assert(r->tail == (size_t)r->input.offset);
|
assert(r->tail == (size_t)r->input->offset);
|
||||||
|
|
||||||
r->head = (size_t)offset;
|
r->head = (size_t)offset;
|
||||||
is->offset = offset;
|
is->offset = offset;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
bool success = input_stream_seek(&r->input, offset, whence,
|
bool success = input_stream_seek(r->input, offset, whence,
|
||||||
error_r);
|
error_r);
|
||||||
copy_attributes(is);
|
copy_attributes(r);
|
||||||
|
|
||||||
/* disable the buffer, because r->input has left the
|
/* disable the buffer, because r->input has left the
|
||||||
buffered range now */
|
buffered range now */
|
||||||
@ -213,7 +213,7 @@ static const struct input_plugin rewind_input_plugin = {
|
|||||||
.seek = input_rewind_seek,
|
.seek = input_rewind_seek,
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
struct input_stream *
|
||||||
input_rewind_open(struct input_stream *is)
|
input_rewind_open(struct input_stream *is)
|
||||||
{
|
{
|
||||||
struct input_rewind *c;
|
struct input_rewind *c;
|
||||||
@ -224,17 +224,12 @@ input_rewind_open(struct input_stream *is)
|
|||||||
if (is->plugin != &input_plugin_curl)
|
if (is->plugin != &input_plugin_curl)
|
||||||
/* due to limitations in the input_plugin API, we only
|
/* due to limitations in the input_plugin API, we only
|
||||||
(explicitly) support the CURL input plugin */
|
(explicitly) support the CURL input plugin */
|
||||||
return;
|
return is;
|
||||||
|
|
||||||
c = g_new(struct input_rewind, 1);
|
c = g_new(struct input_rewind, 1);
|
||||||
|
input_stream_init(&c->base, &rewind_input_plugin);
|
||||||
c->tail = 0;
|
c->tail = 0;
|
||||||
|
c->input = is;
|
||||||
|
|
||||||
/* move the CURL input stream to c->input */
|
return &c->base;
|
||||||
c->input = *is;
|
|
||||||
input_curl_reinit(&c->input);
|
|
||||||
|
|
||||||
/* convert the existing input_stream pointer to a "rewind"
|
|
||||||
input stream */
|
|
||||||
is->plugin = &rewind_input_plugin;
|
|
||||||
is->data = c;
|
|
||||||
}
|
}
|
||||||
|
@ -33,15 +33,15 @@ struct input_stream;
|
|||||||
|
|
||||||
#ifdef ENABLE_CURL
|
#ifdef ENABLE_CURL
|
||||||
|
|
||||||
void
|
struct input_stream *
|
||||||
input_rewind_open(struct input_stream *is);
|
input_rewind_open(struct input_stream *is);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline void
|
static inline struct input_stream *
|
||||||
input_rewind_open(struct input_stream *is)
|
input_rewind_open(struct input_stream *is)
|
||||||
{
|
{
|
||||||
(void)is;
|
return is;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,8 +48,7 @@ struct input_plugin {
|
|||||||
*/
|
*/
|
||||||
void (*finish)(void);
|
void (*finish)(void);
|
||||||
|
|
||||||
bool (*open)(struct input_stream *is, const char *url,
|
struct input_stream *(*open)(const char *uri, GError **error_r);
|
||||||
GError **error_r);
|
|
||||||
void (*close)(struct input_stream *is);
|
void (*close)(struct input_stream *is);
|
||||||
|
|
||||||
struct tag *(*tag)(struct input_stream *is);
|
struct tag *(*tag)(struct input_stream *is);
|
||||||
|
@ -32,38 +32,34 @@ input_quark(void)
|
|||||||
return g_quark_from_static_string("input");
|
return g_quark_from_static_string("input");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
struct input_stream *
|
||||||
input_stream_open(struct input_stream *is, const char *url, GError **error_r)
|
input_stream_open(const char *url, GError **error_r)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
assert(error_r == NULL || *error_r == NULL);
|
assert(error_r == NULL || *error_r == NULL);
|
||||||
|
|
||||||
is->seekable = false;
|
|
||||||
is->ready = false;
|
|
||||||
is->offset = 0;
|
|
||||||
is->size = -1;
|
|
||||||
is->mime = NULL;
|
|
||||||
|
|
||||||
for (unsigned i = 0; input_plugins[i] != NULL; ++i) {
|
for (unsigned i = 0; input_plugins[i] != NULL; ++i) {
|
||||||
const struct input_plugin *plugin = input_plugins[i];
|
const struct input_plugin *plugin = input_plugins[i];
|
||||||
|
struct input_stream *is;
|
||||||
|
|
||||||
if (!input_plugins_enabled[i])
|
if (!input_plugins_enabled[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (plugin->open(is, url, &error)) {
|
is = plugin->open(url, &error);
|
||||||
|
if (is != NULL) {
|
||||||
assert(is->plugin != NULL);
|
assert(is->plugin != NULL);
|
||||||
assert(is->plugin->close != NULL);
|
assert(is->plugin->close != NULL);
|
||||||
assert(is->plugin->read != NULL);
|
assert(is->plugin->read != NULL);
|
||||||
assert(is->plugin->eof != NULL);
|
assert(is->plugin->eof != NULL);
|
||||||
assert(!is->seekable || is->plugin->seek != NULL);
|
assert(!is->seekable || is->plugin->seek != NULL);
|
||||||
|
|
||||||
input_rewind_open(is);
|
is = input_rewind_open(is);
|
||||||
|
|
||||||
return true;
|
return is;
|
||||||
} else if (error != NULL) {
|
} else if (error != NULL) {
|
||||||
g_propagate_error(error_r, error);
|
g_propagate_error(error_r, error);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,9 +99,9 @@ input_stream_read(struct input_stream *is, void *ptr, size_t size,
|
|||||||
|
|
||||||
void input_stream_close(struct input_stream *is)
|
void input_stream_close(struct input_stream *is)
|
||||||
{
|
{
|
||||||
is->plugin->close(is);
|
|
||||||
|
|
||||||
g_free(is->mime);
|
g_free(is->mime);
|
||||||
|
|
||||||
|
is->plugin->close(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool input_stream_eof(struct input_stream *is)
|
bool input_stream_eof(struct input_stream *is)
|
||||||
|
@ -38,11 +38,6 @@ struct input_stream {
|
|||||||
*/
|
*/
|
||||||
const struct input_plugin *plugin;
|
const struct input_plugin *plugin;
|
||||||
|
|
||||||
/**
|
|
||||||
* an opaque pointer managed by the plugin
|
|
||||||
*/
|
|
||||||
void *data;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* indicates whether the stream is ready for reading and
|
* indicates whether the stream is ready for reading and
|
||||||
* whether the other attributes in this struct are valid
|
* whether the other attributes in this struct are valid
|
||||||
@ -70,20 +65,28 @@ struct input_stream {
|
|||||||
char *mime;
|
char *mime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
input_stream_init(struct input_stream *is, const struct input_plugin *plugin)
|
||||||
|
{
|
||||||
|
is->plugin = plugin;
|
||||||
|
is->ready = false;
|
||||||
|
is->seekable = false;
|
||||||
|
is->size = -1;
|
||||||
|
is->offset = 0;
|
||||||
|
is->mime = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a new input stream. You may not access it until the "ready"
|
* Opens a new input stream. You may not access it until the "ready"
|
||||||
* flag is set.
|
* flag is set.
|
||||||
*
|
*
|
||||||
* @param is the input_stream object allocated by the caller
|
* @return an #input_stream object on success, NULL on error
|
||||||
* @return true on success
|
|
||||||
*/
|
*/
|
||||||
bool
|
struct input_stream *
|
||||||
input_stream_open(struct input_stream *is, const char *url, GError **error_r);
|
input_stream_open(const char *uri, GError **error_r);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the input stream and free resources. This does not free the
|
* Close the input stream and free resources.
|
||||||
* input_stream pointer itself, because it is assumed to be allocated
|
|
||||||
* by the caller.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
input_stream_close(struct input_stream *is);
|
input_stream_close(struct input_stream *is);
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
struct lastfm_playlist {
|
struct lastfm_playlist {
|
||||||
struct playlist_provider base;
|
struct playlist_provider base;
|
||||||
|
|
||||||
struct input_stream is;
|
struct input_stream *is;
|
||||||
|
|
||||||
struct playlist_provider *xspf;
|
struct playlist_provider *xspf;
|
||||||
};
|
};
|
||||||
@ -85,15 +85,14 @@ lastfm_finish(void)
|
|||||||
static char *
|
static char *
|
||||||
lastfm_get(const char *url)
|
lastfm_get(const char *url)
|
||||||
{
|
{
|
||||||
struct input_stream input_stream;
|
struct input_stream *input_stream;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
bool success;
|
|
||||||
int ret;
|
int ret;
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
size_t length = 0, nbytes;
|
size_t length = 0, nbytes;
|
||||||
|
|
||||||
success = input_stream_open(&input_stream, url, &error);
|
input_stream = input_stream_open(url, &error);
|
||||||
if (!success) {
|
if (input_stream == NULL) {
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
@ -102,10 +101,10 @@ lastfm_get(const char *url)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!input_stream.ready) {
|
while (!input_stream->ready) {
|
||||||
ret = input_stream_buffer(&input_stream, &error);
|
ret = input_stream_buffer(input_stream, &error);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
input_stream_close(&input_stream);
|
input_stream_close(input_stream);
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -113,7 +112,7 @@ lastfm_get(const char *url)
|
|||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
nbytes = input_stream_read(&input_stream, buffer + length,
|
nbytes = input_stream_read(input_stream, buffer + length,
|
||||||
sizeof(buffer) - length, &error);
|
sizeof(buffer) - length, &error);
|
||||||
if (nbytes == 0) {
|
if (nbytes == 0) {
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
@ -121,18 +120,18 @@ lastfm_get(const char *url)
|
|||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input_stream_eof(&input_stream))
|
if (input_stream_eof(input_stream))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* I/O error */
|
/* I/O error */
|
||||||
input_stream_close(&input_stream);
|
input_stream_close(input_stream);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
length += nbytes;
|
length += nbytes;
|
||||||
} while (length < sizeof(buffer));
|
} while (length < sizeof(buffer));
|
||||||
|
|
||||||
input_stream_close(&input_stream);
|
input_stream_close(input_stream);
|
||||||
return g_strndup(buffer, length);
|
return g_strndup(buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +167,6 @@ lastfm_open_uri(const char *uri)
|
|||||||
struct lastfm_playlist *playlist;
|
struct lastfm_playlist *playlist;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
char *p, *q, *response, *session;
|
char *p, *q, *response, *session;
|
||||||
bool success;
|
|
||||||
|
|
||||||
/* handshake */
|
/* handshake */
|
||||||
|
|
||||||
@ -231,10 +229,10 @@ lastfm_open_uri(const char *uri)
|
|||||||
NULL);
|
NULL);
|
||||||
g_free(session);
|
g_free(session);
|
||||||
|
|
||||||
success = input_stream_open(&playlist->is, p, &error);
|
playlist->is = input_stream_open(p, &error);
|
||||||
g_free(p);
|
g_free(p);
|
||||||
|
|
||||||
if (!success) {
|
if (playlist->is == NULL) {
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
g_warning("Failed to load XSPF playlist: %s",
|
g_warning("Failed to load XSPF playlist: %s",
|
||||||
error->message);
|
error->message);
|
||||||
@ -245,10 +243,10 @@ lastfm_open_uri(const char *uri)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!playlist->is.ready) {
|
while (!playlist->is->ready) {
|
||||||
int ret = input_stream_buffer(&playlist->is, &error);
|
int ret = input_stream_buffer(playlist->is, &error);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
input_stream_close(&playlist->is);
|
input_stream_close(playlist->is);
|
||||||
g_free(playlist);
|
g_free(playlist);
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
@ -262,14 +260,14 @@ lastfm_open_uri(const char *uri)
|
|||||||
|
|
||||||
/* last.fm does not send a MIME type, we have to fake it here
|
/* last.fm does not send a MIME type, we have to fake it here
|
||||||
:-( */
|
:-( */
|
||||||
g_free(playlist->is.mime);
|
g_free(playlist->is->mime);
|
||||||
playlist->is.mime = g_strdup("application/xspf+xml");
|
playlist->is->mime = g_strdup("application/xspf+xml");
|
||||||
|
|
||||||
/* parse the XSPF playlist */
|
/* parse the XSPF playlist */
|
||||||
|
|
||||||
playlist->xspf = playlist_list_open_stream(&playlist->is, NULL);
|
playlist->xspf = playlist_list_open_stream(playlist->is, NULL);
|
||||||
if (playlist->xspf == NULL) {
|
if (playlist->xspf == NULL) {
|
||||||
input_stream_close(&playlist->is);
|
input_stream_close(playlist->is);
|
||||||
g_free(playlist);
|
g_free(playlist);
|
||||||
g_warning("Failed to parse XSPF playlist");
|
g_warning("Failed to parse XSPF playlist");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -284,7 +282,7 @@ lastfm_close(struct playlist_provider *_playlist)
|
|||||||
struct lastfm_playlist *playlist = (struct lastfm_playlist *)_playlist;
|
struct lastfm_playlist *playlist = (struct lastfm_playlist *)_playlist;
|
||||||
|
|
||||||
playlist_plugin_close(playlist->xspf);
|
playlist_plugin_close(playlist->xspf);
|
||||||
input_stream_close(&playlist->is);
|
input_stream_close(playlist->is);
|
||||||
g_free(playlist);
|
g_free(playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,10 +293,11 @@ playlist_suffix_supported(const char *suffix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct playlist_provider *
|
struct playlist_provider *
|
||||||
playlist_list_open_path(struct input_stream *is, const char *path_fs)
|
playlist_list_open_path(const char *path_fs)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
const char *suffix;
|
const char *suffix;
|
||||||
|
struct input_stream *is;
|
||||||
struct playlist_provider *playlist;
|
struct playlist_provider *playlist;
|
||||||
|
|
||||||
assert(path_fs != NULL);
|
assert(path_fs != NULL);
|
||||||
@ -305,7 +306,8 @@ playlist_list_open_path(struct input_stream *is, const char *path_fs)
|
|||||||
if (suffix == NULL || !playlist_suffix_supported(suffix))
|
if (suffix == NULL || !playlist_suffix_supported(suffix))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!input_stream_open(is, path_fs, &error)) {
|
is = input_stream_open(path_fs, &error);
|
||||||
|
if (is == NULL) {
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
|
@ -54,12 +54,10 @@ playlist_list_open_stream(struct input_stream *is, const char *uri);
|
|||||||
/**
|
/**
|
||||||
* Opens a playlist from a local file.
|
* Opens a playlist from a local file.
|
||||||
*
|
*
|
||||||
* @param is an uninitialized #input_stream object (must be closed
|
|
||||||
* with input_stream_close() if this function succeeds)
|
|
||||||
* @param path_fs the path of the playlist file
|
* @param path_fs the path of the playlist file
|
||||||
* @return a playlist, or NULL on error
|
* @return a playlist, or NULL on error
|
||||||
*/
|
*/
|
||||||
struct playlist_provider *
|
struct playlist_provider *
|
||||||
playlist_list_open_path(struct input_stream *is, const char *path_fs);
|
playlist_list_open_path(const char *path_fs);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -163,16 +163,15 @@ playlist_open_remote_into_queue(const char *uri, struct playlist *dest)
|
|||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
struct playlist_provider *playlist;
|
struct playlist_provider *playlist;
|
||||||
bool stream = false;
|
struct input_stream *is = NULL;
|
||||||
struct input_stream is;
|
|
||||||
enum playlist_result result;
|
enum playlist_result result;
|
||||||
|
|
||||||
assert(uri_has_scheme(uri));
|
assert(uri_has_scheme(uri));
|
||||||
|
|
||||||
playlist = playlist_list_open_uri(uri);
|
playlist = playlist_list_open_uri(uri);
|
||||||
if (playlist == NULL) {
|
if (playlist == NULL) {
|
||||||
stream = input_stream_open(&is, uri, &error);
|
is = input_stream_open(uri, &error);
|
||||||
if (!stream) {
|
if (is == NULL) {
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
g_warning("Failed to open %s: %s",
|
g_warning("Failed to open %s: %s",
|
||||||
uri, error->message);
|
uri, error->message);
|
||||||
@ -182,9 +181,9 @@ playlist_open_remote_into_queue(const char *uri, struct playlist *dest)
|
|||||||
return PLAYLIST_RESULT_NO_SUCH_LIST;
|
return PLAYLIST_RESULT_NO_SUCH_LIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist = playlist_list_open_stream(&is, uri);
|
playlist = playlist_list_open_stream(is, uri);
|
||||||
if (playlist == NULL) {
|
if (playlist == NULL) {
|
||||||
input_stream_close(&is);
|
input_stream_close(is);
|
||||||
return PLAYLIST_RESULT_NO_SUCH_LIST;
|
return PLAYLIST_RESULT_NO_SUCH_LIST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,8 +191,8 @@ playlist_open_remote_into_queue(const char *uri, struct playlist *dest)
|
|||||||
result = playlist_load_into_queue(uri, playlist, dest);
|
result = playlist_load_into_queue(uri, playlist, dest);
|
||||||
playlist_plugin_close(playlist);
|
playlist_plugin_close(playlist);
|
||||||
|
|
||||||
if (stream)
|
if (is != NULL)
|
||||||
input_stream_close(&is);
|
input_stream_close(is);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -203,15 +202,13 @@ playlist_open_path_into_queue(const char *path_fs, const char *uri,
|
|||||||
struct playlist *dest)
|
struct playlist *dest)
|
||||||
{
|
{
|
||||||
struct playlist_provider *playlist;
|
struct playlist_provider *playlist;
|
||||||
struct input_stream is;
|
|
||||||
enum playlist_result result;
|
enum playlist_result result;
|
||||||
|
|
||||||
if ((playlist = playlist_list_open_uri(path_fs)) != NULL)
|
if ((playlist = playlist_list_open_uri(path_fs)) != NULL)
|
||||||
result = playlist_load_into_queue(uri, playlist, dest);
|
result = playlist_load_into_queue(uri, playlist, dest);
|
||||||
else if ((playlist = playlist_list_open_path(&is, path_fs)) != NULL) {
|
else if ((playlist = playlist_list_open_path(path_fs)) != NULL)
|
||||||
result = playlist_load_into_queue(uri, playlist, dest);
|
result = playlist_load_into_queue(uri, playlist, dest);
|
||||||
input_stream_close(&is);
|
else
|
||||||
} else
|
|
||||||
return PLAYLIST_RESULT_NO_SUCH_LIST;
|
return PLAYLIST_RESULT_NO_SUCH_LIST;
|
||||||
|
|
||||||
playlist_plugin_close(playlist);
|
playlist_plugin_close(playlist);
|
||||||
|
@ -101,7 +101,7 @@ song_file_update(struct song *song)
|
|||||||
char *path_fs;
|
char *path_fs;
|
||||||
const struct decoder_plugin *plugin;
|
const struct decoder_plugin *plugin;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct input_stream is = { .plugin = NULL };
|
struct input_stream *is = NULL;
|
||||||
|
|
||||||
assert(song_is_file(song));
|
assert(song_is_file(song));
|
||||||
|
|
||||||
@ -141,26 +141,25 @@ song_file_update(struct song *song)
|
|||||||
if (plugin->stream_tag != NULL) {
|
if (plugin->stream_tag != NULL) {
|
||||||
/* open the input_stream (if not already
|
/* open the input_stream (if not already
|
||||||
open) */
|
open) */
|
||||||
if (is.plugin == NULL &&
|
if (is == NULL)
|
||||||
!input_stream_open(&is, path_fs, NULL))
|
is = input_stream_open(path_fs, NULL);
|
||||||
is.plugin = NULL;
|
|
||||||
|
|
||||||
/* now try the stream_tag() method */
|
/* now try the stream_tag() method */
|
||||||
if (is.plugin != NULL) {
|
if (is != NULL) {
|
||||||
song->tag = decoder_plugin_stream_tag(plugin,
|
song->tag = decoder_plugin_stream_tag(plugin,
|
||||||
&is);
|
is);
|
||||||
if (song->tag != NULL)
|
if (song->tag != NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
input_stream_seek(&is, 0, SEEK_SET, NULL);
|
input_stream_seek(is, 0, SEEK_SET, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin = decoder_plugin_from_suffix(suffix, plugin);
|
plugin = decoder_plugin_from_suffix(suffix, plugin);
|
||||||
} while (plugin != NULL);
|
} while (plugin != NULL);
|
||||||
|
|
||||||
if (is.plugin != NULL)
|
if (is != NULL)
|
||||||
input_stream_close(&is);
|
input_stream_close(is);
|
||||||
|
|
||||||
if (song->tag != NULL && tag_is_empty(song->tag))
|
if (song->tag != NULL && tag_is_empty(song->tag))
|
||||||
song->tag = tag_fallback(path_fs, song->tag);
|
song->tag = tag_fallback(path_fs, song->tag);
|
||||||
|
@ -44,8 +44,7 @@ my_log_func(const gchar *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level,
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *uri;
|
const char *uri;
|
||||||
struct input_stream is;
|
struct input_stream *is = NULL;
|
||||||
bool stream_open = false;
|
|
||||||
bool success;
|
bool success;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
struct playlist_provider *playlist;
|
struct playlist_provider *playlist;
|
||||||
@ -88,8 +87,8 @@ int main(int argc, char **argv)
|
|||||||
if (playlist == NULL) {
|
if (playlist == NULL) {
|
||||||
/* open the stream and wait until it becomes ready */
|
/* open the stream and wait until it becomes ready */
|
||||||
|
|
||||||
success = input_stream_open(&is, uri, &error);
|
is = input_stream_open(uri, &error);
|
||||||
if (!success) {
|
if (is == NULL) {
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
@ -98,8 +97,8 @@ int main(int argc, char **argv)
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!is.ready) {
|
while (!is->ready) {
|
||||||
int ret = input_stream_buffer(&is, &error);
|
int ret = input_stream_buffer(is, &error);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
/* error */
|
/* error */
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
@ -112,13 +111,11 @@ int main(int argc, char **argv)
|
|||||||
g_usleep(10000);
|
g_usleep(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_open = true;
|
|
||||||
|
|
||||||
/* open the playlist */
|
/* open the playlist */
|
||||||
|
|
||||||
playlist = playlist_list_open_stream(&is, uri);
|
playlist = playlist_list_open_stream(is, uri);
|
||||||
if (playlist == NULL) {
|
if (playlist == NULL) {
|
||||||
input_stream_close(&is);
|
input_stream_close(is);
|
||||||
g_printerr("Failed to open playlist\n");
|
g_printerr("Failed to open playlist\n");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
@ -145,8 +142,8 @@ int main(int argc, char **argv)
|
|||||||
/* deinitialize everything */
|
/* deinitialize everything */
|
||||||
|
|
||||||
playlist_plugin_close(playlist);
|
playlist_plugin_close(playlist);
|
||||||
if (stream_open)
|
if (is != NULL)
|
||||||
input_stream_close(&is);
|
input_stream_close(is);
|
||||||
playlist_list_global_finish();
|
playlist_list_global_finish();
|
||||||
input_stream_global_finish();
|
input_stream_global_finish();
|
||||||
config_global_finish();
|
config_global_finish();
|
||||||
|
@ -170,17 +170,17 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
tag = decoder_plugin_tag_dup(plugin, path);
|
tag = decoder_plugin_tag_dup(plugin, path);
|
||||||
if (tag == NULL && plugin->stream_tag != NULL) {
|
if (tag == NULL && plugin->stream_tag != NULL) {
|
||||||
struct input_stream is;
|
struct input_stream *is = input_stream_open(path, &error);
|
||||||
|
|
||||||
if (!input_stream_open(&is, path, &error)) {
|
if (is == NULL) {
|
||||||
g_printerr("Failed to open %s: %s\n",
|
g_printerr("Failed to open %s: %s\n",
|
||||||
path, error->message);
|
path, error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tag = decoder_plugin_stream_tag(plugin, &is);
|
tag = decoder_plugin_stream_tag(plugin, is);
|
||||||
input_stream_close(&is);
|
input_stream_close(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
decoder_plugin_deinit_all();
|
decoder_plugin_deinit_all();
|
||||||
|
@ -145,7 +145,6 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder,
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
bool ret;
|
|
||||||
const char *decoder_name;
|
const char *decoder_name;
|
||||||
struct decoder decoder;
|
struct decoder decoder;
|
||||||
|
|
||||||
@ -179,10 +178,9 @@ int main(int argc, char **argv)
|
|||||||
decoder_plugin_file_decode(decoder.plugin, &decoder,
|
decoder_plugin_file_decode(decoder.plugin, &decoder,
|
||||||
decoder.uri);
|
decoder.uri);
|
||||||
} else if (decoder.plugin->stream_decode != NULL) {
|
} else if (decoder.plugin->stream_decode != NULL) {
|
||||||
struct input_stream is;
|
struct input_stream *is =
|
||||||
|
input_stream_open(decoder.uri, &error);
|
||||||
ret = input_stream_open(&is, decoder.uri, &error);
|
if (is == NULL) {
|
||||||
if (!ret) {
|
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
@ -192,9 +190,9 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
decoder_plugin_stream_decode(decoder.plugin, &decoder, &is);
|
decoder_plugin_stream_decode(decoder.plugin, &decoder, is);
|
||||||
|
|
||||||
input_stream_close(&is);
|
input_stream_close(is);
|
||||||
} else {
|
} else {
|
||||||
g_printerr("Decoder plugin is not usable\n");
|
g_printerr("Decoder plugin is not usable\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -103,7 +103,7 @@ dump_input_stream(struct input_stream *is)
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
struct input_stream is;
|
struct input_stream *is;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
@ -133,9 +133,10 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* open the stream and dump it */
|
/* open the stream and dump it */
|
||||||
|
|
||||||
if (input_stream_open(&is, argv[1], &error)) {
|
is = input_stream_open(argv[1], &error);
|
||||||
ret = dump_input_stream(&is);
|
if (is != NULL) {
|
||||||
input_stream_close(&is);
|
ret = dump_input_stream(is);
|
||||||
|
input_stream_close(is);
|
||||||
} else {
|
} else {
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
|
Loading…
Reference in New Issue
Block a user