You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Spotify Connect plugin can only pass Ogg Vorbis to the renderer. Spotify items that exist only as MP3 cannot play in Kalinka, and Spotify skips them as unavailable. Passing MP3 through needs the renderer's MP3 decoder to play live, paced HTTP sources, as the Vorbis decoder has since #225. Today it cannot.
Background
The plugin runs librespot with --passthrough: Spotify's compressed audio is served to the renderer unchanged, and the renderer decodes it. librespot's passthrough only supports Ogg Vorbis.
At 320 kbps, librespot prefers OGG_VORBIS_320, then MP3_320, MP3_256, then OGG_VORBIS_160. A passthrough load of an MP3 file fails outright, so the plugin now limits librespot to Vorbis files. A track without Vorbis files is skipped.
How often Spotify serves MP3-only items is unknown. librespot notes that most podcasts are 96 kbps Vorbis. Worth measuring before building this.
Reads wait for the full requested size.readCallback calls waitForData(token, size), and Buffer::waitForData waits for min(size, capacity) bytes. minimp3 requests up to 128 KiB (MINIMP3_IO_SIZE): about 3.3 s at 320 kbps, more than the default read-ahead. The producer only releases more after playback advances, so this can block. The live Vorbis path waits for one byte and returns a short read.
Length comes from the total sample count.mp3.samples feeds the start-offset check and streamSize. Neither is known for a live source.
MIME and format mapping already work: audio/mpeg and mp3 select FormatMpeg in NativePlayer.cpp. No server or SDK change is expected.
Proposed change
For live sources (X-Kalinka-Live: 1, unknown length), keeping the finite-file path unchanged:
Decode without scanning or seeking back. MP3D_DO_NOT_SCAN alone is not enough, because open still seeks to 0 and back to the first frame. Frame-by-frame mp3dec_decode_frame over a sliding input buffer avoids seeks entirely.
Return short reads: wait for at least one byte and read what is available.
Report an unknown stream size, and take position from decoded frames. Live sources start at timeline_offset_ms, not startOffsetMs.
Acceptance
A paced, lengthless audio/mpeg live response starts after its first frames, without reading ahead of the producer.
Pause and resume work without being treated as EOF, and snapshots report advancing position, as for live Vorbis.
Finite MP3 files (local files, Jamendo) keep their duration and seeking.
Summary
The Spotify Connect plugin can only pass Ogg Vorbis to the renderer. Spotify items that exist only as MP3 cannot play in Kalinka, and Spotify skips them as unavailable. Passing MP3 through needs the renderer's MP3 decoder to play live, paced HTTP sources, as the Vorbis decoder has since #225. Today it cannot.
Background
--passthrough: Spotify's compressed audio is served to the renderer unchanged, and the renderer decodes it. librespot's passthrough only supports Ogg Vorbis.OGG_VORBIS_320, thenMP3_320,MP3_256, thenOGG_VORBIS_160. A passthrough load of an MP3 file fails outright, so the plugin now limits librespot to Vorbis files. A track without Vorbis files is skipped.What blocks it in the renderer
Mp3StreamDecoderassumes a finite, seekable file:mp3dec_ex_open_cb(..., MP3D_SEEK_TO_SAMPLE)seeks to 0, then scans to EOF to build a seek index unless a Xing/Info tag is found, then seeks back to the first frame. A live source is produced only ~2–3 s ahead of the playback the renderer reports, so open never returns and playback never starts. Unfinished live responses can't seek backwards either.readCallbackcallswaitForData(token, size), andBuffer::waitForDatawaits formin(size, capacity)bytes. minimp3 requests up to 128 KiB (MINIMP3_IO_SIZE): about 3.3 s at 320 kbps, more than the default read-ahead. The producer only releases more after playback advances, so this can block. The live Vorbis path waits for one byte and returns a short read.mp3.samplesfeeds the start-offset check andstreamSize. Neither is known for a live source.MIME and format mapping already work:
audio/mpegandmp3selectFormatMpeginNativePlayer.cpp. No server or SDK change is expected.Proposed change
For live sources (
X-Kalinka-Live: 1, unknown length), keeping the finite-file path unchanged:MP3D_DO_NOT_SCANalone is not enough, because open still seeks to 0 and back to the first frame. Frame-by-framemp3dec_decode_frameover a sliding input buffer avoids seeks entirely.timeline_offset_ms, notstartOffsetMs.Acceptance
audio/mpeglive response starts after its first frames, without reading ahead of the producer.Follow-up in kalinka-plugin-spotify
Not part of this issue, but needed before Spotify can use it:
PassthroughDecoderrejects non-Ogg formats), and removal of the Vorbis-only file filter.audio/mpegwithTrackSource(format="mp3").Related: #208