Dynamic channel name updates and playlist crossfade transition
- Fix channel name not updating in frame player when playlist changes - Use localStorage polling (2s interval) for cross-frame communication - Fix API response access: use bracket notation for 'channel-name' property - Add skip command after playlist load to trigger crossfade to new playlist - Add #PHASE metadata to Asteroid-Low-Orbit.m3u playlist
This commit is contained in:
parent
18c251c8c4
commit
987d01beaa
|
|
@ -429,10 +429,17 @@
|
|||
;; Copy playlist to stream-queue.m3u
|
||||
(copy-playlist-to-stream-queue playlist-path)
|
||||
;; Load into in-memory queue
|
||||
(let ((count (load-queue-from-m3u-file)))
|
||||
(let ((count (load-queue-from-m3u-file))
|
||||
(channel-name (get-curated-channel-name)))
|
||||
;; Skip current track to trigger crossfade to new playlist
|
||||
(handler-case
|
||||
(liquidsoap-command "stream-queue_m3u.skip")
|
||||
(error (e)
|
||||
(format *error-output* "Warning: Could not skip track: ~a~%" e)))
|
||||
(api-output `(("status" . "success")
|
||||
("message" . ,(format nil "Loaded playlist: ~a" name))
|
||||
("count" . ,count)
|
||||
("channel-name" . ,channel-name)
|
||||
("paths" . ,(read-m3u-file-paths stream-queue-path))))))
|
||||
(api-output `(("status" . "error")
|
||||
("message" . "Playlist file not found"))
|
||||
|
|
|
|||
|
|
@ -653,7 +653,12 @@
|
|||
(if (= (ps:@ data status) "success")
|
||||
(progn
|
||||
(show-toast (+ "✓ Loaded " (ps:@ data count) " tracks from " name))
|
||||
(load-current-queue))
|
||||
(load-current-queue)
|
||||
;; Update channel name in all channel selectors
|
||||
;; Use bracket notation because API returns "channel-name" with hyphen
|
||||
(let ((channel-name (aref data "channel-name")))
|
||||
(when channel-name
|
||||
(update-channel-selector-name channel-name))))
|
||||
(alert (+ "Error loading playlist: " (or (ps:@ data message) "Unknown error")))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error loading playlist:" error))
|
||||
|
|
@ -705,6 +710,29 @@
|
|||
(setf html (+ html "</div>"))
|
||||
(setf (ps:@ container inner-h-t-m-l) html))))))
|
||||
|
||||
;; Update channel selector name in UI after loading a new playlist
|
||||
(defun update-channel-selector-name (channel-name)
|
||||
"Update the curated channel option text in all channel selectors"
|
||||
(ps:chain console (log "Updating channel name to:" channel-name))
|
||||
|
||||
;; Store in localStorage so popout player can pick it up
|
||||
(ps:chain local-storage (set-item "curated-channel-name" channel-name))
|
||||
|
||||
;; Update in current document
|
||||
(let ((channel-selector (ps:chain document (get-element-by-id "stream-channel"))))
|
||||
(when channel-selector
|
||||
(let ((curated-option (ps:chain channel-selector (query-selector "option[value='curated']"))))
|
||||
(when curated-option
|
||||
(setf (ps:@ curated-option text-content) (+ "🎧 " channel-name))))))
|
||||
|
||||
;; Use postMessage to notify all frames about the channel name change
|
||||
(when (and (ps:@ window top)
|
||||
(not (= (ps:@ window top) window)))
|
||||
;; Post to top window which will relay to all frames
|
||||
(ps:chain window top (post-message
|
||||
(ps:create :type "channel-name-update" :channel-name channel-name)
|
||||
"*"))))
|
||||
|
||||
;; Save current queue to stream-queue.m3u
|
||||
(defun save-stream-queue ()
|
||||
(ps:chain
|
||||
|
|
|
|||
|
|
@ -556,6 +556,24 @@
|
|||
;; Update quality selector state based on channel
|
||||
(update-quality-selector-state)
|
||||
|
||||
;; Check for channel name changes from localStorage periodically
|
||||
(let ((last-channel-name (ps:chain local-storage (get-item "curated-channel-name"))))
|
||||
(ps:chain console (log "Frame player: initial channel name from localStorage:" last-channel-name))
|
||||
(set-interval
|
||||
(lambda ()
|
||||
(let ((current-channel-name (ps:chain local-storage (get-item "curated-channel-name"))))
|
||||
(when (and current-channel-name
|
||||
(not (= current-channel-name last-channel-name)))
|
||||
(ps:chain console (log "Frame player: channel name changed from" last-channel-name "to" current-channel-name))
|
||||
(setf last-channel-name current-channel-name)
|
||||
(let ((channel-selector (ps:chain document (get-element-by-id "stream-channel"))))
|
||||
(when channel-selector
|
||||
(let ((curated-option (ps:chain channel-selector (query-selector "option[value='curated']"))))
|
||||
(when curated-option
|
||||
(ps:chain console (log "Frame player: updating curated option text"))
|
||||
(setf (ps:@ curated-option text-content) (+ "🎧 " current-channel-name)))))))))
|
||||
2000))
|
||||
|
||||
;; Start now playing updates
|
||||
(set-timeout update-mini-now-playing 1000)
|
||||
(set-interval update-mini-now-playing 5000))))
|
||||
|
|
@ -582,6 +600,16 @@
|
|||
;; Update quality selector state based on channel
|
||||
(update-quality-selector-state)
|
||||
|
||||
;; Listen for channel name changes from localStorage
|
||||
(ps:chain window (add-event-listener "storage"
|
||||
(lambda (e)
|
||||
(when (= (ps:@ e key) "curated-channel-name")
|
||||
(let ((channel-selector (ps:chain document (get-element-by-id "popout-stream-channel"))))
|
||||
(when channel-selector
|
||||
(let ((curated-option (ps:chain channel-selector (query-selector "option[value='curated']"))))
|
||||
(when curated-option
|
||||
(setf (ps:@ curated-option text-content) (+ "🎧 " (ps:@ e new-value)))))))))))
|
||||
|
||||
;; Start now playing updates
|
||||
(update-popout-now-playing)
|
||||
(set-interval update-popout-now-playing 5000)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#EXTM3U
|
||||
#PLAYLIST:Asteroid Low Orbit - Ambient Electronic Journey
|
||||
#PLAYLIST:Low Orbit
|
||||
#PHASE:Low Orbit
|
||||
#DURATION:12 hours (approx)
|
||||
#CURATOR:Asteroid Radio
|
||||
#DESCRIPTION:A 12-hour voyage through ambient, IDM, and space music
|
||||
|
||||
#EXTINF:-1,Brian Eno - Emerald And Lime
|
||||
/app/music/Brian Eno/2011 - Small Craft On a Milk Sea/A1 Emerald And Lime.flac
|
||||
|
|
|
|||
Loading…
Reference in New Issue