diff options
Diffstat (limited to '')
-rw-r--r-- | src/decoder/mad_decoder_plugin.c (renamed from src/decoder/mad_plugin.c) | 132 |
1 files changed, 62 insertions, 70 deletions
diff --git a/src/decoder/mad_plugin.c b/src/decoder/mad_decoder_plugin.c index 1ef7183fa..87dfbeabd 100644 --- a/src/decoder/mad_plugin.c +++ b/src/decoder/mad_decoder_plugin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2009 The Music Player Daemon Project + * Copyright (C) 2003-2010 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,10 +17,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "../decoder_api.h" -#include "../conf.h" #include "config.h" +#include "decoder_api.h" +#include "conf.h" #include "tag_id3.h" +#include "audio_check.h" #include <assert.h> #include <unistd.h> @@ -125,6 +126,7 @@ struct mp3_data { unsigned int drop_end_frames; unsigned int drop_start_samples; unsigned int drop_end_samples; + bool found_replay_gain; bool found_xing; bool found_first_frame; bool decoded_first_frame; @@ -148,6 +150,7 @@ mp3_data_init(struct mp3_data *data, struct decoder *decoder, data->drop_end_frames = 0; data->drop_start_samples = 0; data->drop_end_samples = 0; + data->found_replay_gain = false; data->found_xing = false; data->found_first_frame = false; data->decoded_first_frame = false; @@ -164,7 +167,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); @@ -351,8 +354,7 @@ parse_id3_replay_gain_info(struct id3_tag *tag) #endif static void mp3_parse_id3(struct mp3_data *data, size_t tagsize, - struct tag **mpd_tag, - struct replay_gain_info **replay_gain_info_r) + struct tag **mpd_tag) { #ifdef HAVE_ID3TAG struct id3_tag *id3_tag = NULL; @@ -405,13 +407,13 @@ static void mp3_parse_id3(struct mp3_data *data, size_t tagsize, } } - if (replay_gain_info_r) { + if (data->decoder != NULL) { struct replay_gain_info *tmp_rgi = parse_id3_replay_gain_info(id3_tag); if (tmp_rgi != NULL) { - if (*replay_gain_info_r) - replay_gain_info_free(*replay_gain_info_r); - *replay_gain_info_r = tmp_rgi; + decoder_replay_gain(data->decoder, tmp_rgi); + replay_gain_info_free(tmp_rgi); + data->found_replay_gain = true; } } @@ -420,7 +422,6 @@ static void mp3_parse_id3(struct mp3_data *data, size_t tagsize, g_free(allocated); #else /* !HAVE_ID3TAG */ (void)mpd_tag; - (void)replay_gain_info_r; /* This code is enabled when libid3tag is disabled. Instead of parsing the ID3 frame, it just skips it. */ @@ -448,8 +449,7 @@ id3_tag_query(const void *p0, size_t length) #endif /* !HAVE_ID3TAG */ static enum mp3_action -decode_next_frame_header(struct mp3_data *data, G_GNUC_UNUSED struct tag **tag, - G_GNUC_UNUSED struct replay_gain_info **replay_gain_info_r) +decode_next_frame_header(struct mp3_data *data, G_GNUC_UNUSED struct tag **tag) { enum mad_layer layer; @@ -471,7 +471,7 @@ decode_next_frame_header(struct mp3_data *data, G_GNUC_UNUSED struct tag **tag, if (tagsize > 0) { if (tag && !(*tag)) { mp3_parse_id3(data, (size_t)tagsize, - tag, replay_gain_info_r); + tag); } else { mad_stream_skip(&(data->stream), tagsize); @@ -779,10 +779,10 @@ mp3_frame_duration(const struct mad_frame *frame) MAD_UNITS_MILLISECONDS) / 1000.0; } -static off_t +static goffset mp3_this_frame_offset(const struct mp3_data *data) { - off_t offset = data->input_stream->offset; + goffset offset = data->input_stream->offset; if (data->stream.this_frame != NULL) offset -= data->stream.bufend - data->stream.this_frame; @@ -792,7 +792,7 @@ mp3_this_frame_offset(const struct mp3_data *data) return offset; } -static off_t +static goffset mp3_rest_including_this_frame(const struct mp3_data *data) { return data->input_stream->size - mp3_this_frame_offset(data); @@ -804,7 +804,7 @@ mp3_rest_including_this_frame(const struct mp3_data *data) static void mp3_filesize_to_song_length(struct mp3_data *data) { - off_t rest = mp3_rest_including_this_frame(data); + goffset rest = mp3_rest_including_this_frame(data); if (rest > 0) { float frame_duration = mp3_frame_duration(&data->frame); @@ -819,8 +819,7 @@ mp3_filesize_to_song_length(struct mp3_data *data) } static bool -mp3_decode_first_frame(struct mp3_data *data, struct tag **tag, - struct replay_gain_info **replay_gain_info_r) +mp3_decode_first_frame(struct mp3_data *data, struct tag **tag) { struct xing xing; struct lame lame; @@ -834,8 +833,7 @@ mp3_decode_first_frame(struct mp3_data *data, struct tag **tag, while (true) { do { - ret = decode_next_frame_header(data, tag, - replay_gain_info_r); + ret = decode_next_frame_header(data, tag); } while (ret == DECODE_CONT); if (ret == DECODE_BREAK) return false; @@ -878,11 +876,15 @@ mp3_decode_first_frame(struct mp3_data *data, struct tag **tag, /* Album gain isn't currently used. See comment in * parse_lame() for details. -- jat */ - if (replay_gain_info_r && !*replay_gain_info_r && + if (data->decoder != NULL && + !data->found_replay_gain && lame.track_gain) { - *replay_gain_info_r = replay_gain_info_new(); - (*replay_gain_info_r)->tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain; - (*replay_gain_info_r)->tuples[REPLAY_GAIN_TRACK].peak = lame.peak; + struct replay_gain_info *rgi + = replay_gain_info_new(); + rgi->tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain; + rgi->tuples[REPLAY_GAIN_TRACK].peak = lame.peak; + decoder_replay_gain(data->decoder, rgi); + replay_gain_info_free(rgi); } } } @@ -913,33 +915,29 @@ static void mp3_data_finish(struct mp3_data *data) } /* this is primarily used for getting total time for tags */ -static int mp3_total_file_time(const char *file) +static int +mad_decoder_total_file_time(struct input_stream *is) { - struct input_stream input_stream; struct mp3_data data; int ret; - if (!input_stream_open(&input_stream, file)) - return -1; - mp3_data_init(&data, NULL, &input_stream); - if (!mp3_decode_first_frame(&data, NULL, NULL)) + mp3_data_init(&data, NULL, is); + if (!mp3_decode_first_frame(&data, NULL)) ret = -1; else ret = data.total_time + 0.5; mp3_data_finish(&data); - input_stream_close(&input_stream); return ret; } static bool mp3_open(struct input_stream *is, struct mp3_data *data, - struct decoder *decoder, struct tag **tag, - struct replay_gain_info **replay_gain_info_r) + struct decoder *decoder, struct tag **tag) { mp3_data_init(data, decoder, is); *tag = NULL; - if (!mp3_decode_first_frame(data, tag, replay_gain_info_r)) { + if (!mp3_decode_first_frame(data, tag)) { mp3_data_finish(data); if (tag && *tag) tag_free(*tag); @@ -998,8 +996,7 @@ mp3_update_timer_next_frame(struct mp3_data *data) * Sends the synthesized current frame via decoder_data(). */ static enum decoder_command -mp3_send_pcm(struct mp3_data *data, unsigned i, unsigned pcm_length, - struct replay_gain_info *replay_gain_info) +mp3_send_pcm(struct mp3_data *data, unsigned i, unsigned pcm_length) { unsigned max_samples; @@ -1024,9 +1021,7 @@ mp3_send_pcm(struct mp3_data *data, unsigned i, unsigned pcm_length, cmd = decoder_data(data->decoder, data->input_stream, data->output_buffer, sizeof(data->output_buffer[0]) * num_samples, - data->elapsed_time, - data->bit_rate / 1000, - replay_gain_info); + data->bit_rate / 1000); if (cmd != DECODE_COMMAND_NONE) return cmd; } @@ -1038,8 +1033,7 @@ mp3_send_pcm(struct mp3_data *data, unsigned i, unsigned pcm_length, * Synthesize the current frame and send it via decoder_data(). */ static enum decoder_command -mp3_synth_and_send(struct mp3_data *data, - struct replay_gain_info *replay_gain_info) +mp3_synth_and_send(struct mp3_data *data) { unsigned i, pcm_length; enum decoder_command cmd; @@ -1080,7 +1074,7 @@ mp3_synth_and_send(struct mp3_data *data, pcm_length -= data->drop_end_samples; } - cmd = mp3_send_pcm(data, i, pcm_length, replay_gain_info); + cmd = mp3_send_pcm(data, i, pcm_length); if (cmd != DECODE_COMMAND_NONE) return cmd; @@ -1094,7 +1088,7 @@ mp3_synth_and_send(struct mp3_data *data, } static bool -mp3_read(struct mp3_data *data, struct replay_gain_info **replay_gain_info_r) +mp3_read(struct mp3_data *data) { struct decoder *decoder = data->decoder; enum mp3_action ret; @@ -1111,9 +1105,7 @@ mp3_read(struct mp3_data *data, struct replay_gain_info **replay_gain_info_r) data->mute_frame = MUTEFRAME_NONE; break; case MUTEFRAME_NONE: - cmd = mp3_synth_and_send(data, - replay_gain_info_r != NULL - ? *replay_gain_info_r : NULL); + cmd = mp3_synth_and_send(data); if (cmd == DECODE_COMMAND_SEEK) { unsigned long j; @@ -1142,8 +1134,7 @@ mp3_read(struct mp3_data *data, struct replay_gain_info **replay_gain_info_r) do { struct tag *tag = NULL; - ret = decode_next_frame_header(data, &tag, - replay_gain_info_r); + ret = decode_next_frame_header(data, &tag); if (tag != NULL) { decoder_tag(decoder, data->input_stream, tag); @@ -1170,29 +1161,34 @@ mp3_read(struct mp3_data *data, struct replay_gain_info **replay_gain_info_r) return ret != DECODE_BREAK; } -static void mp3_audio_format(struct mp3_data *data, struct audio_format *af) -{ - af->bits = 24; - af->sample_rate = (data->frame).header.samplerate; - af->channels = MAD_NCHANNELS(&(data->frame).header); -} - static void mp3_decode(struct decoder *decoder, struct input_stream *input_stream) { struct mp3_data data; + GError *error = NULL; struct tag *tag = NULL; - struct replay_gain_info *replay_gain_info = NULL; struct audio_format audio_format; - if (!mp3_open(input_stream, &data, decoder, &tag, &replay_gain_info)) { + if (!mp3_open(input_stream, &data, decoder, &tag)) { if (decoder_get_command(decoder) == DECODE_COMMAND_NONE) g_warning ("Input does not appear to be a mp3 bit stream.\n"); return; } - mp3_audio_format(&data, &audio_format); + if (!audio_format_init_checked(&audio_format, + data.frame.header.samplerate, + SAMPLE_FORMAT_S24_P32, + MAD_NCHANNELS(&data.frame.header), + &error)) { + g_warning("%s", error->message); + g_error_free(error); + + if (tag != NULL) + tag_free(tag); + mp3_data_finish(&data); + return; + } decoder_initialized(decoder, &audio_format, data.input_stream->seekable, data.total_time); @@ -1202,10 +1198,7 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream) tag_free(tag); } - while (mp3_read(&data, &replay_gain_info)) ; - - if (replay_gain_info) - replay_gain_info_free(replay_gain_info); + while (mp3_read(&data)) ; if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK && data.mute_frame == MUTEFRAME_SEEK) @@ -1214,16 +1207,15 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream) mp3_data_finish(&data); } -static struct tag *mp3_tag_dup(const char *file) +static struct tag * +mad_decoder_stream_tag(struct input_stream *is) { struct tag *tag; int total_time; - total_time = mp3_total_file_time(file); - if (total_time < 0) { - g_debug("Failed to get total song time from: %s", file); + total_time = mad_decoder_total_file_time(is); + if (total_time < 0) return NULL; - } tag = tag_new(); tag->time = total_time; @@ -1237,7 +1229,7 @@ const struct decoder_plugin mad_decoder_plugin = { .name = "mad", .init = mp3_plugin_init, .stream_decode = mp3_decode, - .tag_dup = mp3_tag_dup, + .stream_tag = mad_decoder_stream_tag, .suffixes = mp3_suffixes, .mime_types = mp3_mime_types }; |