diff --git a/cl-streamer/harmony-backend.lisp b/cl-streamer/harmony-backend.lisp index 161e1a5..b6746d4 100644 --- a/cl-streamer/harmony-backend.lisp +++ b/cl-streamer/harmony-backend.lisp @@ -290,12 +290,19 @@ FILE-PATH can be a string or pathname. ON-END is passed to harmony:play (default :free). 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)) (harmony:*server* server) (tags (read-audio-metadata path)) (display-title (format-display-title path title)) - (track-info (list :file (namestring path) + (track-info (list :file path-string :display-title display-title :artist (getf tags :artist) :title (getf tags :title) diff --git a/playlist-scheduler.lisp b/playlist-scheduler.lisp index 7bc3616..3330521 100644 --- a/playlist-scheduler.lisp +++ b/playlist-scheduler.lisp @@ -312,14 +312,21 @@ ;;; This ensures the scheduler starts after the server is fully initialized (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 (progn (load-schedule-from-db) (start-playlist-scheduler) - (let ((current-playlist (get-current-scheduled-playlist))) - (when current-playlist - (load-scheduled-playlist current-playlist))) - (log:info "Playlist scheduler started")) + ;; 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))) + (when current-playlist + (load-scheduled-playlist current-playlist)) + (log:info "Playlist scheduler started")))) (error (e) (log:error "Scheduler failed to start: ~a" e)))) diff --git a/stream-harmony.lisp b/stream-harmony.lisp index ef5b572..ac41c44 100644 --- a/stream-harmony.lisp +++ b/stream-harmony.lisp @@ -27,6 +27,10 @@ (defvar *current-playlist-path* nil "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) "Save the current track file path and playlist to the state file. Called on each track change so we can resume after restart." @@ -72,6 +76,7 @@ (m3u-to-file-list playlist-path)))) (when file-list (setf *current-playlist-path* playlist-path) + (setf *resumed-from-saved-state* t) (let ((pos (when saved-file (position saved-file file-list :test #'string=)))) (if pos