sound.pulse.open

sound.pulse

open(opts) -> dev, err

Open a playback stream on the sound server

sound.open calls this for server = "pulse". The handshake blocks, up to five seconds a step, since a device opens before lev.run.

opts fielddefaultdescription
socketfrom server()the server's socket path
name"lilgame"the client and stream name a mixer shows
rate48000sample rate, Hz; the server converts
channels21 or 2
period1024frames per period: what wait waits for
periods4periods in the ring the server keeps
connectpulse_core.connectthe suite's seam: takes the connect table

The ring is the whole latency: the server splits it between its sink and the stream's queue. prebuf is the server's default, about the ring, so playback starts once the ring is nearly full, as on a card. A server that grants a ring under a period is refused, with the error naming both: write could send no more than the ring, and sound.run would count each cut period as played.

The device answers the PCM device's methods with these differences:

methoddescription
dev:fd()the socket; wait is what to wait on
dev:format()always "f32"; nothing is clamped
dev:avail()frames the server asked for and has not had
dev:write(buf)sends up to avail() frames; nil and "EAGAIN" at none; nil and "EPIPE" after the server's underflow, until recover
dev:recover()clears the underflow; the server buffers again by itself
dev:start()playback starts before the ring fills
dev:drop()the server drops what it holds
dev:close()ends the stream and the connection
dev:wait(t)yields to LEV until a period is asked for, an underflow waits, or the stream fails: true, or nil and "timeout" after t seconds, or nil and the error
dev:info()the protocol versions, the sink, the granted ring in bytes, sink_latency in seconds, and the counts of underflows, overflows, starts and refused commands

A lost server answers nil and "connection lost", never "EPIPE", so sound.run ends rather than recover forever.