input_stream: return errors with GError
This commit is contained in:
parent
d000d31355
commit
228b03edf8
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef MPD_ARCHIVE_PLUGIN_H
|
||||
#define MPD_ARCHIVE_PLUGIN_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
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.
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -25,20 +25,32 @@
|
||||
#include <glib.h>
|
||||
#include <assert.h>
|
||||
|
||||
bool
|
||||
input_stream_open(struct input_stream *is, const char *url)
|
||||
static inline GQuark
|
||||
input_quark(void)
|
||||
{
|
||||
return g_quark_from_static_string("input");
|
||||
}
|
||||
|
||||
bool
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -88,17 +88,24 @@ int main(int argc, char **argv)
|
||||
if (playlist == NULL) {
|
||||
/* open the stream and wait until it becomes ready */
|
||||
|
||||
success = input_stream_open(&is, uri);
|
||||
success = input_stream_open(&is, uri, &error);
|
||||
if (!success) {
|
||||
g_printerr("input_stream_open() failed\n");
|
||||
if (error != NULL) {
|
||||
g_warning("%s", error->message);
|
||||
g_error_free(error);
|
||||
} else
|
||||
g_printerr("input_stream_open() failed\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
while (!is.ready) {
|
||||
int ret = input_stream_buffer(&is);
|
||||
if (ret < 0)
|
||||
int ret = input_stream_buffer(&is, &error);
|
||||
if (ret < 0) {
|
||||
/* error */
|
||||
g_warning("%s", error->message);
|
||||
g_error_free(error);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
/* nothing was buffered - wait */
|
||||
|
@ -93,7 +93,7 @@ decoder_read(G_GNUC_UNUSED struct decoder *decoder,
|
||||
struct input_stream *is,
|
||||
void *buffer, size_t length)
|
||||
{
|
||||
return input_stream_read(is, buffer, length);
|
||||
return input_stream_read(is, buffer, length, NULL);
|
||||
}
|
||||
|
||||
enum decoder_command
|
||||
|
@ -114,7 +114,7 @@ decoder_read(G_GNUC_UNUSED struct decoder *decoder,
|
||||
struct input_stream *is,
|
||||
void *buffer, size_t length)
|
||||
{
|
||||
return input_stream_read(is, buffer, length);
|
||||
return input_stream_read(is, buffer, length, NULL);
|
||||
}
|
||||
|
||||
enum decoder_command
|
||||
@ -175,9 +175,16 @@ int main(int argc, char **argv)
|
||||
} else if (decoder.plugin->stream_decode != NULL) {
|
||||
struct input_stream is;
|
||||
|
||||
ret = input_stream_open(&is, decoder.uri);
|
||||
if (!ret)
|
||||
ret = input_stream_open(&is, decoder.uri, &error);
|
||||
if (!ret) {
|
||||
if (error != NULL) {
|
||||
g_warning("%s", error->message);
|
||||
g_error_free(error);
|
||||
} else
|
||||
g_printerr("input_stream_open() failed\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
decoder_plugin_stream_decode(decoder.plugin, &decoder, &is);
|
||||
|
||||
|
@ -45,6 +45,7 @@ my_log_func(const gchar *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level,
|
||||
static int
|
||||
dump_input_stream(struct input_stream *is)
|
||||
{
|
||||
GError *error = NULL;
|
||||
char buffer[4096];
|
||||
size_t num_read;
|
||||
ssize_t num_written;
|
||||
@ -52,10 +53,13 @@ dump_input_stream(struct input_stream *is)
|
||||
/* wait until the stream becomes ready */
|
||||
|
||||
while (!is->ready) {
|
||||
int ret = input_stream_buffer(is);
|
||||
if (ret < 0)
|
||||
int ret = input_stream_buffer(is, &error);
|
||||
if (ret < 0) {
|
||||
/* error */
|
||||
g_warning("%s", error->message);
|
||||
g_error_free(error);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
/* nothing was buffered - wait */
|
||||
@ -77,9 +81,16 @@ dump_input_stream(struct input_stream *is)
|
||||
tag_free(tag);
|
||||
}
|
||||
|
||||
num_read = input_stream_read(is, buffer, sizeof(buffer));
|
||||
if (num_read == 0)
|
||||
num_read = input_stream_read(is, buffer, sizeof(buffer),
|
||||
&error);
|
||||
if (num_read == 0) {
|
||||
if (error != NULL) {
|
||||
g_warning("%s", error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
num_written = write(1, buffer, num_read);
|
||||
if (num_written <= 0)
|
||||
@ -122,11 +133,15 @@ int main(int argc, char **argv)
|
||||
|
||||
/* open the stream and dump it */
|
||||
|
||||
if (input_stream_open(&is, argv[1])) {
|
||||
if (input_stream_open(&is, argv[1], &error)) {
|
||||
ret = dump_input_stream(&is);
|
||||
input_stream_close(&is);
|
||||
} else {
|
||||
g_printerr("input_stream_open() failed\n");
|
||||
if (error != NULL) {
|
||||
g_warning("%s", error->message);
|
||||
g_error_free(error);
|
||||
} else
|
||||
g_printerr("input_stream_open() failed\n");
|
||||
ret = 2;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user