Skip to main content

playback_run

Function playback_run 

Source
pub(crate) fn playback_run(
    inner: &Inner,
    settings: &PbSettings,
    queue: &PlayQueue,
)
Expand description

Drive one whole mic-playback run on the playback thread. The body handed to spawn_worker; the mirror of capture_run for the uplink.

This thread solely owns the PA playback stream, so writes are serialized structurally with no executor. It mirrors capture_run’s lifecycle: start_state goes RUNNING once the first session is up, FAILED (with a last_error) when the run gives up, and IDLE on a clean stop; it returns when stop_state leaves STOP_NONE or the retry budget is spent.

Session loop: the sink can die under a live stream (PulseAudio/PipeWire restart, sink removed). Breaking out there would leave the mic uplink dead until something upstream noticed and restarted the whole playback, losing every packet in between, so the session is reopened with the same backoff and budgets capture uses.

Buffer sizing and the prebuf timing rule (load-bearing): tlength is the target latency in bytes, and prebuf is a quarter of it, floored to one frame. prebuf must NOT be zero: with prebuf == 0 PulseAudio starts playback instantly, the realtime read pointer then runs ahead of the write index, and every SeekMode::Relative write lands “in the past” — the server silently discards it forever (observed as bytes flowing at exactly realtime rate while the sink monitor stayed silent). A quarter-buffer prebuf makes the stream wait for data before starting and re-prebuffer after each underrun, so a late chunk plays slightly delayed instead of vanishing.

Hot loop: pumps on the ~20 ms bound, then, whenever the server is writable, drains that many bytes from the PlayQueue (clamped and frame-aligned) and writes them with free_cb = None, so PA copies the bytes and the scratch buffer is reused next iteration. Newly queued bytes are picked up on the next pump — no cross-thread wakeup is needed, mirroring capture’s poll style — and a stop is observed within the pump bound.