Merge release 0.15.9 from branch 'v0.15.x'
Conflicts: NEWS configure.ac src/cue/cue_tag.c src/decoder/mpcdec_decoder_plugin.c src/player_thread.c
This commit is contained in:
commit
e9beea072d
9
NEWS
9
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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -92,6 +92,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.
|
||||
*/
|
||||
@ -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) {
|
||||
|
@ -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 */
|
||||
|
16
src/tag.c
16
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)
|
||||
{
|
||||
|
@ -183,6 +183,15 @@ struct tag *tag_dup(const struct tag *tag);
|
||||
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.
|
||||
|
Loading…
Reference in New Issue
Block a user