diff options
40 files changed, 270 insertions, 144 deletions
diff --git a/Makefile.am b/Makefile.am index f8f5ae951..e4a01b870 100644 --- a/Makefile.am +++ b/Makefile.am @@ -707,7 +707,7 @@ endif libinput_a_SOURCES = \ src/InputInit.cxx src/InputInit.hxx \ src/InputRegistry.cxx src/InputRegistry.hxx \ - src/InputStream.cxx \ + src/InputStream.cxx src/InputStream.hxx \ src/InputPlugin.hxx \ src/InputInternal.cxx src/InputInternal.hxx \ src/input/RewindInputPlugin.cxx src/input/RewindInputPlugin.hxx \ diff --git a/src/DecoderAPI.cxx b/src/DecoderAPI.cxx index 0e127ec02..56c25e489 100644 --- a/src/DecoderAPI.cxx +++ b/src/DecoderAPI.cxx @@ -31,6 +31,7 @@ extern "C" { #include "DecoderControl.hxx" #include "DecoderInternal.hxx" #include "song.h" +#include "InputStream.hxx" #include <glib.h> diff --git a/src/DecoderInternal.cxx b/src/DecoderInternal.cxx index 505d2bc94..af36e1763 100644 --- a/src/DecoderInternal.cxx +++ b/src/DecoderInternal.cxx @@ -24,7 +24,6 @@ #include "MusicBuffer.hxx" #include "MusicChunk.hxx" #include "tag.h" -#include "input_stream.h" #include <assert.h> diff --git a/src/DecoderThread.cxx b/src/DecoderThread.cxx index b821c6d7a..4b9cdfd81 100644 --- a/src/DecoderThread.cxx +++ b/src/DecoderThread.cxx @@ -29,7 +29,7 @@ #include "fs/Path.hxx" #include "decoder_api.h" #include "tag.h" -#include "input_stream.h" +#include "InputStream.hxx" extern "C" { #include "decoder_list.h" diff --git a/src/InputInternal.cxx b/src/InputInternal.cxx index a5e5ecd59..8fc4fa0a8 100644 --- a/src/InputInternal.cxx +++ b/src/InputInternal.cxx @@ -19,7 +19,7 @@ #include "config.h" #include "InputInternal.hxx" -#include "input_stream.h" +#include "InputStream.hxx" #include <assert.h> diff --git a/src/InputStream.cxx b/src/InputStream.cxx index a39af2bd6..e55450d91 100644 --- a/src/InputStream.cxx +++ b/src/InputStream.cxx @@ -18,7 +18,7 @@ */ #include "config.h" -#include "input_stream.h" +#include "InputStream.hxx" #include "InputRegistry.hxx" #include "InputPlugin.hxx" #include "input/RewindInputPlugin.hxx" @@ -118,6 +118,52 @@ input_stream_lock_wait_ready(struct input_stream *is) g_mutex_unlock(is->mutex); } +const char * +input_stream_get_mime_type(const struct input_stream *is) +{ + assert(is != NULL); + assert(is->ready); + + return is->mime; +} + +void +input_stream_override_mime_type(struct input_stream *is, const char *mime) +{ + assert(is != NULL); + assert(is->ready); + + g_free(is->mime); + is->mime = g_strdup(mime); +} + +goffset +input_stream_get_size(const struct input_stream *is) +{ + assert(is != NULL); + assert(is->ready); + + return is->size; +} + +goffset +input_stream_get_offset(const struct input_stream *is) +{ + assert(is != NULL); + assert(is->ready); + + return is->offset; +} + +bool +input_stream_is_seekable(const struct input_stream *is) +{ + assert(is != NULL); + assert(is->ready); + + return is->seekable; +} + bool input_stream_cheap_seeking(const struct input_stream *is) { diff --git a/src/InputStream.hxx b/src/InputStream.hxx new file mode 100644 index 000000000..8a82888f0 --- /dev/null +++ b/src/InputStream.hxx @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_INPUT_STREAM_HXX +#define MPD_INPUT_STREAM_HXX + +#include "input_stream.h" +#include "check.h" +#include "gcc.h" + +#include <glib.h> + +struct input_stream { + /** + * the plugin which implements this input stream + */ + const struct input_plugin *plugin; + + /** + * The absolute URI which was used to open this stream. May + * be NULL if this is unknown. + */ + char *uri; + + /** + * A mutex that protects the mutable attributes of this object + * and its implementation. It must be locked before calling + * any of the public methods. + * + * This object is allocated by the client, and the client is + * responsible for freeing it. + */ + GMutex *mutex; + + /** + * A cond that gets signalled when the state of this object + * changes from the I/O thread. The client of this object may + * wait on it. Optional, may be NULL. + * + * This object is allocated by the client, and the client is + * responsible for freeing it. + */ + GCond *cond; + + /** + * indicates whether the stream is ready for reading and + * whether the other attributes in this struct are valid + */ + bool ready; + + /** + * if true, then the stream is fully seekable + */ + bool seekable; + + /** + * the size of the resource, or -1 if unknown + */ + goffset size; + + /** + * the current offset within the stream + */ + goffset offset; + + /** + * the MIME content type of the resource, or NULL if unknown + */ + char *mime; +}; + +gcc_nonnull(1) +static inline void +input_stream_lock(struct input_stream *is) +{ + g_mutex_lock(is->mutex); +} + +gcc_nonnull(1) +static inline void +input_stream_unlock(struct input_stream *is) +{ + g_mutex_unlock(is->mutex); +} + +#endif diff --git a/src/PlaylistRegistry.cxx b/src/PlaylistRegistry.cxx index f919f388b..1e9edd443 100644 --- a/src/PlaylistRegistry.cxx +++ b/src/PlaylistRegistry.cxx @@ -233,19 +233,19 @@ playlist_list_open_stream_mime2(struct input_stream *is, const char *mime) } static struct playlist_provider * -playlist_list_open_stream_mime(struct input_stream *is) +playlist_list_open_stream_mime(struct input_stream *is, const char *full_mime) { - assert(is->mime != NULL); + assert(full_mime != NULL); - const char *semicolon = strchr(is->mime, ';'); + const char *semicolon = strchr(full_mime, ';'); if (semicolon == NULL) - return playlist_list_open_stream_mime2(is, is->mime); + return playlist_list_open_stream_mime2(is, full_mime); - if (semicolon == is->mime) + if (semicolon == full_mime) return NULL; /* probe only the portion before the semicolon*/ - char *mime = g_strndup(is->mime, semicolon - is->mime); + char *mime = g_strndup(full_mime, semicolon - full_mime); struct playlist_provider *playlist = playlist_list_open_stream_mime2(is, mime); g_free(mime); @@ -285,8 +285,9 @@ playlist_list_open_stream(struct input_stream *is, const char *uri) input_stream_lock_wait_ready(is); - if (is->mime != NULL) { - playlist = playlist_list_open_stream_mime(is); + const char *const mime = input_stream_get_mime_type(is); + if (mime != NULL) { + playlist = playlist_list_open_stream_mime(is, mime); if (playlist != NULL) return playlist; } diff --git a/src/archive/Bzip2ArchivePlugin.cxx b/src/archive/Bzip2ArchivePlugin.cxx index 1e7c0c80e..c8d8f3977 100644 --- a/src/archive/Bzip2ArchivePlugin.cxx +++ b/src/archive/Bzip2ArchivePlugin.cxx @@ -26,6 +26,7 @@ #include "ArchiveInternal.hxx" #include "ArchivePlugin.hxx" #include "InputInternal.hxx" +#include "InputStream.hxx" #include "InputPlugin.hxx" #include "refcount.h" diff --git a/src/archive/Iso9660ArchivePlugin.cxx b/src/archive/Iso9660ArchivePlugin.cxx index a3bf600a0..d081fe330 100644 --- a/src/archive/Iso9660ArchivePlugin.cxx +++ b/src/archive/Iso9660ArchivePlugin.cxx @@ -26,6 +26,7 @@ #include "ArchiveInternal.hxx" #include "ArchivePlugin.hxx" #include "InputInternal.hxx" +#include "InputStream.hxx" #include "InputPlugin.hxx" #include "refcount.h" diff --git a/src/archive/ZzipArchivePlugin.cxx b/src/archive/ZzipArchivePlugin.cxx index ea6ec4e75..28c3f46a4 100644 --- a/src/archive/ZzipArchivePlugin.cxx +++ b/src/archive/ZzipArchivePlugin.cxx @@ -26,6 +26,7 @@ #include "ArchiveInternal.hxx" #include "ArchivePlugin.hxx" #include "InputInternal.hxx" +#include "InputStream.hxx" #include "InputPlugin.hxx" #include "refcount.h" diff --git a/src/decoder/FLACIOHandle.hxx b/src/decoder/FLACIOHandle.hxx index 0c2c24770..505d2db1a 100644 --- a/src/decoder/FLACIOHandle.hxx +++ b/src/decoder/FLACIOHandle.hxx @@ -21,7 +21,7 @@ #define MPD_FLAC_IO_HANDLE_HXX #include "gcc.h" -#include "input_stream.h" +#include "InputStream.hxx" #include <FLAC/callback.h> diff --git a/src/decoder/FLACInput.cxx b/src/decoder/FLACInput.cxx index 99f321cdd..ba0a86ce8 100644 --- a/src/decoder/FLACInput.cxx +++ b/src/decoder/FLACInput.cxx @@ -21,7 +21,7 @@ #include "FLACInput.hxx" #include "decoder_api.h" #include "gcc.h" -#include "input_stream.h" +#include "InputStream.hxx" FLAC__StreamDecoderReadStatus FLACInput::Read(FLAC__byte buffer[], size_t *bytes) diff --git a/src/decoder/FfmpegDecoderPlugin.cxx b/src/decoder/FfmpegDecoderPlugin.cxx index ac2883305..e89f35ef6 100644 --- a/src/decoder/FfmpegDecoderPlugin.cxx +++ b/src/decoder/FfmpegDecoderPlugin.cxx @@ -25,6 +25,7 @@ #include "decoder_api.h" #include "FfmpegMetaData.hxx" #include "tag_handler.h" +#include "InputStream.hxx" extern "C" { #include "audio_check.h" diff --git a/src/decoder/OpusDecoderPlugin.cxx b/src/decoder/OpusDecoderPlugin.cxx index f0c0a442d..8be95ab2e 100644 --- a/src/decoder/OpusDecoderPlugin.cxx +++ b/src/decoder/OpusDecoderPlugin.cxx @@ -28,6 +28,7 @@ #include "OggCodec.hxx" #include "audio_check.h" #include "tag_handler.h" +#include "InputStream.hxx" #include <opus.h> #include <ogg/ogg.h> diff --git a/src/decoder/VorbisDecoderPlugin.cxx b/src/decoder/VorbisDecoderPlugin.cxx index 01a558def..488786ed8 100644 --- a/src/decoder/VorbisDecoderPlugin.cxx +++ b/src/decoder/VorbisDecoderPlugin.cxx @@ -21,6 +21,7 @@ #include "VorbisDecoderPlugin.h" #include "VorbisComments.hxx" #include "decoder_api.h" +#include "InputStream.hxx" #include "OggCodec.hxx" extern "C" { diff --git a/src/decoder/WavpackDecoderPlugin.cxx b/src/decoder/WavpackDecoderPlugin.cxx index fdd910c84..aeecf6415 100644 --- a/src/decoder/WavpackDecoderPlugin.cxx +++ b/src/decoder/WavpackDecoderPlugin.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "WavpackDecoderPlugin.hxx" #include "decoder_api.h" +#include "InputStream.hxx" extern "C" { #include "audio_check.h" diff --git a/src/decoder/audiofile_decoder_plugin.c b/src/decoder/audiofile_decoder_plugin.c index b344795e7..d2ceee8ae 100644 --- a/src/decoder/audiofile_decoder_plugin.c +++ b/src/decoder/audiofile_decoder_plugin.c @@ -69,14 +69,14 @@ static AFfileoffset audiofile_file_length(AFvirtualfile *vfile) { struct input_stream *is = (struct input_stream *) vfile->closure; - return is->size; + return input_stream_get_size(is); } static AFfileoffset audiofile_file_tell(AFvirtualfile *vfile) { struct input_stream *is = (struct input_stream *) vfile->closure; - return is->offset; + return input_stream_get_offset(is); } static void @@ -93,7 +93,7 @@ audiofile_file_seek(AFvirtualfile *vfile, AFfileoffset offset, int is_relative) struct input_stream *is = (struct input_stream *) vfile->closure; int whence = (is_relative ? SEEK_CUR : SEEK_SET); if (input_stream_lock_seek(is, offset, whence, NULL)) { - return is->offset; + return input_stream_get_offset(is); } else { return -1; } @@ -166,7 +166,7 @@ audiofile_stream_decode(struct decoder *decoder, struct input_stream *is) char chunk[CHUNK_SIZE]; enum decoder_command cmd; - if (!is->seekable) { + if (!input_stream_is_seekable(is)) { g_warning("not seekable"); return; } @@ -194,7 +194,7 @@ audiofile_stream_decode(struct decoder *decoder, struct input_stream *is) total_time = ((float)frame_count / (float)audio_format.sample_rate); - bit_rate = (uint16_t)(is->size * 8.0 / total_time / 1000.0 + 0.5); + bit_rate = (uint16_t)(input_stream_get_size(is) * 8.0 / total_time / 1000.0 + 0.5); fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1); diff --git a/src/decoder/dsdiff_decoder_plugin.c b/src/decoder/dsdiff_decoder_plugin.c index 4e21e91de..44d12d899 100644 --- a/src/decoder/dsdiff_decoder_plugin.c +++ b/src/decoder/dsdiff_decoder_plugin.c @@ -128,12 +128,12 @@ dsdiff_read_prop_snd(struct decoder *decoder, struct input_stream *is, goffset end_offset) { struct dsdiff_chunk_header header; - while ((goffset)(is->offset + sizeof(header)) <= end_offset) { + while ((goffset)(input_stream_get_offset(is) + sizeof(header)) <= end_offset) { if (!dsdiff_read_chunk_header(decoder, is, &header)) return false; - goffset chunk_end_offset = - is->offset + dsdiff_chunk_size(&header); + goffset chunk_end_offset = input_stream_get_offset(is) + + dsdiff_chunk_size(&header); if (chunk_end_offset > end_offset) return false; @@ -174,7 +174,7 @@ dsdiff_read_prop_snd(struct decoder *decoder, struct input_stream *is, } } - return is->offset == end_offset; + return input_stream_get_offset(is) == end_offset; } /** @@ -186,7 +186,7 @@ dsdiff_read_prop(struct decoder *decoder, struct input_stream *is, const struct dsdiff_chunk_header *prop_header) { uint64_t prop_size = dsdiff_chunk_size(prop_header); - goffset end_offset = is->offset + prop_size; + goffset end_offset = input_stream_get_offset(is) + prop_size; struct dsdlib_id prop_id; if (prop_size < sizeof(prop_id) || @@ -261,8 +261,8 @@ dsdiff_read_metadata_extra(struct decoder *decoder, struct input_stream *is, /* Now process all the remaining chunk headers in the stream and record their position and size */ - while ( is->offset < is->size ) - { + const goffset size = input_stream_get_size(is); + while (input_stream_get_offset(is) < size) { uint64_t chunk_size = dsdiff_chunk_size(chunk_header); /* DIIN chunk, is directly followed by other chunks */ @@ -272,19 +272,19 @@ dsdiff_read_metadata_extra(struct decoder *decoder, struct input_stream *is, /* DIAR chunk - DSDIFF native tag for Artist */ if (dsdlib_id_equals(&chunk_header->id, "DIAR")) { chunk_size = dsdiff_chunk_size(chunk_header); - metadata->diar_offset = is->offset; + metadata->diar_offset = input_stream_get_offset(is); } /* DITI chunk - DSDIFF native tag for Title */ if (dsdlib_id_equals(&chunk_header->id, "DITI")) { chunk_size = dsdiff_chunk_size(chunk_header); - metadata->diti_offset = is->offset; + metadata->diti_offset = input_stream_get_offset(is); } #ifdef HAVE_ID3TAG /* 'ID3 ' chunk, offspec. Used by sacdextract */ if (dsdlib_id_equals(&chunk_header->id, "ID3 ")) { chunk_size = dsdiff_chunk_size(chunk_header); - metadata->id3_offset = is->offset; + metadata->id3_offset = input_stream_get_offset(is); metadata->id3_size = chunk_size; } #endif @@ -293,7 +293,7 @@ dsdiff_read_metadata_extra(struct decoder *decoder, struct input_stream *is, break; } - if ( is->offset < is->size ) { + if (input_stream_get_offset(is) < size) { if (!dsdiff_read_chunk_header(decoder, is, chunk_header)) return false; } @@ -355,7 +355,8 @@ dsdiff_read_metadata(struct decoder *decoder, struct input_stream *is, /* ignore unknown chunk */ uint64_t chunk_size; chunk_size = dsdiff_chunk_size(chunk_header); - goffset chunk_end_offset = is->offset + chunk_size; + goffset chunk_end_offset = input_stream_get_offset(is) + + chunk_size; if (!dsdlib_skip_to(decoder, is, chunk_end_offset)) return false; diff --git a/src/decoder/dsdlib.c b/src/decoder/dsdlib.c index c788184e2..d3043fb05 100644 --- a/src/decoder/dsdlib.c +++ b/src/decoder/dsdlib.c @@ -64,24 +64,24 @@ bool dsdlib_skip_to(struct decoder *decoder, struct input_stream *is, goffset offset) { - if (is->seekable) + if (input_stream_is_seekable(is)) return input_stream_seek(is, offset, SEEK_SET, NULL); - if (is->offset > offset) + if (input_stream_get_offset(is) > offset) return false; char buffer[8192]; - while (is->offset < offset) { + while (input_stream_get_offset(is) < offset) { size_t length = sizeof(buffer); - if (offset - is->offset < (goffset)length) - length = offset - is->offset; + if (offset - input_stream_get_offset(is) < (goffset)length) + length = offset - input_stream_get_offset(is); size_t nbytes = decoder_read(decoder, is, buffer, length); if (nbytes == 0) return false; } - assert(is->offset == offset); + assert(input_stream_get_offset(is) == offset); return true; } @@ -97,7 +97,7 @@ dsdlib_skip(struct decoder *decoder, struct input_stream *is, if (delta == 0) return true; - if (is->seekable) + if (input_stream_is_seekable(is)) return input_stream_seek(is, delta, SEEK_CUR, NULL); char buffer[8192]; @@ -139,10 +139,12 @@ dsdlib_tag_id3(struct input_stream *is, id3_length_t count; /* Prevent broken files causing problems */ - if (is->offset >= is->size) + const goffset size = input_stream_get_size(is); + const goffset offset = input_stream_get_offset(is); + if (offset >= size) return; - count = is->size - is->offset; + count = size - offset; /* Check and limit id3 tag size to prevent a stack overflow */ if (count == 0 || count > 4096) diff --git a/src/decoder/dsf_decoder_plugin.c b/src/decoder/dsf_decoder_plugin.c index 6700f739a..23576a629 100644 --- a/src/decoder/dsf_decoder_plugin.c +++ b/src/decoder/dsf_decoder_plugin.c @@ -165,14 +165,15 @@ dsf_read_metadata(struct decoder *decoder, struct input_stream *is, metadata->chunk_size = data_size; /* data_size cannot be bigger or equal to total file size */ - if (data_size >= (unsigned) is->size) + const uint64_t size = (uint64_t)input_stream_get_size(is); + if (data_size >= size) return false; metadata->channels = (unsigned) dsf_fmt_chunk.channelnum; metadata->sample_rate = samplefreq; #ifdef HAVE_ID3TAG /* metada_offset cannot be bigger then or equal to total file size */ - if (metadata_offset >= (unsigned) is->size) + if (metadata_offset >= size) metadata->id3_offset = 0; else metadata->id3_offset = (goffset) metadata_offset; diff --git a/src/decoder/faad_decoder_plugin.c b/src/decoder/faad_decoder_plugin.c index 911f033b8..c8dbb966c 100644 --- a/src/decoder/faad_decoder_plugin.c +++ b/src/decoder/faad_decoder_plugin.c @@ -175,7 +175,8 @@ faad_song_duration(struct decoder_buffer *buffer, struct input_stream *is) size_t length; bool success; - fileread = is->size >= 0 ? is->size : 0; + const goffset size = input_stream_get_size(is); + fileread = size >= 0 ? size : 0; decoder_buffer_fill(buffer); data = decoder_buffer_read(buffer, &length); @@ -201,7 +202,7 @@ faad_song_duration(struct decoder_buffer *buffer, struct input_stream *is) return -1; } - if (is->seekable && length >= 2 && + if (input_stream_is_seekable(is) && length >= 2 && data[0] == 0xFF && ((data[1] & 0xF6) == 0xF0)) { /* obtain the duration from the ADTS header */ float song_length = adts_song_duration(buffer); diff --git a/src/decoder/mad_decoder_plugin.c b/src/decoder/mad_decoder_plugin.c index 0c27ac119..4e2e03311 100644 --- a/src/decoder/mad_decoder_plugin.c +++ b/src/decoder/mad_decoder_plugin.c @@ -755,7 +755,7 @@ mp3_frame_duration(const struct mad_frame *frame) static goffset mp3_this_frame_offset(const struct mp3_data *data) { - goffset offset = data->input_stream->offset; + goffset offset = input_stream_get_offset(data->input_stream); if (data->stream.this_frame != NULL) offset -= data->stream.bufend - data->stream.this_frame; @@ -768,7 +768,8 @@ mp3_this_frame_offset(const struct mp3_data *data) static goffset mp3_rest_including_this_frame(const struct mp3_data *data) { - return data->input_stream->size - mp3_this_frame_offset(data); + return input_stream_get_size(data->input_stream) + - mp3_this_frame_offset(data); } /** @@ -841,7 +842,7 @@ mp3_decode_first_frame(struct mp3_data *data, struct tag **tag) if (parse_lame(&lame, &ptr, &bitlen)) { if (gapless_playback && - data->input_stream->seekable) { + input_stream_is_seekable(data->input_stream)) { data->drop_start_samples = lame.encoder_delay + DECODERDELAY; data->drop_end_samples = lame.encoder_padding; @@ -1081,7 +1082,7 @@ mp3_read(struct mp3_data *data) if (cmd == DECODE_COMMAND_SEEK) { unsigned long j; - assert(data->input_stream->seekable); + assert(input_stream_is_seekable(data->input_stream)); j = mp3_time_to_frame(data, decoder_seek_where(decoder)); @@ -1163,7 +1164,8 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream) } decoder_initialized(decoder, &audio_format, - data.input_stream->seekable, data.total_time); + input_stream_is_seekable(input_stream), + data.total_time); if (tag != NULL) { decoder_tag(decoder, input_stream, tag); diff --git a/src/decoder/modplug_decoder_plugin.c b/src/decoder/modplug_decoder_plugin.c index 21ee79e7e..bc3d81767 100644 --- a/src/decoder/modplug_decoder_plugin.c +++ b/src/decoder/modplug_decoder_plugin.c @@ -41,19 +41,21 @@ static GByteArray *mod_loadfile(struct decoder *decoder, struct input_stream *is GByteArray *bdatas; size_t ret; - if (is->size == 0) { + const goffset size = input_stream_get_size(is); + + if (size == 0) { g_warning("file is empty"); return NULL; } - if (is->size > MODPLUG_FILE_LIMIT) { + if (size > MODPLUG_FILE_LIMIT) { g_warning("file too large"); return NULL; } //known/unknown size, preallocate array, lets read in chunks - if (is->size > 0) { - bdatas = g_byte_array_sized_new(is->size); + if (size > 0) { + bdatas = g_byte_array_sized_new(size); } else { bdatas = g_byte_array_sized_new(MODPLUG_PREALLOC_BLOCK); } @@ -126,7 +128,8 @@ mod_decode(struct decoder *decoder, struct input_stream *is) assert(audio_format_valid(&audio_format)); decoder_initialized(decoder, &audio_format, - is->seekable, ModPlug_GetLength(f) / 1000.0); + input_stream_is_seekable(is), + ModPlug_GetLength(f) / 1000.0); do { ret = ModPlug_Read(f, audio_buffer, MODPLUG_FRAME_SIZE); diff --git a/src/decoder/mpcdec_decoder_plugin.c b/src/decoder/mpcdec_decoder_plugin.c index d4768b35b..77db2416b 100644 --- a/src/decoder/mpcdec_decoder_plugin.c +++ b/src/decoder/mpcdec_decoder_plugin.c @@ -70,7 +70,7 @@ mpc_tell_cb(cb_first_arg) { struct mpc_decoder_data *data = (struct mpc_decoder_data *) cb_data; - return (long)(data->is->offset); + return (long)input_stream_get_offset(data->is); } static mpc_bool_t @@ -78,7 +78,7 @@ mpc_canseek_cb(cb_first_arg) { struct mpc_decoder_data *data = (struct mpc_decoder_data *) cb_data; - return data->is->seekable; + return input_stream_is_seekable(data->is); } static mpc_int32_t @@ -86,7 +86,7 @@ mpc_getsize_cb(cb_first_arg) { struct mpc_decoder_data *data = (struct mpc_decoder_data *) cb_data; - return data->is->size; + return input_stream_get_size(data->is); } /* this _looks_ performance-critical, don't de-inline -- eric */ @@ -222,7 +222,7 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is) decoder_replay_gain(mpd_decoder, &replay_gain_info); decoder_initialized(mpd_decoder, &audio_format, - is->seekable, + input_stream_is_seekable(is), mpc_streaminfo_get_length(&info)); do { diff --git a/src/decoder/pcm_decoder_plugin.c b/src/decoder/pcm_decoder_plugin.c index fc7dffc05..d529cef5c 100644 --- a/src/decoder/pcm_decoder_plugin.c +++ b/src/decoder/pcm_decoder_plugin.c @@ -38,8 +38,9 @@ pcm_stream_decode(struct decoder *decoder, struct input_stream *is) .channels = 2, }; - const bool reverse_endian = is->mime != NULL && - strcmp(is->mime, "audio/x-mpd-cdda-pcm-reverse") == 0; + const char *const mime = input_stream_get_mime_type(is); + const bool reverse_endian = mime != NULL && + strcmp(mime, "audio/x-mpd-cdda-pcm-reverse") == 0; GError *error = NULL; enum decoder_command cmd; @@ -47,10 +48,12 @@ pcm_stream_decode(struct decoder *decoder, struct input_stream *is) double time_to_size = audio_format_time_to_size(&audio_format); float total_time = -1; - if (is->size >= 0) - total_time = is->size / time_to_size; + const goffset size = input_stream_get_size(is); + if (size >= 0) + total_time = size / time_to_size; - decoder_initialized(decoder, &audio_format, is->seekable, total_time); + decoder_initialized(decoder, &audio_format, + input_stream_is_seekable(is), total_time); do { char buffer[4096]; diff --git a/src/decoder/sndfile_decoder_plugin.c b/src/decoder/sndfile_decoder_plugin.c index 8dd98236f..e70a2dc2e 100644 --- a/src/decoder/sndfile_decoder_plugin.c +++ b/src/decoder/sndfile_decoder_plugin.c @@ -32,7 +32,7 @@ sndfile_vio_get_filelen(void *user_data) { const struct input_stream *is = user_data; - return is->size; + return input_stream_get_size(is); } static sf_count_t @@ -45,7 +45,7 @@ sndfile_vio_seek(sf_count_t offset, int whence, void *user_data) if (!success) return -1; - return is->offset; + return input_stream_get_offset(is); } static sf_count_t @@ -79,7 +79,7 @@ sndfile_vio_tell(void *user_data) { const struct input_stream *is = user_data; - return is->offset; + return input_stream_get_offset(is); } /** diff --git a/src/input/CdioParanoiaInputPlugin.cxx b/src/input/CdioParanoiaInputPlugin.cxx index e8dabd88f..19001fbe9 100644 --- a/src/input/CdioParanoiaInputPlugin.cxx +++ b/src/input/CdioParanoiaInputPlugin.cxx @@ -24,6 +24,7 @@ #include "config.h" #include "CdioParanoiaInputPlugin.hxx" #include "InputInternal.hxx" +#include "InputStream.hxx" #include "InputPlugin.hxx" #include "refcount.h" diff --git a/src/input/CurlInputPlugin.cxx b/src/input/CurlInputPlugin.cxx index ed70de072..a2ad20b15 100644 --- a/src/input/CurlInputPlugin.cxx +++ b/src/input/CurlInputPlugin.cxx @@ -19,12 +19,13 @@ #include "config.h" #include "CurlInputPlugin.hxx" +#include "InputInternal.hxx" +#include "InputStream.hxx" #include "InputPlugin.hxx" #include "conf.h" #include "tag.h" #include "IcyMetaDataParser.hxx" #include "event/MultiSocketMonitor.hxx" -#include "InputInternal.hxx" #include "event/Loop.hxx" #include "IOThread.hxx" #include "glib_compat.h" diff --git a/src/input/DespotifyInputPlugin.cxx b/src/input/DespotifyInputPlugin.cxx index af550cab5..e17bbb663 100644 --- a/src/input/DespotifyInputPlugin.cxx +++ b/src/input/DespotifyInputPlugin.cxx @@ -21,6 +21,7 @@ #include "DespotifyInputPlugin.hxx" #include "DespotifyUtils.hxx" #include "InputInternal.hxx" +#include "InputStream.hxx" #include "InputPlugin.hxx" #include "tag.h" diff --git a/src/input/FfmpegInputPlugin.cxx b/src/input/FfmpegInputPlugin.cxx index 3e59bca9c..1893a01e7 100644 --- a/src/input/FfmpegInputPlugin.cxx +++ b/src/input/FfmpegInputPlugin.cxx @@ -23,6 +23,7 @@ #include "config.h" #include "FfmpegInputPlugin.hxx" #include "InputInternal.hxx" +#include "InputStream.hxx" #include "InputPlugin.hxx" extern "C" { diff --git a/src/input/FileInputPlugin.cxx b/src/input/FileInputPlugin.cxx index 8d3ef7510..2d0bfcbbb 100644 --- a/src/input/FileInputPlugin.cxx +++ b/src/input/FileInputPlugin.cxx @@ -20,6 +20,7 @@ #include "config.h" /* must be first for large file support */ #include "FileInputPlugin.hxx" #include "InputInternal.hxx" +#include "InputStream.hxx" #include "InputPlugin.hxx" #include "fd_util.h" #include "open.h" diff --git a/src/input/MmsInputPlugin.cxx b/src/input/MmsInputPlugin.cxx index 719aca29d..934521708 100644 --- a/src/input/MmsInputPlugin.cxx +++ b/src/input/MmsInputPlugin.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "MmsInputPlugin.hxx" #include "InputInternal.hxx" +#include "InputStream.hxx" #include "InputPlugin.hxx" #include <glib.h> diff --git a/src/input/RewindInputPlugin.cxx b/src/input/RewindInputPlugin.cxx index 241a5fb5a..d77bb1207 100644 --- a/src/input/RewindInputPlugin.cxx +++ b/src/input/RewindInputPlugin.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "RewindInputPlugin.hxx" #include "InputInternal.hxx" +#include "InputStream.hxx" #include "InputPlugin.hxx" #include "tag.h" diff --git a/src/input/SoupInputPlugin.cxx b/src/input/SoupInputPlugin.cxx index 44c26be5a..be4892629 100644 --- a/src/input/SoupInputPlugin.cxx +++ b/src/input/SoupInputPlugin.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "SoupInputPlugin.hxx" #include "InputPlugin.hxx" +#include "InputStream.hxx" #include "InputInternal.hxx" #include "IOThread.hxx" #include "event/Loop.hxx" diff --git a/src/input_stream.h b/src/input_stream.h index d5b1dae2e..0d32c0742 100644 --- a/src/input_stream.h +++ b/src/input_stream.h @@ -29,64 +29,7 @@ #include <stdbool.h> #include <sys/types.h> -struct input_stream { - /** - * the plugin which implements this input stream - */ - const struct input_plugin *plugin; - - /** - * The absolute URI which was used to open this stream. May - * be NULL if this is unknown. - */ - char *uri; - - /** - * A mutex that protects the mutable attributes of this object - * and its implementation. It must be locked before calling - * any of the public methods. - * - * This object is allocated by the client, and the client is - * responsible for freeing it. - */ - GMutex *mutex; - - /** - * A cond that gets signalled when the state of this object - * changes from the I/O thread. The client of this object may - * wait on it. Optional, may be NULL. - * - * This object is allocated by the client, and the client is - * responsible for freeing it. - */ - GCond *cond; - - /** - * indicates whether the stream is ready for reading and - * whether the other attributes in this struct are valid - */ - bool ready; - - /** - * if true, then the stream is fully seekable - */ - bool seekable; - - /** - * the size of the resource, or -1 if unknown - */ - goffset size; - - /** - * the current offset within the stream - */ - goffset offset; - - /** - * the MIME content type of the resource, or NULL if unknown - */ - char *mime; -}; +struct input_stream; #ifdef __cplusplus extern "C" { @@ -119,20 +62,6 @@ gcc_nonnull(1) void input_stream_close(struct input_stream *is); -gcc_nonnull(1) -static inline void -input_stream_lock(struct input_stream *is) -{ - g_mutex_lock(is->mutex); -} - -gcc_nonnull(1) -static inline void -input_stream_unlock(struct input_stream *is) -{ - g_mutex_unlock(is->mutex); -} - /** * Check for errors that may have occurred in the I/O thread. * @@ -167,6 +96,26 @@ gcc_nonnull(1) void input_stream_lock_wait_ready(struct input_stream *is); +gcc_nonnull_all gcc_pure +const char * +input_stream_get_mime_type(const struct input_stream *is); + +gcc_nonnull_all +void +input_stream_override_mime_type(struct input_stream *is, const char *mime); + +gcc_nonnull_all gcc_pure +goffset +input_stream_get_size(const struct input_stream *is); + +gcc_nonnull_all gcc_pure +goffset +input_stream_get_offset(const struct input_stream *is); + +gcc_nonnull_all gcc_pure +bool +input_stream_is_seekable(const struct input_stream *is); + /** * Determines whether seeking is cheap. This is true for local files. */ diff --git a/src/playlist/LastFMPlaylistPlugin.cxx b/src/playlist/LastFMPlaylistPlugin.cxx index 67192574d..36c89fea1 100644 --- a/src/playlist/LastFMPlaylistPlugin.cxx +++ b/src/playlist/LastFMPlaylistPlugin.cxx @@ -242,8 +242,7 @@ lastfm_open_uri(const char *uri, GMutex *mutex, GCond *cond) /* last.fm does not send a MIME type, we have to fake it here :-( */ - g_free(playlist->is->mime); - playlist->is->mime = g_strdup("application/xspf+xml"); + input_stream_override_mime_type(playlist->is, "application/xspf+xml"); g_mutex_unlock(mutex); diff --git a/test/dump_text_file.cxx b/test/dump_text_file.cxx index 28a645a4f..dc3f9d6a8 100644 --- a/test/dump_text_file.cxx +++ b/test/dump_text_file.cxx @@ -20,7 +20,7 @@ #include "config.h" #include "IOThread.hxx" #include "InputInit.hxx" -#include "input_stream.h" +#include "InputStream.hxx" #include "conf.h" #include "stdbin.h" diff --git a/test/read_tags.cxx b/test/read_tags.cxx index f971c5ce1..a634d72b6 100644 --- a/test/read_tags.cxx +++ b/test/read_tags.cxx @@ -24,7 +24,7 @@ extern "C" { } #include "decoder_api.h" #include "InputInit.hxx" -#include "input_stream.h" +#include "InputStream.hxx" #include "audio_format.h" extern "C" { #include "tag_ape.h" diff --git a/test/run_input.cxx b/test/run_input.cxx index 55f60b9fe..b215eefea 100644 --- a/test/run_input.cxx +++ b/test/run_input.cxx @@ -23,6 +23,7 @@ #include "tag.h" #include "conf.h" #include "input_stream.h" +#include "InputStream.hxx" #include "InputInit.hxx" #include "IOThread.hxx" |