Apply easilok's ParenScript fixes and fix playlist creation
ParenScript player.lisp fixes (from easilok): - Replace == with = for JavaScript equality - Replace inner-html with inner-h-t-m-l - Replace parseInt with parse-int - Replace let with let* where needed for sequential bindings - Replace new "FormData" with new -Form-data - Fix audio event listener chaining - Replace Promise chains with setTimeout callbacks playlist-management.lisp: - Remove track-ids field (column doesn't exist, using junction table)
This commit is contained in:
parent
a8b681621d
commit
00bcf46c27
|
|
@ -93,15 +93,15 @@
|
||||||
|
|
||||||
;; Restore user quality preference
|
;; Restore user quality preference
|
||||||
(let ((selector (ps:chain document (get-element-by-id "live-stream-quality")))
|
(let ((selector (ps:chain document (get-element-by-id "live-stream-quality")))
|
||||||
(stream-quality (ps:chain (ps:@ local-storage (get-item "stream-quality")) "aac")))
|
(stream-quality (or (ps:chain local-storage (get-item "stream-quality")) "aac")))
|
||||||
(when (and selector (not (== (ps:@ selector value) stream-quality)))
|
(when (and selector (not (= (ps:@ selector value) stream-quality)))
|
||||||
(setf (ps:@ selector value) stream-quality)
|
(setf (ps:@ selector value) stream-quality)
|
||||||
(ps:chain selector (dispatch-event (new "Event" "change"))))))))
|
(ps:chain selector (dispatch-event (new "Event" "change"))))))))
|
||||||
|
|
||||||
;; Frame redirection logic
|
;; Frame redirection logic
|
||||||
(defun redirect-when-frame ()
|
(defun redirect-when-frame ()
|
||||||
(let ((path (ps:@ window location pathname))
|
(let* ((path (ps:@ window location pathname))
|
||||||
(is-frameset-page (not (== (ps:@ window parent) (ps:@ window self))))
|
(is-frameset-page (not (= (ps:@ window parent) (ps:@ window self))))
|
||||||
(is-content-frame (ps:chain path (includes "player-content"))))
|
(is-content-frame (ps:chain path (includes "player-content"))))
|
||||||
|
|
||||||
(when (and is-frameset-page (not is-content-frame))
|
(when (and is-frameset-page (not is-content-frame))
|
||||||
|
|
@ -133,13 +133,12 @@
|
||||||
(add-event-listener "input" update-volume))
|
(add-event-listener "input" update-volume))
|
||||||
|
|
||||||
;; Audio player events
|
;; Audio player events
|
||||||
(when *audio-player*
|
(when (and *audio-player* (ps:chain *audio-player* add-event-listener))
|
||||||
(ps:chain *audio-player*
|
(ps:chain *audio-player* (add-event-listener "loadedmetadata" update-time-display))
|
||||||
(add-event-listener "loadedmetadata" update-time-display)
|
(ps:chain *audio-player* (add-event-listener "timeupdate" update-time-display))
|
||||||
(add-event-listener "timeupdate" update-time-display)
|
(ps:chain *audio-player* (add-event-listener "ended" handle-track-end))
|
||||||
(add-event-listener "ended" handle-track-end)
|
(ps:chain *audio-player* (add-event-listener "play" (lambda () (update-play-button "⏸️ Pause"))))
|
||||||
(add-event-listener "play" (lambda () (update-play-button "⏸️ Pause")))
|
(ps:chain *audio-player* (add-event-listener "pause" (lambda () (update-play-button "▶️ Play")))))
|
||||||
(add-event-listener "pause" (lambda () (update-play-button "▶️ Play")))))
|
|
||||||
|
|
||||||
;; Playlist controls
|
;; Playlist controls
|
||||||
(ps:chain (ps:chain document (get-element-by-id "create-playlist"))
|
(ps:chain (ps:chain document (get-element-by-id "create-playlist"))
|
||||||
|
|
@ -162,17 +161,17 @@
|
||||||
(then (lambda (result)
|
(then (lambda (result)
|
||||||
;; Handle RADIANCE API wrapper format
|
;; Handle RADIANCE API wrapper format
|
||||||
(let ((data (or (ps:@ result data) result)))
|
(let ((data (or (ps:@ result data) result)))
|
||||||
(if (== (ps:@ data status) "success")
|
(if (= (ps:@ data status) "success")
|
||||||
(progn
|
(progn
|
||||||
(setf *tracks* (or (ps:@ data tracks) (array)))
|
(setf *tracks* (or (ps:@ data tracks) (array)))
|
||||||
(display-tracks *tracks*))
|
(display-tracks *tracks*))
|
||||||
(progn
|
(progn
|
||||||
(ps:chain console (error "Error loading tracks:" (ps:@ data error)))
|
(ps:chain console (error "Error loading tracks:" (ps:@ data error)))
|
||||||
(setf (ps:chain (ps:chain document (get-element-by-id "track-list")) inner-html)
|
(setf (ps:chain (ps:chain document (get-element-by-id "track-list")) inner-h-t-m-l)
|
||||||
"<div class=\"error\">Error loading tracks</div>"))))))
|
"<div class=\"error\">Error loading tracks</div>"))))))
|
||||||
(catch (lambda (error)
|
(catch (lambda (error)
|
||||||
(ps:chain console (error "Error loading tracks:" error))
|
(ps:chain console (error "Error loading tracks:" error))
|
||||||
(setf (ps:chain (ps:chain document (get-element-by-id "track-list")) inner-html)
|
(setf (ps:chain (ps:chain document (get-element-by-id "track-list")) inner-h-t-m-l)
|
||||||
"<div class=\"error\">Error loading tracks</div>")))))
|
"<div class=\"error\">Error loading tracks</div>")))))
|
||||||
|
|
||||||
;; Display tracks in library
|
;; Display tracks in library
|
||||||
|
|
@ -186,14 +185,14 @@
|
||||||
(let ((container (ps:chain document (get-element-by-id "track-list")))
|
(let ((container (ps:chain document (get-element-by-id "track-list")))
|
||||||
(pagination-controls (ps:chain document (get-element-by-id "library-pagination-controls"))))
|
(pagination-controls (ps:chain document (get-element-by-id "library-pagination-controls"))))
|
||||||
|
|
||||||
(if (== (ps:@ *filtered-library-tracks* length) 0)
|
(if (= (ps:@ *filtered-library-tracks* length) 0)
|
||||||
(progn
|
(progn
|
||||||
(setf (ps:@ container inner-html) "<div class=\"no-tracks\">No tracks found</div>")
|
(setf (ps:@ container inner-h-t-m-l) "<div class=\"no-tracks\">No tracks found</div>")
|
||||||
(setf (ps:@ pagination-controls style display) "none")
|
(setf (ps:@ pagination-controls style display) "none")
|
||||||
(return)))
|
(return)))
|
||||||
|
|
||||||
;; Calculate pagination
|
;; Calculate pagination
|
||||||
(let ((total-pages (ceiling (/ (ps:@ *filtered-library-tracks* length) *library-tracks-per-page*)))
|
(let* ((total-pages (ceiling (/ (ps:@ *filtered-library-tracks* length) *library-tracks-per-page*)))
|
||||||
(start-index (* (- *library-current-page* 1) *library-tracks-per-page*))
|
(start-index (* (- *library-current-page* 1) *library-tracks-per-page*))
|
||||||
(end-index (+ start-index *library-tracks-per-page*))
|
(end-index (+ start-index *library-tracks-per-page*))
|
||||||
(tracks-to-show (ps:chain *filtered-library-tracks* (slice start-index end-index))))
|
(tracks-to-show (ps:chain *filtered-library-tracks* (slice start-index end-index))))
|
||||||
|
|
@ -203,7 +202,7 @@
|
||||||
(map (lambda (track page-index)
|
(map (lambda (track page-index)
|
||||||
;; Find the actual index in the full tracks array
|
;; Find the actual index in the full tracks array
|
||||||
(let ((actual-index (ps:chain *tracks*
|
(let ((actual-index (ps:chain *tracks*
|
||||||
(find-index (lambda (trk) (== (ps:@ trk id) (ps:@ track id)))))))
|
(find-index (lambda (trk) (= (ps:@ trk id) (ps:@ track id)))))))
|
||||||
(+ "<div class=\"track-item\" data-track-id=\"" (ps:@ track id) "\" data-index=\"" actual-index "\">"
|
(+ "<div class=\"track-item\" data-track-id=\"" (ps:@ track id) "\" data-index=\"" actual-index "\">"
|
||||||
"<div class=\"track-info\">"
|
"<div class=\"track-info\">"
|
||||||
"<div class=\"track-title\">" (or (ps:@ track title) "Unknown Title") "</div>"
|
"<div class=\"track-title\">" (or (ps:@ track title) "Unknown Title") "</div>"
|
||||||
|
|
@ -216,7 +215,7 @@
|
||||||
"</div>"))))
|
"</div>"))))
|
||||||
(join ""))))
|
(join ""))))
|
||||||
|
|
||||||
(setf (ps:@ container inner-html) tracks-html)
|
(setf (ps:@ container inner-h-t-m-l) tracks-html)
|
||||||
|
|
||||||
;; Update pagination controls
|
;; Update pagination controls
|
||||||
(setf (ps:chain (ps:chain document (get-element-by-id "library-page-info")) text-content)
|
(setf (ps:chain (ps:chain document (get-element-by-id "library-page-info")) text-content)
|
||||||
|
|
@ -249,7 +248,7 @@
|
||||||
|
|
||||||
(defun change-library-tracks-per-page ()
|
(defun change-library-tracks-per-page ()
|
||||||
(setf *library-tracks-per-page*
|
(setf *library-tracks-per-page*
|
||||||
(parseInt (ps:chain (ps:chain document (get-element-by-id "library-tracks-per-page")) value)))
|
(parse-int (ps:chain (ps:chain document (get-element-by-id "library-tracks-per-page")) value)))
|
||||||
(setf *library-current-page* 1)
|
(setf *library-current-page* 1)
|
||||||
(render-library-page))
|
(render-library-page))
|
||||||
|
|
||||||
|
|
@ -312,13 +311,13 @@
|
||||||
;; Play from queue
|
;; Play from queue
|
||||||
(let ((next-track (ps:chain *play-queue* (shift))))
|
(let ((next-track (ps:chain *play-queue* (shift))))
|
||||||
(play-track (ps:chain *tracks*
|
(play-track (ps:chain *tracks*
|
||||||
(find-index (lambda (trk) (== (ps:@ trk id) (ps:@ next-track id))))))
|
(find-index (lambda (trk) (= (ps:@ trk id) (ps:@ next-track id))))))
|
||||||
(update-queue-display))
|
(update-queue-display))
|
||||||
;; Play next track in library
|
;; Play next track in library
|
||||||
(let ((next-index (if *is-shuffled*
|
(let ((next-index (if *is-shuffled*
|
||||||
(floor (* (random) (ps:@ *tracks* length)))
|
(floor (* (random) (ps:@ *tracks* length)))
|
||||||
(mod (+ *current-track-index* 1) (ps:@ *tracks* length)))))
|
(mod (+ *current-track-index* 1) (ps:@ *tracks* length)))))
|
||||||
(play-track next-index)))))
|
(play-track next-index))))
|
||||||
|
|
||||||
;; Handle track end
|
;; Handle track end
|
||||||
(defun handle-track-end ()
|
(defun handle-track-end ()
|
||||||
|
|
@ -344,7 +343,7 @@
|
||||||
|
|
||||||
;; Update volume
|
;; Update volume
|
||||||
(defun update-volume ()
|
(defun update-volume ()
|
||||||
(let ((volume (/ (parseInt (ps:chain (ps:chain document (get-element-by-id "volume-slider")) value)) 100)))
|
(let ((volume (/ (parse-int (ps:chain (ps:chain document (get-element-by-id "volume-slider")) value)) 100)))
|
||||||
(when *audio-player*
|
(when *audio-player*
|
||||||
(setf (ps:@ *audio-player* volume) volume))))
|
(setf (ps:@ *audio-player* volume) volume))))
|
||||||
|
|
||||||
|
|
@ -386,8 +385,8 @@
|
||||||
;; Update queue display
|
;; Update queue display
|
||||||
(defun update-queue-display ()
|
(defun update-queue-display ()
|
||||||
(let ((container (ps:chain document (get-element-by-id "play-queue"))))
|
(let ((container (ps:chain document (get-element-by-id "play-queue"))))
|
||||||
(if (== (ps:@ *play-queue* length) 0)
|
(if (= (ps:@ *play-queue* length) 0)
|
||||||
(setf (ps:@ container inner-html) "<div class=\"empty-queue\">Queue is empty</div>")
|
(setf (ps:@ container inner-h-t-m-l) "<div class=\"empty-queue\">Queue is empty</div>")
|
||||||
(let ((queue-html (ps:chain *play-queue*
|
(let ((queue-html (ps:chain *play-queue*
|
||||||
(map (lambda (track index)
|
(map (lambda (track index)
|
||||||
(+ "<div class=\"queue-item\">"
|
(+ "<div class=\"queue-item\">"
|
||||||
|
|
@ -398,7 +397,7 @@
|
||||||
"<button onclick=\"removeFromQueue(" index ")\" class=\"btn btn-sm btn-danger\">✖️</button>"
|
"<button onclick=\"removeFromQueue(" index ")\" class=\"btn btn-sm btn-danger\">✖️</button>"
|
||||||
"</div>")))
|
"</div>")))
|
||||||
(join ""))))
|
(join ""))))
|
||||||
(setf (ps:@ container inner-html) queue-html))))
|
(setf (ps:@ container inner-h-t-m-l) queue-html)))))
|
||||||
|
|
||||||
;; Remove track from queue
|
;; Remove track from queue
|
||||||
(defun remove-from-queue (index)
|
(defun remove-from-queue (index)
|
||||||
|
|
@ -413,25 +412,25 @@
|
||||||
;; Create playlist
|
;; Create playlist
|
||||||
(defun create-playlist ()
|
(defun create-playlist ()
|
||||||
(let ((name (ps:chain (ps:chain document (get-element-by-id "new-playlist-name")) value (trim))))
|
(let ((name (ps:chain (ps:chain document (get-element-by-id "new-playlist-name")) value (trim))))
|
||||||
(when (not (== name ""))
|
(when (not (= name ""))
|
||||||
(let ((form-data (new "FormData")))
|
(let ((form-data (new -Form-data)))
|
||||||
(ps:chain form-data (append "name" name))
|
(ps:chain form-data (append "name" name))
|
||||||
(ps:chain form-data (append "description" ""))
|
(ps:chain form-data (append "description" ""))
|
||||||
|
|
||||||
(ps:chain (fetch "/api/asteroid/playlists/create"
|
(ps:chain (fetch "/api/asteroid/playlists/create"
|
||||||
(ps:create :method "POST" :body form-data))
|
(ps:create :method "POST" :body form-data))
|
||||||
(then (lambda (response) (ps:chain response (json))))
|
(then (lambda (response)
|
||||||
|
(ps:chain response (json))))
|
||||||
(then (lambda (result)
|
(then (lambda (result)
|
||||||
;; Handle RADIANCE API wrapper format
|
;; Handle RADIANCE API wrapper format
|
||||||
(let ((data (or (ps:@ result data) result)))
|
(let ((data (or (ps:@ result data) result)))
|
||||||
(if (== (ps:@ data status) "success")
|
(if (= (ps:@ data status) "success")
|
||||||
(progn
|
(progn
|
||||||
(alert (+ "Playlist \"" name "\" created successfully!"))
|
(alert (+ "Playlist \"" name "\" created successfully!"))
|
||||||
(setf (ps:chain (ps:chain document (get-element-by-id "new-playlist-name")) value) "")
|
(setf (ps:chain (ps:chain document (get-element-by-id "new-playlist-name")) value) "")
|
||||||
|
|
||||||
;; Wait a moment then reload playlists
|
;; Wait a moment then reload playlists
|
||||||
(ps:chain (new "Promise" (lambda (resolve) (setTimeout resolve 500)))
|
(set-timeout load-playlists 500))
|
||||||
(then (lambda () (load-playlists)))))
|
|
||||||
(alert (+ "Error creating playlist: " (ps:@ data message)))))))
|
(alert (+ "Error creating playlist: " (ps:@ data message)))))))
|
||||||
(catch (lambda (error)
|
(catch (lambda (error)
|
||||||
(ps:chain console (error "Error creating playlist:" error))
|
(ps:chain console (error "Error creating playlist:" error))
|
||||||
|
|
@ -453,54 +452,55 @@
|
||||||
(then (lambda (create-result)
|
(then (lambda (create-result)
|
||||||
;; Handle RADIANCE API wrapper format
|
;; Handle RADIANCE API wrapper format
|
||||||
(let ((create-data (or (ps:@ create-result data) create-result)))
|
(let ((create-data (or (ps:@ create-result data) create-result)))
|
||||||
(if (== (ps:@ create-data status) "success")
|
(if (= (ps:@ create-data status) "success")
|
||||||
(progn
|
(progn
|
||||||
;; Wait a moment for database to update
|
;; Wait a moment for database to update, then fetch playlists
|
||||||
(ps:chain (new "Promise" (lambda (resolve) (setTimeout resolve 500)))
|
(set-timeout
|
||||||
(then (lambda ()
|
(lambda ()
|
||||||
;; Get the new playlist ID by fetching playlists
|
;; Get the new playlist ID by fetching playlists
|
||||||
(ps:chain (fetch "/api/asteroid/playlists")
|
(ps:chain (fetch "/api/asteroid/playlists")
|
||||||
(then (lambda (response) (ps:chain response (json))))
|
(then (lambda (response) (ps:chain response (json))))
|
||||||
(then (lambda (playlists-result)
|
(then (lambda (playlists-result)
|
||||||
;; Handle RADIANCE API wrapper format
|
;; Handle RADIANCE API wrapper format
|
||||||
(let ((playlist-result-data (or (ps:@ playlists-result data) playlists-result)))
|
(let ((playlist-result-data (or (ps:@ playlists-result data) playlists-result)))
|
||||||
(if (and (== (ps:@ playlist-result-data status) "success")
|
(if (and (= (ps:@ playlist-result-data status) "success")
|
||||||
(> (ps:@ playlist-result-data playlists length) 0))
|
(> (ps:@ playlist-result-data playlists length) 0))
|
||||||
(progn
|
(progn
|
||||||
;; Find the playlist with matching name (most recent)
|
;; Find the playlist with matching name (most recent)
|
||||||
(let ((new-playlist (or (ps:chain (ps:@ playlist-result-data playlists)
|
(let ((new-playlist (or (ps:chain (ps:@ playlist-result-data playlists)
|
||||||
(find (lambda (p) (== (ps:@ p name) name))))
|
(find (lambda (p) (= (ps:@ p name) name))))
|
||||||
(aref (ps:@ playlist-result-data playlists)
|
(aref (ps:@ playlist-result-data playlists)
|
||||||
(- (ps:@ playlist-result-data playlists length) 1)))))
|
(- (ps:@ playlist-result-data playlists length) 1)))))
|
||||||
|
|
||||||
;; Add all tracks from queue to playlist
|
;; Add all tracks from queue to playlist
|
||||||
(let ((added-count 0))
|
(let ((added-count 0))
|
||||||
(ps:chain *play-queue*
|
(ps:chain *play-queue*
|
||||||
(for-each (lambda (track)
|
(for-each (lambda (track)
|
||||||
(let ((track-id (ps:@ track id)))
|
(let ((track-id (ps:@ track id)))
|
||||||
(when track-id
|
(when track-id
|
||||||
(let ((add-form-data (new "FormData")))
|
(let ((add-form-data (new -Form-data)))
|
||||||
(ps:chain add-form-data (append "playlist-id" (ps:@ new-playlist id)))
|
(ps:chain add-form-data (append "playlist-id" (ps:@ new-playlist id)))
|
||||||
(ps:chain add-form-data (append "track-id" track-id))
|
(ps:chain add-form-data (append "track-id" track-id))
|
||||||
|
|
||||||
(ps:chain (fetch "/api/asteroid/playlists/add-track"
|
(ps:chain (fetch "/api/asteroid/playlists/add-track"
|
||||||
(ps:create :method "POST" :body add-form-data))
|
(ps:create :method "POST" :body add-form-data))
|
||||||
(then (lambda (response) (ps:chain response (json))))
|
(then (lambda (response) (ps:chain response (json))))
|
||||||
(then (lambda (add-result)
|
(then (lambda (add-result)
|
||||||
(when (== (ps:@ add-result data status) "success")
|
(when (= (ps:@ add-result data status) "success")
|
||||||
(setf added-count (+ added-count 1)))))
|
(setf added-count (+ added-count 1)))))
|
||||||
(catch (lambda (err)
|
(catch (lambda (err)
|
||||||
(ps:chain console (log "Error adding track:" err)))))))))))
|
(ps:chain console (log "Error adding track:" err)))))))))))
|
||||||
|
|
||||||
(alert (+ "Playlist \"" name "\" created with " added-count " tracks!"))
|
(alert (+ "Playlist \"" name "\" created with " added-count " tracks!"))
|
||||||
(load-playlists))))
|
(load-playlists))))
|
||||||
(progn
|
(progn
|
||||||
(alert (+ "Playlist created but could not add tracks. Error: "
|
(alert (+ "Playlist created but could not add tracks. Error: "
|
||||||
(or (ps:@ playlist-result-data message) "Unknown")))
|
(or (ps:@ playlist-result-data message) "Unknown")))
|
||||||
(load-playlists))))))
|
(load-playlists))))))
|
||||||
(catch (lambda (error)
|
(catch (lambda (error)
|
||||||
(ps:chain console (error "Error fetching playlists:" error))
|
(ps:chain console (error "Error fetching playlists:" error))
|
||||||
(alert "Playlist created but could not add tracks"))))))))
|
(alert "Playlist created but could not add tracks")))))
|
||||||
|
500))
|
||||||
(alert (+ "Error creating playlist: " (ps:@ create-data message)))))))
|
(alert (+ "Error creating playlist: " (ps:@ create-data message)))))))
|
||||||
(catch (lambda (error)
|
(catch (lambda (error)
|
||||||
(ps:chain console (error "Error saving queue as playlist:" error))
|
(ps:chain console (error "Error saving queue as playlist:" error))
|
||||||
|
|
@ -514,9 +514,9 @@
|
||||||
(then (lambda (response) (ps:chain response (json))))
|
(then (lambda (response) (ps:chain response (json))))
|
||||||
(then (lambda (result)
|
(then (lambda (result)
|
||||||
(let ((playlists (cond
|
(let ((playlists (cond
|
||||||
((and (ps:@ result data) (== (ps:@ result data status) "success"))
|
((and (ps:@ result data) (= (ps:@ result data status) "success"))
|
||||||
(or (ps:@ result data playlists) (array)))
|
(or (ps:@ result data playlists) (array)))
|
||||||
((== (ps:@ result status) "success")
|
((= (ps:@ result status) "success")
|
||||||
(or (ps:@ result playlists) (array)))
|
(or (ps:@ result playlists) (array)))
|
||||||
(t
|
(t
|
||||||
(array)))))
|
(array)))))
|
||||||
|
|
@ -529,8 +529,8 @@
|
||||||
(defun display-playlists (playlists)
|
(defun display-playlists (playlists)
|
||||||
(let ((container (ps:chain document (get-element-by-id "playlists-container"))))
|
(let ((container (ps:chain document (get-element-by-id "playlists-container"))))
|
||||||
|
|
||||||
(if (or (not playlists) (== (ps:@ playlists length) 0))
|
(if (or (not playlists) (= (ps:@ playlists length) 0))
|
||||||
(setf (ps:@ container inner-html) "<div class=\"no-playlists\">No playlists created yet.</div>")
|
(setf (ps:@ container inner-h-t-m-l) "<div class=\"no-playlists\">No playlists created yet.</div>")
|
||||||
(let ((playlists-html (ps:chain playlists
|
(let ((playlists-html (ps:chain playlists
|
||||||
(map (lambda (playlist)
|
(map (lambda (playlist)
|
||||||
(+ "<div class=\"playlist-item\">"
|
(+ "<div class=\"playlist-item\">"
|
||||||
|
|
@ -541,10 +541,10 @@
|
||||||
"<div class=\"playlist-actions\">"
|
"<div class=\"playlist-actions\">"
|
||||||
"<button onclick=\"loadPlaylist(" (ps:@ playlist id) ")\" class=\"btn btn-sm btn-info\">📂 Load</button>"
|
"<button onclick=\"loadPlaylist(" (ps:@ playlist id) ")\" class=\"btn btn-sm btn-info\">📂 Load</button>"
|
||||||
"</div>"
|
"</div>"
|
||||||
"</div>"))
|
"</div>")))
|
||||||
(join "")))))
|
(join ""))))
|
||||||
|
|
||||||
(setf (ps:@ container inner-html) playlists-html)))))
|
(setf (ps:@ container inner-h-t-m-l) playlists-html)))))
|
||||||
|
|
||||||
;; Load playlist into queue
|
;; Load playlist into queue
|
||||||
(defun load-playlist (playlist-id)
|
(defun load-playlist (playlist-id)
|
||||||
|
|
@ -554,7 +554,7 @@
|
||||||
(then (lambda (result)
|
(then (lambda (result)
|
||||||
;; Handle RADIANCE API wrapper format
|
;; Handle RADIANCE API wrapper format
|
||||||
(let ((data (or (ps:@ result data) result)))
|
(let ((data (or (ps:@ result data) result)))
|
||||||
(if (and (== (ps:@ data status) "success") (ps:@ data playlist))
|
(if (and (= (ps:@ data status) "success") (ps:@ data playlist))
|
||||||
(let ((playlist (ps:@ data playlist)))
|
(let ((playlist (ps:@ data playlist)))
|
||||||
|
|
||||||
;; Clear current queue
|
;; Clear current queue
|
||||||
|
|
@ -566,7 +566,7 @@
|
||||||
(for-each (lambda (track)
|
(for-each (lambda (track)
|
||||||
;; Find the full track object from our tracks array
|
;; Find the full track object from our tracks array
|
||||||
(let ((full-track (ps:chain *tracks*
|
(let ((full-track (ps:chain *tracks*
|
||||||
(find (lambda (trk) (== (ps:@ trk id) (ps:@ track id)))))))
|
(find (lambda (trk) (= (ps:@ trk id) (ps:@ track id)))))))
|
||||||
(when full-track
|
(when full-track
|
||||||
(setf (aref *play-queue* (ps:@ *play-queue* length)) full-track)))))
|
(setf (aref *play-queue* (ps:@ *play-queue* length)) full-track)))))
|
||||||
|
|
||||||
|
|
@ -577,11 +577,11 @@
|
||||||
(when (> (ps:@ *play-queue* length) 0)
|
(when (> (ps:@ *play-queue* length) 0)
|
||||||
(let ((first-track (ps:chain *play-queue* (shift)))
|
(let ((first-track (ps:chain *play-queue* (shift)))
|
||||||
(track-index (ps:chain *tracks*
|
(track-index (ps:chain *tracks*
|
||||||
(find-index (lambda (trk) (== (ps:@ trk id) (ps:@ first-track id))))))
|
(find-index (lambda (trk) (= (ps:@ trk id) (ps:@ first-track id))))))
|
||||||
)
|
)
|
||||||
(when (>= track-index 0)
|
(when (>= track-index 0)
|
||||||
(play-track track-index))))))
|
(play-track track-index))))))
|
||||||
(when (or (not (ps:@ playlist tracks)) (== (ps:@ playlist tracks length) 0))
|
(when (or (not (ps:@ playlist tracks)) (= (ps:@ playlist tracks length) 0))
|
||||||
(alert (+ "Playlist \"" (ps:@ playlist name) "\" is empty"))))
|
(alert (+ "Playlist \"" (ps:@ playlist name) "\" is empty"))))
|
||||||
(alert (+ "Error loading playlist: " (or (ps:@ data message) "Unknown error")))))))
|
(alert (+ "Error loading playlist: " (or (ps:@ data message) "Unknown error")))))))
|
||||||
(catch (lambda (error)
|
(catch (lambda (error)
|
||||||
|
|
@ -631,23 +631,24 @@
|
||||||
;; Update now playing information
|
;; Update now playing information
|
||||||
(defun update-now-playing ()
|
(defun update-now-playing ()
|
||||||
(ps:chain
|
(ps:chain
|
||||||
(ps:chain (fetch "/api/asteroid/partial/now-playing"))
|
(fetch "/api/asteroid/partial/now-playing")
|
||||||
(then (lambda (response)
|
(then (lambda (response)
|
||||||
(let ((content-type (ps:chain response (headers) (get "content-type"))))
|
(let ((content-type (ps:chain response headers (get "content-type"))))
|
||||||
(if (ps:chain content-type (includes "text/html"))
|
(if (ps:chain content-type (includes "text/html"))
|
||||||
(ps:chain response (text))
|
(ps:chain response (text))
|
||||||
(progn
|
(progn
|
||||||
(ps:chain console (log "Error connecting to stream"))
|
(ps:chain console (log "Error connecting to stream"))
|
||||||
"")))))
|
"")))))
|
||||||
(then (lambda (data)
|
(then (lambda (data)
|
||||||
(setf (ps:chain (ps:chain document (get-element-by-id "now-playing")) inner-html) data)))
|
(setf (ps:chain document (get-element-by-id "now-playing") inner-h-t-m-l) data)))
|
||||||
|
|
||||||
(catch (lambda (error)
|
(catch (lambda (error)
|
||||||
(ps:chain console (log "Could not fetch stream status:" error))))))
|
(ps:chain console (log "Could not fetch stream status:" error))))))
|
||||||
|
|
||||||
;; Initial update after 1 second
|
;; Initial update after 1 second
|
||||||
(ps:chain (setTimeout update-now-playing 1000))
|
(set-timeout update-now-playing 1000)
|
||||||
;; Update live stream info every 10 seconds
|
;; Update live stream info every 10 seconds
|
||||||
(ps:chain (set-interval update-now-playing 10000))
|
(set-interval update-now-playing 10000)
|
||||||
|
|
||||||
;; Make functions globally accessible for onclick handlers
|
;; Make functions globally accessible for onclick handlers
|
||||||
(defvar window (ps:@ window))
|
(defvar window (ps:@ window))
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,9 @@
|
||||||
(setf (dm:field playlist "user-id") user-id)
|
(setf (dm:field playlist "user-id") user-id)
|
||||||
(setf (dm:field playlist "name") name)
|
(setf (dm:field playlist "name") name)
|
||||||
(setf (dm:field playlist "description") (or description ""))
|
(setf (dm:field playlist "description") (or description ""))
|
||||||
(setf (dm:field playlist "track-ids") "") ; Empty string for text field
|
;; Note: track-ids column removed - using playlist_tracks junction table instead
|
||||||
;; Let database default handle created-date (CURRENT_TIMESTAMP)
|
;; Let database default handle created-date (CURRENT_TIMESTAMP)
|
||||||
(format t "Creating playlist with user-id: ~a (type: ~a)~%" user-id (type-of user-id))
|
(format t "Creating playlist with user-id: ~a (type: ~a)~%" user-id (type-of user-id))
|
||||||
(format t "Playlist data: ~a~%" (data-model-as-alist playlist))
|
|
||||||
(dm:insert playlist)
|
(dm:insert playlist)
|
||||||
t))
|
t))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue