Commit d3b763a4 authored by Max Kellermann's avatar Max Kellermann

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).
parent 816b6ad4
...@@ -45,10 +45,12 @@ struct bz2_archive_file { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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 ...@@ -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, ...@@ -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 ...@@ -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) ...@@ -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 { ...@@ -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); ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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, ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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, ...@@ -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, ...@@ -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 @@ ...@@ -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, ...@@ -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, ...@@ -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 ...@@ -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, ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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");
m->base.ready = true;
is->plugin = &input_plugin_mms; return &m->base;
is->data = m;
is->ready = true;
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, ...@@ -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) ...@@ -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 @@ ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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, ...@@ -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, ...@@ -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 = { ...@@ -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) ...@@ -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; ...@@ -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 { ...@@ -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) ...@@ -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, ...@@ -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)
......
...@@ -39,11 +39,6 @@ struct input_stream { ...@@ -39,11 +39,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 { ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment