release v0.18.9
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJTEwdzAAoJECNuiljG20USkFYP/i1PaM7O20e2EPE7ELhffk1I PEL6WiuCxfEHP+JbH/RPy/CdyKIqx3TTeaktXzOJmCcU+5fAgbpIwfK689ZjpE7Y U+7aPfGudfjYTxM/bigEo+1XAIYWJCJ2IlopN0lRIZSquUm8rfxosqsNzJFrhwsK 40Ps36XdpYUA3z9dugyJjeKQETkjJa5Y55C1yml5RRUz+yPqyiPelm0dSlx3Ggce KpmNZfp8g8/stwb08iw+qk+cNKP75eJwPdFmQrsc91QxP1oW7ERWhiICA0ZtqaNe T0Ld5+wZ6uTJSztQiUsWrJYS1yKix5q1Za8tyFr3a9NPI+iIjsALXqU9k7zmZ6Id GK0Xr9Noo1o80QeGkd60nJyCQXbEU/V0p9D/QiDVei+IvK6mbxF3y2gPA7wobgrC KEDgsJZ+0fjmgdx+eb8ydg0uIwHrk04u0YKukUqA3bkNS/PUEICPqblcg8Spf89I RMdjq2HFcpkaIwGvryfHIbTNUbonAziMzmiJ0WQA1FCD3x1WELvBf09GzAsUEoFX Be0Co15rODOByo5ryZvSJv5BCr2RuCPwzNF+V26nMaKK7EloQWmbO0rpkRLVRk81 qo1JmElm6SyeE3kHqVW/NyrPxLtd7VngV+z9hXr95szUjCjMv/MK169r4jumLTex RLyPDkhkQLDIijamhjfZ =nX0n -----END PGP SIGNATURE----- Merge tag 'release-0.18.9'
This commit is contained in:
commit
503ed9c331
7
NEWS
7
NEWS
@ -39,13 +39,18 @@ ver 0.19 (not yet released)
|
|||||||
* install systemd unit for socket activation
|
* install systemd unit for socket activation
|
||||||
* Android port
|
* Android port
|
||||||
|
|
||||||
ver 0.18.9 (not yet released)
|
ver 0.18.9 (2014/03/02)
|
||||||
|
* protocol
|
||||||
|
- "findadd" requires the "add" permission
|
||||||
|
* output
|
||||||
|
- alsa: improved workaround for noise after manual song change
|
||||||
* decoder
|
* decoder
|
||||||
- vorbis: fix linker failure when libvorbis/libogg are static
|
- vorbis: fix linker failure when libvorbis/libogg are static
|
||||||
* encoder
|
* encoder
|
||||||
- vorbis: fix another linker failure
|
- vorbis: fix another linker failure
|
||||||
* output
|
* output
|
||||||
- pipe: fix hanging child process due to blocked signals
|
- 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)
|
ver 0.18.8 (2014/02/07)
|
||||||
* decoder
|
* decoder
|
||||||
|
@ -99,7 +99,7 @@ static const struct command commands[] = {
|
|||||||
{ "enableoutput", PERMISSION_ADMIN, 1, 1, handle_enableoutput },
|
{ "enableoutput", PERMISSION_ADMIN, 1, 1, handle_enableoutput },
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
{ "find", PERMISSION_READ, 2, -1, handle_find },
|
{ "find", PERMISSION_READ, 2, -1, handle_find },
|
||||||
{ "findadd", PERMISSION_READ, 2, -1, handle_findadd},
|
{ "findadd", PERMISSION_ADD, 2, -1, handle_findadd},
|
||||||
#endif
|
#endif
|
||||||
{ "idle", PERMISSION_READ, 0, -1, handle_idle },
|
{ "idle", PERMISSION_READ, 0, -1, handle_idle },
|
||||||
{ "kill", PERMISSION_ADMIN, -1, -1, handle_kill },
|
{ "kill", PERMISSION_ADMIN, -1, -1, handle_kill },
|
||||||
|
@ -105,12 +105,16 @@ struct AlsaOutput {
|
|||||||
snd_pcm_uframes_t period_position;
|
snd_pcm_uframes_t period_position;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to non-zero when the Raspberry Pi workaround has been
|
* Do we need to call snd_pcm_prepare() before the next write?
|
||||||
* activated in alsa_recover(); decremented by each write.
|
* It means that we put the device to SND_PCM_STATE_SETUP by
|
||||||
* This will avoid activating it again, leading to an endless
|
* calling snd_pcm_drop().
|
||||||
* loop. This problem was observed with a "RME Digi9636/52".
|
*
|
||||||
|
* 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.
|
* This buffer gets allocated after opening the ALSA device.
|
||||||
@ -671,8 +675,6 @@ alsa_open(AudioOutput *ao, AudioFormat &audio_format, Error &error)
|
|||||||
{
|
{
|
||||||
AlsaOutput *ad = (AlsaOutput *)ao;
|
AlsaOutput *ad = (AlsaOutput *)ao;
|
||||||
|
|
||||||
ad->pi_workaround = 0;
|
|
||||||
|
|
||||||
int err = snd_pcm_open(&ad->pcm, alsa_device(ad),
|
int err = snd_pcm_open(&ad->pcm, alsa_device(ad),
|
||||||
SND_PCM_STREAM_PLAYBACK, ad->mode);
|
SND_PCM_STREAM_PLAYBACK, ad->mode);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
@ -694,6 +696,8 @@ alsa_open(AudioOutput *ao, AudioFormat &audio_format, Error &error)
|
|||||||
ad->in_frame_size = audio_format.GetFrameSize();
|
ad->in_frame_size = audio_format.GetFrameSize();
|
||||||
ad->out_frame_size = ad->pcm_export->GetFrameSize(audio_format);
|
ad->out_frame_size = ad->pcm_export->GetFrameSize(audio_format);
|
||||||
|
|
||||||
|
ad->must_prepare = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -731,29 +735,6 @@ alsa_recover(AlsaOutput *ad, int err)
|
|||||||
case SND_PCM_STATE_XRUN:
|
case SND_PCM_STATE_XRUN:
|
||||||
ad->period_position = 0;
|
ad->period_position = 0;
|
||||||
err = snd_pcm_prepare(ad->pcm);
|
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;
|
break;
|
||||||
case SND_PCM_STATE_DISCONNECTED:
|
case SND_PCM_STATE_DISCONNECTED:
|
||||||
break;
|
break;
|
||||||
@ -796,6 +777,7 @@ alsa_cancel(AudioOutput *ao)
|
|||||||
AlsaOutput *ad = (AlsaOutput *)ao;
|
AlsaOutput *ad = (AlsaOutput *)ao;
|
||||||
|
|
||||||
ad->period_position = 0;
|
ad->period_position = 0;
|
||||||
|
ad->must_prepare = true;
|
||||||
|
|
||||||
snd_pcm_drop(ad->pcm);
|
snd_pcm_drop(ad->pcm);
|
||||||
}
|
}
|
||||||
@ -817,6 +799,16 @@ alsa_play(AudioOutput *ao, const void *chunk, size_t size,
|
|||||||
|
|
||||||
assert(size % ad->in_frame_size == 0);
|
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);
|
chunk = ad->pcm_export->Export(chunk, size, size);
|
||||||
|
|
||||||
assert(size % ad->out_frame_size == 0);
|
assert(size % ad->out_frame_size == 0);
|
||||||
@ -829,9 +821,6 @@ alsa_play(AudioOutput *ao, const void *chunk, size_t size,
|
|||||||
ad->period_position = (ad->period_position + ret)
|
ad->period_position = (ad->period_position + ret)
|
||||||
% ad->period_frames;
|
% ad->period_frames;
|
||||||
|
|
||||||
if (ad->pi_workaround > 0)
|
|
||||||
--ad->pi_workaround;
|
|
||||||
|
|
||||||
size_t bytes_written = ret * ad->out_frame_size;
|
size_t bytes_written = ret * ad->out_frame_size;
|
||||||
return ad->pcm_export->CalcSourceSize(bytes_written);
|
return ad->pcm_export->CalcSourceSize(bytes_written);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user