Add Liquidsoap/Icecast controls, fix library scan
- Add Liquidsoap control panel: status display, skip track, reload playlist, restart container - Add Icecast restart button to System Status section - Remove redundant Web Player Control section from admin - Fix music library scan to follow symlinks (truename resolution) - Fix database timestamp error (let PostgreSQL default handle added-date) - Update docker-compose mount for stream-queue.m3u - Clean up playlist path handling
This commit is contained in:
parent
74a9448e9a
commit
22b2a2d87e
240
asteroid.lisp
240
asteroid.lisp
|
|
@ -303,6 +303,246 @@
|
|||
("message" . "Queue loaded from M3U file")
|
||||
("count" . ,count))))))
|
||||
|
||||
;;; Playlist File Management APIs
|
||||
;;; These manage .m3u files in the playlists/ directory
|
||||
;;; stream-queue.m3u lives at PROJECT ROOT (for Docker mount), saved playlists in playlists/
|
||||
|
||||
(defun get-playlists-directory ()
|
||||
"Get the path to the playlists directory (for saved playlists)"
|
||||
(merge-pathnames "playlists/" (asdf:system-source-directory :asteroid)))
|
||||
|
||||
(defun get-stream-queue-path ()
|
||||
"Get the path to stream-queue.m3u (in playlists/ directory for Docker mount)"
|
||||
(merge-pathnames "playlists/stream-queue.m3u" (asdf:system-source-directory :asteroid)))
|
||||
|
||||
(defun list-playlist-files ()
|
||||
"List all .m3u files in the playlists directory, excluding stream-queue.m3u"
|
||||
(let ((playlist-dir (get-playlists-directory)))
|
||||
(when (probe-file playlist-dir)
|
||||
(remove-if (lambda (path)
|
||||
(string= (file-namestring path) "stream-queue.m3u"))
|
||||
(directory (merge-pathnames "*.m3u" playlist-dir))))))
|
||||
|
||||
(defun read-m3u-file-paths (filepath)
|
||||
"Read an m3u file and return list of file paths (excluding comments)"
|
||||
(when (probe-file filepath)
|
||||
(with-open-file (stream filepath :direction :input)
|
||||
(loop for line = (read-line stream nil)
|
||||
while line
|
||||
unless (or (string= line "")
|
||||
(and (> (length line) 0) (char= (char line 0) #\#)))
|
||||
collect (string-trim '(#\Space #\Tab #\Return #\Newline) line)))))
|
||||
|
||||
(defun copy-playlist-to-stream-queue (source-path)
|
||||
"Copy a playlist file to stream-queue.m3u at project root"
|
||||
(let ((dest-path (get-stream-queue-path)))
|
||||
(with-open-file (in source-path :direction :input)
|
||||
(with-open-file (out dest-path :direction :output
|
||||
:if-exists :supersede
|
||||
:if-does-not-exist :create)
|
||||
(loop for line = (read-line in nil)
|
||||
while line
|
||||
do (write-line line out))))
|
||||
t))
|
||||
|
||||
(define-api asteroid/stream/playlists () ()
|
||||
"List available playlist files (excluding stream-queue.m3u)"
|
||||
(require-role :admin)
|
||||
(with-error-handling
|
||||
(let ((files (list-playlist-files)))
|
||||
(api-output `(("status" . "success")
|
||||
("playlists" . ,(mapcar (lambda (path)
|
||||
(file-namestring path))
|
||||
files)))))))
|
||||
|
||||
(define-api asteroid/stream/playlists/load (name) ()
|
||||
"Load a playlist file into stream-queue.m3u and return its contents"
|
||||
(require-role :admin)
|
||||
(with-error-handling
|
||||
(let* ((playlist-path (merge-pathnames name (get-playlists-directory)))
|
||||
(stream-queue-path (get-stream-queue-path)))
|
||||
(if (probe-file playlist-path)
|
||||
(progn
|
||||
;; 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)))
|
||||
(api-output `(("status" . "success")
|
||||
("message" . ,(format nil "Loaded playlist: ~a" name))
|
||||
("count" . ,count)
|
||||
("paths" . ,(read-m3u-file-paths stream-queue-path))))))
|
||||
(api-output `(("status" . "error")
|
||||
("message" . "Playlist file not found"))
|
||||
:status 404)))))
|
||||
|
||||
(define-api asteroid/stream/playlists/save () ()
|
||||
"Save current stream queue to stream-queue.m3u"
|
||||
(require-role :admin)
|
||||
(with-error-handling
|
||||
(regenerate-stream-playlist)
|
||||
(api-output `(("status" . "success")
|
||||
("message" . "Stream queue saved")))))
|
||||
|
||||
(define-api asteroid/stream/playlists/save-as (name) ()
|
||||
"Save current stream queue to a new playlist file"
|
||||
(require-role :admin)
|
||||
(with-error-handling
|
||||
(let* ((safe-name (if (cl-ppcre:scan "\\.m3u$" name) name (format nil "~a.m3u" name)))
|
||||
(playlist-path (merge-pathnames safe-name (get-playlists-directory))))
|
||||
;; Generate playlist to the new file
|
||||
(generate-m3u-playlist *stream-queue* playlist-path)
|
||||
;; Also save to stream-queue.m3u
|
||||
(regenerate-stream-playlist)
|
||||
(api-output `(("status" . "success")
|
||||
("message" . ,(format nil "Saved as: ~a" safe-name)))))))
|
||||
|
||||
(define-api asteroid/stream/playlists/clear () ()
|
||||
"Clear stream-queue.m3u (Liquidsoap will fall back to random)"
|
||||
(require-role :admin)
|
||||
(with-error-handling
|
||||
(let ((stream-queue-path (get-stream-queue-path)))
|
||||
;; Write empty m3u file
|
||||
(with-open-file (out stream-queue-path :direction :output
|
||||
:if-exists :supersede
|
||||
:if-does-not-exist :create)
|
||||
(format out "#EXTM3U~%"))
|
||||
;; Clear in-memory queue
|
||||
(setf *stream-queue* '())
|
||||
(api-output `(("status" . "success")
|
||||
("message" . "Stream queue cleared - Liquidsoap will use random playback"))))))
|
||||
|
||||
(define-api asteroid/stream/playlists/current () ()
|
||||
"Get current stream-queue.m3u contents with track info"
|
||||
(require-role :admin)
|
||||
(with-error-handling
|
||||
(let* ((stream-queue-path (get-stream-queue-path))
|
||||
(paths (read-m3u-file-paths stream-queue-path))
|
||||
(all-tracks (dm:get "tracks" (db:query :all))))
|
||||
(api-output `(("status" . "success")
|
||||
("count" . ,(length paths))
|
||||
("tracks" . ,(mapcar (lambda (docker-path)
|
||||
(let* ((host-path (convert-from-docker-path docker-path))
|
||||
(track (find-if
|
||||
(lambda (trk)
|
||||
(string= (dm:field trk "file-path") host-path))
|
||||
all-tracks)))
|
||||
(if track
|
||||
`(("id" . ,(dm:id track))
|
||||
("title" . ,(dm:field track "title"))
|
||||
("artist" . ,(dm:field track "artist"))
|
||||
("album" . ,(dm:field track "album"))
|
||||
("path" . ,docker-path))
|
||||
`(("id" . nil)
|
||||
("title" . ,(file-namestring docker-path))
|
||||
("artist" . "Unknown")
|
||||
("album" . "Unknown")
|
||||
("path" . ,docker-path)))))
|
||||
paths)))))))
|
||||
|
||||
;;; Liquidsoap Control APIs
|
||||
;;; Control Liquidsoap via telnet interface on port 1234
|
||||
|
||||
(defun liquidsoap-command (command)
|
||||
"Send a command to Liquidsoap via telnet and return the response"
|
||||
(handler-case
|
||||
(let ((result (uiop:run-program
|
||||
(format nil "echo '~a' | nc -q1 127.0.0.1 1234" command)
|
||||
:output :string
|
||||
:error-output :string
|
||||
:ignore-error-status t)))
|
||||
;; Remove the trailing "END" line
|
||||
(let ((lines (cl-ppcre:split "\\n" result)))
|
||||
(string-trim '(#\Space #\Newline #\Return)
|
||||
(format nil "~{~a~^~%~}"
|
||||
(remove-if (lambda (l) (string= (string-trim '(#\Space #\Return) l) "END"))
|
||||
lines)))))
|
||||
(error (e)
|
||||
(format nil "Error: ~a" e))))
|
||||
|
||||
(defun parse-liquidsoap-metadata (raw-metadata)
|
||||
"Parse Liquidsoap metadata string and extract current track info"
|
||||
(when (and raw-metadata (> (length raw-metadata) 0))
|
||||
;; The metadata contains multiple tracks, separated by --- N ---
|
||||
;; --- 1 --- is the CURRENT track (most recent), at the end of the output
|
||||
;; Split by --- N --- pattern and get the last section
|
||||
(let* ((sections (cl-ppcre:split "---\\s*\\d+\\s*---" raw-metadata))
|
||||
(current-section (car (last sections))))
|
||||
(when current-section
|
||||
(let ((artist (cl-ppcre:register-groups-bind (val)
|
||||
("artist=\"([^\"]+)\"" current-section) val))
|
||||
(title (cl-ppcre:register-groups-bind (val)
|
||||
("title=\"([^\"]+)\"" current-section) val))
|
||||
(album (cl-ppcre:register-groups-bind (val)
|
||||
("album=\"([^\"]+)\"" current-section) val)))
|
||||
(if (or artist title)
|
||||
(format nil "~@[~a~]~@[ - ~a~]~@[ (~a)~]"
|
||||
artist title album)
|
||||
"Unknown"))))))
|
||||
|
||||
(defun format-remaining-time (seconds-str)
|
||||
"Format remaining seconds as MM:SS"
|
||||
(handler-case
|
||||
(let ((seconds (parse-integer (cl-ppcre:regex-replace "\\..*" seconds-str ""))))
|
||||
(format nil "~d:~2,'0d" (floor seconds 60) (mod seconds 60)))
|
||||
(error () seconds-str)))
|
||||
|
||||
(define-api asteroid/liquidsoap/status () ()
|
||||
"Get Liquidsoap status including uptime and current track"
|
||||
(require-role :admin)
|
||||
(with-error-handling
|
||||
(let ((uptime (liquidsoap-command "uptime"))
|
||||
(metadata-raw (liquidsoap-command "output.icecast.1.metadata"))
|
||||
(remaining-raw (liquidsoap-command "output.icecast.1.remaining")))
|
||||
(api-output `(("status" . "success")
|
||||
("uptime" . ,(string-trim '(#\Space #\Newline #\Return) uptime))
|
||||
("metadata" . ,(parse-liquidsoap-metadata metadata-raw))
|
||||
("remaining" . ,(format-remaining-time
|
||||
(string-trim '(#\Space #\Newline #\Return) remaining-raw))))))))
|
||||
|
||||
(define-api asteroid/liquidsoap/skip () ()
|
||||
"Skip the current track in Liquidsoap"
|
||||
(require-role :admin)
|
||||
(with-error-handling
|
||||
(let ((result (liquidsoap-command "stream-queue_m3u.skip")))
|
||||
(api-output `(("status" . "success")
|
||||
("message" . "Track skipped")
|
||||
("result" . ,(string-trim '(#\Space #\Newline #\Return) result)))))))
|
||||
|
||||
(define-api asteroid/liquidsoap/reload () ()
|
||||
"Force Liquidsoap to reload the playlist"
|
||||
(require-role :admin)
|
||||
(with-error-handling
|
||||
(let ((result (liquidsoap-command "stream-queue_m3u.reload")))
|
||||
(api-output `(("status" . "success")
|
||||
("message" . "Playlist reloaded")
|
||||
("result" . ,(string-trim '(#\Space #\Newline #\Return) result)))))))
|
||||
|
||||
(define-api asteroid/liquidsoap/restart () ()
|
||||
"Restart the Liquidsoap Docker container"
|
||||
(require-role :admin)
|
||||
(with-error-handling
|
||||
(let ((result (uiop:run-program
|
||||
"docker restart asteroid-liquidsoap"
|
||||
:output :string
|
||||
:error-output :string
|
||||
:ignore-error-status t)))
|
||||
(api-output `(("status" . "success")
|
||||
("message" . "Liquidsoap container restarting")
|
||||
("result" . ,result))))))
|
||||
|
||||
(define-api asteroid/icecast/restart () ()
|
||||
"Restart the Icecast Docker container"
|
||||
(require-role :admin)
|
||||
(with-error-handling
|
||||
(let ((result (uiop:run-program
|
||||
"docker restart asteroid-icecast"
|
||||
:output :string
|
||||
:error-output :string
|
||||
:ignore-error-status t)))
|
||||
(api-output `(("status" . "success")
|
||||
("message" . "Icecast container restarting")
|
||||
("result" . ,result))))))
|
||||
|
||||
(defun get-track-by-id (track-id)
|
||||
"Get a track by its ID - handles type mismatches"
|
||||
(dm:get-one "tracks" (db:query (:= '_id track-id))))
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ services:
|
|||
volumes:
|
||||
- ${MUSIC_LIBRARY:-../music/library}:/app/music:ro
|
||||
- ./asteroid-radio-docker.liq:/app/asteroid-radio.liq:ro
|
||||
- ${QUEUE_PLAYLIST:-../stream-queue.m3u}:/app/stream-queue.m3u:ro
|
||||
- ${QUEUE_PLAYLIST:-../playlists/stream-queue.m3u}:/app/stream-queue.m3u:ro
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- asteroid-network
|
||||
|
|
|
|||
|
|
@ -23,11 +23,12 @@
|
|||
"DOMContentLoaded"
|
||||
(lambda ()
|
||||
(load-tracks)
|
||||
(update-player-status)
|
||||
(setup-event-listeners)
|
||||
(load-stream-queue)
|
||||
;; Update player status every 5 seconds
|
||||
(set-interval update-player-status 5000))))
|
||||
(load-playlist-list)
|
||||
(load-current-queue)
|
||||
(refresh-liquidsoap-status)
|
||||
;; Update Liquidsoap status every 10 seconds
|
||||
(set-interval refresh-liquidsoap-status 10000))))
|
||||
|
||||
;; Setup all event listeners
|
||||
(defun setup-event-listeners ()
|
||||
|
|
@ -70,21 +71,52 @@
|
|||
|
||||
;; Queue controls
|
||||
(let ((refresh-queue-btn (ps:chain document (get-element-by-id "refresh-queue")))
|
||||
(load-m3u-btn (ps:chain document (get-element-by-id "load-from-m3u")))
|
||||
(clear-queue-btn (ps:chain document (get-element-by-id "clear-queue-btn")))
|
||||
(save-queue-btn (ps:chain document (get-element-by-id "save-queue-btn")))
|
||||
(save-as-btn (ps:chain document (get-element-by-id "save-as-btn")))
|
||||
(add-random-btn (ps:chain document (get-element-by-id "add-random-tracks")))
|
||||
(queue-search-input (ps:chain document (get-element-by-id "queue-track-search"))))
|
||||
(queue-search-input (ps:chain document (get-element-by-id "queue-track-search")))
|
||||
;; Playlist controls
|
||||
(playlist-select (ps:chain document (get-element-by-id "playlist-select")))
|
||||
(load-playlist-btn (ps:chain document (get-element-by-id "load-playlist-btn")))
|
||||
(refresh-playlists-btn (ps:chain document (get-element-by-id "refresh-playlists-btn"))))
|
||||
|
||||
(when refresh-queue-btn
|
||||
(ps:chain refresh-queue-btn (add-event-listener "click" load-stream-queue)))
|
||||
(when load-m3u-btn
|
||||
(ps:chain load-m3u-btn (add-event-listener "click" load-queue-from-m3u)))
|
||||
(ps:chain refresh-queue-btn (add-event-listener "click" load-current-queue)))
|
||||
(when clear-queue-btn
|
||||
(ps:chain clear-queue-btn (add-event-listener "click" clear-stream-queue)))
|
||||
(when save-queue-btn
|
||||
(ps:chain save-queue-btn (add-event-listener "click" save-stream-queue)))
|
||||
(when save-as-btn
|
||||
(ps:chain save-as-btn (add-event-listener "click" save-queue-as-new)))
|
||||
(when add-random-btn
|
||||
(ps:chain add-random-btn (add-event-listener "click" add-random-tracks)))
|
||||
(when queue-search-input
|
||||
(ps:chain queue-search-input (add-event-listener "input" search-tracks-for-queue)))))
|
||||
(ps:chain queue-search-input (add-event-listener "input" search-tracks-for-queue)))
|
||||
;; Playlist controls
|
||||
(when load-playlist-btn
|
||||
(ps:chain load-playlist-btn (add-event-listener "click" load-selected-playlist)))
|
||||
(when refresh-playlists-btn
|
||||
(ps:chain refresh-playlists-btn (add-event-listener "click" load-playlist-list))))
|
||||
|
||||
;; Liquidsoap controls
|
||||
(let ((ls-refresh-btn (ps:chain document (get-element-by-id "ls-refresh-status")))
|
||||
(ls-skip-btn (ps:chain document (get-element-by-id "ls-skip")))
|
||||
(ls-reload-btn (ps:chain document (get-element-by-id "ls-reload")))
|
||||
(ls-restart-btn (ps:chain document (get-element-by-id "ls-restart"))))
|
||||
(when ls-refresh-btn
|
||||
(ps:chain ls-refresh-btn (add-event-listener "click" refresh-liquidsoap-status)))
|
||||
(when ls-skip-btn
|
||||
(ps:chain ls-skip-btn (add-event-listener "click" liquidsoap-skip)))
|
||||
(when ls-reload-btn
|
||||
(ps:chain ls-reload-btn (add-event-listener "click" liquidsoap-reload)))
|
||||
(when ls-restart-btn
|
||||
(ps:chain ls-restart-btn (add-event-listener "click" liquidsoap-restart))))
|
||||
|
||||
;; Icecast restart
|
||||
(let ((icecast-restart-btn (ps:chain document (get-element-by-id "icecast-restart"))))
|
||||
(when icecast-restart-btn
|
||||
(ps:chain icecast-restart-btn (add-event-listener "click" icecast-restart)))))
|
||||
|
||||
;; Load tracks from API
|
||||
(defun load-tracks ()
|
||||
|
|
@ -406,44 +438,6 @@
|
|||
(setf html (+ html "</div>"))
|
||||
(setf (ps:@ container inner-h-t-m-l) html))))))
|
||||
|
||||
;; Clear stream queue
|
||||
(defun clear-stream-queue ()
|
||||
(unless (confirm "Clear the entire stream queue? This will stop playback until new tracks are added.")
|
||||
(return))
|
||||
|
||||
(ps:chain
|
||||
(fetch "/api/asteroid/stream/queue/clear" (ps:create :method "POST"))
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(if (= (ps:@ data status) "success")
|
||||
(progn
|
||||
(alert "Queue cleared successfully")
|
||||
(load-stream-queue))
|
||||
(alert (+ "Error clearing queue: " (or (ps:@ data message) "Unknown error")))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error clearing queue:" error))
|
||||
(alert "Error clearing queue")))))
|
||||
|
||||
;; Load queue from M3U file
|
||||
(defun load-queue-from-m3u ()
|
||||
(unless (confirm "Load queue from stream-queue.m3u file? This will replace the current queue.")
|
||||
(return))
|
||||
|
||||
(ps:chain
|
||||
(fetch "/api/asteroid/stream/queue/load-m3u" (ps:create :method "POST"))
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(if (= (ps:@ data status) "success")
|
||||
(progn
|
||||
(alert (+ "Successfully loaded " (ps:@ data count) " tracks from M3U file!"))
|
||||
(load-stream-queue))
|
||||
(alert (+ "Error loading from M3U: " (or (ps:@ data message) "Unknown error")))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error loading from M3U:" error))
|
||||
(alert (+ "Error loading from M3U: " (ps:@ error message)))))))
|
||||
|
||||
;; Move track up in queue
|
||||
(defun move-track-up (index)
|
||||
(when (= index 0) (return))
|
||||
|
|
@ -610,6 +604,256 @@
|
|||
(setf html (+ html "</div>"))
|
||||
(setf (ps:@ container inner-h-t-m-l) html))))))
|
||||
|
||||
;; ========================================
|
||||
;; Playlist File Management
|
||||
;; ========================================
|
||||
|
||||
;; Load list of available playlists into dropdown
|
||||
(defun load-playlist-list ()
|
||||
(ps:chain
|
||||
(fetch "/api/asteroid/stream/playlists")
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(when (= (ps:@ data status) "success")
|
||||
(let ((select (ps:chain document (get-element-by-id "playlist-select")))
|
||||
(playlists (or (ps:@ data playlists) (array))))
|
||||
(when select
|
||||
;; Clear existing options except the first one
|
||||
(setf (ps:@ select inner-h-t-m-l)
|
||||
"<option value=\"\">-- Select a playlist --</option>")
|
||||
;; Add playlist options
|
||||
(ps:chain playlists
|
||||
(for-each (lambda (name)
|
||||
(let ((option (ps:chain document (create-element "option"))))
|
||||
(setf (ps:@ option value) name)
|
||||
(setf (ps:@ option text-content) name)
|
||||
(ps:chain select (append-child option))))))))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error loading playlists:" error))))))
|
||||
|
||||
;; Load selected playlist
|
||||
(defun load-selected-playlist ()
|
||||
(let* ((select (ps:chain document (get-element-by-id "playlist-select")))
|
||||
(name (ps:@ select value)))
|
||||
(when (= name "")
|
||||
(alert "Please select a playlist first")
|
||||
(return))
|
||||
|
||||
(unless (confirm (+ "Load playlist '" name "'? This will replace the current stream queue."))
|
||||
(return))
|
||||
|
||||
(ps:chain
|
||||
(fetch (+ "/api/asteroid/stream/playlists/load?name=" (encode-u-r-i-component name))
|
||||
(ps:create :method "POST"))
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(if (= (ps:@ data status) "success")
|
||||
(progn
|
||||
(show-toast (+ "✓ Loaded " (ps:@ data count) " tracks from " name))
|
||||
(load-current-queue))
|
||||
(alert (+ "Error loading playlist: " (or (ps:@ data message) "Unknown error")))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error loading playlist:" error))
|
||||
(alert "Error loading playlist"))))))
|
||||
|
||||
;; Load current queue contents (from stream-queue.m3u)
|
||||
(defun load-current-queue ()
|
||||
(ps:chain
|
||||
(fetch "/api/asteroid/stream/playlists/current")
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(when (= (ps:@ data status) "success")
|
||||
(let ((tracks (or (ps:@ data tracks) (array)))
|
||||
(count (or (ps:@ data count) 0)))
|
||||
;; Update count display
|
||||
(let ((count-el (ps:chain document (get-element-by-id "queue-count"))))
|
||||
(when count-el
|
||||
(setf (ps:@ count-el text-content) count)))
|
||||
;; Display tracks
|
||||
(display-current-queue tracks))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error loading current queue:" error))
|
||||
(let ((container (ps:chain document (get-element-by-id "stream-queue-container"))))
|
||||
(when container
|
||||
(setf (ps:@ container inner-h-t-m-l)
|
||||
"<div class=\"error\">Error loading queue</div>")))))))
|
||||
|
||||
;; Display current queue contents
|
||||
(defun display-current-queue (tracks)
|
||||
(let ((container (ps:chain document (get-element-by-id "stream-queue-container"))))
|
||||
(when container
|
||||
(if (= (ps:@ tracks length) 0)
|
||||
(setf (ps:@ container inner-h-t-m-l)
|
||||
"<div class=\"empty-state\">Queue is empty. Liquidsoap will use random playback from the music library.</div>")
|
||||
(let ((html "<div class=\"queue-items\">"))
|
||||
(ps:chain tracks
|
||||
(for-each (lambda (track index)
|
||||
(setf html
|
||||
(+ html
|
||||
"<div class=\"queue-item\" data-index=\"" index "\">"
|
||||
"<span class=\"queue-position\">" (+ index 1) "</span>"
|
||||
"<div class=\"queue-track-info\">"
|
||||
"<div class=\"track-title\">" (or (ps:@ track title) "Unknown") "</div>"
|
||||
"<div class=\"track-artist\">" (or (ps:@ track artist) "Unknown Artist")
|
||||
(if (ps:@ track album) (+ " - " (ps:@ track album)) "") "</div>"
|
||||
"</div>"
|
||||
"</div>")))))
|
||||
(setf html (+ html "</div>"))
|
||||
(setf (ps:@ container inner-h-t-m-l) html))))))
|
||||
|
||||
;; Save current queue to stream-queue.m3u
|
||||
(defun save-stream-queue ()
|
||||
(ps:chain
|
||||
(fetch "/api/asteroid/stream/playlists/save" (ps:create :method "POST"))
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(if (= (ps:@ data status) "success")
|
||||
(show-toast "✓ Queue saved")
|
||||
(alert (+ "Error saving queue: " (or (ps:@ data message) "Unknown error")))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error saving queue:" error))
|
||||
(alert "Error saving queue")))))
|
||||
|
||||
;; Save queue as new playlist
|
||||
(defun save-queue-as-new ()
|
||||
(let* ((input (ps:chain document (get-element-by-id "save-as-name")))
|
||||
(name (ps:chain (ps:@ input value) (trim))))
|
||||
(when (= name "")
|
||||
(alert "Please enter a name for the new playlist")
|
||||
(return))
|
||||
|
||||
(ps:chain
|
||||
(fetch (+ "/api/asteroid/stream/playlists/save-as?name=" (encode-u-r-i-component name))
|
||||
(ps:create :method "POST"))
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(if (= (ps:@ data status) "success")
|
||||
(progn
|
||||
(show-toast (+ "✓ Saved as " name))
|
||||
(setf (ps:@ input value) "")
|
||||
(load-playlist-list))
|
||||
(alert (+ "Error saving playlist: " (or (ps:@ data message) "Unknown error")))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error saving playlist:" error))
|
||||
(alert "Error saving playlist"))))))
|
||||
|
||||
;; Clear stream queue (updated to use new API)
|
||||
(defun clear-stream-queue ()
|
||||
(unless (confirm "Clear the stream queue? Liquidsoap will fall back to random playback from the music library.")
|
||||
(return))
|
||||
|
||||
(ps:chain
|
||||
(fetch "/api/asteroid/stream/playlists/clear" (ps:create :method "POST"))
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(if (= (ps:@ data status) "success")
|
||||
(progn
|
||||
(show-toast "✓ Queue cleared")
|
||||
(load-current-queue))
|
||||
(alert (+ "Error clearing queue: " (or (ps:@ data message) "Unknown error")))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error clearing queue:" error))
|
||||
(alert "Error clearing queue")))))
|
||||
|
||||
;; ========================================
|
||||
;; Liquidsoap Control Functions
|
||||
;; ========================================
|
||||
|
||||
;; Refresh Liquidsoap status
|
||||
(defun refresh-liquidsoap-status ()
|
||||
(ps:chain
|
||||
(fetch "/api/asteroid/liquidsoap/status")
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(when (= (ps:@ data status) "success")
|
||||
(let ((uptime-el (ps:chain document (get-element-by-id "ls-uptime")))
|
||||
(remaining-el (ps:chain document (get-element-by-id "ls-remaining")))
|
||||
(metadata-el (ps:chain document (get-element-by-id "ls-metadata"))))
|
||||
(when uptime-el
|
||||
(setf (ps:@ uptime-el text-content) (or (ps:@ data uptime) "--")))
|
||||
(when remaining-el
|
||||
(setf (ps:@ remaining-el text-content) (or (ps:@ data remaining) "--")))
|
||||
(when metadata-el
|
||||
(setf (ps:@ metadata-el text-content) (or (ps:@ data metadata) "--"))))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error fetching Liquidsoap status:" error))))))
|
||||
|
||||
;; Skip current track
|
||||
(defun liquidsoap-skip ()
|
||||
(ps:chain
|
||||
(fetch "/api/asteroid/liquidsoap/skip" (ps:create :method "POST"))
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(if (= (ps:@ data status) "success")
|
||||
(progn
|
||||
(show-toast "⏭️ Track skipped")
|
||||
(set-timeout refresh-liquidsoap-status 1000))
|
||||
(alert (+ "Error skipping track: " (or (ps:@ data message) "Unknown error")))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error skipping track:" error))
|
||||
(alert "Error skipping track")))))
|
||||
|
||||
;; Reload playlist
|
||||
(defun liquidsoap-reload ()
|
||||
(ps:chain
|
||||
(fetch "/api/asteroid/liquidsoap/reload" (ps:create :method "POST"))
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(if (= (ps:@ data status) "success")
|
||||
(show-toast "📂 Playlist reloaded")
|
||||
(alert (+ "Error reloading playlist: " (or (ps:@ data message) "Unknown error")))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error reloading playlist:" error))
|
||||
(alert "Error reloading playlist")))))
|
||||
|
||||
;; Restart Liquidsoap container
|
||||
(defun liquidsoap-restart ()
|
||||
(unless (confirm "Restart Liquidsoap container? This will cause a brief interruption to the stream.")
|
||||
(return))
|
||||
|
||||
(show-toast "🔄 Restarting Liquidsoap...")
|
||||
(ps:chain
|
||||
(fetch "/api/asteroid/liquidsoap/restart" (ps:create :method "POST"))
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(if (= (ps:@ data status) "success")
|
||||
(progn
|
||||
(show-toast "✓ Liquidsoap restarting")
|
||||
;; Refresh status after a delay to let container restart
|
||||
(set-timeout refresh-liquidsoap-status 5000))
|
||||
(alert (+ "Error restarting Liquidsoap: " (or (ps:@ data message) "Unknown error")))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error restarting Liquidsoap:" error))
|
||||
(alert "Error restarting Liquidsoap")))))
|
||||
|
||||
;; Restart Icecast container
|
||||
(defun icecast-restart ()
|
||||
(unless (confirm "Restart Icecast container? This will disconnect all listeners temporarily.")
|
||||
(return))
|
||||
|
||||
(show-toast "🔄 Restarting Icecast...")
|
||||
(ps:chain
|
||||
(fetch "/api/asteroid/icecast/restart" (ps:create :method "POST"))
|
||||
(then (lambda (response) (ps:chain response (json))))
|
||||
(then (lambda (result)
|
||||
(let ((data (or (ps:@ result data) result)))
|
||||
(if (= (ps:@ data status) "success")
|
||||
(show-toast "✓ Icecast restarting - listeners will reconnect automatically")
|
||||
(alert (+ "Error restarting Icecast: " (or (ps:@ data message) "Unknown error")))))))
|
||||
(catch (lambda (error)
|
||||
(ps:chain console (error "Error restarting Icecast:" error))
|
||||
(alert "Error restarting Icecast")))))
|
||||
|
||||
;; Make functions globally accessible for onclick handlers
|
||||
(setf (ps:@ window go-to-page) go-to-page)
|
||||
(setf (ps:@ window previous-page) previous-page)
|
||||
|
|
|
|||
|
|
@ -1,163 +1,98 @@
|
|||
#EXTM3U
|
||||
#EXTINF:370,Vector Lovers - City Lights From a Train
|
||||
Vector Lovers/City Lights From a Train.flac
|
||||
#EXTINF:400,The Black Dog - Psil-Cosyin
|
||||
The Black Dog/Psil-Cosyin.flac
|
||||
#EXTINF:320,Plaid - Eyen
|
||||
Plaid/Eyen.flac
|
||||
#EXTINF:330,ISAN - Birds Over Barges
|
||||
ISAN/Birds Over Barges.flac
|
||||
#EXTINF:360,Ochre - Bluebottle Farm
|
||||
Ochre/Bluebottle Farm.flac
|
||||
#EXTINF:390,Arovane - Theme
|
||||
Arovane/Theme.flac
|
||||
#EXTINF:380,Proem - Deep Like Airline Failure
|
||||
Proem/Deep Like Airline Failure.flac
|
||||
#EXTINF:310,Solvent - My Radio (Remix)
|
||||
Solvent/My Radio (Remix).flac
|
||||
#EXTINF:350,Bochum Welt - Marylebone (7th)
|
||||
Bochum Welt/Marylebone (7th).flac
|
||||
#EXTINF:290,Mrs Jynx - Shibuya Lullaby
|
||||
Mrs Jynx/Shibuya Lullaby.flac
|
||||
#EXTINF:340,Kettel - Whisper Me Wishes
|
||||
Kettel/Whisper Me Wishes.flac
|
||||
#EXTINF:360,Christ. - Perlandine Friday
|
||||
Christ./Perlandine Friday.flac
|
||||
#EXTINF:330,Cepia - Ithaca
|
||||
Cepia/Ithaca.flac
|
||||
#EXTINF:340,Datassette - Vacuform
|
||||
Datassette/Vacuform.flac
|
||||
#EXTINF:390,Plant43 - Dreams of the Sentient City
|
||||
Plant43/Dreams of the Sentient City.flac
|
||||
#EXTINF:410,Claro Intelecto - Peace of Mind (Electrosoul)
|
||||
Claro Intelecto/Peace of Mind (Electrosoul).flac
|
||||
#EXTINF:430,E.R.P. - Evoked
|
||||
E.R.P./Evoked.flac
|
||||
#EXTINF:310,Der Zyklus - Formenverwandler
|
||||
Der Zyklus/Formenverwandler.flac
|
||||
#EXTINF:330,Dopplereffekt - Infophysix
|
||||
Dopplereffekt/Infophysix.flac
|
||||
#EXTINF:350,Drexciya - Wavejumper
|
||||
Drexciya/Wavejumper.flac
|
||||
#EXTINF:375,The Other People Place - Sorrow & A Cup of Joe
|
||||
The Other People Place/Sorrow & A Cup of Joe.flac
|
||||
#EXTINF:340,Arpanet - Wireless Internet
|
||||
Arpanet/Wireless Internet.flac
|
||||
#EXTINF:380,Legowelt - Sturmvogel
|
||||
Legowelt/Sturmvogel.flac
|
||||
#EXTINF:310,DMX Krew - Space Paranoia
|
||||
DMX Krew/Space Paranoia.flac
|
||||
#EXTINF:360,Skywave Theory - Nova Drift
|
||||
Skywave Theory/Nova Drift.flac
|
||||
#EXTINF:460,Pye Corner Audio - Transmission Four
|
||||
Pye Corner Audio/Transmission Four.flac
|
||||
#EXTINF:390,B12 - Heaven Sent
|
||||
B12/Heaven Sent.flac
|
||||
#EXTINF:450,Higher Intelligence Agency - Tortoise
|
||||
Higher Intelligence Agency/Tortoise.flac
|
||||
#EXTINF:420,Biosphere - Kobresia
|
||||
Biosphere/Kobresia.flac
|
||||
#EXTINF:870,Global Communication - 14:31
|
||||
Global Communication/14:31.flac
|
||||
#EXTINF:500,Monolake - Cyan
|
||||
Monolake/Cyan.flac
|
||||
#EXTINF:660,Deepchord - Electromagnetic
|
||||
Deepchord/Electromagnetic.flac
|
||||
#EXTINF:1020,GAS - Pop 4
|
||||
GAS/Pop 4.flac
|
||||
#EXTINF:600,Yagya - Rigning Nýju
|
||||
Yagya/Rigning Nýju.flac
|
||||
#EXTINF:990,Voices From The Lake - Velo di Maya
|
||||
Voices From The Lake/Velo di Maya.flac
|
||||
#EXTINF:3720,ASC - Time Heals All
|
||||
ASC/Time Heals All.flac
|
||||
#EXTINF:540,36 - Room 237
|
||||
36/Room 237.flac
|
||||
#EXTINF:900,Loscil - Endless Falls
|
||||
Loscil/Endless Falls.flac
|
||||
#EXTINF:450,Kiasmos - Looped
|
||||
Kiasmos/Looped.flac
|
||||
#EXTINF:590,Underworld - Rez
|
||||
Underworld/Rez.flac
|
||||
#EXTINF:570,Orbital - Halcyon + On + On
|
||||
Orbital/Halcyon + On + On.flac
|
||||
#EXTINF:1080,The Orb - A Huge Ever Growing Pulsating Brain
|
||||
The Orb/A Huge Ever Growing Pulsating Brain.flac
|
||||
#EXTINF:360,Autechre - Slip
|
||||
Autechre/Slip.flac
|
||||
#EXTINF:400,Labradford - S (Mi Media Naranja)
|
||||
Labradford/S (Mi Media Naranja).flac
|
||||
#EXTINF:350,Vector Lovers - Rusting Cars and Wildflowers
|
||||
Vector Lovers/Rusting Cars and Wildflowers.flac
|
||||
#EXTINF:390,The Black Dog - Raxmus
|
||||
The Black Dog/Raxmus.flac
|
||||
#EXTINF:315,Plaid - Hawkmoth
|
||||
Plaid/Hawkmoth.flac
|
||||
#EXTINF:320,ISAN - What This Button Did
|
||||
ISAN/What This Button Did.flac
|
||||
#EXTINF:370,Ochre - Circadies
|
||||
Ochre/Circadies.flac
|
||||
#EXTINF:420,Arovane - Tides
|
||||
Arovane/Tides.flac
|
||||
#EXTINF:370,Proem - Nothing is as It Seems
|
||||
Proem/Nothing is as It Seems.flac
|
||||
#EXTINF:300,Solvent - Loss For Words
|
||||
Solvent/Loss For Words.flac
|
||||
#EXTINF:340,Bochum Welt - Saint (77sunset)
|
||||
Bochum Welt/Saint (77sunset).flac
|
||||
#EXTINF:280,Mrs Jynx - Stay Home
|
||||
Mrs Jynx/Stay Home.flac
|
||||
#EXTINF:330,Kettel - Church
|
||||
Kettel/Church.flac
|
||||
#EXTINF:370,Christ. - Cordate
|
||||
Christ./Cordate.flac
|
||||
#EXTINF:350,Datassette - Computers Elevate
|
||||
Datassette/Computers Elevate.flac
|
||||
#EXTINF:420,Plant43 - The Cold Surveyor
|
||||
Plant43/The Cold Surveyor.flac
|
||||
#EXTINF:380,Claro Intelecto - Section
|
||||
Claro Intelecto/Section.flac
|
||||
#EXTINF:440,E.R.P. - Vox Automaton
|
||||
E.R.P./Vox Automaton.flac
|
||||
#EXTINF:300,Dopplereffekt - Z-Boson
|
||||
Dopplereffekt/Z-Boson.flac
|
||||
#EXTINF:380,Drexciya - Digital Tsunami
|
||||
Drexciya/Digital Tsunami.flac
|
||||
#EXTINF:350,The Other People Place - You Said You Want Me
|
||||
The Other People Place/You Said You Want Me.flac
|
||||
#EXTINF:370,Legowelt - Star Gazing
|
||||
Legowelt/Star Gazing.flac
|
||||
#EXTINF:440,Pye Corner Audio - Electronic Rhythm Number 3
|
||||
Pye Corner Audio/Electronic Rhythm Number 3.flac
|
||||
#EXTINF:460,B12 - Infinite Lites (Classic Mix)
|
||||
B12/Infinite Lites (Classic Mix).flac
|
||||
#EXTINF:390,Biosphere - The Things I Tell You
|
||||
Biosphere/The Things I Tell You.flac
|
||||
#EXTINF:580,Global Communication - 9:39
|
||||
Global Communication/9:39.flac
|
||||
#EXTINF:460,Monolake - T-Channel
|
||||
Monolake/T-Channel.flac
|
||||
#EXTINF:690,Deepchord - Vantage Isle (Variant)
|
||||
Deepchord/Vantage Isle (Variant).flac
|
||||
#EXTINF:840,GAS - Königsforst 5
|
||||
GAS/Königsforst 5.flac
|
||||
#EXTINF:520,Yagya - The Salt on Her Cheeks
|
||||
Yagya/The Salt on Her Cheeks.flac
|
||||
#EXTINF:720,Voices From The Lake - Dream State
|
||||
Voices From The Lake/Dream State.flac
|
||||
#EXTINF:510,36 - Night Rain
|
||||
36/Night Rain.flac
|
||||
#EXTINF:470,Loscil - First Narrows
|
||||
Loscil/First Narrows.flac
|
||||
#EXTINF:400,Kiasmos - Burnt
|
||||
Kiasmos/Burnt.flac
|
||||
#EXTINF:570,Underworld - Jumbo (Extended)
|
||||
Underworld/Jumbo (Extended).flac
|
||||
#EXTINF:480,Orbital - Belfast
|
||||
Orbital/Belfast.flac
|
||||
#EXTINF:540,The Orb - Little Fluffy Clouds (Ambient Mix)
|
||||
The Orb/Little Fluffy Clouds (Ambient Mix).flac
|
||||
#EXTINF:390,Autechre - Nine
|
||||
Autechre/Nine.flac
|
||||
#EXTINF:380,Labradford - G (Mi Media Naranja)
|
||||
Labradford/G (Mi Media Naranja).flac
|
||||
#PLAYLIST:Asteroid Low Orbit - Ambient Electronic Journey
|
||||
#CURATOR:Asteroid Radio
|
||||
|
||||
#EXTINF:-1,Brian Eno - Emerald And Lime
|
||||
/app/music/Brian Eno/2011 - Small Craft On a Milk Sea/A1 Emerald And Lime.flac
|
||||
#EXTINF:-1,Brian Eno - Complex Heaven
|
||||
/app/music/Brian Eno/2011 - Small Craft On a Milk Sea/A2 Complex Heaven.flac
|
||||
#EXTINF:-1,Brian Eno - Dust Shuffle
|
||||
/app/music/Brian Eno/2011 - Small Craft On a Milk Sea/B4 Dust Shuffle.flac
|
||||
#EXTINF:-1,Brian Eno - Garden of Stars
|
||||
/app/music/Brian Eno/2022 - ForeverAndEverNoMore/04 Garden of Stars.flac
|
||||
#EXTINF:-1,Brian Eno - There Were Bells
|
||||
/app/music/Brian Eno/2022 - ForeverAndEverNoMore/06 There Were Bells.flac
|
||||
#EXTINF:-1,Biosphere - Drifter
|
||||
/app/music/Biosphere - The Petrified Forest (2017) - CD FLAC/01. Biosphere - Drifter.flac
|
||||
#EXTINF:-1,Biosphere - Black Mesa
|
||||
/app/music/Biosphere - The Petrified Forest (2017) - CD FLAC/02. Biosphere - Black Mesa.flac
|
||||
#EXTINF:-1,Biosphere - Skålbrekka
|
||||
/app/music/Biosphere - The Senja Recordings (2019) [FLAC]/01 - Skålbrekka.flac
|
||||
#EXTINF:-1,Biosphere - Bjorvika
|
||||
/app/music/Biosphere - The Senja Recordings (2019) [FLAC]/04 - Bjorvika.flac
|
||||
#EXTINF:-1,Biosphere - Out Of The Cradle
|
||||
/app/music/Biosphere - Departed Glories (2016) - FLAC WEB/01 - Out Of The Cradle.flac
|
||||
#EXTINF:-1,Biosphere - Down On Ropes
|
||||
/app/music/Biosphere - Departed Glories (2016) - FLAC WEB/03 - Down On Ropes.flac
|
||||
#EXTINF:-1,Biosphere - Microtunneling
|
||||
/app/music/Biosphere - Sound Installations -2000-2009 [FLAC]/Biosphere - Sound Installations -2000-2009- - 04 Microtunneling.flac
|
||||
#EXTINF:-1,Autechre - Dael
|
||||
/app/music/Autechre/1995 - Tri Repetae/01 Dael.flac
|
||||
#EXTINF:-1,Autechre - Further
|
||||
/app/music/Autechre/1994 - Amber/08 Further.flac
|
||||
#EXTINF:-1,Autechre - north spiral
|
||||
/app/music/Autechre - 2018 - NTS Session 1/NTS Session 1-006-Autechre-north spiral.flac
|
||||
#EXTINF:-1,Four Tet - Alap
|
||||
/app/music/Four Tet - New Energy {CD} [FLAC] (2017)/01 Alap.flac
|
||||
#EXTINF:-1,Four Tet - Scientists
|
||||
/app/music/Four Tet - New Energy {CD} [FLAC] (2017)/06 Scientists.flac
|
||||
#EXTINF:-1,Four Tet - Green
|
||||
/app/music/Four Tet - Sixteen Oceans (2020) {Text Records - TEXT051} [CD FLAC]/12 - Four Tet - Green.flac
|
||||
#EXTINF:-1,Four Tet - Parallel 8
|
||||
/app/music/Four Tet - Parallel (2020) - WEB FLAC/08. Parallel 8.flac
|
||||
#EXTINF:-1,Clark - Spring But Dark
|
||||
/app/music/Clark - Death Peak (2017) [FLAC]/01 - Spring But Dark.flac
|
||||
#EXTINF:-1,Clark - Kiri's Glee
|
||||
/app/music/Clark - Kiri Variations (2019) [WEB FLAC]/04 - Kiri's Glee.flac
|
||||
#EXTINF:-1,Clark - Primary Pluck
|
||||
/app/music/Clark - Kiri Variations (2019) [WEB FLAC]/08 - Primary Pluck.flac
|
||||
#EXTINF:-1,Clark - Cannibal Homecoming
|
||||
/app/music/Clark - Kiri Variations (2019) [WEB FLAC]/11 - Cannibal Homecoming.flac
|
||||
#EXTINF:-1,Clark - Absence (Bibio Remix)
|
||||
/app/music/Clark - Feast Beast (2013) [24 Bit WEB FLAC] [16-44]/1.12. Clark - Absence (Bibio Remix).flac
|
||||
#EXTINF:-1,Tycho - Glider
|
||||
/app/music/Tycho - Epoch (Deluxe Version) (2019) [WEB FLAC16-44.1]/01 - Glider.flac
|
||||
#EXTINF:-1,Tycho - Source
|
||||
/app/music/Tycho - Epoch (Deluxe Version) (2019) [WEB FLAC16-44.1]/07 - Source.flac
|
||||
#EXTINF:-1,Tycho - Rings
|
||||
/app/music/Tycho - Epoch (Deluxe Version) (2019) [WEB FLAC16-44.1]/09 - Rings.flac
|
||||
#EXTINF:-1,Tycho - Into The Woods
|
||||
/app/music/Tycho - Simulcast (2020) [WEB FLAC]/04 - Into The Woods.flac
|
||||
#EXTINF:-1,Tycho - Ascension
|
||||
/app/music/Thievery Corporation and Tycho - Fragments Ascension EP (flac)/3. Tycho - Ascension.flac
|
||||
#EXTINF:-1,Ulrich Schnauss - Negative Sunrise (2019 Version)
|
||||
/app/music/Ulrich Schnauss - No Further Ahead Than Tomorrow (2020) - WEB FLAC/09. Negative Sunrise (2019 Version).flac
|
||||
#EXTINF:-1,Ulrich Schnauss - Like a Ghost in Your Own Life
|
||||
/app/music/Ulrich Schnauss - A Long Way To Fall - Rebound (2020) - WEB FLAC/03. Like a Ghost in Your Own Life.flac
|
||||
#EXTINF:-1,Ulrich Schnauss & Jonas Munk - Solitary Falling
|
||||
/app/music/Ulrich Schnauss & Jonas Munk - Eight Fragments Of An Illusion (2021) - WEB FLAC/03. Solitary Falling.flac
|
||||
#EXTINF:-1,Ulrich Schnauss & Jonas Munk - Narkomfin
|
||||
/app/music/Ulrich Schnauss & Jonas Munk - Eight Fragments Of An Illusion (2021) - WEB FLAC/05. Narkomfin.flac
|
||||
#EXTINF:-1,Ulrich Schnauss & Jonas Munk - Polychrome
|
||||
/app/music/Ulrich Schnauss & Jonas Munk - Eight Fragments Of An Illusion (2021) - WEB FLAC/08. Polychrome.flac
|
||||
#EXTINF:-1,Proem - Winter Wolves
|
||||
/app/music/Proem - 2018 Modern Rope (WEB)/01. Winter Wolves.flac
|
||||
#EXTINF:-1,Proem - Modern Rope
|
||||
/app/music/Proem - 2018 Modern Rope (WEB)/05. Modern Rope.flac
|
||||
#EXTINF:-1,Proem - Kids That Hate Live Things
|
||||
/app/music/Proem - Until Here for Years (n5md, 2019) flac/11 - Kids That Hate Live Things.flac
|
||||
#EXTINF:-1,Proem - End Tail
|
||||
/app/music/Proem - Twelve Tails-(2021) @FLAC [16-48]/07 - End Tail.flac
|
||||
#EXTINF:-1,Proem - In a Timeless, Lightless World
|
||||
/app/music/Proem/2019 - As They Go/Proem - As They Go - 05 In a Timeless, Lightless World.flac
|
||||
#EXTINF:-1,arovane - komposition no. 1
|
||||
/app/music/arovane - Wirkung (2020) [WEB FLAC16]/17. arovane - komposition no. 1.flac
|
||||
#EXTINF:-1,arovane - hymn
|
||||
/app/music/arovane - Wirkung (2020) [WEB FLAC16]/12. arovane - hymn.flac
|
||||
#EXTINF:-1,Aphex Twin - CHEETAHT7b
|
||||
/app/music/Aphex Twin (2016) Cheetah EP [WEB] [FLAC]/Cheetah EP-002-Aphex Twin-CHEETAHT7b.flac
|
||||
#EXTINF:-1,Aphex Twin - CHEETA2 ms800
|
||||
/app/music/Aphex Twin (2016) Cheetah EP [WEB] [FLAC]/Cheetah EP-004-Aphex Twin-CHEETA2 ms800.flac
|
||||
#EXTINF:-1,Plaid - Sun Electric - Tee (Plaid Mix)
|
||||
/app/music/Plaid - Stem Sell (Plaid Remixes) [2021] (WEB - FLAC - Lossless)/17-Sun_Electric-Tee_(Plaid_Mix).flac
|
||||
#EXTINF:-1,Plaid - Origamibiro - Impressions Of Football (Plaid Remix)
|
||||
/app/music/Plaid - Stem Sell (Plaid Remixes) [2021] (WEB - FLAC - Lossless)/11-Origamibiro-Impressions_Of_Football_(Plaid_Remix).flac
|
||||
#EXTINF:-1,Plaid - Ricardo Tobar - After The Movie (Plaid Remix)
|
||||
/app/music/Plaid - Stem Sell (Plaid Remixes) [2021] (WEB - FLAC - Lossless)/21-Ricardo_Tobar-After_The_Movie_(Plaid_Remix).flac
|
||||
#EXTINF:-1,Plaid - Esem - Yourturn (Plaid Remix)
|
||||
/app/music/Plaid - Stem Sell (Plaid Remixes) [2021] (WEB - FLAC - Lossless)/26-Esem-Yourturn_(Plaid_Remix).flac
|
||||
|
|
|
|||
|
|
@ -1,371 +1,144 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1,Underworld - Underworld - Confusion The Waitress
|
||||
/app/music/Underworld/1996 - Second Toughest In The Infants/03. Underworld - Confusion The Waitress.flac
|
||||
#EXTINF:-1,The Orb - Towers Of Dub
|
||||
/app/music/The Orb/1992 - UFOrb/04-Towers Of Dub.mp3
|
||||
#EXTINF:-1,Drexciya - Drexciya - Intensified Magnetron
|
||||
/app/music/Drexciya/2013 - Journey Of The Deep Sea Dweller III/04. Drexciya - Intensified Magnetron.mp3
|
||||
#EXTINF:-1,Labradford - Balanced on It's Own Flame
|
||||
/app/music/Labradford/1995 - A Stable Reference/6 Balanced on It's Own Flame.flac
|
||||
#EXTINF:-1,Vector Lovers - City Lights From A Train
|
||||
/app/music/Vector Lovers/2005 - Capsule For One/01 - City Lights From A Train.mp3
|
||||
#EXTINF:-1,Labradford - Leta O'Steen. Design assistance by John Piper
|
||||
/app/music/Labradford/1999 - E luxo so/6. Leta O'Steen. Design assistance by John Piper.flac
|
||||
#EXTINF:-1,Tape Loop Orchestra - Tape Loop Orchestra - Chapter 1 Reel One
|
||||
/app/music/Tape Loop Orchestra/2009 - 1953 Culture Festival/01 Tape Loop Orchestra - Chapter 1 Reel One.mp3
|
||||
#EXTINF:-1,Orbital - Time Becomes
|
||||
/app/music/Orbital/1993 - Orbital - Orbital 2 (Brown Album - TRUCD2, 828 386.2)/00. Time Becomes.mp3
|
||||
#EXTINF:-1,Proem - Proem - You Shall Have Ever Been - 05 No You Are $
|
||||
/app/music/Proem/2006 - You Shall Have Ever Been/Proem - You Shall Have Ever Been - 05 No You Are $.flac
|
||||
#EXTINF:-1,Pye Corner Audio - Pye Corner Audio - The Simplest Equation
|
||||
/app/music/Pye Corner Audio/EP's & Singles/2016 - Pye Corner Audio With Dalhous - Run For The Shadows EP (WEB, #LPS13)/02 - Pye Corner Audio - The Simplest Equation.mp3
|
||||
#EXTINF:-1,Brian Eno - Emerald and Lime
|
||||
/app/music/Brian Eno/2024 - Eno (Original Motion Picture Soundtrack)/12. Emerald and Lime.flac
|
||||
#EXTINF:-1,Bark Psychosis - (07) [Bark Psychosis] A Street Scene
|
||||
/app/music/Bark Psychosis/1994 - Game Over/(07) [Bark Psychosis] A Street Scene.flac
|
||||
#EXTINF:-1,Model 500 - model_500-digital_solutions
|
||||
/app/music/Model 500/2015 - Digital Solutions/08-model_500-digital_solutions.flac
|
||||
#EXTINF:-1,Labradford - Banco
|
||||
/app/music/Labradford/1995 - A Stable Reference/4 Banco.flac
|
||||
#EXTINF:-1,Labradford - Skyward With Motion
|
||||
/app/music/Labradford/1993 - Prazision LP/11 Skyward With Motion.flac
|
||||
#EXTINF:-1,Pye Corner Audio - The Mirror Ball Cracked
|
||||
/app/music/Pye Corner Audio/2012 - Sleep Games (WEB, #GBX017)/08 - The Mirror Ball Cracked.mp3
|
||||
#EXTINF:-1,Brian Eno - Foreign Affairs
|
||||
/app/music/Brian Eno/1978 - After The Heat/01 - Foreign Affairs.flac
|
||||
#EXTINF:-1,The Other People Place - B1 - Moonlight Rendezvous
|
||||
/app/music/The Other People Place/2017 - Lifestyles Of The Laptop Café/B1 - Moonlight Rendezvous.flac
|
||||
#EXTINF:-1,Drexciya - Unknown Journey IX
|
||||
/app/music/Drexciya/2013 - Journey of the Deep Sea Dweller IV/10. Unknown Journey IX.mp3
|
||||
#EXTINF:-1,Orbital - Crash And Carry
|
||||
/app/music/Orbital/1994 - Orbital - Snivilisation (TRUCD5, 828 536.2)/04. Crash And Carry.mp3
|
||||
#EXTINF:-1,Proem - Proem - Before it finds you - 09 We can watch it burn to the ground
|
||||
/app/music/Proem/2013 - Before it finds you/Proem - Before it finds you - 09 We can watch it burn to the ground.flac
|
||||
#EXTINF:-1,Proem - Proem - Before it finds you - 01 Stone into gravel
|
||||
/app/music/Proem/2013 - Before it finds you/Proem - Before it finds you - 01 Stone into gravel.flac
|
||||
#EXTINF:-1,Drexciya - Intro (The Unknown Aquazone)
|
||||
/app/music/Drexciya/2013 - Journey of the Deep Sea Dweller IV/01. Intro (The Unknown Aquazone).mp3
|
||||
#EXTINF:-1,Teeth Of The Sea - Get With the Program
|
||||
/app/music/Teeth Of The Sea/2023 - Hive/02 Get With the Program.flac
|
||||
#EXTINF:-1,Proem - Proem - Vault ep.4-4 - 02 Little girls
|
||||
/app/music/Proem/2015 - Vault ep.4-4/Proem - Vault ep.4-4 - 02 Little girls.flac
|
||||
#EXTINF:-1,Drexciya - Black Sea
|
||||
/app/music/Drexciya/2013 - Journey of the Deep Sea Dweller IV/14. Black Sea.mp3
|
||||
#EXTINF:-1,Autechre - Yulquen
|
||||
/app/music/Autechre/1994 - Amber/09 Yulquen.flac
|
||||
#EXTINF:-1,The Other People Place - C2 - Running From Love
|
||||
/app/music/The Other People Place/2017 - Lifestyles Of The Laptop Café/C2 - Running From Love.flac
|
||||
#EXTINF:-1,Brian Eno - D2 Written, Forgotten
|
||||
/app/music/Brian Eno/2011 - Small Craft On a Milk Sea/D2 Written, Forgotten.flac
|
||||
#EXTINF:-1,Autechre - Stud
|
||||
/app/music/Autechre/1995 - Tri Repetae/05 Stud.flac
|
||||
#EXTINF:-1,Model 500 - model_500-electric_night
|
||||
/app/music/Model 500/2015 - Digital Solutions/02-model_500-electric_night.flac
|
||||
#EXTINF:-1,The Orb - Close Encounters
|
||||
/app/music/The Orb/1992 - UFOrb/05-Close Encounters.mp3
|
||||
#EXTINF:-1,Model 500 - model_500-hi_nrg
|
||||
/app/music/Model 500/2015 - Digital Solutions/01-model_500-hi_nrg.flac
|
||||
#EXTINF:-1,Brian Eno - B3 Bone Jump
|
||||
/app/music/Brian Eno/2011 - Small Craft On a Milk Sea/B3 Bone Jump.flac
|
||||
#EXTINF:-1,Labradford - by Chris Johnston, Craig Markva, Jamie Evans,
|
||||
/app/music/Labradford/1999 - E luxo so/4. by Chris Johnston, Craig Markva, Jamie Evans,.flac
|
||||
#EXTINF:-1,The Orb - Star 6 & 7 8 9
|
||||
/app/music/The Orb/1991 - The Orb's Adventures Beyond the Ultraworld (Double Album)/09 Star 6 & 7 8 9.mp3
|
||||
#EXTINF:-1,Proem - Proem - Vault ep.1-4 (Noise) - 02 Half a Heart
|
||||
/app/music/Proem/2016 - Vault ep.1-4 (Noise)/Proem - Vault ep.1-4 (Noise) - 02 Half a Heart.flac
|
||||
#EXTINF:-1,Dopplereffekt - Spirangle
|
||||
/app/music/Dopplereffekt/2017 - Cellular Automata/08. Spirangle.flac
|
||||
#EXTINF:-1,Drexciya - Unknown Journey VII
|
||||
/app/music/Drexciya/2013 - Journey of the Deep Sea Dweller IV/06. Unknown Journey VII.mp3
|
||||
#EXTINF:-1,Drexciya - Mantaray
|
||||
/app/music/Drexciya/2013 - Journey of the Deep Sea Dweller IV/04. Mantaray.mp3
|
||||
#EXTINF:-1,Pye Corner Audio - Pye Corner Audio - Untitled
|
||||
/app/music/Pye Corner Audio/EP's & Singles/2017 - Pye Corner Audio, Silent Servant, Not Waving - Limited Edition EP (Vinyl, #E031COL)/02 - Pye Corner Audio - Untitled.mp3
|
||||
#EXTINF:-1,Underworld - Underworld - Juanita, Kiteless, To Dream Of Love
|
||||
/app/music/Underworld/1996 - Second Toughest In The Infants/01. Underworld - Juanita, Kiteless, To Dream Of Love.flac
|
||||
#EXTINF:-1,Proem - Proem - As They Go - 05 In a Timeless, Lightless World
|
||||
/app/music/Proem/2019 - As They Go/Proem - As They Go - 05 In a Timeless, Lightless World.flac
|
||||
#EXTINF:-1,Model 500 - model_500-standing_in_tomorow
|
||||
/app/music/Model 500/2015 - Digital Solutions/03-model_500-standing_in_tomorow.flac
|
||||
#EXTINF:-1,The Orb - Plum Island
|
||||
/app/music/The Orb/2001 - Cydonia/09-Plum Island.mp3
|
||||
#EXTINF:-1,Orbital - Lush 3-2
|
||||
/app/music/Orbital/1993 - Orbital - Orbital 2 (Brown Album - TRUCD2, 828 386.2)/00. Lush 3-2.mp3
|
||||
#EXTINF:-1,Dopplereffekt - Exponential Decay
|
||||
/app/music/Dopplereffekt/2017 - Cellular Automata/09. Exponential Decay.flac
|
||||
#EXTINF:-1,Brian Eno - Garden of Stars
|
||||
/app/music/Brian Eno/2022 - ForeverAndEverNoMore/04 Garden of Stars.flac
|
||||
#EXTINF:-1,The Other People Place - B2 - You Said You Want Me
|
||||
/app/music/The Other People Place/2017 - Lifestyles Of The Laptop Café/B2 - You Said You Want Me.flac
|
||||
#EXTINF:-1,Dopplereffekt - Mandelbrot Set
|
||||
/app/music/Dopplereffekt/2017 - Cellular Automata/07. Mandelbrot Set.flac
|
||||
#EXTINF:-1,Autechre - Foil
|
||||
/app/music/Autechre/1994 - Amber/01 Foil.flac
|
||||
#EXTINF:-1,Proem - Proem - As They Go - 04 What is Needed
|
||||
/app/music/Proem/2019 - As They Go/Proem - As They Go - 04 What is Needed.flac
|
||||
#EXTINF:-1,Vector Lovers - Post Arctic Industries
|
||||
/app/music/Vector Lovers/2005 - Capsule For One/06 - Post Arctic Industries.mp3
|
||||
#EXTINF:-1,Proem - proem - Negativ - 12 Skylup
|
||||
/app/music/Proem/2001 - Negativ/proem - Negativ - 12 Skylup.flac
|
||||
#EXTINF:-1,Model 500 - model_500-encounter
|
||||
/app/music/Model 500/2015 - Digital Solutions/04-model_500-encounter.flac
|
||||
#EXTINF:-1,Kraftwerk - Pocket Calculator
|
||||
/app/music/Kraftwerk/1981 - Computer World/02 - Pocket Calculator.flac
|
||||
#EXTINF:-1,Tape Loop Orchestra - Tape Loop Orchestra - Chapter 13 Reel Two End
|
||||
/app/music/Tape Loop Orchestra/2009 - 1953 Culture Festival/13 Tape Loop Orchestra - Chapter 13 Reel Two End.mp3
|
||||
#EXTINF:-1,Pye Corner Audio - Corrupt Data
|
||||
/app/music/Pye Corner Audio/2017 - Half-Light (Prower Remixed) (WEB, #MTH011)/01 - Corrupt Data.mp3
|
||||
#EXTINF:-1,Kiasmos - Kiasmos - II - 04 Laced
|
||||
/app/music/Kiasmos/2024 - II/Kiasmos - II - 04 Laced.flac
|
||||
#EXTINF:-1,Pye Corner Audio - Mindshaft
|
||||
/app/music/Pye Corner Audio/2019 - Hollow Earth (WEB, #GBX032 DL)/05 - Mindshaft.mp3
|
||||
#EXTINF:-1,Labradford - G
|
||||
/app/music/Labradford/1997 - Mi Media Naranja/2 G.flac
|
||||
#EXTINF:-1,Dopplereffekt - Isotropy
|
||||
/app/music/Dopplereffekt/2017 - Cellular Automata/04. Isotropy.flac
|
||||
#EXTINF:-1,Autechre - Further
|
||||
/app/music/Autechre/1994 - Amber/08 Further.flac
|
||||
#EXTINF:-1,Proem - Proem - You Shall Have Ever Been - 02 Eck The Badly Drawn
|
||||
/app/music/Proem/2006 - You Shall Have Ever Been/Proem - You Shall Have Ever Been - 02 Eck The Badly Drawn.flac
|
||||
#EXTINF:-1,Autechre - C-Pach
|
||||
/app/music/Autechre/1995 - Tri Repetae/07 C-Pach.flac
|
||||
#EXTINF:-1,Kraftwerk - Neon Lights
|
||||
/app/music/Kraftwerk/1978 - The Man-Machine/05 - Neon Lights.flac
|
||||
#EXTINF:-1,Labradford - twenty
|
||||
/app/music/Labradford/2001 - fixed..context/1 twenty.flac
|
||||
#EXTINF:-1,Bark Psychosis - (01) [Bark Psychosis] Blue
|
||||
/app/music/Bark Psychosis/1994 - Game Over/(01) [Bark Psychosis] Blue.flac
|
||||
#EXTINF:-1,Vector Lovers - Substrata
|
||||
/app/music/Vector Lovers/2005 - Capsule For One/03 - Substrata.mp3
|
||||
#EXTINF:-1,Kraftwerk - Computer World
|
||||
/app/music/Kraftwerk/1981 - Computer World/01 - Computer World.flac
|
||||
#EXTINF:-1,Underworld - Underworld - Air Towel
|
||||
/app/music/Underworld/1996 - Second Toughest In The Infants/06. Underworld - Air Towel.flac
|
||||
#EXTINF:-1,Underworld - Underworld - Blueski
|
||||
/app/music/Underworld/1996 - Second Toughest In The Infants/07. Underworld - Blueski.flac
|
||||
#EXTINF:-1,Labradford - Experience The Gated Oscillator
|
||||
/app/music/Labradford/1993 - Prazision LP/05 Experience The Gated Oscillator.flac
|
||||
#EXTINF:-1,Dopplereffekt - Gestalt Intelligence
|
||||
/app/music/Dopplereffekt/2017 - Cellular Automata/03. Gestalt Intelligence.flac
|
||||
#EXTINF:-1,Labradford - Dulcimers played by Peter Neff. Strings played
|
||||
/app/music/Labradford/1999 - E luxo so/3. Dulcimers played by Peter Neff. Strings played.flac
|
||||
#EXTINF:-1,Tape Loop Orchestra - Tape Loop Orchestra - Chapter 14 Tails Out
|
||||
/app/music/Tape Loop Orchestra/2009 - 1953 Culture Festival/14 Tape Loop Orchestra - Chapter 14 Tails Out.mp3
|
||||
#EXTINF:-1,Labradford - up to pizmo
|
||||
/app/music/Labradford/2001 - fixed..context/2 up to pizmo.flac
|
||||
#EXTINF:-1,Orbital - Sad But True
|
||||
/app/music/Orbital/1994 - Orbital - Snivilisation (TRUCD5, 828 536.2)/03. Sad But True.mp3
|
||||
#EXTINF:-1,Orbital - Lush 3-1
|
||||
/app/music/Orbital/1993 - Orbital - Orbital 2 (Brown Album - TRUCD2, 828 386.2)/00. Lush 3-1.mp3
|
||||
#EXTINF:-1,Dopplereffekt - Cellular Automata
|
||||
/app/music/Dopplereffekt/2017 - Cellular Automata/01. Cellular Automata.flac
|
||||
#EXTINF:-1,The Orb - Little Fluffy Clouds
|
||||
/app/music/The Orb/1991 - The Orb's Adventures Beyond the Ultraworld (Double Album)/01 Little Fluffy Clouds.mp3
|
||||
#EXTINF:-1,Bark Psychosis - All Different Things
|
||||
/app/music/Bark Psychosis/1994 - Independency/03 - All Different Things.flac
|
||||
#EXTINF:-1,Orbital - Kein Trink Wasser
|
||||
/app/music/Orbital/1994 - Orbital - Snivilisation (TRUCD5, 828 536.2)/07. Kein Trink Wasser.mp3
|
||||
#EXTINF:-1,The Orb - Perpetual Dawn
|
||||
/app/music/The Orb/1991 - The Orb's Adventures Beyond the Ultraworld (Double Album)/06 Perpetual Dawn.mp3
|
||||
#EXTINF:-1,Underworld - Underworld - Stagger
|
||||
/app/music/Underworld/1996 - Second Toughest In The Infants/08. Underworld - Stagger.flac
|
||||
#EXTINF:-1,Dopplereffekt - von Neumann Probe
|
||||
/app/music/Dopplereffekt/2017 - Cellular Automata/02. von Neumann Probe.flac
|
||||
#EXTINF:-1,The Orb - EDM
|
||||
/app/music/The Orb/2001 - Cydonia/12-EDM.mp3
|
||||
#EXTINF:-1,Teeth Of The Sea - Reaper
|
||||
/app/music/Teeth Of The Sea/2013 - Master/02 - Reaper.mp3
|
||||
#EXTINF:-1,Drexciya - Drexciya - Aquabahn
|
||||
/app/music/Drexciya/2013 - Journey Of The Deep Sea Dweller III/03. Drexciya - Aquabahn.mp3
|
||||
#EXTINF:-1,Autechre - Rsdio
|
||||
/app/music/Autechre/1995 - Tri Repetae/10 Rsdio.flac
|
||||
#EXTINF:-1,Teeth Of The Sea - Transfinite
|
||||
/app/music/Teeth Of The Sea/2010 - Your Mercury/01 Transfinite.mp3
|
||||
#EXTINF:-1,Orbital - Philosophy By Numbers
|
||||
/app/music/Orbital/1994 - Orbital - Snivilisation (TRUCD5, 828 536.2)/06. Philosophy By Numbers.mp3
|
||||
#EXTINF:-1,Autechre - Dael
|
||||
/app/music/Autechre/1995 - Tri Repetae/01 Dael.flac
|
||||
#EXTINF:-1,Vector Lovers - Boulevard
|
||||
/app/music/Vector Lovers/2005 - Capsule For One/09 - Boulevard.mp3
|
||||
#EXTINF:-1,Brian Eno - Reflection
|
||||
/app/music/Brian Eno/2017 - Reflection/01. Reflection.mp3
|
||||
#EXTINF:-1,Kiasmos - Thrown
|
||||
/app/music/Kiasmos/2012 - Thrown EP/01 - Thrown.flac
|
||||
#EXTINF:-1,The Other People Place - A2 - It's Your Love
|
||||
/app/music/The Other People Place/2017 - Lifestyles Of The Laptop Café/A2 - It's Your Love.flac
|
||||
#EXTINF:-1,Drexciya - Unknown Journey VIII
|
||||
/app/music/Drexciya/2013 - Journey of the Deep Sea Dweller IV/07. Unknown Journey VIII.mp3
|
||||
#EXTINF:-1,Bark Psychosis - I Know
|
||||
/app/music/Bark Psychosis/1994 - Independency/01 - I Know.flac
|
||||
#EXTINF:-1,Underworld - Underworld - Rowla
|
||||
/app/music/Underworld/1996 - Second Toughest In The Infants/04. Underworld - Rowla.flac
|
||||
#EXTINF:-1,Orbital - Forever
|
||||
/app/music/Orbital/1994 - Orbital - Snivilisation (TRUCD5, 828 536.2)/01. Forever.mp3
|
||||
#EXTINF:-1,Autechre - Clipper
|
||||
/app/music/Autechre/1995 - Tri Repetae/02 Clipper.flac
|
||||
#EXTINF:-1,The Other People Place - C1 - Let Me Be Me
|
||||
/app/music/The Other People Place/2017 - Lifestyles Of The Laptop Café/C1 - Let Me Be Me.flac
|
||||
#EXTINF:-1,Kraftwerk - Metropolis
|
||||
/app/music/Kraftwerk/1978 - The Man-Machine/03 - Metropolis.flac
|
||||
#EXTINF:-1,Labradford - The Cipher
|
||||
/app/music/Labradford/1996 - Labradford/4 The Cipher.flac
|
||||
#EXTINF:-1,Autechre - Silverside
|
||||
/app/music/Autechre/1994 - Amber/03 Silverside.flac
|
||||
#EXTINF:-1,Autechre - Nine
|
||||
/app/music/Autechre/1994 - Amber/07 Nine.flac
|
||||
#EXTINF:-1,Kraftwerk - Numbers
|
||||
/app/music/Kraftwerk/1981 - Computer World/03 - Numbers.flac
|
||||
#EXTINF:-1,Pye Corner Audio - Recrypt
|
||||
/app/music/Pye Corner Audio/2011 - Black Mill Tapes Volume 2 - Do You Synthesize (WEB, #pca002)/06 - Recrypt.mp3
|
||||
#EXTINF:-1,The Other People Place - D1 - Lifestyles Of The Casual
|
||||
/app/music/The Other People Place/2017 - Lifestyles Of The Laptop Café/D1 - Lifestyles Of The Casual.flac
|
||||
#EXTINF:-1,Autechre - Teartear
|
||||
/app/music/Autechre/1994 - Amber/11 Teartear.flac
|
||||
#EXTINF:-1,Teeth Of The Sea - in the space capsule (love theme)
|
||||
/app/music/Teeth Of The Sea/2011 - Hypnoticon/01 in the space capsule (love theme).mp3
|
||||
#EXTINF:-1,Kiasmos - Dragged
|
||||
/app/music/Kiasmos/2014 - Kiasmos/06 - Dragged.flac
|
||||
#EXTINF:-1,Dopplereffekt - Ulams Spiral
|
||||
/app/music/Dopplereffekt/2017 - Cellular Automata/06. Ulams Spiral.flac
|
||||
#EXTINF:-1,Brian Eno - Stiff
|
||||
/app/music/Brian Eno/2024 - Eno (Original Motion Picture Soundtrack)/11. Stiff.flac
|
||||
#EXTINF:-1,The Orb - A Huge Ever Growing Pulsating Brain That Rules From The Centre Of The Ultraworld_ Live Mix Mk 10
|
||||
/app/music/The Orb/1991 - The Orb's Adventures Beyond the Ultraworld (Double Album)/10 A Huge Ever Growing Pulsating Brain That Rules From The Centre Of The Ultraworld_ Live Mix Mk 10.mp3
|
||||
#EXTINF:-1,The Orb - Sticky End
|
||||
/app/music/The Orb/1992 - UFOrb/07-Sticky End.mp3
|
||||
#EXTINF:-1,Vector Lovers - Microtron
|
||||
/app/music/Vector Lovers/2005 - Capsule For One/04 - Microtron.mp3
|
||||
#EXTINF:-1,Kraftwerk - Home Computer
|
||||
/app/music/Kraftwerk/1981 - Computer World/06 - Home Computer.flac
|
||||
#EXTINF:-1,Pye Corner Audio - Foreshadowed
|
||||
/app/music/Pye Corner Audio/2012 - Black Mill Tapes Volume 3 - All Pathways Open (WEB, #pca003)/08 - Foreshadowed.mp3
|
||||
#EXTINF:-1,Tape Loop Orchestra - Tape Loop Orchestra - Chapter 2 Yasujiro Ozu
|
||||
/app/music/Tape Loop Orchestra/2009 - 1953 Culture Festival/02 Tape Loop Orchestra - Chapter 2 Yasujiro Ozu.mp3
|
||||
#EXTINF:-1,Brian Eno - Verdigris
|
||||
/app/music/Brian Eno/2020 - Roger Eno and Brian Eno - Mixing Colours/08 Verdigris.flac
|
||||
#EXTINF:-1,Tape Loop Orchestra - The Word On My Lips Is Your Name
|
||||
/app/music/Tape Loop Orchestra/2012 - The Word On My Lips Is Your Name/Disc 1 - The Word On My Lips Is Your Name/01 - The Word On My Lips Is Your Name.flac
|
||||
#EXTINF:-1,Vector Lovers - Melodies And Memory
|
||||
/app/music/Vector Lovers/2005 - Capsule For One/07 - Melodies And Memory.mp3
|
||||
#EXTINF:-1,Vector Lovers - To The Stars
|
||||
/app/music/Vector Lovers/2005 - Capsule For One/12 - To The Stars.mp3
|
||||
#EXTINF:-1,Dopplereffekt - Pascal's Recursion
|
||||
/app/music/Dopplereffekt/2017 - Cellular Automata/05. Pascal's Recursion.flac
|
||||
#EXTINF:-1,Orbital - Walk Now
|
||||
/app/music/Orbital/1993 - Orbital - Orbital 2 (Brown Album - TRUCD2, 828 386.2)/00. Walk Now.mp3
|
||||
#EXTINF:-1,Orbital - Quality Seconds
|
||||
/app/music/Orbital/1994 - Orbital - Snivilisation (TRUCD5, 828 536.2)/08. Quality Seconds.mp3
|
||||
#EXTINF:-1,Vector Lovers - Nostalgia 4 The Future
|
||||
/app/music/Vector Lovers/2005 - Capsule For One/05 - Nostalgia 4 The Future.mp3
|
||||
#EXTINF:-1,Brian Eno - D3 Late Anthropocene
|
||||
/app/music/Brian Eno/2011 - Small Craft On a Milk Sea/D3 Late Anthropocene.flac
|
||||
#EXTINF:-1,Autechre - Gnit
|
||||
/app/music/Autechre/1995 - Tri Repetae/08 Gnit.flac
|
||||
#EXTINF:-1,Pye Corner Audio - Electronic Rhythm Number Seven
|
||||
/app/music/Pye Corner Audio/2011 - Black Mill Tapes Volume 2 - Do You Synthesize (WEB, #pca002)/02 - Electronic Rhythm Number Seven.mp3
|
||||
#EXTINF:-1,Proem - Proem - Socially Inept - 05 Pinching Point
|
||||
/app/music/Proem/2004 - Socially Inept/Proem - Socially Inept - 05 Pinching Point.flac
|
||||
#EXTINF:-1,Vector Lovers - Empty Buildings, Falling Rain
|
||||
/app/music/Vector Lovers/2005 - Capsule For One/08 - Empty Buildings, Falling Rain.mp3
|
||||
#EXTINF:-1,Model 500 - model_500-control
|
||||
/app/music/Model 500/2015 - Digital Solutions/09-model_500-control.flac
|
||||
#EXTINF:-1,Proem - Proem - Vault ep.2-4 (Drone) - 02 Another Dull Moment
|
||||
/app/music/Proem/2016 - Vault ep.2-4 (Drone)/Proem - Vault ep.2-4 (Drone) - 02 Another Dull Moment.flac
|
||||
#EXTINF:-1,Teeth Of The Sea - Her Wraith
|
||||
/app/music/Teeth Of The Sea/2019 - WRAITH/06 - Her Wraith.flac
|
||||
#EXTINF:-1,Brian Eno - Slow Movement Sand
|
||||
/app/music/Brian Eno/2020 - Roger Eno and Brian Eno - Mixing Colours/18 Slow Movement Sand.flac
|
||||
#EXTINF:-1,Drexciya - Drexciya - You Don't Know
|
||||
/app/music/Drexciya/2013 - Journey Of The Deep Sea Dweller III/13. Drexciya - You Don't Know.mp3
|
||||
#EXTINF:-1,Proem - Proem - You Shall Have Ever Been - 07 Reddings
|
||||
/app/music/Proem/2006 - You Shall Have Ever Been/Proem - You Shall Have Ever Been - 07 Reddings.flac
|
||||
#EXTINF:-1,Teeth Of The Sea - Fortean Steed
|
||||
/app/music/Teeth Of The Sea/2019 - WRAITH/04 - Fortean Steed.flac
|
||||
#EXTINF:-1,Kraftwerk - The Model
|
||||
/app/music/Kraftwerk/1978 - The Man-Machine/04 - The Model.flac
|
||||
#EXTINF:-1,Pye Corner Audio - Yesterday's Entertainment
|
||||
/app/music/Pye Corner Audio/2012 - Sleep Games (WEB, #GBX017)/07 - Yesterday's Entertainment.mp3
|
||||
#EXTINF:-1,Brian Eno - B2 Forms Of Anger
|
||||
/app/music/Brian Eno/2011 - Small Craft On a Milk Sea/B2 Forms Of Anger.flac
|
||||
#EXTINF:-1,Vector Lovers - Neon Sky Rain
|
||||
/app/music/Vector Lovers/2005 - Capsule For One/10 - Neon Sky Rain.mp3
|
||||
#EXTINF:-1,Vector Lovers - Capsule For One
|
||||
/app/music/Vector Lovers/2005 - Capsule For One/11 - Capsule For One.mp3
|
||||
#EXTINF:-1,Pye Corner Audio - Solar Waves
|
||||
/app/music/Pye Corner Audio/EP's & Singles/2019 - Dark Phase EP (WEB, #AF025)/02 - Solar Waves.mp3
|
||||
#EXTINF:-1,Kraftwerk - Computer Love
|
||||
/app/music/Kraftwerk/1981 - Computer World/05 - Computer Love.flac
|
||||
#EXTINF:-1,Kiasmos - Held (Dauwd Remix)
|
||||
/app/music/Kiasmos/2015 - Looped/02 Held (Dauwd Remix).flac
|
||||
#EXTINF:-1,Tape Loop Orchestra - Tape Loop Orchestra - Chapter 9 Setsu Ko Hara
|
||||
/app/music/Tape Loop Orchestra/2009 - 1953 Culture Festival/09 Tape Loop Orchestra - Chapter 9 Setsu Ko Hara.mp3
|
||||
#EXTINF:-1,The Orb - Back Side of the Moon
|
||||
/app/music/The Orb/1991 - The Orb's Adventures Beyond the Ultraworld (Double Album)/04 Back Side of the Moon.mp3
|
||||
#EXTINF:-1,Model 500 - model_500-storm
|
||||
/app/music/Model 500/2015 - Digital Solutions/05-model_500-storm.flac
|
||||
#EXTINF:-1,Autechre - Montreal
|
||||
/app/music/Autechre/1994 - Amber/02 Montreal.flac
|
||||
#EXTINF:-1,Bark Psychosis - bark psychosis - eyes & smiles
|
||||
/app/music/Bark Psychosis/1994 - Hex/05 - bark psychosis - eyes & smiles.mp3
|
||||
#EXTINF:-1,The Other People Place - D2 - Sunrays
|
||||
/app/music/The Other People Place/2017 - Lifestyles Of The Laptop Café/D2 - Sunrays.flac
|
||||
#EXTINF:-1,Bark Psychosis - (06) [Bark Psychosis] Bloodrush
|
||||
/app/music/Bark Psychosis/1994 - Game Over/(06) [Bark Psychosis] Bloodrush.flac
|
||||
#EXTINF:-1,Bark Psychosis - bark psychosis - pendulum man
|
||||
/app/music/Bark Psychosis/1994 - Hex/07 - bark psychosis - pendulum man.mp3
|
||||
#EXTINF:-1,Autechre - Slip
|
||||
/app/music/Autechre/1994 - Amber/04 Slip.flac
|
||||
#EXTINF:-1,Kiasmos - Swayed
|
||||
/app/music/Kiasmos/2014 - Kiasmos/04 - Swayed.flac
|
||||
#EXTINF:-1,The Other People Place - A1 - Eye Contact
|
||||
/app/music/The Other People Place/2017 - Lifestyles Of The Laptop Café/A1 - Eye Contact.flac
|
||||
#EXTINF:-1,Kiasmos - Rival Consoles - Milo
|
||||
/app/music/Kiasmos/2009 - 65, Milo (Kiasmos & Rival Consoles) (WEB)/03. Rival Consoles - Milo.flac
|
||||
#EXTINF:-1,Teeth Of The Sea - Butterfly House
|
||||
/app/music/Teeth Of The Sea/2023 - Hive/03 Butterfly House.flac
|
||||
#EXTINF:-1,The Orb - A Mile Long Lump of Lard
|
||||
/app/music/The Orb/2001 - Cydonia/07-A Mile Long Lump of Lard.mp3
|
||||
#EXTINF:-1,Autechre - Eutow
|
||||
/app/music/Autechre/1995 - Tri Repetae/06 Eutow.flac
|
||||
#EXTINF:-1,Model 500 - model_500-the_groove
|
||||
/app/music/Model 500/2015 - Digital Solutions/06-model_500-the_groove.flac
|
||||
#EXTINF:-1,Bark Psychosis - bark psychosis - big shot
|
||||
/app/music/Bark Psychosis/1994 - Hex/04 - bark psychosis - big shot.mp3
|
||||
#EXTINF:-1,Kiasmos - Rival Consoles - ARP
|
||||
/app/music/Kiasmos/2009 - 65, Milo (Kiasmos & Rival Consoles) (WEB)/05. Rival Consoles - ARP.flac
|
||||
#EXTINF:-1,Kraftwerk - Spacelab
|
||||
/app/music/Kraftwerk/1978 - The Man-Machine/02 - Spacelab.flac
|
||||
#EXTINF:-1,Brian Eno - Who Gives a Thought
|
||||
/app/music/Brian Eno/2022 - ForeverAndEverNoMore/01 Who Gives a Thought.flac
|
||||
#EXTINF:-1,Proem - Proem - Vault ep.4-4 - 04 v. jirku 1
|
||||
/app/music/Proem/2015 - Vault ep.4-4/Proem - Vault ep.4-4 - 04 v. jirku 1.flac
|
||||
#EXTINF:-1,Tape Loop Orchestra - The Burnley Brass Band Plays On In My Heart
|
||||
/app/music/Tape Loop Orchestra/2012 - The Word On My Lips Is Your Name/Disc 2 - The Burnley Brass Band Plays On In My Heart/01 - The Burnley Brass Band Plays On In My Heart.flac
|
||||
#EXTINF:-1,Proem - Proem - Before it finds you - 06 Pretense for piano and synth
|
||||
/app/music/Proem/2013 - Before it finds you/Proem - Before it finds you - 06 Pretense for piano and synth.flac
|
||||
#EXTINF:-1,Orbital - Remind
|
||||
/app/music/Orbital/1993 - Orbital - Orbital 2 (Brown Album - TRUCD2, 828 386.2)/00. Remind.mp3
|
||||
#EXTINF:-1,Underworld - Underworld - Pearls Girl
|
||||
/app/music/Underworld/1996 - Second Toughest In The Infants/05. Underworld - Pearls Girl.flac
|
||||
#EXTINF:-1,Underworld - Underworld - Banstyle Sappys Curry
|
||||
/app/music/Underworld/1996 - Second Toughest In The Infants/02. Underworld - Banstyle Sappys Curry.flac
|
||||
#EXTINF:-1,Orbital - Attached
|
||||
/app/music/Orbital/1994 - Orbital - Snivilisation (TRUCD5, 828 536.2)/10. Attached.mp3
|
||||
#EXTINF:-1,Labradford - P
|
||||
/app/music/Labradford/1997 - Mi Media Naranja/7 P.flac
|
||||
#EXTINF:-1,Drexciya - Drexciya - Vampire Island
|
||||
/app/music/Drexciya/2013 - Journey Of The Deep Sea Dweller III/10. Drexciya - Vampire Island.mp3
|
||||
#EXTINF:-1,Vector Lovers - Arrival, Metropolis
|
||||
/app/music/Vector Lovers/2005 - Capsule For One/02 - Arrival, Metropolis.mp3
|
||||
#EXTINF:-1,Teeth Of The Sea - Teeth Of The Sea - Highly Deadly Black Tarantula - 03 Field Punishment
|
||||
/app/music/Teeth Of The Sea/2015 - Highly Deadly Black Tarantula/Teeth Of The Sea - Highly Deadly Black Tarantula - 03 Field Punishment.flac
|
||||
#EXTINF:-1,Kiasmos - Swept (Tale of Us remix)
|
||||
/app/music/Kiasmos/2015 - Swept EP/04 - Swept (Tale of Us remix).mp3
|
||||
#EXTINF:-1,Proem - Proem - Vault ep.1-4 (Noise) - 05 Only Eat the Grey Wolves
|
||||
/app/music/Proem/2016 - Vault ep.1-4 (Noise)/Proem - Vault ep.1-4 (Noise) - 05 Only Eat the Grey Wolves.flac
|
||||
#EXTINF:-1,The Orb - Firestar
|
||||
/app/music/The Orb/2001 - Cydonia/06-Firestar.mp3
|
||||
#EXTINF:-1,Tape Loop Orchestra - Tape Loop Orchestra - Chapter 11 Late Autumn
|
||||
/app/music/Tape Loop Orchestra/2009 - 1953 Culture Festival/11 Tape Loop Orchestra - Chapter 11 Late Autumn.mp3
|
||||
#EXTINF:-1,Kraftwerk - The Man·Machine
|
||||
/app/music/Kraftwerk/1978 - The Man-Machine/06 - The Man·Machine.flac
|
||||
#PLAYLIST:Escape Velocity - A Christmas Journey Through Space
|
||||
#PHASE:Escape Velocity
|
||||
#DURATION:12 hours (approx)
|
||||
#CURATOR:Asteroid Radio
|
||||
#DESCRIPTION:A festive 12-hour voyage blending Christmas classics with ambient, IDM, and space music for the holiday season
|
||||
|
||||
# === PHASE 1: WINTER AWAKENING (Ambient Beginnings) ===
|
||||
#EXTINF:-1,Brian Eno - Snow
|
||||
/app/music/Brian Eno/2020 - Roger Eno and Brian Eno - Mixing Colours/09 Snow.flac
|
||||
#EXTINF:-1,Brian Eno - Wintergreen
|
||||
/app/music/Brian Eno/2020 - Roger Eno and Brian Eno - Mixing Colours/04 Wintergreen.flac
|
||||
#EXTINF:-1,Proem - Winter Wolves
|
||||
/app/music/Proem - 2018 Modern Rope (WEB)/01. Winter Wolves.flac
|
||||
#EXTINF:-1,Tim Hecker - Winter's Coming
|
||||
/app/music/Tim Hecker - The North Water Original Score (2021 - WEB - FLAC)/Tim Hecker - The North Water (Original Score) - 10 Winter's Coming.flac
|
||||
#EXTINF:-1,Biosphere - Drifter
|
||||
/app/music/Biosphere - The Petrified Forest (2017) - CD FLAC/01. Biosphere - Drifter.flac
|
||||
#EXTINF:-1,Dead Voices On Air - On Winters Gibbet
|
||||
/app/music/Dead Voices On Air - Ghohst Stories (FLAC)/02 - On Winters Gibbet.flac
|
||||
#EXTINF:-1,Color Therapy - Wintering
|
||||
/app/music/Color Therapy - Mr. Wolf Is Dead (2015) WEB FLAC/12 - Wintering.flac
|
||||
|
||||
# === PHASE 2: CHRISTMAS ARRIVAL (TSO Introduction) ===
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - The Ghosts Of Christmas Eve
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Christmas Attic/01 The Ghosts Of Christmas Eve.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Christmas In The Air
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Christmas Attic/14 Christmas In The Air.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Christmas Canon
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Christmas Attic/08 Christmas Canon.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Appalachian Snowfall
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Christmas Attic/11 Appalachian Snowfall.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - The Snow Came Down
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Christmas Attic/13 The Snow Came Down.flac
|
||||
|
||||
# === PHASE 3: AMBIENT INTERLUDE (Space & Atmosphere) ===
|
||||
#EXTINF:-1,Biosphere - 10 Snurp 1937
|
||||
/app/music/Biosphere - Sound Installations -2000-2009 [FLAC]/Biosphere - Sound Installations -2000-2009- - 10 Snurp 1937.flac
|
||||
#EXTINF:-1,Biosphere - 05 Fluvialmorphologie
|
||||
/app/music/Biosphere - Sound Installations -2000-2009 [FLAC]/Biosphere - Sound Installations -2000-2009- - 05 Fluvialmorphologie.flac
|
||||
#EXTINF:-1,God is an Astronaut - Winter Dusk-Awakening
|
||||
/app/music/God is an Astronaut - Epitaph (2018) WEB FLAC/03. Winter Dusk-Awakening.flac
|
||||
#EXTINF:-1,Proem - Snow Drifts
|
||||
/app/music/Proem - Twelve Tails-(2021) @FLAC [16-48]/11 - Snow Drifts.flac
|
||||
#EXTINF:-1,Proem - Stick to Music Snowflake
|
||||
/app/music/Proem - Until Here for Years (n5md, 2019) flac/04 - Stick to Music Snowflake.flac
|
||||
#EXTINF:-1,Four Tet - 04 Tremper
|
||||
/app/music/Four Tet - New Energy {CD} [FLAC] (2017)/04 Tremper.flac
|
||||
|
||||
# === PHASE 4: CHRISTMAS EVE STORIES ===
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - First Snow (Instrumental)
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/Christmas Eve and Other Stories/04 First Snow (Instrumental).flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - The Silent Nutcracker (Instrumental)
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/Christmas Eve and Other Stories/05 The Silent Nutcracker (Instrumental).flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - A Mad Russian's Christmas (Instrumental)
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/Christmas Eve and Other Stories/06 A Mad Russian's Christmas (Instrumental).flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Christmas Eve,Sarajevo 12,24 (Instrumental)
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/Christmas Eve and Other Stories/08 Christmas Eve,Sarajevo 12,24 (Instrumental).flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - This Christmas Day
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/Christmas Eve and Other Stories/14 This Christmas Day.flac
|
||||
|
||||
# === PHASE 5: ELECTRONIC DREAMS (IDM & Ambient) ===
|
||||
#EXTINF:-1,Autechre - NTS Session 1-005-Autechre-carefree counter dronal
|
||||
/app/music/Autechre - 2018 - NTS Session 1/NTS Session 1-005-Autechre-carefree counter dronal.flac
|
||||
#EXTINF:-1,Clark - Living Fantasy
|
||||
/app/music/Clark - Death Peak (2017) [FLAC]/08 - Living Fantasy.flac
|
||||
#EXTINF:-1,Clark - My Machines (Clark Remix)
|
||||
/app/music/Clark - Feast Beast (2013) [24 Bit WEB FLAC] [16-44]/1.17. Battles - My Machines (Clark Remix).flac
|
||||
#EXTINF:-1,Plaid - Dancers
|
||||
/app/music/Plaid - Polymer (2019) [WEB FLAC]/07 - Dancers.flac
|
||||
#EXTINF:-1,Faux Tales - Avalon
|
||||
/app/music/Faux Tales - 2015 - Kairos [FLAC] {Kensai Records KNS006 WEB}/3 - Avalon.flac
|
||||
#EXTINF:-1,Color Therapy - Expect Delays (feat. Ulrich Schnauss)
|
||||
/app/music/Color Therapy - Mr. Wolf Is Dead (2015) WEB FLAC/11 - Expect Delays (feat. Ulrich Schnauss).flac
|
||||
|
||||
# === PHASE 6: THE LOST CHRISTMAS EVE ===
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - The Lost Christmas Eve
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Lost Christmas Eve/02 The Lost Christmas Eve.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Christmas Dreams
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Lost Christmas Eve/03 Christmas Dreams.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Wizards in Winter
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Lost Christmas Eve/04 Wizards in Winter.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Christmas Concerto
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Lost Christmas Eve/07 Christmas Concerto.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Queen Of The Winter Night
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Lost Christmas Eve/08 Queen Of The Winter Night.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Christmas Nights In Blue
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Lost Christmas Eve/09 Christmas Nights In Blue.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Christmas Jazz
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Lost Christmas Eve/10 Christmas Jazz.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Christmas Jam
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Lost Christmas Eve/11 Christmas Jam.flac
|
||||
|
||||
# === PHASE 7: CLASSICAL WINTER (Nutcracker & More) ===
|
||||
#EXTINF:-1,Various Artists - Dance of the Sugar-Plum Fairy
|
||||
/app/music/Various Artists - The 50 Darkest Pieces of Classical Music (2011) - FLAC/CD 1/02 - Tchaikovsky - The Nutcracker - Dance of the Sugar-Plum Fairy.flac
|
||||
#EXTINF:-1,Quaeschning and Ulrich Schnauss - Thirst
|
||||
/app/music/Quaeschning and Ulrich Schnauss - Synthwaves (2017) {vista003, GER, CD} [FLAC]/06 - Thirst.flac
|
||||
#EXTINF:-1,Proem - 04. Drawing Room Anguish
|
||||
/app/music/Proem - 2018 Modern Rope (WEB)/04. Drawing Room Anguish.flac
|
||||
#EXTINF:-1,Dead Voices On Air - 07. Dogger Doorlopende Split
|
||||
/app/music/Dead Voices On Air - Frankie Pett En De Onderzeer Boten (2017) web/07. Dogger Doorlopende Split.flac
|
||||
|
||||
# === PHASE 8: WISDOM & REFLECTION ===
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - What Is Christmas
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Lost Christmas Eve/13 What Is Christmas.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - The Wisdom Of Snow
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Lost Christmas Eve/15 The Wisdom Of Snow.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Christmas Bells, Carousels & Time
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Lost Christmas Eve/18 Christmas Bells, Carousels & Time.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Christmas Canon Rock
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Lost Christmas Eve/21 Christmas Canon Rock.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Midnight Christmas Eve
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Christmas Attic/05 Midnight Christmas Eve.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Dream Child (A Christmas Dream)
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Christmas Attic/15 Dream Child (A Christmas Dream).flac
|
||||
|
||||
# === PHASE 9: DEEP SPACE JOURNEY (Extended Ambient) ===
|
||||
#EXTINF:-1,Dead Voices On Air - Red Howls
|
||||
/app/music/Dead Voices On Air - Ghohst Stories (FLAC)/01 - Red Howls.flac
|
||||
#EXTINF:-1,Cut Copy - Airborne
|
||||
/app/music/Cut Copy - Haiku From Zero (2017) [FLAC] {2557864014}/05 - Airborne.flac
|
||||
#EXTINF:-1,Owl City - 01 Hot Air Balloon
|
||||
/app/music/Owl City - Ocean Eyes (Deluxe Edition) [Flac,Cue,Logs]/Disc 2/01 Hot Air Balloon.flac
|
||||
#EXTINF:-1,VA - What Is Loneliness (feat. Danny Claire) [Skylex Radio Edit]
|
||||
/app/music/VA - Melodic Vocal Trance 2017/24. Airborn, Bogdan Vix & KeyPlayer - What Is Loneliness (feat. Danny Claire) [Skylex Radio Edit].flac
|
||||
#EXTINF:-1,VA - Winter Took Over (Radio Edit)
|
||||
/app/music/VA - Melodic Vocal Trance 2017/22. Bluskay, KeyPlayer & Esmee Bor Stotijn - Winter Took Over (Radio Edit).flac
|
||||
#EXTINF:-1,Alison Krauss and Union Station - My Opening Farewell
|
||||
/app/music/Alison Krauss and Union Station - Paper Airplane (flac)/11 - Alison Krauss & Union Station - My Opening Farewell.flac
|
||||
#EXTINF:-1,Bedouin Soundclash - Money Worries (E-Clair Refix)
|
||||
/app/music/Bedouin Soundclash - Sounding a Mosaic (2004) [FLAC] {SD1267}/14 - Money Worries (E-Clair Refix).flac
|
||||
|
||||
# === PHASE 10: RETURN TO WINTER (Closing Circle) ===
|
||||
#EXTINF:-1,Brian Eno - Snow
|
||||
/app/music/Brian Eno/2020 - Roger Eno and Brian Eno - Mixing Colours/09 Snow.flac
|
||||
#EXTINF:-1,Proem - Winter Wolves
|
||||
/app/music/Proem - 2018 Modern Rope (WEB)/01. Winter Wolves.flac
|
||||
#EXTINF:-1,God is an Astronaut - Winter Dusk-Awakening
|
||||
/app/music/God is an Astronaut - Epitaph (2018) WEB FLAC/03. Winter Dusk-Awakening.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - The Snow Came Down
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Christmas Attic/13 The Snow Came Down.flac
|
||||
#EXTINF:-1,Trans-Siberian Orchestra - Christmas In The Air
|
||||
/app/music/Trans-Siberian Orchestra - The Christmas Trilogy (2004) [FLAC]/The Christmas Attic/14 Christmas In The Air.flac
|
||||
|
|
|
|||
|
|
@ -10,13 +10,14 @@
|
|||
"Recursively scan directory for supported audio files"
|
||||
(when (cl-fad:directory-exists-p directory)
|
||||
(remove-if-not #'supported-audio-file-p
|
||||
(cl-fad:list-directory directory :follow-symlinks nil))))
|
||||
(cl-fad:list-directory directory :follow-symlinks t))))
|
||||
|
||||
(defun scan-directory-for-music-recursively (path)
|
||||
"Recursively scan directory and all subdirectories for music files"
|
||||
(let ((files-in-current-dir (scan-directory-for-music path))
|
||||
(files-in-subdirs (loop for directory in (uiop:subdirectories path)
|
||||
appending (scan-directory-for-music-recursively directory))))
|
||||
(let* ((resolved-path (truename path))
|
||||
(files-in-current-dir (scan-directory-for-music resolved-path))
|
||||
(files-in-subdirs (loop for directory in (uiop:subdirectories resolved-path)
|
||||
appending (scan-directory-for-music-recursively directory))))
|
||||
(append files-in-current-dir files-in-subdirs)))
|
||||
|
||||
(defun extract-metadata-with-taglib (file-path)
|
||||
|
|
@ -92,16 +93,25 @@
|
|||
(setf (dm:field track "file-path") file-path)
|
||||
(setf (dm:field track "format") (getf metadata :format))
|
||||
(setf (dm:field track "bitrate") (getf metadata :bitrate))
|
||||
(setf (dm:field track "added-date") (local-time:timestamp-to-unix (local-time:now)))
|
||||
;; Let database default handle added-date (CURRENT_TIMESTAMP)
|
||||
(setf (dm:field track "play-count") 0)
|
||||
(dm:insert track)
|
||||
t))))
|
||||
|
||||
(defun scan-music-library (&optional (directory *music-library-path*))
|
||||
"Scan music library directory and add tracks to database"
|
||||
(format t "~%=== SCAN DEBUG ===~%")
|
||||
(format t "Input directory: ~a~%" directory)
|
||||
(format t "Directory exists: ~a~%" (probe-file directory))
|
||||
(handler-case
|
||||
(format t "Resolved path: ~a~%" (truename directory))
|
||||
(error (e) (format t "Cannot resolve truename: ~a~%" e)))
|
||||
(let ((audio-files (scan-directory-for-music-recursively directory))
|
||||
(added-count 0)
|
||||
(skipped-count 0))
|
||||
(format t "Found ~a audio files~%" (length audio-files))
|
||||
(when (> (length audio-files) 0)
|
||||
(format t "First few files: ~{~a~%~}~%" (subseq audio-files 0 (min 3 (length audio-files)))))
|
||||
(dolist (file audio-files)
|
||||
(let ((metadata (extract-metadata-with-taglib file)))
|
||||
(when metadata
|
||||
|
|
@ -111,6 +121,7 @@
|
|||
(incf skipped-count))
|
||||
(error (e)
|
||||
(format t "Error adding ~a: ~a~%" file e))))))
|
||||
(format t "Added: ~a, Skipped: ~a~%" added-count skipped-count)
|
||||
added-count))
|
||||
|
||||
;; Initialize music directory structure
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
<div class="status-card">
|
||||
<h3>Icecast Status</h3>
|
||||
<p class="status-error" data-text="icecast-status">🔴 Not Running</p>
|
||||
<button id="icecast-restart" class="btn btn-danger btn-sm" style="margin-top: 8px;">🔄 Restart</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -162,43 +163,91 @@
|
|||
<!-- Stream Queue Management -->
|
||||
<div class="admin-section">
|
||||
<h2>🎵 Stream Queue Management</h2>
|
||||
<p>Manage the live stream playback queue. Changes take effect within 5-10 seconds.</p>
|
||||
<p>Manage the live stream playback queue. Liquidsoap watches <code>stream-queue.m3u</code> and reloads automatically.</p>
|
||||
|
||||
<div class="queue-controls">
|
||||
<button id="refresh-queue" class="btn btn-secondary">🔄 Refresh Queue</button>
|
||||
<button id="load-from-m3u" class="btn btn-success">📂 Load Queue from M3U</button>
|
||||
<button id="clear-queue-btn" class="btn btn-warning">🗑️ Clear Queue</button>
|
||||
<button id="add-random-tracks" class="btn btn-info">🎲 Add 10 Random Tracks</button>
|
||||
<!-- Playlist Selection -->
|
||||
<div class="playlist-controls" style="margin-bottom: 20px; padding: 15px; background: #2a2a2a; border-radius: 8px;">
|
||||
<h3 style="margin-top: 0;">📋 Load Playlist</h3>
|
||||
<div style="display: flex; gap: 10px; align-items: center; flex-wrap: wrap;">
|
||||
<select id="playlist-select" class="sort-select" style="min-width: 250px;">
|
||||
<option value="">-- Select a playlist --</option>
|
||||
</select>
|
||||
<button id="load-playlist-btn" class="btn btn-success">📂 Load Selected</button>
|
||||
<button id="refresh-playlists-btn" class="btn btn-secondary">🔄 Refresh List</button>
|
||||
</div>
|
||||
<p style="margin: 10px 0 0 0; font-size: 0.9em; color: #888;">
|
||||
Loading a playlist will copy it to <code>stream-queue.m3u</code> and Liquidsoap will start playing it.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="stream-queue-container" class="queue-list">
|
||||
<!-- Queue Controls -->
|
||||
<div class="queue-controls" style="margin-bottom: 15px;">
|
||||
<button id="refresh-queue" class="btn btn-secondary">🔄 Refresh Queue</button>
|
||||
<button id="save-queue-btn" class="btn btn-primary">💾 Save Queue</button>
|
||||
<button id="clear-queue-btn" class="btn btn-warning">🗑️ Clear Queue</button>
|
||||
<button id="add-random-tracks" class="btn btn-info">🎲 Add 10 Random</button>
|
||||
</div>
|
||||
|
||||
<!-- Save As -->
|
||||
<div style="margin-bottom: 15px; display: flex; gap: 10px; align-items: center;">
|
||||
<input type="text" id="save-as-name" placeholder="New playlist name..." class="search-input" style="max-width: 250px;">
|
||||
<button id="save-as-btn" class="btn btn-success">💾 Save As New Playlist</button>
|
||||
</div>
|
||||
|
||||
<!-- Queue Status -->
|
||||
<div id="queue-status" style="margin-bottom: 15px; padding: 10px; background: #1a1a1a; border-radius: 4px;">
|
||||
<span id="queue-count">0</span> tracks in queue
|
||||
</div>
|
||||
|
||||
<!-- Queue Contents -->
|
||||
<div id="stream-queue-container" class="queue-list" style="max-height: 400px; overflow-y: auto;">
|
||||
<div class="loading">Loading queue...</div>
|
||||
</div>
|
||||
|
||||
<div class="queue-actions">
|
||||
<div class="queue-actions" style="margin-top: 20px;">
|
||||
<h3>Add Tracks to Queue</h3>
|
||||
<input type="text" id="queue-track-search" placeholder="Search tracks to add..." class="search-input">
|
||||
<div id="queue-track-results" class="track-results"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Player Control -->
|
||||
<!-- Liquidsoap Stream Control -->
|
||||
<div class="admin-section">
|
||||
<h2>Player Control</h2>
|
||||
<div class="card">
|
||||
<h3>🎵 Player Control</h3>
|
||||
<div class="player-controls">
|
||||
<button id="player-play" class="btn btn-primary" onclick="playTrack()">▶️ Play</button>
|
||||
<button id="player-pause" class="btn btn-secondary" onclick="pausePlayer()">⏸️ Pause</button>
|
||||
<button id="player-stop" class="btn btn-secondary" onclick="stopPlayer()">⏹️ Stop</button>
|
||||
<button id="player-resume" class="btn btn-secondary" onclick="resumePlayer()">▶️ Resume</button>
|
||||
<h2>📡 Stream Control (Liquidsoap)</h2>
|
||||
<p>Control the live audio stream. Commands are sent directly to Liquidsoap.</p>
|
||||
|
||||
<!-- Status Display -->
|
||||
<div id="liquidsoap-status" style="margin-bottom: 20px; padding: 15px; background: #1a1a1a; border-radius: 8px;">
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
|
||||
<div>
|
||||
<strong>Uptime:</strong> <span id="ls-uptime">--</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Remaining:</strong> <span id="ls-remaining">--</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="player-status" class="status-info">
|
||||
Status: <span id="player-state">Unknown</span><br>
|
||||
Current Track: <span id="current-track">None</span>
|
||||
<div style="margin-top: 10px;">
|
||||
<strong>Now Playing:</strong> <span id="ls-metadata">--</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Control Buttons -->
|
||||
<div class="queue-controls" style="margin-bottom: 15px;">
|
||||
<button id="ls-refresh-status" class="btn btn-secondary">🔄 Refresh Status</button>
|
||||
<button id="ls-skip" class="btn btn-warning">⏭️ Skip Track</button>
|
||||
<button id="ls-reload" class="btn btn-info">📂 Reload Playlist</button>
|
||||
<button id="ls-restart" class="btn btn-danger">🔄 Restart Container</button>
|
||||
</div>
|
||||
|
||||
<p style="font-size: 0.9em; color: #888;">
|
||||
<strong>Skip Track:</strong> Immediately skip to the next track in the playlist.<br>
|
||||
<strong>Reload Playlist:</strong> Force Liquidsoap to re-read stream-queue.m3u.<br>
|
||||
<strong>Restart Container:</strong> Restart the Liquidsoap Docker container (causes brief stream interruption).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- User Management -->
|
||||
<div class="admin-section">
|
||||
<div class="card">
|
||||
<h3>👥 User Management</h3>
|
||||
<p>Manage user accounts, roles, and permissions.</p>
|
||||
|
|
|
|||
Loading…
Reference in New Issue