[client] audio/pa: wait until stream is ready before starting playback

Uncorking the stream does not work if the stream is not ready yet.
This commit is contained in:
Chris Spencer 2022-02-20 18:50:30 +00:00 committed by Geoffrey McRae
parent 84b5478b02
commit a13c90bd27

View File

@ -37,6 +37,7 @@ struct PulseAudio
int sinkIndex; int sinkIndex;
bool sinkCorked; bool sinkCorked;
bool sinkMuted; bool sinkMuted;
bool sinkStarting;
int sinkMaxPeriodFrames; int sinkMaxPeriodFrames;
int sinkSampleRate; int sinkSampleRate;
int sinkChannels; int sinkChannels;
@ -218,6 +219,16 @@ static void pulseaudio_free(void)
pa_threaded_mainloop_unlock(pa.loop); pa_threaded_mainloop_unlock(pa.loop);
} }
static void pulseaudio_state_cb(pa_stream * p, void * userdata)
{
if (pa.sinkStarting && pa_stream_get_state(pa.sink) == PA_STREAM_READY)
{
pa_stream_cork(pa.sink, 0, NULL, NULL);
pa.sinkCorked = false;
pa.sinkStarting = false;
}
}
static void pulseaudio_write_cb(pa_stream * p, size_t nbytes, void * userdata) static void pulseaudio_write_cb(pa_stream * p, size_t nbytes, void * userdata)
{ {
// PulseAudio tries to pull data from the stream as soon as it is created for // PulseAudio tries to pull data from the stream as soon as it is created for
@ -279,6 +290,7 @@ static void pulseaudio_setup(int channels, int sampleRate,
pa.sinkSampleRate = sampleRate; pa.sinkSampleRate = sampleRate;
pa.sink = pa_stream_new(pa.context, "Looking Glass", &spec, NULL); pa.sink = pa_stream_new(pa.context, "Looking Glass", &spec, NULL);
pa_stream_set_state_callback (pa.sink, pulseaudio_state_cb , NULL);
pa_stream_set_write_callback (pa.sink, pulseaudio_write_cb , NULL); pa_stream_set_write_callback (pa.sink, pulseaudio_write_cb , NULL);
pa_stream_set_underflow_callback(pa.sink, pulseaudio_underflow_cb, NULL); pa_stream_set_underflow_callback(pa.sink, pulseaudio_underflow_cb, NULL);
pa_stream_set_overflow_callback (pa.sink, pulseaudio_overflow_cb , NULL); pa_stream_set_overflow_callback (pa.sink, pulseaudio_overflow_cb , NULL);
@ -291,6 +303,7 @@ static void pulseaudio_setup(int channels, int sampleRate,
pa.sinkPullFn = pullFn; pa.sinkPullFn = pullFn;
pa.sinkMaxPeriodFrames = attribs.tlength / pa.sinkStride; pa.sinkMaxPeriodFrames = attribs.tlength / pa.sinkStride;
pa.sinkCorked = true; pa.sinkCorked = true;
pa.sinkStarting = false;
*maxPeriodFrames = pa.sinkMaxPeriodFrames; *maxPeriodFrames = pa.sinkMaxPeriodFrames;
@ -303,8 +316,16 @@ static void pulseaudio_start(void)
return; return;
pa_threaded_mainloop_lock(pa.loop); pa_threaded_mainloop_lock(pa.loop);
pa_stream_cork(pa.sink, 0, NULL, NULL);
pa.sinkCorked = false; pa_stream_state_t state = pa_stream_get_state(pa.sink);
if (state == PA_STREAM_CREATING)
pa.sinkStarting = true;
else
{
pa_stream_cork(pa.sink, 0, NULL, NULL);
pa.sinkCorked = false;
}
pa_threaded_mainloop_unlock(pa.loop); pa_threaded_mainloop_unlock(pa.loop);
} }
@ -318,7 +339,8 @@ static void pulseaudio_stop(void)
pa_threaded_mainloop_lock(pa.loop); pa_threaded_mainloop_lock(pa.loop);
pa_stream_cork(pa.sink, 1, NULL, NULL); pa_stream_cork(pa.sink, 1, NULL, NULL);
pa.sinkCorked = true; pa.sinkCorked = true;
pa.sinkStarting = false;
if (needLock) if (needLock)
pa_threaded_mainloop_unlock(pa.loop); pa_threaded_mainloop_unlock(pa.loop);