summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS9
-rw-r--r--src/cue/cue_tag.c18
-rw-r--r--src/decoder/mad_decoder_plugin.c4
-rw-r--r--src/decoder/mpcdec_decoder_plugin.c11
-rw-r--r--src/player_thread.c27
-rw-r--r--src/playlist.c3
-rw-r--r--src/tag.c16
-rw-r--r--src/tag.h9
8 files changed, 74 insertions, 23 deletions
diff --git a/NEWS b/NEWS
index 31c699e91..c95f951cc 100644
--- a/NEWS
+++ b/NEWS
@@ -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 */
diff --git a/src/tag.c b/src/tag.c
index fb4c40a55..aa96a468f 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -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)
{
diff --git a/src/tag.h b/src/tag.h
index 549a696de..6931453f7 100644
--- a/src/tag.h
+++ b/src/tag.h
@@ -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.
*/