Commit Graph

8 Commits

Author SHA1 Message Date
Glenn Thompson bcfda2ebb6 int16 pack encoding + fix playlist resume across schedule changes
- Replace default float packer with int16 packer (mixed:make-packer :encoding :int16)
  cl-mixed now handles float→s16 conversion in optimized C code instead of
  per-sample Lisp loop. Halves pack buffer memory (2 vs 4 bytes/sample).
- Remove float-to-s16 helper (no longer needed)
- Fix resume-from-saved-state: when saved playlist differs from currently
  scheduled playlist, use the scheduled one from the beginning instead of
  continuing the old playlist. Prevents stale playlist playing after restart.
2026-03-06 18:56:10 +03:00
Glenn Thompson f39abeb8f8 Fix playlist resume and SIMPLE-ARRAY pathname errors
- Add *resumed-from-saved-state* flag to prevent scheduler's db:connected
  trigger from overwriting resumed playlist position with full playlist
- Use sb-ext:parse-native-namestring in play-file to prevent SBCL from
  interpreting brackets in directory names (e.g. [WEB FLAC]) as wildcard
  patterns, which caused non-simple-string pathname components that broke
  cl-flac's CFFI calls
2026-03-05 18:21:32 +03:00
Glenn Thompson 1807e58971 Remove Icecast/Liquidsoap, migrate fully to Harmony/CL-Streamer
- Delete all Icecast/Liquidsoap config files, Dockerfiles, and .liq scripts
- Remove icecast/liquidsoap services from docker-compose.yml (keep postgres)
- Remove liquidsoap-command, parse-liquidsoap-metadata, format-remaining-time
- Remove liquidsoap-command-succeeded-p, liquidsoap-reload-and-skip
- Remove icecast-now-playing, check-icecast-status, check-liquidsoap-status
- Remove icecast XML polling from listener-stats.lisp
- Replace asteroid/liquidsoap/* APIs with asteroid/stream/* APIs
- Simplify all if-harmony-else-liquidsoap branches to Harmony-only
- Update admin template: single Stream Status card, pipeline controls
- Update about.ctml credits: Harmony + CL-Mixed replace Icecast + Liquidsoap
- Update status.ctml server name to CL-Streamer / Harmony
- Update parenscript/admin.lisp: stream-* functions, new API endpoints
- Export pipeline-running-p from cl-streamer/harmony package
2026-03-05 17:24:12 +03:00
Glenn Thompson 9ae7546466 Fix playlist stalls, FLAC/taglib errors, and playback state resume
- Prevent play-list thread death on scheduler playlist change:
  drain-queue-into-remaining drains full scheduler queue at once,
  updates loop-queue reference so repeat replays correct playlist,
  top-level handler-case prevents thread from dying silently

- Fix taglib SIMPLE-ARRAY CHARACTER type errors:
  ensure-simple-string coerces metadata strings and trims whitespace

- Fix FLAC::FILE slot unbound errors:
  retry once with 200ms delay for transient init failures

- Improve playback state persistence:
  save playlist path alongside track file so restart loads the
  correct playlist instead of always falling back to stream-queue.m3u

- Startup now uses resume-from-saved-state to resolve saved playlist
  and track position, falls back to stream-queue.m3u only if no state
2026-03-05 13:25:15 +03:00
Glenn Thompson d66d4fe46c Crossfade timing, scheduler fix, playback resume, auth noise cleanup
- Delay metadata/track-change notification by 1s after crossfade completes
- Log 'Loading next:' instead of 'Now playing:' during crossfade prep
- Add diagnostic logging: track duration check, crossfade trigger time
- harmony-load-playlist defaults to skip=nil: scheduler queues tracks
  without interrupting current playback
- Save current track to .playback-state.lisp on each track change,
  resume from saved position on restart
- Replace ~50 format-t debug statements in auth with log:info/log:warn
- Remove password hash logging for security
- Add .playback-state.lisp to .gitignore
2026-03-04 00:23:25 +03:00
Glenn Thompson 6e23efe1e4 Fix listener count and recently-played rendering
- Use total listener count across all mounts instead of per-mount
  (asteroid.lisp icecast-status API, stream-harmony.lisp now-playing)
- Fix recently-played.lisp: equal -> = for ParenScript string comparison
- Remove non-existent asteroid-shuffle.mp3 mount from recently-played JS
- Map all mount references to existing asteroid.mp3/asteroid.aac
2026-03-03 23:25:23 +03:00
Glenn Thompson 77458467c4 Fix integration: CORS, auto-start, mount names, Icecast bypass
CORS fix (icy-protocol.lisp):
- Add Access-Control-Allow-Origin: * to stream response headers
- Browser audio player can now connect cross-origin (port 8080 -> 8000)

Auto-start (asteroid.lisp -main):
- Start cl-streamer pipeline automatically on boot
- Load stream-queue.m3u and begin playback immediately
- Wrapped in handler-case so streaming failure doesn't block web server

Mount names (stream-harmony.lisp):
- Renamed /stream.mp3 -> /asteroid.mp3, /stream.aac -> /asteroid.aac
- Matches existing frontend URLs, zero template changes needed

Icecast bypass (asteroid.lisp, listener-stats.lisp):
- Front page uses get-now-playing-stats instead of icecast-now-playing
- check-icecast-status returns cl-streamer status when pipeline is active
- check-liquidsoap-status returns N/A when using cl-streamer
- asteroid/icecast-status API returns cl-streamer data directly
- poll-and-store-stats uses cl-streamer listener counts directly
- Eliminates hanging HTTP requests to port 8000 for Icecast XML

Tested: full browser streaming working end-to-end
2026-03-03 22:29:21 +03:00
Glenn Thompson dad1418bf8 Integrate cl-streamer into Asteroid Radio (replaces Icecast + Liquidsoap)
New files:
- stream-harmony.lisp: Bridge between cl-streamer pipeline and Asteroid app
  - start-harmony-streaming / stop-harmony-streaming lifecycle
  - on-harmony-track-change callback: feeds recently-played, DB track lookup
  - harmony-now-playing: returns same alist format as icecast-now-playing
  - harmony-load-playlist: loads M3U, converts Docker paths, feeds queue
  - harmony-skip-track / harmony-get-status

Pipeline control (harmony-backend.lisp):
- Add pipeline-current-track, pipeline-on-track-change callback
- Add pipeline-skip, pipeline-queue-files, pipeline-get-queue, pipeline-clear-queue
- play-list now supports skip flag, queue consumption, loop-queue mode
- notify-track-change fires callback after crossfade completes

Graceful fallback - all touch points check *harmony-pipeline*:
- frontend-partials.lisp: now-playing endpoints try Harmony first, fall back to Icecast
- asteroid.lisp: admin APIs (status/skip/reload/restart) try Harmony first
- playlist-scheduler.lisp: load-scheduled-playlist tries Harmony first
- asteroid.asd: added cl-streamer subsystem dependencies

Docker scripts updated:
- start.sh / stop.sh: only start/stop postgres (cl-streamer replaces streaming)
2026-03-03 21:27:29 +03:00