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
This commit is contained in:
parent
1807e58971
commit
f39abeb8f8
|
|
@ -290,12 +290,19 @@
|
||||||
FILE-PATH can be a string or pathname.
|
FILE-PATH can be a string or pathname.
|
||||||
ON-END is passed to harmony:play (default :free).
|
ON-END is passed to harmony:play (default :free).
|
||||||
UPDATE-METADATA controls whether ICY metadata is updated immediately."
|
UPDATE-METADATA controls whether ICY metadata is updated immediately."
|
||||||
(let* ((path (pathname file-path))
|
(let* ((path-string (etypecase file-path
|
||||||
|
(string file-path)
|
||||||
|
(pathname (namestring file-path))))
|
||||||
|
;; Use parse-native-namestring to prevent SBCL from interpreting
|
||||||
|
;; brackets as wildcard patterns. Standard (pathname ...) turns
|
||||||
|
;; "[FLAC]" into a wild component with non-simple strings, which
|
||||||
|
;; causes SIMPLE-ARRAY errors in cl-flac's CFFI calls.
|
||||||
|
(path (sb-ext:parse-native-namestring path-string))
|
||||||
(server (pipeline-harmony-server pipeline))
|
(server (pipeline-harmony-server pipeline))
|
||||||
(harmony:*server* server)
|
(harmony:*server* server)
|
||||||
(tags (read-audio-metadata path))
|
(tags (read-audio-metadata path))
|
||||||
(display-title (format-display-title path title))
|
(display-title (format-display-title path title))
|
||||||
(track-info (list :file (namestring path)
|
(track-info (list :file path-string
|
||||||
:display-title display-title
|
:display-title display-title
|
||||||
:artist (getf tags :artist)
|
:artist (getf tags :artist)
|
||||||
:title (getf tags :title)
|
:title (getf tags :title)
|
||||||
|
|
|
||||||
|
|
@ -312,14 +312,21 @@
|
||||||
;;; This ensures the scheduler starts after the server is fully initialized
|
;;; This ensures the scheduler starts after the server is fully initialized
|
||||||
|
|
||||||
(define-trigger db:connected ()
|
(define-trigger db:connected ()
|
||||||
"Start the playlist scheduler after database connection is established"
|
"Start the playlist scheduler after database connection is established.
|
||||||
|
Loads the current scheduled playlist only if the pipeline has no tracks
|
||||||
|
(i.e., we did NOT just resume from saved state)."
|
||||||
(handler-case
|
(handler-case
|
||||||
(progn
|
(progn
|
||||||
(load-schedule-from-db)
|
(load-schedule-from-db)
|
||||||
(start-playlist-scheduler)
|
(start-playlist-scheduler)
|
||||||
|
;; Only load scheduled playlist if we didn't just resume from saved state
|
||||||
|
(if *resumed-from-saved-state*
|
||||||
|
(progn
|
||||||
|
(setf *resumed-from-saved-state* nil)
|
||||||
|
(log:info "Playlist scheduler started (resumed from saved state, skipping initial load)"))
|
||||||
(let ((current-playlist (get-current-scheduled-playlist)))
|
(let ((current-playlist (get-current-scheduled-playlist)))
|
||||||
(when current-playlist
|
(when current-playlist
|
||||||
(load-scheduled-playlist current-playlist)))
|
(load-scheduled-playlist current-playlist))
|
||||||
(log:info "Playlist scheduler started"))
|
(log:info "Playlist scheduler started"))))
|
||||||
(error (e)
|
(error (e)
|
||||||
(log:error "Scheduler failed to start: ~a" e))))
|
(log:error "Scheduler failed to start: ~a" e))))
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,10 @@
|
||||||
(defvar *current-playlist-path* nil
|
(defvar *current-playlist-path* nil
|
||||||
"Path of the currently active playlist file.")
|
"Path of the currently active playlist file.")
|
||||||
|
|
||||||
|
(defvar *resumed-from-saved-state* nil
|
||||||
|
"Set to T when startup successfully resumed from saved playback state.
|
||||||
|
Prevents the scheduler from overwriting the resumed position.")
|
||||||
|
|
||||||
(defun save-playback-state (track-file-path)
|
(defun save-playback-state (track-file-path)
|
||||||
"Save the current track file path and playlist to the state file.
|
"Save the current track file path and playlist to the state file.
|
||||||
Called on each track change so we can resume after restart."
|
Called on each track change so we can resume after restart."
|
||||||
|
|
@ -72,6 +76,7 @@
|
||||||
(m3u-to-file-list playlist-path))))
|
(m3u-to-file-list playlist-path))))
|
||||||
(when file-list
|
(when file-list
|
||||||
(setf *current-playlist-path* playlist-path)
|
(setf *current-playlist-path* playlist-path)
|
||||||
|
(setf *resumed-from-saved-state* t)
|
||||||
(let ((pos (when saved-file
|
(let ((pos (when saved-file
|
||||||
(position saved-file file-list :test #'string=))))
|
(position saved-file file-list :test #'string=))))
|
||||||
(if pos
|
(if pos
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue