Compare commits

...

10 Commits

Author SHA1 Message Date
Max Kellermann
2784d65618 release v0.18.9 2014-03-02 11:25:01 +01:00
Max Kellermann
47ea69233b output/alsa: remove the obsolete Raspberry Pi workaround
Has been superseded by the previous commit.
2014-03-02 11:22:04 +01:00
Max Kellermann
a884e37de1 output/alsa: call snd_pcm_prepare() after snd_pcm_drop()
Don't wait for an optimistic write to fail.  This is an improved
workaround for the infamous Raspberry Pi bug (see commit af991765).
It works much better and comes without the negative side effects.  The
old workaround is now obsolete.
2014-03-02 11:12:25 +01:00
Max Kellermann
0102a8665a event/SignalMonitor: fix build failure due to missing signal.h include 2014-03-02 10:21:31 +01:00
Max Kellermann
d34ae0850c AllCommands: "findadd" requires the "add" permission 2014-02-27 23:08:22 +01:00
Max Kellermann
6526de024a output/pulse: remove bogus g_free() call 2014-02-24 21:23:49 +01:00
Max Kellermann
5e1e92626c event/SignalMonitor: unblock signals after fork
Fixes hanging child process in the "pipe" output plugin.
2014-02-18 19:13:50 +01:00
Max Kellermann
7fee85c80a configure.ac: fix linker failure when libvorbis/libogg are static
Link libvorbisfile first, followed to libvorbis and finally libogg.
This order is necessary because libvorbisfile depends on libvorbis.
2014-02-18 18:39:19 +01:00
Max Kellermann
5d87a274a5 configure.ac: link the Vorbis encoder with libogg
Fixes another linker failure.  Similar to commit ea406875
2014-02-17 19:42:38 +01:00
Max Kellermann
57e862712a configure.ac: prepare for 0.18.9 2014-02-09 22:58:14 +01:00
6 changed files with 63 additions and 40 deletions

13
NEWS

@@ -1,3 +1,16 @@
ver 0.18.9 (2014/03/02)
* protocol
- "findadd" requires the "add" permission
* output
- alsa: improved workaround for noise after manual song change
* decoder
- vorbis: fix linker failure when libvorbis/libogg are static
* encoder
- vorbis: fix another linker failure
* output
- pipe: fix hanging child process due to blocked signals
* fix build failure due to missing signal.h include
ver 0.18.8 (2014/02/07)
* decoder
- ffmpeg: support libav v10_alpha1

@@ -1,6 +1,6 @@
AC_PREREQ(2.60)
AC_INIT(mpd, 0.18.8, mpd-devel@musicpd.org)
AC_INIT(mpd, 0.18.9, mpd-devel@musicpd.org)
VERSION_MAJOR=0
VERSION_MINOR=18
@@ -1023,7 +1023,7 @@ if test x$enable_tremor = xyes; then
fi
fi
MPD_AUTO_PKG(vorbis, VORBIS, [vorbis vorbisfile ogg],
MPD_AUTO_PKG(vorbis, VORBIS, [vorbisfile vorbis ogg],
[Ogg Vorbis decoder], [libvorbis not found])
if test x$enable_vorbis = xyes; then
AC_DEFINE(ENABLE_VORBIS_DECODER, 1, [Define for Ogg Vorbis support])
@@ -1139,7 +1139,7 @@ fi
AM_CONDITIONAL(ENABLE_FLAC_ENCODER, test x$enable_flac_encoder = xyes)
dnl ---------------------------- Ogg Vorbis Encoder ---------------------------
MPD_AUTO_PKG(vorbis_encoder, VORBISENC, [vorbisenc vorbis],
MPD_AUTO_PKG(vorbis_encoder, VORBISENC, [vorbisenc vorbis ogg],
[Ogg Vorbis encoder], [libvorbisenc not found])
if test x$enable_vorbis_encoder = xyes; then

@@ -90,7 +90,7 @@ static const struct command commands[] = {
{ "disableoutput", PERMISSION_ADMIN, 1, 1, handle_disableoutput },
{ "enableoutput", PERMISSION_ADMIN, 1, 1, handle_enableoutput },
{ "find", PERMISSION_READ, 2, -1, handle_find },
{ "findadd", PERMISSION_READ, 2, -1, handle_findadd},
{ "findadd", PERMISSION_ADD, 2, -1, handle_findadd},
{ "idle", PERMISSION_READ, 0, -1, handle_idle },
{ "kill", PERMISSION_ADMIN, -1, -1, handle_kill },
{ "list", PERMISSION_READ, 1, -1, handle_list },

@@ -39,6 +39,12 @@
#include <algorithm>
#ifdef USE_SIGNALFD
#include <pthread.h>
#endif
#include <signal.h>
class SignalMonitor final : private SocketMonitor {
#ifdef USE_SIGNALFD
SignalFD fd;
@@ -99,7 +105,21 @@ static std::atomic_bool signal_pending[MAX_SIGNAL];
static Manual<SignalMonitor> monitor;
#ifndef USE_SIGNALFD
#ifdef USE_SIGNALFD
/**
* This is a pthread_atfork() callback that unblocks the signals that
* were blocked for our signalfd(). Without this, our child processes
* would inherit the blocked signals.
*/
static void
at_fork_child()
{
sigprocmask(SIG_UNBLOCK, &signal_mask, nullptr);
}
#else
static void
SignalCallback(int signo)
{
@@ -108,6 +128,7 @@ SignalCallback(int signo)
if (!signal_pending[signo].exchange(true))
monitor->WakeUp();
}
#endif
void
@@ -115,6 +136,8 @@ SignalMonitorInit(EventLoop &loop)
{
#ifdef USE_SIGNALFD
sigemptyset(&signal_mask);
pthread_atfork(nullptr, nullptr, at_fork_child);
#endif
monitor.Construct(loop);

@@ -106,12 +106,16 @@ struct AlsaOutput {
snd_pcm_uframes_t period_position;
/**
* Set to non-zero when the Raspberry Pi workaround has been
* activated in alsa_recover(); decremented by each write.
* This will avoid activating it again, leading to an endless
* loop. This problem was observed with a "RME Digi9636/52".
* Do we need to call snd_pcm_prepare() before the next write?
* It means that we put the device to SND_PCM_STATE_SETUP by
* calling snd_pcm_drop().
*
* Without this flag, we could easily recover after a failed
* optimistic write (returning -EBADFD), but the Raspberry Pi
* audio driver is infamous for generating ugly artefacts from
* this.
*/
unsigned pi_workaround;
bool must_prepare;
/**
* This buffer gets allocated after opening the ALSA device.
@@ -676,8 +680,6 @@ alsa_open(struct audio_output *ao, AudioFormat &audio_format, Error &error)
{
AlsaOutput *ad = (AlsaOutput *)ao;
ad->pi_workaround = 0;
int err = snd_pcm_open(&ad->pcm, alsa_device(ad),
SND_PCM_STREAM_PLAYBACK, ad->mode);
if (err < 0) {
@@ -699,6 +701,8 @@ alsa_open(struct audio_output *ao, AudioFormat &audio_format, Error &error)
ad->in_frame_size = audio_format.GetFrameSize();
ad->out_frame_size = ad->pcm_export->GetFrameSize(audio_format);
ad->must_prepare = false;
return true;
}
@@ -736,29 +740,6 @@ alsa_recover(AlsaOutput *ad, int err)
case SND_PCM_STATE_XRUN:
ad->period_position = 0;
err = snd_pcm_prepare(ad->pcm);
if (err == 0 && ad->pi_workaround == 0) {
/* this works around a driver bug observed on
the Raspberry Pi: after snd_pcm_drop(), the
whole ring buffer must be invalidated, but
the snd_pcm_prepare() call above makes the
driver play random data that just happens
to be still in the buffer; by adding and
cancelling some silence, this bug does not
occur */
alsa_write_silence(ad, ad->period_frames);
/* cancel the silence data right away to avoid
increasing latency; even though this
function call invalidates the portion of
silence, the driver seems to avoid the
bug */
snd_pcm_reset(ad->pcm);
/* disable the workaround for some time */
ad->pi_workaround = 8;
}
break;
case SND_PCM_STATE_DISCONNECTED:
break;
@@ -801,6 +782,7 @@ alsa_cancel(struct audio_output *ao)
AlsaOutput *ad = (AlsaOutput *)ao;
ad->period_position = 0;
ad->must_prepare = true;
snd_pcm_drop(ad->pcm);
}
@@ -822,6 +804,16 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size,
assert(size % ad->in_frame_size == 0);
if (ad->must_prepare) {
ad->must_prepare = false;
int err = snd_pcm_prepare(ad->pcm);
if (err < 0) {
error.Set(alsa_output_domain, err, snd_strerror(-err));
return 0;
}
}
chunk = ad->pcm_export->Export(chunk, size, size);
assert(size % ad->out_frame_size == 0);
@@ -834,9 +826,6 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size,
ad->period_position = (ad->period_position + ret)
% ad->period_frames;
if (ad->pi_workaround > 0)
--ad->pi_workaround;
size_t bytes_written = ret * ad->out_frame_size;
return ad->pcm_export->CalcSourceSize(bytes_written);
}

@@ -369,8 +369,6 @@ pulse_output_enable(struct audio_output *ao, Error &error)
po->mainloop = pa_threaded_mainloop_new();
if (po->mainloop == nullptr) {
g_free(po);
error.Set(pulse_output_domain,
"pa_threaded_mainloop_new() has failed");
return false;