[client] audio/pw: drop restarting state

Automatically restarting playback once draining has completed could result
in playback starting too early (i.e., before there is enough data in the
ring buffer to avoid underrunning). `audio_playbackData` will keep invoking
`start` until it returns true anyway, so we can just allow draining to
complete normally and wait for `start` to be called again.
This commit is contained in:
Chris Spencer 2022-01-24 21:04:17 +00:00 committed by Geoffrey McRae
parent 8580978321
commit 68b42e1c1a

View File

@ -33,8 +33,7 @@ typedef enum
{ {
STREAM_STATE_INACTIVE, STREAM_STATE_INACTIVE,
STREAM_STATE_ACTIVE, STREAM_STATE_ACTIVE,
STREAM_STATE_DRAINING, STREAM_STATE_DRAINING
STREAM_STATE_RESTARTING
} }
StreamState; StreamState;
@ -123,20 +122,8 @@ static void pipewire_onPlaybackProcess(void * userdata)
static void pipewire_onPlaybackDrained(void * userdata) static void pipewire_onPlaybackDrained(void * userdata)
{ {
pw_thread_loop_lock(pw.thread); pw_thread_loop_lock(pw.thread);
pw_stream_set_active(pw.playback.stream, false);
if (pw.playback.state == STREAM_STATE_RESTARTING) pw.playback.state = STREAM_STATE_INACTIVE;
{
// A play command was received while we were in the middle of stopping;
// switch straight back into playing
pw_stream_set_active(pw.playback.stream, true);
pw.playback.state = STREAM_STATE_ACTIVE;
}
else
{
pw_stream_set_active(pw.playback.stream, false);
pw.playback.state = STREAM_STATE_INACTIVE;
}
pw_thread_loop_unlock(pw.thread); pw_thread_loop_unlock(pw.thread);
} }
@ -274,8 +261,7 @@ static bool pipewire_playbackStart(int framesBuffered)
bool start = false; bool start = false;
if (pw.playback.state != STREAM_STATE_ACTIVE && if (pw.playback.state != STREAM_STATE_ACTIVE)
pw.playback.state != STREAM_STATE_RESTARTING)
{ {
pw_thread_loop_lock(pw.thread); pw_thread_loop_lock(pw.thread);
@ -291,9 +277,8 @@ static bool pipewire_playbackStart(int framesBuffered)
break; break;
case STREAM_STATE_DRAINING: case STREAM_STATE_DRAINING:
// We are in the middle of draining the PipeWire buffers; we will need // We are in the middle of draining the PipeWire buffers; we need to
// to reactivate the stream once this has completed // wait for this to complete before allowing the new playback to start
pw.playback.state = STREAM_STATE_RESTARTING;
break; break;
default: default:
@ -308,30 +293,12 @@ static bool pipewire_playbackStart(int framesBuffered)
static void pipewire_playbackStop(void) static void pipewire_playbackStop(void)
{ {
if (pw.playback.state != STREAM_STATE_ACTIVE && if (pw.playback.state != STREAM_STATE_ACTIVE)
pw.playback.state != STREAM_STATE_RESTARTING)
return; return;
pw_thread_loop_lock(pw.thread); pw_thread_loop_lock(pw.thread);
pw_stream_flush(pw.playback.stream, true);
switch (pw.playback.state) pw.playback.state = STREAM_STATE_DRAINING;
{
case STREAM_STATE_ACTIVE:
pw_stream_flush(pw.playback.stream, true);
pw.playback.state = STREAM_STATE_DRAINING;
break;
case STREAM_STATE_RESTARTING:
// A stop was requested, and then a start while PipeWire was draining, and
// now another stop. PipeWire hasn't finished draining yet so just switch
// the state back
pw.playback.state = STREAM_STATE_DRAINING;
break;
default:
DEBUG_UNREACHABLE();
}
pw_thread_loop_unlock(pw.thread); pw_thread_loop_unlock(pw.thread);
} }