diff options
author | Max Kellermann <max@duempel.org> | 2008-11-03 18:24:01 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2008-11-03 18:24:01 +0100 |
commit | ac96022c1de5573b9c4ff03990ac07c4bba8e3f9 (patch) | |
tree | e40cd0334b1fd332c49e7aa48f8a7dbe308c2e0f | |
parent | 8bb2da063f59e7586c61f88c1fb2d268e6191e5c (diff) | |
download | mpd-ac96022c1de5573b9c4ff03990ac07c4bba8e3f9.tar.gz mpd-ac96022c1de5573b9c4ff03990ac07c4bba8e3f9.tar.xz mpd-ac96022c1de5573b9c4ff03990ac07c4bba8e3f9.zip |
decoder_api: automatically send stream tag
If an input stream provides tags (e.g. from an icecast server), send
them in the decoder_data() and decoder_tag() methods. Removed the
according code from the mp3 and oggvorbis plugins - decoders shouldn't
have to care about stream tags.
This patch also adds the missing decoder_tag() invocation to the mp3
plugin.
-rw-r--r-- | src/decoder/mp3_plugin.c | 46 | ||||
-rw-r--r-- | src/decoder/oggvorbis_plugin.c | 10 | ||||
-rw-r--r-- | src/decoder_api.c | 51 | ||||
-rw-r--r-- | src/decoder_internal.h | 3 | ||||
-rw-r--r-- | src/decoder_thread.c | 1 |
5 files changed, 60 insertions, 51 deletions
diff --git a/src/decoder/mp3_plugin.c b/src/decoder/mp3_plugin.c index 7f742361d..f3edf9d20 100644 --- a/src/decoder/mp3_plugin.c +++ b/src/decoder/mp3_plugin.c @@ -942,19 +942,6 @@ mp3_synth_and_send(struct mp3_data *data, ReplayGainInfo *replay_gain_info) return DECODE_COMMAND_STOP; } - if (data->input_stream->meta_title) { - struct tag *tag = tag_new(); - if (data->input_stream->meta_name) { - tag_add_item(tag, TAG_ITEM_NAME, - data->input_stream->meta_name); - } - tag_add_item(tag, TAG_ITEM_TITLE, - data->input_stream->meta_title); - free(data->input_stream->meta_title); - data->input_stream->meta_title = NULL; - tag_free(tag); - } - if (!data->decoded_first_frame) { i = data->drop_start_samples; data->decoded_first_frame = true; @@ -1079,37 +1066,14 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream) mp3_audio_format(&data, &audio_format); - if (input_stream->meta_title) { - if (tag) - tag_free(tag); - tag = tag_new(); - tag_add_item(tag, TAG_ITEM_TITLE, input_stream->meta_title); - free(input_stream->meta_title); - input_stream->meta_title = NULL; - if (input_stream->meta_name) { - tag_add_item(tag, TAG_ITEM_NAME, - input_stream->meta_name); - } - tag_free(tag); - } else if (tag) { - if (input_stream->meta_name) { - tag_clear_items_by_type(tag, TAG_ITEM_NAME); - tag_add_item(tag, TAG_ITEM_NAME, - input_stream->meta_name); - } - tag_free(tag); - } else if (input_stream->meta_name) { - tag = tag_new(); - if (input_stream->meta_name) { - tag_add_item(tag, TAG_ITEM_NAME, - input_stream->meta_name); - } - tag_free(tag); - } - decoder_initialized(decoder, &audio_format, data.input_stream->seekable, data.total_time); + if (tag != NULL) { + decoder_tag(decoder, input_stream, tag); + tag_free(tag); + } + while (mp3_read(&data, &replay_gain_info)) ; if (replay_gain_info) diff --git a/src/decoder/oggvorbis_plugin.c b/src/decoder/oggvorbis_plugin.c index d5402aa66..f86bf3fc4 100644 --- a/src/decoder/oggvorbis_plugin.c +++ b/src/decoder/oggvorbis_plugin.c @@ -181,23 +181,14 @@ static struct tag *oggCommentsParse(char **comments) static void putOggCommentsIntoOutputBuffer(struct decoder *decoder, struct input_stream *is, - char *streamName, char **comments) { struct tag *tag; tag = oggCommentsParse(comments); - if (!tag && streamName) { - tag = tag_new(); - } if (!tag) return; - if (streamName) { - tag_clear_items_by_type(tag, TAG_ITEM_NAME); - tag_add_item(tag, TAG_ITEM_NAME, streamName); - } - decoder_tag(decoder, is, tag); tag_free(tag); } @@ -288,7 +279,6 @@ oggvorbis_decode(struct decoder *decoder, struct input_stream *inStream) } comments = ov_comment(&vf, -1)->user_comments; putOggCommentsIntoOutputBuffer(decoder, inStream, - inStream->meta_name, comments); ogg_getReplayGainInfo(comments, &replayGainInfo); } diff --git a/src/decoder_api.c b/src/decoder_api.c index e0dccdd01..6d577ec79 100644 --- a/src/decoder_api.c +++ b/src/decoder_api.c @@ -118,6 +118,33 @@ size_t decoder_read(struct decoder *decoder, } /** + * Add the tag items from the input stream (meta_name, meta_title) to + * a duplicate of the specified tag. The return value has to be freed + * with tag_free(). If this function returns NULL, then there are no + * tags provided by the stream. + */ +static struct tag * +tag_add_stream_tags(const struct tag *src_tag, const struct input_stream *is) +{ + struct tag *tag; + + assert(src_tag != NULL); + assert(is != NULL); + + if ((is->meta_name == NULL || tag_has_type(src_tag, TAG_ITEM_NAME)) && + (is->meta_title == NULL || tag_has_type(src_tag, TAG_ITEM_TITLE))) + return NULL; + + tag = tag_dup(src_tag); + if (is->meta_name != NULL && !tag_has_type(src_tag, TAG_ITEM_NAME)) + tag_add_item(tag, TAG_ITEM_NAME, is->meta_name); + if (is->meta_title != NULL && !tag_has_type(src_tag, TAG_ITEM_TITLE)) + tag_add_item(tag, TAG_ITEM_TITLE, is->meta_title); + + return tag; +} + +/** * All chunks are full of decoded data; wait for the player to free * one. */ @@ -148,6 +175,20 @@ decoder_data(struct decoder *decoder, size_t nbytes; char *data; + if (is != NULL && !decoder->stream_tag_sent) { + struct tag *tag1 = tag_new(), *tag2; + + tag2 = tag_add_stream_tags(tag1, is); + tag_free(tag1); + + if (tag2 != NULL) { + music_pipe_tag(tag2); + tag_free(tag2); + } + + decoder->stream_tag_sent = true; + } + if (audio_format_equals(&dc.in_audio_format, &dc.out_audio_format)) { data = _data; } else { @@ -193,11 +234,21 @@ enum decoder_command decoder_tag(mpd_unused struct decoder *decoder, struct input_stream *is, const struct tag *tag) { + struct tag *tag2 = is != NULL ? tag_add_stream_tags(tag, is) : NULL; + + if (tag2 != NULL) + tag = tag2; + while (!music_pipe_tag(tag)) { enum decoder_command cmd = need_chunks(is); if (cmd != DECODE_COMMAND_NONE) return cmd; } + if (tag2 != NULL) + tag_free(tag2); + + decoder->stream_tag_sent = true; + return DECODE_COMMAND_NONE; } diff --git a/src/decoder_internal.h b/src/decoder_internal.h index 7a36e011c..9d3d6abea 100644 --- a/src/decoder_internal.h +++ b/src/decoder_internal.h @@ -28,6 +28,9 @@ struct decoder { struct pcm_convert_state conv_state; bool seeking; + + /** has the tag from the input stream been sent yet? */ + bool stream_tag_sent; }; #endif diff --git a/src/decoder_thread.c b/src/decoder_thread.c index d66094cd2..040e34f84 100644 --- a/src/decoder_thread.c +++ b/src/decoder_thread.c @@ -72,6 +72,7 @@ static void decodeStart(void) } decoder.seeking = false; + decoder.stream_tag_sent = false; dc.state = DECODE_STATE_START; dc.command = DECODE_COMMAND_NONE; |