diff options
-rw-r--r-- | NEWS | 9 | ||||
-rw-r--r-- | src/cue/cue_tag.c | 18 | ||||
-rw-r--r-- | src/decoder/mad_decoder_plugin.c | 4 | ||||
-rw-r--r-- | src/decoder/mpcdec_decoder_plugin.c | 11 | ||||
-rw-r--r-- | src/player_thread.c | 27 | ||||
-rw-r--r-- | src/playlist.c | 3 | ||||
-rw-r--r-- | src/tag.c | 16 | ||||
-rw-r--r-- | src/tag.h | 9 |
8 files changed, 74 insertions, 23 deletions
@@ -96,6 +96,15 @@ ver 0.16 (20??/??/??) * added libwrap support +ver 0.15.9 (2010/03/21) +* decoders: + - mad: fix crash when seeking at end of song + - mpcdec: fix negative shift on fixed-point samples + - mpcdec: fix replay gain formula with v8 +* playlist: fix single+repeat in random mode +* player: postpone song tags during cross-fade + + ver 0.15.8 (2010/01/17) * input: - curl: allow rewinding with Icy-Metadata diff --git a/src/cue/cue_tag.c b/src/cue/cue_tag.c index 46dfb1b50..67919ce37 100644 --- a/src/cue/cue_tag.c +++ b/src/cue/cue_tag.c @@ -155,22 +155,6 @@ cue_tag_track(struct Cdtext *cdtext, struct Rem *rem) return tag; } -static struct tag * -cue_tag_merge(struct tag *a, struct tag *b) -{ - if (a != NULL && b != NULL) { - struct tag *merge_tag = tag_merge(a, b); - tag_free(a); - tag_free(b); - return merge_tag; - } else if (a != NULL) - return a; - else if (b != NULL) - return b; - else - return NULL; -} - struct tag * cue_tag(struct Cd *cd, unsigned tnum) { @@ -190,7 +174,7 @@ cue_tag(struct Cd *cd, unsigned tnum) track_tag = cue_tag_track(track_get_cdtext(track), track_get_rem(track)); - tag = cue_tag_merge(cd_tag, track_tag); + tag = tag_merge_replace(cd_tag, track_tag); if (tag == NULL) return NULL; diff --git a/src/decoder/mad_decoder_plugin.c b/src/decoder/mad_decoder_plugin.c index 6f6ee8fa4..57221d878 100644 --- a/src/decoder/mad_decoder_plugin.c +++ b/src/decoder/mad_decoder_plugin.c @@ -1238,10 +1238,6 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream) while (mp3_read(&data)) ; - if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK && - data.mute_frame == MUTEFRAME_SEEK) - decoder_command_finished(decoder); - mp3_data_finish(&data); } diff --git a/src/decoder/mpcdec_decoder_plugin.c b/src/decoder/mpcdec_decoder_plugin.c index e41ae779d..4df8dd218 100644 --- a/src/decoder/mpcdec_decoder_plugin.c +++ b/src/decoder/mpcdec_decoder_plugin.c @@ -25,6 +25,7 @@ #include <mpcdec/mpcdec.h> #else #include <mpc/mpcdec.h> +#include <math.h> #endif #include <glib.h> @@ -105,7 +106,7 @@ mpc_to_mpd_sample(MPC_SAMPLE_FORMAT sample) const int shift = bits - MPC_FIXED_POINT_SCALE_SHIFT; if (shift < 0) - val = sample << -shift; + val = sample >> -shift; else val = sample << shift; #else @@ -206,10 +207,18 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is) struct replay_gain_info replay_gain_info; replay_gain_info_init(&replay_gain_info); +#ifdef MPC_IS_OLD_API replay_gain_info.tuples[REPLAY_GAIN_ALBUM].gain = info.gain_album * 0.01; replay_gain_info.tuples[REPLAY_GAIN_ALBUM].peak = info.peak_album / 32767.0; replay_gain_info.tuples[REPLAY_GAIN_TRACK].gain = info.gain_title * 0.01; replay_gain_info.tuples[REPLAY_GAIN_TRACK].peak = info.peak_title / 32767.0; +#else + replay_gain_info.tuples[REPLAY_GAIN_ALBUM].gain = MPC_OLD_GAIN_REF - (info.gain_album / 256.); + replay_gain_info.tuples[REPLAY_GAIN_ALBUM].peak = pow(10, info.peak_album / 256. / 20) / 32767; + replay_gain_info.tuples[REPLAY_GAIN_TRACK].gain = MPC_OLD_GAIN_REF - (info.gain_title / 256.); + replay_gain_info.tuples[REPLAY_GAIN_TRACK].peak = pow(10, info.peak_title / 256. / 20) / 32767; +#endif + decoder_replay_gain(mpd_decoder, &replay_gain_info); decoder_initialized(mpd_decoder, &audio_format, diff --git a/src/player_thread.c b/src/player_thread.c index d3f5d7ccb..8fa089c1f 100644 --- a/src/player_thread.c +++ b/src/player_thread.c @@ -93,6 +93,13 @@ struct player { unsigned cross_fade_chunks; /** + * The tag of the "next" song during cross-fade. It is + * postponed, and sent to the output thread when the new song + * really begins. + */ + struct tag *cross_fade_tag; + + /** * The current audio format for the audio outputs. */ struct audio_format play_audio_format; @@ -649,6 +656,14 @@ play_next_chunk(struct player *player) chunk = music_pipe_shift(player->pipe); assert(chunk != NULL); + /* don't send the tags of the new song (which + is being faded in) yet; postpone it until + the current song is faded out */ + player->cross_fade_tag = + tag_merge_replace(player->cross_fade_tag, + other_chunk->tag); + other_chunk->tag = NULL; + if (isnan(pc.mixramp_delay_seconds)) { mix_ratio = ((float)cross_fade_position) / player->cross_fade_chunks; @@ -687,6 +702,14 @@ play_next_chunk(struct player *player) assert(chunk != NULL); + /* insert the postponed tag if cross-fading is finished */ + + if (player->xfade != XFADE_ENABLED && player->cross_fade_tag != NULL) { + chunk->tag = tag_merge_replace(chunk->tag, + player->cross_fade_tag); + player->cross_fade_tag = NULL; + } + /* play the current chunk */ success = play_chunk(player->song, chunk, &player->play_audio_format); @@ -769,6 +792,7 @@ static void do_play(struct decoder_control *dc) .xfade = XFADE_UNKNOWN, .cross_fading = false, .cross_fade_chunks = 0, + .cross_fade_tag = NULL, .elapsed_time = 0.0, }; @@ -939,6 +963,9 @@ static void do_play(struct decoder_control *dc) music_pipe_clear(player.pipe, player_buffer); music_pipe_free(player.pipe); + if (player.cross_fade_tag != NULL) + tag_free(player.cross_fade_tag); + player_lock(); if (player.queued) { diff --git a/src/playlist.c b/src/playlist.c index 916613096..e708ce00f 100644 --- a/src/playlist.c +++ b/src/playlist.c @@ -139,7 +139,8 @@ playlist_update_queued_song(struct playlist *playlist, const struct song *prev) ? queue_next_order(&playlist->queue, playlist->current) : 0; - if (next_order == 0 && playlist->queue.random) { + if (next_order == 0 && playlist->queue.random && + !playlist->queue.single) { /* shuffle the song order again, so we get a different order each time the playlist is played completely */ @@ -282,6 +282,22 @@ tag_merge(const struct tag *base, const struct tag *add) return ret; } +struct tag * +tag_merge_replace(struct tag *base, struct tag *add) +{ + if (add == NULL) + return base; + + if (base == NULL) + return add; + + struct tag *tag = tag_merge(base, add); + tag_free(base); + tag_free(add); + + return tag; +} + const char * tag_get_value(const struct tag *tag, enum tag_type type) { @@ -184,6 +184,15 @@ struct tag * tag_merge(const struct tag *base, const struct tag *add); /** + * Merges the data from two tags. Any of the two may be NULL. Both + * are freed by this function. + * + * @return a newly allocated tag, which must be freed with tag_free() + */ +struct tag * +tag_merge_replace(struct tag *base, struct tag *add); + +/** * Returns true if the tag contains no items. This ignores the "time" * attribute. */ |