Streams ALAC-over-RTP audio to an AirPlay/RAOP receiver after the RTSP handshake. Owns three UDP sockets:
- audio — sends RTP audio (PT 0x60) to
device:server_port - control — bound on our
control_port(6001), sends periodicsync(0xd4) - timing — bound on our
timing_port(6002), answers the device's timing requests (0xd2 → 0xd3)
Packet formats follow the RAOP wire format (see AirPlay.Rtp). Audio is paced
against wall-clock: each tick sends however
many 352-sample frames are now due, after an initial ~2 s pre-buffer so the
receiver (which delays by the 88200-sample latency) can start cleanly.
Summary
Functions
Start streaming frames (list of 352-sample s16le stereo chunks) over the
already-open sockets. opts: :server_port (required), :control_port
(device's control port), :start_seq, :start_ts.
Returns a specification to start this module under a supervisor.
Open the UDP sockets and start answering the receiver's timing requests, WITHOUT
streaming yet. opts: :local_control_port (6001), :local_timing_port (6002).
Functions
Start streaming frames (list of 352-sample s16le stereo chunks) over the
already-open sockets. opts: :server_port (required), :control_port
(device's control port), :start_seq, :start_ts.
Returns a specification to start this module under a supervisor.
See Supervisor.
Open the UDP sockets and start answering the receiver's timing requests, WITHOUT
streaming yet. opts: :local_control_port (6001), :local_timing_port (6002).
This must run before the RTSP SETUP: AirPlay receivers (HomePods especially)
probe our timing port with an NTP 0xd2 request during SETUP and return
"520 Origin Error" if it's unreachable or unanswered. Binding + answering here
is what lets SETUP succeed. Call begin/3 once the handshake yields the ports.