Merge branch 'v0.16.x'

Conflicts:
	NEWS
	configure.ac
This commit is contained in:
Max Kellermann 2011-01-07 23:52:23 +01:00
commit 1a2ea4c06c
15 changed files with 115 additions and 87 deletions

20
NEWS
View File

@ -5,6 +5,21 @@ ver 0.17 (2010/??/??)
- osx: allow user to specify other audio devices
ver 0.16.1 (2010/??/??)
* audio_check: fix parameter in prototype
* add void casts to suppress "result unused" warnings (clang)
* input:
- ffado: disable by default
* decoder:
- mad: work around build failure on Solaris
* output:
- solaris: add missing parameter to open_cloexec() cal
- osx: fix up audio format first, then apply it to device
* player_thread: discard empty chunks while cross-fading
* player_thread: fix assertion failure due to early seek
* output_thread: fix double lock
ver 0.16 (2010/12/11)
* protocol:
- send song modification time to client
@ -119,6 +134,11 @@ ver 0.16 (2010/12/11)
* make single mode 'sticky'
ver 0.15.16 (2010/??/??)
* encoders:
- lame: explicitly configure the output sample rate
ver 0.15.15 (2010/11/08)
* input:
- rewind: fix assertion failure

View File

@ -162,7 +162,7 @@ AC_ARG_ENABLE(documentation,
AC_ARG_ENABLE(ffado,
AS_HELP_STRING([--enable-ffado], [enable libffado (FireWire) support]),,
[enable_ffado=auto])
[enable_ffado=no])
AC_ARG_ENABLE(ffmpeg,
AS_HELP_STRING([--enable-ffmpeg],
@ -1510,23 +1510,23 @@ dnl ---------------------------------------------------------------------------
echo ''
echo '########### MPD CONFIGURATION ############'
echo -ne '\nArchive support:\n\t'
printf '\nArchive support:\n\t'
results(bzip2,[bzip2])
results(iso9660,[ISO9660])
results(zzip,[ZIP])
if test x$with_zeroconf != xno; then
echo -ne '\nAutodiscovery support:\n\t'
printf '\nAutodiscovery support:\n\t'
results(avahi, [Avahi])
results(bonjour, [Bonjour])
fi
echo -ne '\nClient support:\n\t'
printf '\nClient support:\n\t'
results(ipv6, "IPv6")
results(tcp, "TCP")
results(un,[UNIX Domain Sockets])
echo -ne '\nFile format support:\n\t'
printf '\nFile format support:\n\t'
results(aac, [AAC])
results(sidplay, [C64 SID])
results(ffmpeg, [FFMPEG])
@ -1534,7 +1534,7 @@ results(flac, [FLAC])
results(fluidsynth, [FluidSynth])
results(gme, [GME])
results(sndfile, [libsndfile])
echo -ne '\n\t'
printf '\n\t'
results(mikmod, [MikMod])
results(modplug, [MODPLUG])
results(mad, [MAD])
@ -1542,23 +1542,23 @@ results(mpg123, [MPG123])
results(mp4, [MP4])
results(mpc, [Musepack])
results(oggflac, [OggFLAC], flac)
echo -ne '\n\t'
printf '\n\t'
results(tremor, [OggTremor])
results(vorbis, [OggVorbis])
results(audiofile, [WAVE])
results(wavpack, [WavPack])
results(wildmidi, [WildMidi])
echo -en '\nOther features:\n\t'
printf '\nOther features:\n\t'
results(lsr, [libsamplerate])
results(inotify, [inotify])
results(sqlite, [SQLite])
echo -en '\nMetadata support:\n\t'
printf '\nMetadata support:\n\t'
results(cue,[cue])
results(id3,[ID3])
echo -en '\nPlayback support:\n\t'
printf '\nPlayback support:\n\t'
results(alsa,ALSA)
results(ffado,FFADO)
results(fifo,FIFO)
@ -1567,14 +1567,14 @@ results(httpd_output,[HTTP Daemon])
results(jack,[JACK])
results(ao,[libao])
results(oss,[OSS])
echo -ne '\n\t'
printf '\n\t'
results(openal,[OpenAL])
results(osx, [OS X])
results(pipe_output, [Pipeline])
results(pulse, [PulseAudio])
results(mvp, [Media MVP])
results(shout, [SHOUTcast])
echo -ne '\n\t'
printf '\n\t'
results(solaris, [Solaris])
results(winmm_output, [WinMM])
@ -1582,7 +1582,7 @@ if
test x$enable_shout = xyes ||
test x$enable_recorder = xyes ||
test x$enable_httpd_output = xyes; then
echo -en '\nStreaming encoder support:\n\t'
printf '\nStreaming encoder support:\n\t'
results(flac_encoder, [FLAC])
results(lame_encoder, [LAME])
results(vorbis_encoder, [Ogg Vorbis])
@ -1590,20 +1590,20 @@ if
results(wave_encoder, [WAVE])
fi
echo -en '\nStreaming support:\n\t'
printf '\nStreaming support:\n\t'
results(curl,[CURL])
results(lastfm,[Last.FM])
results(mms,[MMS])
results(cdio_paranoia, [CDIO_PARANOIA])
echo -ne '\n\n##########################################\n\n'
printf '\n\n##########################################\n\n'
if test x$enable_sndfile = xyes && test x$enable_modplug = xyes; then
AC_MSG_WARN([compilation may fail, because libmodplug conflicts with libsndfile])
AC_MSG_WARN([libmodplug ships modplug/sndfile.h, which hides libsndfile's sndfile.h])
fi
echo -ne 'Generating files needed for compilation\n'
echo 'Generating files needed for compilation'
dnl ---------------------------------------------------------------------------
dnl Generate files

View File

@ -58,7 +58,7 @@ if test x$enable_aac = xyes; then
fi
if test x$enable_aac = xyes; then
AC_MSG_CHECKING(that FAAD2 uses buffer and bufferlen)
AC_COMPILE_IFELSE([
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <faad.h>
int main() {
@ -82,9 +82,9 @@ int main() {
return 0;
}
],[AC_MSG_RESULT(yes);AC_DEFINE(HAVE_FAAD_BUFLEN_FUNCS,1,[Define if FAAD2 uses buflen in function calls])],[AC_MSG_RESULT(no);
])],[AC_MSG_RESULT(yes);AC_DEFINE(HAVE_FAAD_BUFLEN_FUNCS,1,[Define if FAAD2 uses buflen in function calls])],[AC_MSG_RESULT(no);
AC_MSG_CHECKING(that FAAD2 can even be used)
AC_COMPILE_IFELSE([
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <faad.h>
int main() {
@ -113,7 +113,7 @@ int main() {
return 0;
}
],AC_MSG_RESULT(yes),[AC_MSG_RESULT(no);enable_aac=no])
])],AC_MSG_RESULT(yes),[AC_MSG_RESULT(no);enable_aac=no])
])
fi
if test x$enable_aac = xyes; then
@ -136,7 +136,7 @@ if test x$enable_aac = xyes; then
CPPFLAGS=$CFLAGS
AC_MSG_CHECKING(for broken libfaad headers)
AC_COMPILE_IFELSE([
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <faad.h>
#include <stddef.h>
#include <stdint.h>
@ -148,7 +148,7 @@ int main() {
faacDecInit2(NULL, NULL, 0, &sample_rate, &channels);
return 0;
}
],
])],
[AC_MSG_RESULT(correct)],
[AC_MSG_RESULT(broken);
AC_DEFINE(HAVE_FAAD_LONG, 1, [Define if faad.h uses the broken "unsigned long" pointers])])

View File

@ -4,9 +4,9 @@ AC_DEFUN([MPD_CHECK_FLAG],[
[mpd_check_cflag_$var],[
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $1"
AC_COMPILE_IFELSE([
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
int main(void) { return 0; }
], [ eval "mpd_check_cflag_$var=yes"
])], [ eval "mpd_check_cflag_$var=yes"
], [ eval "mpd_check_cflag_$var=no" ])
CFLAGS="$save_CFLAGS"
])

View File

@ -1,19 +1,19 @@
AC_DEFUN([results], [
dnl This is a hack to allow "with" names, otherwise "enable".
num=`expr match $1 'with'`
num=`expr $1 : 'with'`
if test "$num" != "0"; then
var="`echo '$'$1`"
else
var="`echo '$'enable_$1`"
fi
echo -n '('
printf '('
if eval "test x$var = xyes"; then
echo -n '+'
printf '+'
elif test -n "$3" && eval "test x$var = x$3"; then
echo -n '+'
printf '+'
else
echo -n '-'
printf '-'
fi
echo -n "$2) "
printf '%s) ' "$2"
])

View File

@ -38,7 +38,7 @@ bool
audio_check_sample_rate(unsigned long sample_rate, GError **error_r);
bool
audio_check_sample_format(unsigned sample_format, GError **error_r);
audio_check_sample_format(enum sample_format, GError **error_r);
bool
audio_check_channel_count(unsigned sample_format, GError **error_r);

View File

@ -547,14 +547,14 @@ enum {
XING_SCALE = 0x00000008L
};
struct version {
struct lame_version {
unsigned major;
unsigned minor;
};
struct lame {
char encoder[10]; /* 9 byte encoder name/version ("LAME3.97b") */
struct version version; /* struct containing just the version */
struct lame_version version; /* struct containing just the version */
float peak; /* replaygain peak */
float track_gain; /* replaygain track gain */
float album_gain; /* replaygain album gain */

View File

@ -30,8 +30,8 @@
#define DIRECTORY_DIR "directory: "
#define DEVICE_INARCHIVE (dev_t)(-1)
#define DEVICE_CONTAINER (dev_t)(-2)
#define DEVICE_INARCHIVE (dev_t)(-1)
#define DEVICE_CONTAINER (dev_t)(-2)
struct directory {
struct dirvec children;

View File

@ -170,6 +170,13 @@ lame_encoder_setup(struct lame_encoder *encoder, GError **error)
return false;
}
if (0 != lame_set_out_samplerate(encoder->gfp,
encoder->audio_format.sample_rate)) {
g_set_error(error, lame_encoder_quark(), 0,
"error setting lame out sample rate");
return false;
}
if (0 > lame_init_params(encoder->gfp)) {
g_set_error(error, lame_encoder_quark(), 0,
"error initializing lame params");

View File

@ -29,6 +29,9 @@
#include <assert.h>
#include <string.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "httpd_output"
struct httpd_client {
/**
* The httpd output object this client is connected to.

View File

@ -332,15 +332,6 @@ osx_output_open(void *data, struct audio_format *audio_format, GError **error)
stream_description.mSampleRate = audio_format->sample_rate;
stream_description.mFormatID = kAudioFormatLinearPCM;
stream_description.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
#if G_BYTE_ORDER == G_BIG_ENDIAN
stream_description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
#endif
stream_description.mBytesPerPacket =
audio_format_frame_size(audio_format);
stream_description.mFramesPerPacket = 1;
stream_description.mBytesPerFrame = stream_description.mBytesPerPacket;
stream_description.mChannelsPerFrame = audio_format->channels;
switch (audio_format->format) {
case SAMPLE_FORMAT_S8:
@ -357,6 +348,16 @@ osx_output_open(void *data, struct audio_format *audio_format, GError **error)
break;
}
#if G_BYTE_ORDER == G_BIG_ENDIAN
stream_description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
#endif
stream_description.mBytesPerPacket =
audio_format_frame_size(audio_format);
stream_description.mFramesPerPacket = 1;
stream_description.mBytesPerFrame = stream_description.mBytesPerPacket;
stream_description.mChannelsPerFrame = audio_format->channels;
result = AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0,
&stream_description,

View File

@ -93,7 +93,7 @@ solaris_output_open(void *data, struct audio_format *audio_format,
/* open the device in non-blocking mode */
so->fd = open_cloexec(so->device, O_WRONLY|O_NONBLOCK);
so->fd = open_cloexec(so->device, O_WRONLY|O_NONBLOCK, 0);
if (so->fd < 0) {
g_set_error(error, solaris_output_quark(), errno,
"Failed to open %s: %s",

View File

@ -303,7 +303,7 @@ ao_wait(struct audio_output *ao)
GTimeVal tv;
g_get_current_time(&tv);
g_time_val_add(&tv, delay * 1000);
g_cond_timed_wait(ao->cond, ao->mutex, &tv);
(void)g_cond_timed_wait(ao->cond, ao->mutex, &tv);
if (ao->command != AO_COMMAND_NONE)
return false;
@ -463,12 +463,9 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
/* don't automatically reopen this device for
10 seconds */
g_mutex_lock(ao->mutex);
assert(ao->fail_timer == NULL);
ao->fail_timer = g_timer_new();
g_mutex_unlock(ao->mutex);
return false;
}

View File

@ -356,16 +356,9 @@ player_check_decoder_startup(struct player *player)
static bool
player_send_silence(struct player *player)
{
struct music_chunk *chunk;
size_t frame_size =
audio_format_frame_size(&player->play_audio_format);
/* this formula ensures that we don't send
partial frames */
unsigned num_frames = sizeof(chunk->data) / frame_size;
assert(audio_format_defined(&player->play_audio_format));
chunk = music_buffer_allocate(player_buffer);
struct music_chunk *chunk = music_buffer_allocate(player_buffer);
if (chunk == NULL) {
g_warning("Failed to allocate silence buffer");
return false;
@ -375,6 +368,12 @@ player_send_silence(struct player *player)
chunk->audio_format = player->play_audio_format;
#endif
size_t frame_size =
audio_format_frame_size(&player->play_audio_format);
/* this formula ensures that we don't send
partial frames */
unsigned num_frames = sizeof(chunk->data) / frame_size;
chunk->times = -1.0; /* undefined time stamp */
chunk->length = num_frames * frame_size;
memset(chunk->data, 0, chunk->length);
@ -396,8 +395,6 @@ static bool player_seek_decoder(struct player *player)
{
struct song *song = pc.next_song;
struct decoder_control *dc = player->dc;
double where;
bool ret;
assert(pc.next_song != NULL);
@ -413,8 +410,7 @@ static bool player_seek_decoder(struct player *player)
/* re-start the decoder */
player_dc_start(player, player->pipe);
ret = player_wait_for_decoder(player);
if (!ret) {
if (!player_wait_for_decoder(player)) {
/* decoder failure */
player_command_finished();
return false;
@ -435,8 +431,7 @@ static bool player_seek_decoder(struct player *player)
/* wait for the decoder to complete initialization */
while (player->decoder_starting) {
ret = player_check_decoder_startup(player);
if (!ret) {
if (!player_check_decoder_startup(player)) {
/* decoder failure */
player_command_finished();
return false;
@ -445,14 +440,13 @@ static bool player_seek_decoder(struct player *player)
/* send the SEEK command */
where = pc.seek_where;
double where = pc.seek_where;
if (where > pc.total_time)
where = pc.total_time - 0.1;
if (where < 0.0)
where = 0.0;
ret = dc_seek(dc, where + song->start_ms / 1000.0);
if (!ret) {
if (!dc_seek(dc, where + song->start_ms / 1000.0)) {
/* decoder failure */
player_command_finished();
return false;
@ -583,14 +577,12 @@ static void player_process_command(struct player *player)
static void
update_song_tag(struct song *song, const struct tag *new_tag)
{
struct tag *old_tag;
if (song_is_file(song))
/* don't update tags of local files, only remote
streams may change tags dynamically */
return;
old_tag = song->tag;
struct tag *old_tag = song->tag;
song->tag = tag_dup(new_tag);
if (old_tag != NULL)
@ -648,15 +640,14 @@ static bool
play_next_chunk(struct player *player)
{
struct decoder_control *dc = player->dc;
struct music_chunk *chunk = NULL;
unsigned cross_fade_position;
bool success;
if (!audio_output_all_wait(64))
/* the output pipe is still large enough, don't send
another chunk */
return true;
unsigned cross_fade_position;
struct music_chunk *chunk = NULL;
if (player->xfade == XFADE_ENABLED &&
player_dc_at_next_song(player) &&
(cross_fade_position = music_pipe_size(player->pipe))
@ -694,6 +685,19 @@ play_next_chunk(struct player *player)
chunk->mix_ratio = nan("");
}
if (music_chunk_is_empty(other_chunk)) {
/* the "other" chunk was a music_chunk
which had only a tag, but no music
data - we cannot cross-fade that;
but since this happens only at the
beginning of the new song, we can
easily recover by throwing it away
now */
music_buffer_return(player_buffer,
other_chunk);
other_chunk = NULL;
}
chunk->other = other_chunk;
} else {
/* there are not enough decoded chunks yet */
@ -732,9 +736,7 @@ play_next_chunk(struct player *player)
/* play the current chunk */
success = play_chunk(player->song, chunk, &player->play_audio_format);
if (!success) {
if (!play_chunk(player->song, chunk, &player->play_audio_format)) {
music_buffer_return(player_buffer, chunk);
player_lock();
@ -776,11 +778,9 @@ play_next_chunk(struct player *player)
static bool
player_song_border(struct player *player)
{
char *uri;
player->xfade = XFADE_UNKNOWN;
uri = song_get_uri(player->song);
char *uri = song_get_uri(player->song);
g_message("played \"%s\"", uri);
g_free(uri);
@ -875,16 +875,17 @@ static void do_play(struct decoder_control *dc)
if (player.decoder_starting) {
/* wait until the decoder is initialized completely */
bool success;
const struct song *song;
success = player_check_decoder_startup(&player);
if (!success)
if (!player_check_decoder_startup(&player))
break;
/* seek to the beginning of the range */
song = decoder_current_song(dc);
const struct song *song = decoder_current_song(dc);
if (song != NULL && song->start_ms > 0 &&
/* we must not send a seek command until
the decoder is initialized
completely */
!player.decoder_starting &&
!dc_seek(dc, song->start_ms / 1000.0))
player_dc_stop(&player);
@ -1092,10 +1093,9 @@ static gpointer player_task(G_GNUC_UNUSED gpointer arg)
void player_create(void)
{
GError *e = NULL;
assert(pc.thread == NULL);
GError *e = NULL;
pc.thread = g_thread_create(player_task, NULL, true, &e);
if (pc.thread == NULL)
MPD_ERROR("Failed to spawn player task: %s", e->message);

View File

@ -47,7 +47,7 @@ poison_noaccess(void *p, size_t length)
memset(p, 0x01, length);
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_NOACCESS(p, length);
(void)VALGRIND_MAKE_MEM_NOACCESS(p, length);
#endif
#endif
}
@ -68,7 +68,7 @@ poison_undefined(void *p, size_t length)
memset(p, 0x02, length);
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_UNDEFINED(p, length);
(void)VALGRIND_MAKE_MEM_UNDEFINED(p, length);
#endif
#endif
}