asteroid/cl-streamer
Glenn Thompson a9e8276e9a feat: End-to-end streaming working! Custom streaming-drain + fixes
Major changes:
- streaming-drain: Custom drain that captures PCM from Harmony's pack
  buffer (raw IEEE 754 floats in unsigned-byte-8 array), converts to
  signed-16 PCM via CFFI, encodes to MP3 via LAME, and writes to
  stream server's ring buffer
- Fixed ring buffer deadlock: buffer-read/buffer-write held lock then
  called buffer-available which tried to acquire same lock. Created
  internal %buffer-available/%buffer-free-space without locking.
- Fixed ring buffer zero-length guard for unbound variable in finally
- Fixed sleep duration in drain: was dividing raw byte count by
  samplerate, now correctly converts to frames first
- Added flexi-streams wrapper for bivalent HTTP socket I/O
- Exported all public API symbols from cl-streamer package
- Added test-stream.lisp end-to-end test script

Verified: Amon Tobin FLAC -> 128kbps MP3 stream at localhost:8000
  file reports: MPEG ADTS, layer III, v1, 128kbps, 44.1kHz, JntStereo
2026-03-03 17:46:55 +03:00
..
README.org feat: Add Harmony backend with dummy drain for streaming pipeline 2026-03-03 16:56:24 +03:00
aac-encoder.lisp feat: Add MP3 and AAC encoder FFI bindings 2026-03-03 16:46:29 +03:00
buffer.lisp feat: End-to-end streaming working! Custom streaming-drain + fixes 2026-03-03 17:46:55 +03:00
cl-streamer.asd feat: Add MP3 and AAC encoder FFI bindings 2026-03-03 16:46:29 +03:00
cl-streamer.lisp feat: Initial cl-streamer skeleton for CL-native streaming 2026-03-03 16:30:49 +03:00
conditions.lisp feat: Initial cl-streamer skeleton for CL-native streaming 2026-03-03 16:30:49 +03:00
encoder.lisp feat: Add MP3 and AAC encoder FFI bindings 2026-03-03 16:46:29 +03:00
fdkaac-ffi.lisp feat: Add MP3 and AAC encoder FFI bindings 2026-03-03 16:46:29 +03:00
harmony-backend.lisp feat: End-to-end streaming working! Custom streaming-drain + fixes 2026-03-03 17:46:55 +03:00
icy-protocol.lisp feat: Add MP3 and AAC encoder FFI bindings 2026-03-03 16:46:29 +03:00
lame-ffi.lisp feat: Add MP3 and AAC encoder FFI bindings 2026-03-03 16:46:29 +03:00
package.lisp feat: End-to-end streaming working! Custom streaming-drain + fixes 2026-03-03 17:46:55 +03:00
stream-server.lisp feat: End-to-end streaming working! Custom streaming-drain + fixes 2026-03-03 17:46:55 +03:00
test-stream.lisp feat: End-to-end streaming working! Custom streaming-drain + fixes 2026-03-03 17:46:55 +03:00

README.org

CL-Streamer

Overview

CL-Streamer is a Common Lisp audio streaming server designed to replace Icecast and Liquidsoap in the Asteroid Radio project.

Status

EXPERIMENTAL - This is an early proof-of-concept.

Features

  • HTTP streaming with ICY metadata protocol
  • Multiple mount points
  • Thread-safe ring buffers for audio data
  • Listener statistics

Dependencies

  • alexandria
  • bordeaux-threads
  • usocket
  • flexi-streams
  • chunga
  • log4cl
  • split-sequence

Optional (for audio backend):

  • harmony
  • cl-mixed
  • cl-mixed-mpg123

Quick Start

(ql:quickload :cl-streamer)

;; Create and start server
(cl-streamer:start :port 8000)

;; Add a mount point
(cl-streamer:add-mount cl-streamer:*server* "/stream.mp3"
                       :content-type "audio/mpeg"
                       :bitrate 128
                       :name "Asteroid Radio")

;; Update now-playing metadata
(cl-streamer:set-now-playing "/stream.mp3" "Artist - Track Title")

;; Write audio data (from encoder)
(cl-streamer:write-audio-data "/stream.mp3" encoded-mp3-bytes)

;; Check listeners
(cl-streamer:get-listener-count)

;; Stop server
(cl-streamer:stop)

Architecture

See docs/CL-STREAMING-ARCHITECTURE.org for the full design document.

License

AGPL-3.0