From 228b03edf8513aa1cdaf4e4647279cc580245555 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 14 Nov 2009 23:53:04 +0100 Subject: input_stream: return errors with GError --- src/archive/bz2_plugin.c | 39 +++++++++----- src/archive/iso_plugin.c | 20 +++++--- src/archive/zzip_archive_plugin.c | 23 ++++++--- src/archive_plugin.h | 6 ++- src/decoder/audiofile_plugin.c | 16 ++++-- src/decoder/faad_plugin.c | 4 +- src/decoder/ffmpeg_plugin.c | 4 +- src/decoder/flac_plugin.c | 4 +- src/decoder/mad_plugin.c | 4 +- src/decoder/modplug_plugin.c | 2 +- src/decoder/mpcdec_plugin.c | 4 +- src/decoder/oggflac_plugin.c | 16 ++++-- src/decoder/sndfile_decoder_plugin.c | 10 ++-- src/decoder/vorbis_plugin.c | 4 +- src/decoder/wavpack_plugin.c | 6 +-- src/decoder_api.c | 10 +++- src/decoder_internal.c | 8 ++- src/decoder_thread.c | 16 ++++-- src/input/archive_input_plugin.c | 9 ++-- src/input/curl_input_plugin.c | 97 ++++++++++++++++++++++------------- src/input/file_input_plugin.c | 38 +++++++++----- src/input/mms_input_plugin.c | 24 ++++++--- src/input_plugin.h | 11 ++-- src/input_stream.c | 37 +++++++++---- src/input_stream.h | 15 +++--- src/playlist/asx_playlist_plugin.c | 12 ++++- src/playlist/lastfm_playlist_plugin.c | 36 ++++++++++--- src/playlist/pls_playlist_plugin.c | 13 ++++- src/playlist/xspf_playlist_plugin.c | 12 ++++- src/playlist_list.c | 17 ++++-- src/playlist_queue.c | 12 ++++- src/text_input_stream.c | 9 +++- 32 files changed, 378 insertions(+), 160 deletions(-) (limited to 'src') diff --git a/src/archive/bz2_plugin.c b/src/archive/bz2_plugin.c index 44a1ddd2f..4e5733225 100644 --- a/src/archive/bz2_plugin.c +++ b/src/archive/bz2_plugin.c @@ -51,11 +51,19 @@ typedef struct { static const struct input_plugin bz2_inputplugin; +static inline GQuark +bz2_quark(void) +{ + return g_quark_from_static_string("bz2"); +} + /* single archive handling allocation helpers */ static bool -bz2_alloc(bz2_context *data) +bz2_alloc(bz2_context *data, GError **error_r) { + int ret; + data->bzstream.bzalloc = NULL; data->bzstream.bzfree = NULL; data->bzstream.opaque = NULL; @@ -64,9 +72,13 @@ bz2_alloc(bz2_context *data) data->bzstream.next_in = (void *) data->buffer; data->bzstream.avail_in = 0; - if (BZ2_bzDecompressInit(&data->bzstream, 0, 0) != BZ_OK) { + ret = BZ2_bzDecompressInit(&data->bzstream, 0, 0); + if (ret != BZ_OK) { g_free(data->buffer); g_free(data); + + g_set_error(error_r, bz2_quark(), ret, + "BZ2_bzDecompressInit() has failed"); return false; } @@ -92,7 +104,7 @@ bz2_open(char *pathname) context = g_malloc(sizeof(*context)); //open archive - if (!input_stream_open(&context->istream, pathname)) { + if (!input_stream_open(&context->istream, pathname, NULL)) { g_warning("failed to open an bzip2 archive %s\n",pathname); g_free(context); return NULL; @@ -153,7 +165,7 @@ bz2_close(struct archive_file *file) static bool bz2_open_stream(struct archive_file *file, struct input_stream *is, - G_GNUC_UNUSED const char *path) + G_GNUC_UNUSED const char *path, GError **error_r) { bz2_context *context = (bz2_context *) file; @@ -163,10 +175,8 @@ bz2_open_stream(struct archive_file *file, struct input_stream *is, is->data = context; is->seekable = false; - if (!bz2_alloc(context)) { - g_warning("alloc bz2 failed\n"); + if (!bz2_alloc(context, error_r)) return false; - } context->eof = false; @@ -184,7 +194,7 @@ bz2_is_close(struct input_stream *is) } static bool -bz2_fillbuffer(bz2_context *context) +bz2_fillbuffer(bz2_context *context, GError **error_r) { size_t count; bz_stream *bzstream; @@ -195,7 +205,8 @@ bz2_fillbuffer(bz2_context *context) return true; count = input_stream_read(&context->istream, - context->buffer, BZ_BUFSIZE); + context->buffer, BZ_BUFSIZE, + error_r); if (count == 0) return false; @@ -205,7 +216,8 @@ bz2_fillbuffer(bz2_context *context) } 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) { bz2_context *context = (bz2_context *) is->data; bz_stream *bzstream; @@ -220,10 +232,8 @@ bz2_is_read(struct input_stream *is, void *ptr, size_t length) bzstream->avail_out = length; do { - if (!bz2_fillbuffer(context)) { - is->error = -1; + if (!bz2_fillbuffer(context, error_r)) return 0; - } bz_result = BZ2_bzDecompress(bzstream); @@ -233,7 +243,8 @@ bz2_is_read(struct input_stream *is, void *ptr, size_t length) } if (bz_result != BZ_OK) { - is->error = bz_result; + g_set_error(error_r, bz2_quark(), bz_result, + "BZ2_bzDecompress() has failed"); return 0; } } while (bzstream->avail_out == length); diff --git a/src/archive/iso_plugin.c b/src/archive/iso_plugin.c index b56653d56..a2880ba86 100644 --- a/src/archive/iso_plugin.c +++ b/src/archive/iso_plugin.c @@ -44,6 +44,12 @@ typedef struct { static const struct input_plugin iso_inputplugin; +static inline GQuark +iso9660_quark(void) +{ + return g_quark_from_static_string("iso9660"); +} + /* archive open && listing routine */ static void @@ -141,7 +147,7 @@ iso_close(struct archive_file *file) static bool iso_open_stream(struct archive_file *file, struct input_stream *is, - const char *pathname) + const char *pathname, GError **error_r) { iso_context *context = (iso_context *) file; //setup file ops @@ -154,7 +160,8 @@ iso_open_stream(struct archive_file *file, struct input_stream *is, context->statbuf = iso9660_ifs_stat_translate (context->iso, pathname); if (context->statbuf == NULL) { - g_warning("file %s not found in iso\n", pathname); + g_set_error(error_r, iso9660_quark(), 0, + "not found in the ISO file: %s", pathname); return false; } context->cur_ofs = 0; @@ -173,7 +180,7 @@ iso_is_close(struct input_stream *is) static size_t -iso_is_read(struct input_stream *is, void *ptr, size_t size) +iso_is_read(struct input_stream *is, void *ptr, size_t size, GError **error_r) { iso_context *context = (iso_context *) is->data; int toread, readed = 0; @@ -197,9 +204,10 @@ iso_is_read(struct input_stream *is, void *ptr, size_t size) context->statbuf->lsn + cur_block, no_blocks); if (readed != no_blocks * ISO_BLOCKSIZE) { - g_warning("error reading ISO file at lsn %lu\n", - (long unsigned int) cur_block ); - return -1; + g_set_error(error_r, iso9660_quark(), 0, + "error reading ISO file at lsn %lu", + (long unsigned int) cur_block); + return 0; } if (left_bytes < size) { readed = left_bytes; diff --git a/src/archive/zzip_archive_plugin.c b/src/archive/zzip_archive_plugin.c index 91c1fed4f..ac6e7dac2 100644 --- a/src/archive/zzip_archive_plugin.c +++ b/src/archive/zzip_archive_plugin.c @@ -40,6 +40,12 @@ struct zzip_archive { static const struct input_plugin zzip_input_plugin; +static inline GQuark +zzip_quark(void) +{ + return g_quark_from_static_string("zzip"); +} + /* archive open && listing routine */ static struct archive_file * @@ -108,7 +114,7 @@ zzip_archive_close(struct archive_file *file) static bool zzip_archive_open_stream(struct archive_file *file, struct input_stream *is, - const char *pathname) + const char *pathname, GError **error_r) { struct zzip_archive *context = (struct zzip_archive *) file; ZZIP_STAT z_stat; @@ -122,7 +128,8 @@ zzip_archive_open_stream(struct archive_file *file, struct input_stream *is, context->file = zzip_file_open(context->dir, pathname, 0); if (!context->file) { - g_warning("file %s not found in the zipfile\n", pathname); + g_set_error(error_r, zzip_quark(), 0, + "not found in the ZIP file: %s", pathname); return false; } zzip_file_stat(context->file, &z_stat); @@ -140,13 +147,15 @@ zzip_input_close(struct input_stream *is) } 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) { struct zzip_archive *context = (struct zzip_archive *) is->data; int ret; ret = zzip_file_read(context->file, ptr, size); if (ret < 0) { - g_warning("error %d reading zipfile\n", ret); + g_set_error(error_r, zzip_quark(), ret, + "zzip_file_read() has failed"); return 0; } return ret; @@ -160,12 +169,14 @@ zzip_input_eof(struct input_stream *is) } static bool -zzip_input_seek(G_GNUC_UNUSED struct input_stream *is, - G_GNUC_UNUSED goffset offset, G_GNUC_UNUSED int whence) +zzip_input_seek(struct input_stream *is, + goffset offset, int whence, GError **error_r) { struct zzip_archive *context = (struct zzip_archive *) is->data; zzip_off_t ofs = zzip_seek(context->file, offset, whence); if (ofs != -1) { + g_set_error(error_r, zzip_quark(), ofs, + "zzip_seek() has failed"); is->offset = ofs; return true; } diff --git a/src/archive_plugin.h b/src/archive_plugin.h index df2dcff47..cb6243f0c 100644 --- a/src/archive_plugin.h +++ b/src/archive_plugin.h @@ -20,6 +20,8 @@ #ifndef MPD_ARCHIVE_PLUGIN_H #define MPD_ARCHIVE_PLUGIN_H +#include + #include struct input_stream; @@ -69,9 +71,11 @@ struct archive_plugin { * the archive file and will automatically close it. * * @param path the path within the archive + * @param error_r location to store the error occuring, or + * NULL to ignore errors */ bool (*open_stream)(struct archive_file *, struct input_stream *is, - const char *path); + const char *path, GError **error_r); /** * closes archive file. diff --git a/src/decoder/audiofile_plugin.c b/src/decoder/audiofile_plugin.c index fcb431db7..a1fefcb0d 100644 --- a/src/decoder/audiofile_plugin.c +++ b/src/decoder/audiofile_plugin.c @@ -47,10 +47,20 @@ static int audiofile_get_duration(const char *file) } static ssize_t -audiofile_file_read(AFvirtualfile *vfile, void *data, size_t nbytes) +audiofile_file_read(AFvirtualfile *vfile, void *data, size_t length) { struct input_stream *is = (struct input_stream *) vfile->closure; - return input_stream_read(is, data, nbytes); + GError *error = NULL; + size_t nbytes; + + nbytes = input_stream_read(is, data, length, &error); + if (nbytes == 0 && error != NULL) { + g_warning("%s", error->message); + g_error_free(error); + return -1; + } + + return nbytes; } static long @@ -80,7 +90,7 @@ audiofile_file_seek(AFvirtualfile *vfile, long offset, int is_relative) { struct input_stream *is = (struct input_stream *) vfile->closure; int whence = (is_relative ? SEEK_CUR : SEEK_SET); - if (input_stream_seek(is, offset, whence)) { + if (input_stream_seek(is, offset, whence, NULL)) { return is->offset; } else { return -1; diff --git a/src/decoder/faad_plugin.c b/src/decoder/faad_plugin.c index 2a05e33e8..c91f8e8f6 100644 --- a/src/decoder/faad_plugin.c +++ b/src/decoder/faad_plugin.c @@ -205,7 +205,7 @@ faad_song_duration(struct decoder_buffer *buffer, struct input_stream *is) /* obtain the duration from the ADTS header */ float song_length = adts_song_duration(buffer); - input_stream_seek(is, tagsize, SEEK_SET); + input_stream_seek(is, tagsize, SEEK_SET, NULL); data = decoder_buffer_read(buffer, &length); if (data != NULL) @@ -330,7 +330,7 @@ faad_get_file_time_float(const char *file) faacDecConfigurationPtr config; struct input_stream is; - if (!input_stream_open(&is, file)) + if (!input_stream_open(&is, file, NULL)) return -1; buffer = decoder_buffer_new(NULL, &is, diff --git a/src/decoder/ffmpeg_plugin.c b/src/decoder/ffmpeg_plugin.c index d9a5f7feb..213621b8c 100644 --- a/src/decoder/ffmpeg_plugin.c +++ b/src/decoder/ffmpeg_plugin.c @@ -101,7 +101,7 @@ static int64_t mpd_ffmpeg_seek(URLContext *h, int64_t pos, int whence) if (whence == AVSEEK_SIZE) return stream->input->size; - ret = input_stream_seek(stream->input, pos, whence); + ret = input_stream_seek(stream->input, pos, whence, NULL); if (!ret) return -1; @@ -434,7 +434,7 @@ static struct tag *ffmpeg_tag(const char *file) struct ffmpeg_context ctx; bool ret; - if (!input_stream_open(&input, file)) { + if (!input_stream_open(&input, file, NULL)) { g_warning("failed to open %s\n", file); return NULL; } diff --git a/src/decoder/flac_plugin.c b/src/decoder/flac_plugin.c index 427d2c4d9..50cf1f020 100644 --- a/src/decoder/flac_plugin.c +++ b/src/decoder/flac_plugin.c @@ -72,7 +72,7 @@ flac_seek_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, if (!data->input_stream->seekable) return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; - if (!input_stream_seek(data->input_stream, offset, SEEK_SET)) + if (!input_stream_seek(data->input_stream, offset, SEEK_SET, NULL)) return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; return FLAC__STREAM_DECODER_SEEK_STATUS_OK; @@ -784,7 +784,7 @@ oggflac_decode(struct decoder *decoder, struct input_stream *input_stream) /* rewind the stream, because ogg_stream_type_detect() has moved it */ - input_stream_seek(input_stream, 0, SEEK_SET); + input_stream_seek(input_stream, 0, SEEK_SET, NULL); flac_decode_internal(decoder, input_stream, true); } diff --git a/src/decoder/mad_plugin.c b/src/decoder/mad_plugin.c index cba40aea0..50c9f62bc 100644 --- a/src/decoder/mad_plugin.c +++ b/src/decoder/mad_plugin.c @@ -165,7 +165,7 @@ mp3_data_init(struct mp3_data *data, struct decoder *decoder, static bool mp3_seek(struct mp3_data *data, long offset) { - if (!input_stream_seek(data->input_stream, offset, SEEK_SET)) + if (!input_stream_seek(data->input_stream, offset, SEEK_SET, NULL)) return false; mad_stream_buffer(&data->stream, data->input_buffer, 0); @@ -920,7 +920,7 @@ static int mp3_total_file_time(const char *file) struct mp3_data data; int ret; - if (!input_stream_open(&input_stream, file)) + if (!input_stream_open(&input_stream, file, NULL)) return -1; mp3_data_init(&data, NULL, &input_stream); if (!mp3_decode_first_frame(&data, NULL, NULL)) diff --git a/src/decoder/modplug_plugin.c b/src/decoder/modplug_plugin.c index 02292992d..df4a99f7f 100644 --- a/src/decoder/modplug_plugin.c +++ b/src/decoder/modplug_plugin.c @@ -163,7 +163,7 @@ static struct tag *mod_tagdup(const char *file) char *title; struct input_stream is; - if (!input_stream_open(&is, file)) { + if (!input_stream_open(&is, file, NULL)) { g_warning("cant open file %s\n", file); return NULL; } diff --git a/src/decoder/mpcdec_plugin.c b/src/decoder/mpcdec_plugin.c index 2f1936e55..bf27ec314 100644 --- a/src/decoder/mpcdec_plugin.c +++ b/src/decoder/mpcdec_plugin.c @@ -60,7 +60,7 @@ mpc_seek_cb(cb_first_arg, mpc_int32_t offset) { struct mpc_decoder_data *data = (struct mpc_decoder_data *) cb_data; - return input_stream_seek(data->is, offset, SEEK_SET); + return input_stream_seek(data->is, offset, SEEK_SET, NULL); } static mpc_int32_t @@ -295,7 +295,7 @@ mpcdec_get_file_duration(const char *file) mpc_streaminfo info; struct mpc_decoder_data data; - if (!input_stream_open(&is, file)) + if (!input_stream_open(&is, file, NULL)) return -1; data.is = &is; diff --git a/src/decoder/oggflac_plugin.c b/src/decoder/oggflac_plugin.c index 3b6987c6d..cff01453c 100644 --- a/src/decoder/oggflac_plugin.c +++ b/src/decoder/oggflac_plugin.c @@ -66,7 +66,7 @@ static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb(G_GNUC_UNUSED const { struct flac_data *data = (struct flac_data *) fdata; - if (!input_stream_seek(data->input_stream, offset, SEEK_SET)) + if (!input_stream_seek(data->input_stream, offset, SEEK_SET, NULL)) return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; @@ -245,13 +245,21 @@ fail: static struct tag * oggflac_tag_dup(const char *file) { + GError *error = NULL; struct input_stream input_stream; OggFLAC__SeekableStreamDecoder *decoder; struct flac_data data; struct tag *tag; - if (!input_stream_open(&input_stream, file)) + if (!input_stream_open(&input_stream, file, &error)) { + if (error != NULL) { + g_warning("%s", error->message); + g_error_free(error); + } + return NULL; + } + if (ogg_stream_type_detect(&input_stream) != FLAC) { input_stream_close(&input_stream); return NULL; @@ -259,7 +267,7 @@ oggflac_tag_dup(const char *file) /* rewind the stream, because ogg_stream_type_detect() has moved it */ - input_stream_seek(&input_stream, 0, SEEK_SET); + input_stream_seek(&input_stream, 0, SEEK_SET, NULL); flac_data_init(&data, NULL, &input_stream); @@ -295,7 +303,7 @@ oggflac_decode(struct decoder * mpd_decoder, struct input_stream *input_stream) /* rewind the stream, because ogg_stream_type_detect() has moved it */ - input_stream_seek(input_stream, 0, SEEK_SET); + input_stream_seek(input_stream, 0, SEEK_SET, NULL); flac_data_init(&data, mpd_decoder, input_stream); diff --git a/src/decoder/sndfile_decoder_plugin.c b/src/decoder/sndfile_decoder_plugin.c index fee0f8292..a5fd4243b 100644 --- a/src/decoder/sndfile_decoder_plugin.c +++ b/src/decoder/sndfile_decoder_plugin.c @@ -40,7 +40,7 @@ sndfile_vio_seek(sf_count_t offset, int whence, void *user_data) struct input_stream *is = user_data; bool success; - success = input_stream_seek(is, offset, whence); + success = input_stream_seek(is, offset, whence, NULL); if (!success) return -1; @@ -51,11 +51,15 @@ static sf_count_t sndfile_vio_read(void *ptr, sf_count_t count, void *user_data) { struct input_stream *is = user_data; + GError *error = NULL; size_t nbytes; - nbytes = input_stream_read(is, ptr, count); - if (nbytes == 0 && is->error != 0) + nbytes = input_stream_read(is, ptr, count, &error); + if (nbytes == 0 && error != NULL) { + g_warning("%s", error->message); + g_error_free(error); return -1; + } return nbytes; } diff --git a/src/decoder/vorbis_plugin.c b/src/decoder/vorbis_plugin.c index cb61e5999..91a9101f1 100755 --- a/src/decoder/vorbis_plugin.c +++ b/src/decoder/vorbis_plugin.c @@ -80,7 +80,7 @@ static int ogg_seek_cb(void *vdata, ogg_int64_t offset, int whence) return data->seekable && decoder_get_command(data->decoder) != DECODE_COMMAND_STOP && - input_stream_seek(data->input_stream, offset, whence) + input_stream_seek(data->input_stream, offset, whence, NULL) ? 0 : -1; } @@ -286,7 +286,7 @@ vorbis_stream_decode(struct decoder *decoder, /* rewind the stream, because ogg_stream_type_detect() has moved it */ - input_stream_seek(input_stream, 0, SEEK_SET); + input_stream_seek(input_stream, 0, SEEK_SET, NULL); data.decoder = decoder; data.input_stream = input_stream; diff --git a/src/decoder/wavpack_plugin.c b/src/decoder/wavpack_plugin.c index 68a958788..da2c8df77 100644 --- a/src/decoder/wavpack_plugin.c +++ b/src/decoder/wavpack_plugin.c @@ -417,13 +417,13 @@ wavpack_input_get_pos(void *id) static int wavpack_input_set_pos_abs(void *id, uint32_t pos) { - return input_stream_seek(wpin(id)->is, pos, SEEK_SET) ? 0 : -1; + return input_stream_seek(wpin(id)->is, pos, SEEK_SET, NULL) ? 0 : -1; } static int wavpack_input_set_pos_rel(void *id, int32_t delta, int mode) { - return input_stream_seek(wpin(id)->is, delta, mode) ? 0 : -1; + return input_stream_seek(wpin(id)->is, delta, mode, NULL) ? 0 : -1; } static int @@ -494,7 +494,7 @@ wavpack_open_wvc(struct decoder *decoder, struct input_stream *is_wvc, wvc_url = g_strconcat(utf8url, "c", NULL); g_free(utf8url); - ret = input_stream_open(is_wvc, wvc_url); + ret = input_stream_open(is_wvc, wvc_url, NULL); g_free(wvc_url); if (!ret) { diff --git a/src/decoder_api.c b/src/decoder_api.c index 5f0425ce1..73b01533f 100644 --- a/src/decoder_api.c +++ b/src/decoder_api.c @@ -154,6 +154,7 @@ size_t decoder_read(struct decoder *decoder, { const struct decoder_control *dc = decoder != NULL ? decoder->dc : NULL; + GError *error = NULL; size_t nbytes; assert(decoder == NULL || @@ -176,7 +177,14 @@ size_t decoder_read(struct decoder *decoder, dc->command != DECODE_COMMAND_NONE) return 0; - nbytes = input_stream_read(is, buffer, length); + nbytes = input_stream_read(is, buffer, length, &error); + + if (G_UNLIKELY(nbytes == 0 && error != NULL)) { + g_warning("%s", error->message); + g_error_free(error); + return 0; + } + if (nbytes > 0 || input_stream_eof(is)) return nbytes; diff --git a/src/decoder_internal.c b/src/decoder_internal.c index cc4d4419f..b376a5755 100644 --- a/src/decoder_internal.c +++ b/src/decoder_internal.c @@ -37,10 +37,16 @@ static bool decoder_input_buffer(struct decoder_control *dc, struct input_stream *is) { + GError *error = NULL; int ret; decoder_unlock(dc); - ret = input_stream_buffer(is); + ret = input_stream_buffer(is, &error); + if (ret < 0) { + g_warning("%s", error->message); + g_error_free(error); + } + decoder_lock(dc); return ret > 0; diff --git a/src/decoder_thread.c b/src/decoder_thread.c index c055d2a32..9f297ad0d 100644 --- a/src/decoder_thread.c +++ b/src/decoder_thread.c @@ -63,8 +63,16 @@ static bool decoder_input_stream_open(struct decoder_control *dc, struct input_stream *is, const char *uri) { - if (!input_stream_open(is, uri)) + GError *error = NULL; + + if (!input_stream_open(is, uri, &error)) { + if (error != NULL) { + g_warning("%s", error->message); + g_error_free(error); + } + return false; + } /* wait for the input stream to become ready; its metadata will be available then */ @@ -73,9 +81,11 @@ decoder_input_stream_open(struct decoder_control *dc, decoder_lock_get_command(dc) != DECODE_COMMAND_STOP) { int ret; - ret = input_stream_buffer(is); + ret = input_stream_buffer(is, &error); if (ret < 0) { input_stream_close(is); + g_warning("%s", error->message); + g_error_free(error); return false; } } @@ -103,7 +113,7 @@ decoder_stream_decode(const struct decoder_plugin *plugin, decoder_unlock(decoder->dc); /* rewind the stream, so each plugin gets a fresh start */ - input_stream_seek(input_stream, 0, SEEK_SET); + input_stream_seek(input_stream, 0, SEEK_SET, NULL); decoder_plugin_stream_decode(plugin, decoder, input_stream); diff --git a/src/input/archive_input_plugin.c b/src/input/archive_input_plugin.c index 18fa735c2..ad077828a 100644 --- a/src/input/archive_input_plugin.c +++ b/src/input/archive_input_plugin.c @@ -34,7 +34,8 @@ * plugin and gzip fetches file from disk */ static bool -input_archive_open(struct input_stream *is, const char *pathname) +input_archive_open(struct input_stream *is, const char *pathname, + GError **error_r) { const struct archive_plugin *arplug; struct archive_file *file; @@ -63,15 +64,15 @@ input_archive_open(struct input_stream *is, const char *pathname) file = arplug->open(archive); //setup fileops - opened = arplug->open_stream(file, is, filename); + opened = arplug->open_stream(file, is, filename, error_r); + g_free(pname); if (!opened) { - g_warning("open inarchive file %s failed\n\n",filename); arplug->close(file); } else { is->ready = true; } - g_free(pname); + return opened; } diff --git a/src/input/curl_input_plugin.c b/src/input/curl_input_plugin.c index 69b19c371..c6e5a30af 100644 --- a/src/input/curl_input_plugin.c +++ b/src/input/curl_input_plugin.c @@ -103,6 +103,12 @@ static struct curl_slist *http_200_aliases; static const char *proxy, *proxy_user, *proxy_password; static unsigned proxy_port; +static inline GQuark +curl_quark(void) +{ + return g_quark_from_static_string("curl"); +} + static bool input_curl_init(const struct config_param *param, G_GNUC_UNUSED GError **error_r) @@ -216,7 +222,7 @@ input_curl_tag(struct input_stream *is) } static bool -input_curl_multi_info_read(struct input_stream *is) +input_curl_multi_info_read(struct input_stream *is, GError **error_r) { struct input_curl *c = is->data; CURLMsg *msg; @@ -229,8 +235,9 @@ input_curl_multi_info_read(struct input_stream *is) is->ready = true; if (msg->data.result != CURLE_OK) { - g_warning("curl failed: %s\n", c->error); - is->error = -1; + g_set_error(error_r, curl_quark(), + msg->data.result, + "curl failed: %s", c->error); return false; } } @@ -246,7 +253,7 @@ input_curl_multi_info_read(struct input_stream *is) * available */ static int -input_curl_select(struct input_curl *c) +input_curl_select(struct input_curl *c, GError **error_r) { fd_set rfds, wfds, efds; int max_fd, ret; @@ -265,8 +272,9 @@ input_curl_select(struct input_curl *c) mcode = curl_multi_fdset(c->multi, &rfds, &wfds, &efds, &max_fd); if (mcode != CURLM_OK) { - g_warning("curl_multi_fdset() failed: %s\n", - curl_multi_strerror(mcode)); + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_fdset() failed: %s", + curl_multi_strerror(mcode)); return -1; } @@ -274,13 +282,15 @@ input_curl_select(struct input_curl *c) ret = select(max_fd + 1, &rfds, &wfds, &efds, &timeout); if (ret < 0) - g_warning("select() failed: %s\n", strerror(errno)); + g_set_error(error_r, g_quark_from_static_string("errno"), + errno, + "select() failed: %s\n", g_strerror(errno)); return ret; } static bool -fill_buffer(struct input_stream *is) +fill_buffer(struct input_stream *is, GError **error_r) { struct input_curl *c = is->data; CURLMcode mcode = CURLM_CALL_MULTI_PERFORM; @@ -292,7 +302,7 @@ fill_buffer(struct input_stream *is) if (mcode != CURLM_CALL_MULTI_PERFORM) { /* if we're still here, there is no input yet - wait for input */ - int ret = input_curl_select(c); + int ret = input_curl_select(c, error_r); if (ret <= 0) /* no data yet or error */ return false; @@ -300,14 +310,15 @@ fill_buffer(struct input_stream *is) mcode = curl_multi_perform(c->multi, &running_handles); if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM) { - g_warning("curl_multi_perform() failed: %s\n", - curl_multi_strerror(mcode)); + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_perform() failed: %s", + curl_multi_strerror(mcode)); c->eof = true; is->ready = true; return false; } - bret = input_curl_multi_info_read(is); + bret = input_curl_multi_info_read(is, error_r); if (!bret) return false; } @@ -411,7 +422,8 @@ copy_icy_tag(struct input_curl *c) } 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) { struct input_curl *c = is->data; bool success; @@ -443,7 +455,7 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size) do { /* fill the buffer */ - success = fill_buffer(is); + success = fill_buffer(is, error_r); if (!success) return 0; @@ -518,7 +530,7 @@ input_curl_eof(G_GNUC_UNUSED struct input_stream *is) } static int -input_curl_buffer(struct input_stream *is) +input_curl_buffer(struct input_stream *is, GError **error_r) { struct input_curl *c = is->data; CURLMcode mcode; @@ -531,7 +543,8 @@ input_curl_buffer(struct input_stream *is) /* not ready yet means the caller is waiting in a busy loop; relax that by calling select() on the socket */ - input_curl_select(c); + if (input_curl_select(c, error_r) < 0) + return -1; do { mcode = curl_multi_perform(c->multi, &running_handles); @@ -539,14 +552,15 @@ input_curl_buffer(struct input_stream *is) g_queue_is_empty(c->buffers)); if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM) { - g_warning("curl_multi_perform() failed: %s\n", - curl_multi_strerror(mcode)); + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_perform() failed: %s", + curl_multi_strerror(mcode)); c->eof = true; is->ready = true; return -1; } - ret = input_curl_multi_info_read(is); + ret = input_curl_multi_info_read(is, error_r); if (!ret) return -1; @@ -672,7 +686,7 @@ input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream) } static bool -input_curl_easy_init(struct input_stream *is) +input_curl_easy_init(struct input_stream *is, GError **error_r) { struct input_curl *c = is->data; CURLcode code; @@ -682,13 +696,18 @@ input_curl_easy_init(struct input_stream *is) c->easy = curl_easy_init(); if (c->easy == NULL) { - g_warning("curl_easy_init() failed\n"); + g_set_error(error_r, curl_quark(), 0, + "curl_easy_init() failed"); return false; } mcode = curl_multi_add_handle(c->multi, c->easy); - if (mcode != CURLM_OK) + if (mcode != CURLM_OK) { + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_add_handle() failed: %s", + curl_multi_strerror(mcode)); return false; + } curl_easy_setopt(c->easy, CURLOPT_USERAGENT, "Music Player Daemon " VERSION); @@ -718,8 +737,12 @@ input_curl_easy_init(struct input_stream *is) } code = curl_easy_setopt(c->easy, CURLOPT_URL, c->url); - if (code != CURLE_OK) + if (code != CURLE_OK) { + g_set_error(error_r, curl_quark(), code, + "curl_easy_setopt() failed: %s", + curl_easy_strerror(code)); return false; + } c->request_headers = NULL; c->request_headers = curl_slist_append(c->request_headers, @@ -730,7 +753,7 @@ input_curl_easy_init(struct input_stream *is) } static bool -input_curl_send_request(struct input_curl *c) +input_curl_send_request(struct input_curl *c, GError **error_r) { CURLMcode mcode; int running_handles; @@ -740,8 +763,9 @@ input_curl_send_request(struct input_curl *c) } while (mcode == CURLM_CALL_MULTI_PERFORM); if (mcode != CURLM_OK) { - g_warning("curl_multi_perform() failed: %s\n", - curl_multi_strerror(mcode)); + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_perform() failed: %s", + curl_multi_strerror(mcode)); return false; } @@ -815,7 +839,8 @@ input_curl_rewind(struct input_stream *is) } 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) { struct input_curl *c = is->data; bool ret; @@ -907,7 +932,7 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence) return true; } - ret = input_curl_easy_init(is); + ret = input_curl_easy_init(is, error_r); if (!ret) return false; @@ -918,15 +943,15 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence) curl_easy_setopt(c->easy, CURLOPT_RANGE, c->range); } - ret = input_curl_send_request(c); + ret = input_curl_send_request(c, error_r); if (!ret) return false; - return input_curl_multi_info_read(is); + return input_curl_multi_info_read(is, error_r); } static bool -input_curl_open(struct input_stream *is, const char *url) +input_curl_open(struct input_stream *is, const char *url, GError **error_r) { struct input_curl *c; bool ret; @@ -944,8 +969,8 @@ input_curl_open(struct input_stream *is, const char *url) c->multi = curl_multi_init(); if (c->multi == NULL) { - g_warning("curl_multi_init() failed\n"); - + g_set_error(error_r, curl_quark(), 0, + "curl_multi_init() failed"); input_curl_free(is); return false; } @@ -953,19 +978,19 @@ input_curl_open(struct input_stream *is, const char *url) icy_clear(&c->icy_metadata); c->tag = NULL; - ret = input_curl_easy_init(is); + ret = input_curl_easy_init(is, error_r); if (!ret) { input_curl_free(is); return false; } - ret = input_curl_send_request(c); + ret = input_curl_send_request(c, error_r); if (!ret) { input_curl_free(is); return false; } - ret = input_curl_multi_info_read(is); + ret = input_curl_multi_info_read(is, error_r); if (!ret) { input_curl_free(is); return false; diff --git a/src/input/file_input_plugin.c b/src/input/file_input_plugin.c index 73dcf4c0f..e8ad87f45 100644 --- a/src/input/file_input_plugin.c +++ b/src/input/file_input_plugin.c @@ -32,8 +32,15 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "input_file" +static inline GQuark +file_quark(void) +{ + return g_quark_from_static_string("file"); +} + static bool -input_file_open(struct input_stream *is, const char *filename) +input_file_open(struct input_stream *is, const char *filename, + GError **error_r) { int fd, ret; struct stat st; @@ -43,9 +50,10 @@ input_file_open(struct input_stream *is, const char *filename) fd = open_cloexec(filename, O_RDONLY, 0); if (fd < 0) { - is->error = errno; - g_debug("Failed to open \"%s\": %s", - filename, g_strerror(errno)); + if (errno != ENOENT && errno != ENOTDIR) + g_set_error(error_r, file_quark(), errno, + "Failed to open \"%s\": %s", + filename, g_strerror(errno)); return false; } @@ -53,14 +61,16 @@ input_file_open(struct input_stream *is, const char *filename) ret = fstat(fd, &st); if (ret < 0) { - is->error = errno; + g_set_error(error_r, file_quark(), errno, + "Failed to stat \"%s\": %s", + filename, g_strerror(errno)); close(fd); return false; } if (!S_ISREG(st.st_mode)) { - g_debug("Not a regular file: %s", filename); - is->error = EINVAL; + g_set_error(error_r, file_quark(), 0, + "Not a regular file: %s", filename); close(fd); return false; } @@ -79,13 +89,15 @@ input_file_open(struct input_stream *is, const char *filename) } 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) { int fd = GPOINTER_TO_INT(is->data); offset = (goffset)lseek(fd, (off_t)offset, whence); if (offset < 0) { - is->error = errno; + g_set_error(error_r, file_quark(), errno, + "Failed to seek: %s", g_strerror(errno)); return false; } @@ -94,16 +106,16 @@ input_file_seek(struct input_stream *is, goffset offset, int whence) } 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) { int fd = GPOINTER_TO_INT(is->data); ssize_t nbytes; nbytes = read(fd, ptr, size); if (nbytes < 0) { - is->error = errno; - g_debug("input_file_read: error reading: %s\n", - strerror(is->error)); + g_set_error(error_r, file_quark(), errno, + "Failed to read: %s", g_strerror(errno)); return 0; } diff --git a/src/input/mms_input_plugin.c b/src/input/mms_input_plugin.c index eb2665afb..b38fb43df 100644 --- a/src/input/mms_input_plugin.c +++ b/src/input/mms_input_plugin.c @@ -36,8 +36,14 @@ struct input_mms { bool eof; }; +static inline GQuark +mms_quark(void) +{ + return g_quark_from_static_string("mms"); +} + static bool -input_mms_open(struct input_stream *is, const char *url) +input_mms_open(struct input_stream *is, const char *url, GError **error_r) { struct input_mms *m; @@ -50,7 +56,7 @@ input_mms_open(struct input_stream *is, const char *url) m = g_new(struct input_mms, 1); m->mms = mmsx_connect(NULL, NULL, url, 128 * 1024); if (m->mms == NULL) { - g_warning("mmsx_connect() failed"); + g_set_error(error_r, mms_quark(), 0, "mmsx_connect() failed"); return false; } @@ -65,7 +71,8 @@ input_mms_open(struct input_stream *is, const char *url) } 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) { struct input_mms *m = is->data; int ret; @@ -73,8 +80,9 @@ input_mms_read(struct input_stream *is, void *ptr, size_t size) ret = mmsx_read(NULL, m->mms, ptr, size); if (ret <= 0) { if (ret < 0) { - is->error = errno; - g_warning("mmsx_read() failed: %s", g_strerror(errno)); + g_set_error(error_r, mms_quark(), errno, + "mmsx_read() failed: %s", + g_strerror(errno)); } m->eof = true; @@ -104,14 +112,16 @@ input_mms_eof(struct input_stream *is) } static int -input_mms_buffer(G_GNUC_UNUSED struct input_stream *is) +input_mms_buffer(G_GNUC_UNUSED struct input_stream *is, + G_GNUC_UNUSED GError **error_r) { return 0; } static bool input_mms_seek(G_GNUC_UNUSED struct input_stream *is, - G_GNUC_UNUSED goffset offset, G_GNUC_UNUSED int whence) + G_GNUC_UNUSED goffset offset, G_GNUC_UNUSED int whence, + G_GNUC_UNUSED GError **error_r) { return false; } diff --git a/src/input_plugin.h b/src/input_plugin.h index b0ba37959..d7dbfa853 100644 --- a/src/input_plugin.h +++ b/src/input_plugin.h @@ -48,14 +48,17 @@ struct input_plugin { */ void (*finish)(void); - bool (*open)(struct input_stream *is, const char *url); + bool (*open)(struct input_stream *is, const char *url, + GError **error_r); void (*close)(struct input_stream *is); struct tag *(*tag)(struct input_stream *is); - int (*buffer)(struct input_stream *is); - size_t (*read)(struct input_stream *is, void *ptr, size_t size); + int (*buffer)(struct input_stream *is, GError **error_r); + size_t (*read)(struct input_stream *is, void *ptr, size_t size, + GError **error_r); bool (*eof)(struct input_stream *is); - bool (*seek)(struct input_stream *is, goffset offset, int whence); + bool (*seek)(struct input_stream *is, goffset offset, int whence, + GError **error_r); }; #endif diff --git a/src/input_stream.c b/src/input_stream.c index 54ea1c995..27cf4abda 100644 --- a/src/input_stream.c +++ b/src/input_stream.c @@ -25,20 +25,32 @@ #include #include +static inline GQuark +input_quark(void) +{ + return g_quark_from_static_string("input"); +} + bool -input_stream_open(struct input_stream *is, const char *url) +input_stream_open(struct input_stream *is, const char *url, GError **error_r) { + GError *error = NULL; + + assert(error_r == NULL || *error_r == NULL); + is->seekable = false; is->ready = false; is->offset = 0; is->size = -1; - is->error = 0; is->mime = NULL; for (unsigned i = 0; input_plugins[i] != NULL; ++i) { const struct input_plugin *plugin = input_plugins[i]; - if (input_plugins_enabled[i] && plugin->open(is, url)) { + if (!input_plugins_enabled[i]) + continue; + + if (plugin->open(is, url, &error)) { assert(is->plugin != NULL); assert(is->plugin->close != NULL); assert(is->plugin->read != NULL); @@ -46,19 +58,24 @@ input_stream_open(struct input_stream *is, const char *url) assert(!is->seekable || is->plugin->seek != NULL); return true; + } else if (error != NULL) { + g_propagate_error(error_r, error); + return false; } } + g_set_error(error_r, input_quark(), 0, "Unrecognized URI"); return false; } bool -input_stream_seek(struct input_stream *is, goffset offset, int whence) +input_stream_seek(struct input_stream *is, goffset offset, int whence, + GError **error_r) { if (is->plugin->seek == NULL) return false; - return is->plugin->seek(is, offset, whence); + return is->plugin->seek(is, offset, whence, error_r); } struct tag * @@ -72,12 +89,13 @@ input_stream_tag(struct input_stream *is) } size_t -input_stream_read(struct input_stream *is, void *ptr, size_t size) +input_stream_read(struct input_stream *is, void *ptr, size_t size, + GError **error_r) { assert(ptr != NULL); assert(size > 0); - return is->plugin->read(is, ptr, size); + return is->plugin->read(is, ptr, size, error_r); } void input_stream_close(struct input_stream *is) @@ -92,10 +110,11 @@ bool input_stream_eof(struct input_stream *is) return is->plugin->eof(is); } -int input_stream_buffer(struct input_stream *is) +int +input_stream_buffer(struct input_stream *is, GError **error_r) { if (is->plugin->buffer == NULL) return 0; - return is->plugin->buffer(is); + return is->plugin->buffer(is, error_r); } diff --git a/src/input_stream.h b/src/input_stream.h index 63327c137..7d61b9d86 100644 --- a/src/input_stream.h +++ b/src/input_stream.h @@ -54,11 +54,6 @@ struct input_stream { */ bool seekable; - /** - * an optional errno error code, set to non-zero after an error occured - */ - int error; - /** * the size of the resource, or -1 if unknown */ @@ -83,7 +78,7 @@ struct input_stream { * @return true on success */ bool -input_stream_open(struct input_stream *is, const char *url); +input_stream_open(struct input_stream *is, const char *url, GError **error_r); /** * Closes the input stream and free resources. This does not free the @@ -102,7 +97,8 @@ input_stream_close(struct input_stream *is); * @param whence the base of the seek, one of SEEK_SET, SEEK_CUR, SEEK_END */ bool -input_stream_seek(struct input_stream *is, goffset offset, int whence); +input_stream_seek(struct input_stream *is, goffset offset, int whence, + GError **error_r); /** * Returns true if the stream has reached end-of-file. @@ -126,7 +122,7 @@ input_stream_tag(struct input_stream *is); * The semantics of this function are not well-defined, and it will * eventually be removed. */ -int input_stream_buffer(struct input_stream *is); +int input_stream_buffer(struct input_stream *is, GError **error_r); /** * Reads data from the stream into the caller-supplied buffer. @@ -138,6 +134,7 @@ int input_stream_buffer(struct input_stream *is); * @return the number of bytes read */ size_t -input_stream_read(struct input_stream *is, void *ptr, size_t size); +input_stream_read(struct input_stream *is, void *ptr, size_t size, + GError **error_r); #endif diff --git a/src/playlist/asx_playlist_plugin.c b/src/playlist/asx_playlist_plugin.c index 901212f90..03a5edea6 100644 --- a/src/playlist/asx_playlist_plugin.c +++ b/src/playlist/asx_playlist_plugin.c @@ -233,9 +233,17 @@ asx_open_stream(struct input_stream *is) &parser, asx_parser_destroy); while (true) { - nbytes = input_stream_read(is, buffer, sizeof(buffer)); - if (nbytes == 0) + nbytes = input_stream_read(is, buffer, sizeof(buffer), &error); + if (nbytes == 0) { + if (error != NULL) { + g_markup_parse_context_free(context); + g_warning("%s", error->message); + g_error_free(error); + return NULL; + } + break; + } success = g_markup_parse_context_parse(context, buffer, nbytes, &error); diff --git a/src/playlist/lastfm_playlist_plugin.c b/src/playlist/lastfm_playlist_plugin.c index c776d25ab..ec499925a 100644 --- a/src/playlist/lastfm_playlist_plugin.c +++ b/src/playlist/lastfm_playlist_plugin.c @@ -86,27 +86,41 @@ static char * lastfm_get(const char *url) { struct input_stream input_stream; + GError *error = NULL; bool success; int ret; char buffer[4096]; size_t length = 0, nbytes; - success = input_stream_open(&input_stream, url); - if (!success) + success = input_stream_open(&input_stream, url, &error); + if (!success) { + if (error != NULL) { + g_warning("%s", error->message); + g_error_free(error); + } + return NULL; + } while (!input_stream.ready) { - ret = input_stream_buffer(&input_stream); + ret = input_stream_buffer(&input_stream, &error); if (ret < 0) { input_stream_close(&input_stream); + g_warning("%s", error->message); + g_error_free(error); return NULL; } } do { nbytes = input_stream_read(&input_stream, buffer + length, - sizeof(buffer) - length); + sizeof(buffer) - length, &error); if (nbytes == 0) { + if (error != NULL) { + g_warning("%s", error->message); + g_error_free(error); + } + if (input_stream_eof(&input_stream)) break; @@ -152,6 +166,7 @@ static struct playlist_provider * lastfm_open_uri(const char *uri) { struct lastfm_playlist *playlist; + GError *error = NULL; char *p, *q, *response, *session; bool success; @@ -216,20 +231,27 @@ lastfm_open_uri(const char *uri) NULL); g_free(session); - success = input_stream_open(&playlist->is, p); + success = input_stream_open(&playlist->is, p, &error); g_free(p); if (!success) { - g_warning("Failed to load XSPF playlist"); + if (error != NULL) { + g_warning("Failed to load XSPF playlist: %s", + error->message); + g_error_free(error); + } else + g_warning("Failed to load XSPF playlist"); g_free(playlist); return NULL; } while (!playlist->is.ready) { - int ret = input_stream_buffer(&playlist->is); + int ret = input_stream_buffer(&playlist->is, &error); if (ret < 0) { input_stream_close(&playlist->is); g_free(playlist); + g_warning("%s", error->message); + g_error_free(error); return NULL; } diff --git a/src/playlist/pls_playlist_plugin.c b/src/playlist/pls_playlist_plugin.c index 5308b7160..30c62b76e 100644 --- a/src/playlist/pls_playlist_plugin.c +++ b/src/playlist/pls_playlist_plugin.c @@ -115,9 +115,18 @@ pls_open_stream(struct input_stream *is) GString *kf_data = g_string_new(""); do { - nbytes = input_stream_read(is, buffer, sizeof(buffer)); - if(nbytes ==0) + nbytes = input_stream_read(is, buffer, sizeof(buffer), &error); + if (nbytes == 0) { + if (error != NULL) { + g_string_free(kf_data, TRUE); + g_warning("%s", error->message); + g_error_free(error); + return NULL; + } + break; + } + kf_data = g_string_append_len(kf_data, buffer,nbytes); /* Limit to 64k */ } while(kf_data->len < 65536); diff --git a/src/playlist/xspf_playlist_plugin.c b/src/playlist/xspf_playlist_plugin.c index 687765b3a..a36463500 100644 --- a/src/playlist/xspf_playlist_plugin.c +++ b/src/playlist/xspf_playlist_plugin.c @@ -253,9 +253,17 @@ xspf_open_stream(struct input_stream *is) &parser, xspf_parser_destroy); while (true) { - nbytes = input_stream_read(is, buffer, sizeof(buffer)); - if (nbytes == 0) + nbytes = input_stream_read(is, buffer, sizeof(buffer), &error); + if (nbytes == 0) { + if (error != NULL) { + g_markup_parse_context_free(context); + g_warning("%s", error->message); + g_error_free(error); + return NULL; + } + break; + } success = g_markup_parse_context_parse(context, buffer, nbytes, &error); diff --git a/src/playlist_list.c b/src/playlist_list.c index 2ea174a2f..1ac4d4358 100644 --- a/src/playlist_list.c +++ b/src/playlist_list.c @@ -159,7 +159,7 @@ playlist_list_open_stream_mime(struct input_stream *is) string_array_contains(plugin->mime_types, is->mime)) { /* rewind the stream, so each plugin gets a fresh start */ - input_stream_seek(is, 0, SEEK_SET); + input_stream_seek(is, 0, SEEK_SET, NULL); playlist = playlist_plugin_open_stream(plugin, is); if (playlist != NULL) @@ -185,7 +185,7 @@ playlist_list_open_stream_suffix(struct input_stream *is, const char *suffix) string_array_contains(plugin->suffixes, suffix)) { /* rewind the stream, so each plugin gets a fresh start */ - input_stream_seek(is, 0, SEEK_SET); + input_stream_seek(is, 0, SEEK_SET, NULL); playlist = playlist_plugin_open_stream(plugin, is); if (playlist != NULL) @@ -237,16 +237,25 @@ playlist_suffix_supported(const char *suffix) struct playlist_provider * playlist_list_open_path(struct input_stream *is, const char *path_fs) { + GError *error = NULL; const char *suffix; struct playlist_provider *playlist; assert(path_fs != NULL); suffix = uri_get_suffix(path_fs); - if (suffix == NULL || !playlist_suffix_supported(suffix) || - !input_stream_open(is, path_fs)) + if (suffix == NULL || !playlist_suffix_supported(suffix)) return NULL; + if (!input_stream_open(is, path_fs, &error)) { + if (error != NULL) { + g_warning("%s", error->message); + g_error_free(error); + } + + return NULL; + } + playlist = playlist_list_open_stream_suffix(is, suffix); if (playlist == NULL) input_stream_close(is); diff --git a/src/playlist_queue.c b/src/playlist_queue.c index 0b4231f59..5b4439bbb 100644 --- a/src/playlist_queue.c +++ b/src/playlist_queue.c @@ -65,6 +65,7 @@ playlist_load_into_queue(struct playlist_provider *source, static enum playlist_result playlist_open_remote_into_queue(const char *uri, struct playlist *dest) { + GError *error = NULL; struct playlist_provider *playlist; bool stream = false; struct input_stream is; @@ -74,9 +75,16 @@ playlist_open_remote_into_queue(const char *uri, struct playlist *dest) playlist = playlist_list_open_uri(uri); if (playlist == NULL) { - stream = input_stream_open(&is, uri); - if (!stream) + stream = input_stream_open(&is, uri, &error); + if (!stream) { + if (error != NULL) { + g_warning("Failed to open %s: %s", + uri, error->message); + g_error_free(error); + } + return PLAYLIST_RESULT_NO_SUCH_LIST; + } playlist = playlist_list_open_stream(&is, uri); if (playlist == NULL) { diff --git a/src/text_input_stream.c b/src/text_input_stream.c index fd402590e..3836430c7 100644 --- a/src/text_input_stream.c +++ b/src/text_input_stream.c @@ -57,6 +57,7 @@ text_input_stream_free(struct text_input_stream *tis) const char * text_input_stream_read(struct text_input_stream *tis) { + GError *error = NULL; void *dest; const char *src, *p; size_t length, nbytes; @@ -67,9 +68,15 @@ text_input_stream_read(struct text_input_stream *tis) do { dest = fifo_buffer_write(tis->buffer, &length); if (dest != NULL) { - nbytes = input_stream_read(tis->is, dest, length); + nbytes = input_stream_read(tis->is, dest, length, + &error); if (nbytes > 0) fifo_buffer_append(tis->buffer, nbytes); + else if (error != NULL) { + g_warning("%s", error->message); + g_error_free(error); + return NULL; + } } src = fifo_buffer_read(tis->buffer, &length); -- cgit v1.2.3