Compare commits
15 Commits
5390b7e8b7
...
2ed92ba003
| Author | SHA1 | Date |
|---|---|---|
|
|
2ed92ba003 | |
|
|
8fd0b06b69 | |
|
|
4ca6570d5e | |
|
|
c9f6cb2aa7 | |
|
|
6c6732d1e0 | |
|
|
8754e7261f | |
|
|
e55210c332 | |
|
|
d66b7b8053 | |
|
|
44096dfb4b | |
|
|
9cbc0a7780 | |
|
|
7a4e9c208a | |
|
|
aa84ff4470 | |
|
|
9bb31ec88c | |
|
|
6c2ed75b15 | |
|
|
d2508451d0 |
|
|
@ -56,3 +56,4 @@ logs/
|
||||||
performance-logs/
|
performance-logs/
|
||||||
|
|
||||||
# Temporary files
|
# Temporary files
|
||||||
|
/static/asteroid.css
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,20 @@
|
||||||
(defpackage :asteroid.app-utils
|
(defpackage :asteroid.app-utils
|
||||||
(:use :cl)
|
(:use :cl)
|
||||||
(:export :internal-disable-debugger)
|
(:export :internal-disable-debugger)
|
||||||
(:export :internal-quit))
|
(:export :internal-quit
|
||||||
|
:pht))
|
||||||
|
|
||||||
(in-package :asteroid.app-utils)
|
(in-package :asteroid.app-utils)
|
||||||
|
|
||||||
|
(defun pht (ht)
|
||||||
|
(alexandria:hash-table-alist ht))
|
||||||
|
|
||||||
(defun internal-disable-debugger ()
|
(defun internal-disable-debugger ()
|
||||||
(labels
|
(labels
|
||||||
((internal-exit (c h)
|
((internal-exit (c h)
|
||||||
(declare (ignore h))
|
(declare (ignore h))
|
||||||
(format t "~a~%" c)
|
(format t "~a~%" c)
|
||||||
(internal-quit)))
|
(internal-quit)))
|
||||||
(setf *debugger-hook* #'internal-exit)))
|
(setf *debugger-hook* #'internal-exit)))
|
||||||
|
|
||||||
(defun internal-quit (&optional code)
|
(defun internal-quit (&optional code)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
:author "Brian O'Reilly <fade@deepsky.com>"
|
:author "Brian O'Reilly <fade@deepsky.com>"
|
||||||
:license "GNU AFFERO GENERAL PUBLIC LICENSE V.3"
|
:license "GNU AFFERO GENERAL PUBLIC LICENSE V.3"
|
||||||
:serial t
|
:serial t
|
||||||
:version "0.0.0"
|
:version "1.0.0"
|
||||||
:defsystem-depends-on (:radiance)
|
:defsystem-depends-on (:radiance)
|
||||||
:class "radiance:virtual-module"
|
:class "radiance:virtual-module"
|
||||||
:depends-on (:slynk
|
:depends-on (:slynk
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
:lass
|
:lass
|
||||||
:parenscript
|
:parenscript
|
||||||
:cl-json
|
:cl-json
|
||||||
|
:cl-csv
|
||||||
:alexandria
|
:alexandria
|
||||||
:local-time
|
:local-time
|
||||||
:taglib
|
:taglib
|
||||||
|
|
@ -28,6 +29,9 @@
|
||||||
:bordeaux-threads
|
:bordeaux-threads
|
||||||
:drakma
|
:drakma
|
||||||
;; radiance interfaces
|
;; radiance interfaces
|
||||||
|
:i-log4cl
|
||||||
|
:i-postmodern
|
||||||
|
:r-clip
|
||||||
:r-data-model
|
:r-data-model
|
||||||
(:interface :auth)
|
(:interface :auth)
|
||||||
(:interface :database)
|
(:interface :database)
|
||||||
|
|
|
||||||
|
|
@ -930,6 +930,20 @@
|
||||||
:default-stream-url (format nil "~a/asteroid.aac" *stream-base-url*)
|
:default-stream-url (format nil "~a/asteroid.aac" *stream-base-url*)
|
||||||
:default-stream-encoding "audio/aac"))
|
:default-stream-encoding "audio/aac"))
|
||||||
|
|
||||||
|
;; About page (non-frameset mode)
|
||||||
|
(define-page about-page #@"/about" ()
|
||||||
|
"About Asteroid Radio"
|
||||||
|
(clip:process-to-string
|
||||||
|
(load-template "about")
|
||||||
|
:title "About - Asteroid Radio"))
|
||||||
|
|
||||||
|
;; About content (for frameset mode)
|
||||||
|
(define-page about-content #@"/about-content" ()
|
||||||
|
"About page content (displayed in content frame)"
|
||||||
|
(clip:process-to-string
|
||||||
|
(load-template "about-content")
|
||||||
|
:title "About - Asteroid Radio"))
|
||||||
|
|
||||||
(define-api asteroid/status () ()
|
(define-api asteroid/status () ()
|
||||||
"Get server status"
|
"Get server status"
|
||||||
(api-output `(("status" . "running")
|
(api-output `(("status" . "running")
|
||||||
|
|
@ -1012,8 +1026,11 @@
|
||||||
|
|
||||||
(defun ensure-radiance-environment ()
|
(defun ensure-radiance-environment ()
|
||||||
"Ensure RADIANCE environment is properly configured for persistence"
|
"Ensure RADIANCE environment is properly configured for persistence"
|
||||||
(unless (radiance:environment)
|
(if (radiance:environment)
|
||||||
(setf (radiance:environment) "asteroid"))
|
(format t "~2&Startup default environment: ~A~2%" (radiance:environment))
|
||||||
|
(progn
|
||||||
|
(setf (radiance:environment) "asteroid")
|
||||||
|
(format t "~2&Set environment to: ~A~2%" (radiance:environment))))
|
||||||
|
|
||||||
(log:info "~2&~15A - ~A~%~15A - ~A~%~15A - ~A~%~15A - ~A~%~15A - ~A~2%"
|
(log:info "~2&~15A - ~A~%~15A - ~A~%~15A - ~A~%~15A - ~A~%~15A - ~A~2%"
|
||||||
":configuration"
|
":configuration"
|
||||||
|
|
@ -1025,7 +1042,16 @@
|
||||||
":template"
|
":template"
|
||||||
(radiance:environment-directory (radiance-core:environment) :template)
|
(radiance:environment-directory (radiance-core:environment) :template)
|
||||||
":static"
|
":static"
|
||||||
(radiance:environment-directory (radiance-core:environment) :static)))
|
(radiance:environment-directory (radiance-core:environment) :static))
|
||||||
|
|
||||||
|
(db:connect :main))
|
||||||
|
|
||||||
|
(defun start-slynk-server-in-new-thread (&optional (port 4009))
|
||||||
|
"Starts a Slynk server in a new thread on the specified port."
|
||||||
|
(bt:make-thread (lambda ()
|
||||||
|
(format t "~&Starting Slynk server on port ~a in a new thread.~%" port)
|
||||||
|
(slynk:create-server :port port :dont-close t))
|
||||||
|
:name (format nil "Slynk Server Thread on Port ~a" port)))
|
||||||
|
|
||||||
(defun -main (&optional args (debug t))
|
(defun -main (&optional args (debug t))
|
||||||
(declare (ignorable args))
|
(declare (ignorable args))
|
||||||
|
|
@ -1035,9 +1061,10 @@
|
||||||
(format t "~%🎵 ASTEROID RADIO - Music for Hackers 🎵~%")
|
(format t "~%🎵 ASTEROID RADIO - Music for Hackers 🎵~%")
|
||||||
(format t "Using stream server at ~a~%" *stream-base-url*)
|
(format t "Using stream server at ~a~%" *stream-base-url*)
|
||||||
|
|
||||||
(format t "Starting RADIANCE web server...~%")
|
|
||||||
(when debug
|
(when debug
|
||||||
(slynk:create-server :port 4009 :dont-close t))
|
(start-slynk-server-in-new-thread 4009))
|
||||||
|
|
||||||
|
(format t "Starting RADIANCE web server...~%")
|
||||||
|
|
||||||
;; Ensure proper environment setup before starting
|
;; Ensure proper environment setup before starting
|
||||||
(ensure-radiance-environment)
|
(ensure-radiance-environment)
|
||||||
|
|
@ -1049,4 +1076,3 @@
|
||||||
;; For now, use the "Scan Library" button in the admin interface
|
;; For now, use the "Scan Library" button in the admin interface
|
||||||
|
|
||||||
(run-server))
|
(run-server))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
;;;; Radiance PostgreSQL Configuration for Asteroid Radio
|
;;;; Radiance PostgreSQL Configuration for Asteroid Radio
|
||||||
;;;; This file configures Radiance to use PostgreSQL instead of the default database
|
;;;; This file configures Radiance to use PostgreSQL instead of the default database
|
||||||
|
|
||||||
(in-package #:radiance-user)
|
(in-package #:i-postmodern)
|
||||||
|
|
||||||
;; PostgreSQL Database Configuration
|
;; PostgreSQL Database Configuration
|
||||||
(setf (config :database :connection)
|
(setf (config :default) :main
|
||||||
'(:type :postgres
|
;; (config :connections :default) :main
|
||||||
:host "localhost" ; Change to "asteroid-postgres" when running in Docker
|
(config :connections :main :host) "localhost"
|
||||||
;; :host "asteroid-postgres"
|
(config :connections :main :port) 5432
|
||||||
:port 5432
|
(config :connections :main :user) (or (uiop:getenv "ASTEROID_DB_USER") "asteroid")
|
||||||
:database "asteroid"
|
(config :connections :main :pass) (or (uiop:getenv "ASTEROID_DB_PASSWORD") "asteroid_db_2025")
|
||||||
:username "asteroid"
|
(config :connections :main :database) (or (uiop:getenv "ASTEROID_DB_NAME") "asteroid"))
|
||||||
:password "asteroid_db_2025"))
|
|
||||||
|
|
||||||
;; Alternative Docker configuration (uncomment when running Asteroid in Docker)
|
;; Alternative Docker configuration (uncomment when running Asteroid in Docker)
|
||||||
;; (setf (config :database :connection)
|
;; (setf (config :database :connection)
|
||||||
|
|
@ -33,6 +32,6 @@
|
||||||
(setf (config :database :pool-size) 10)
|
(setf (config :database :pool-size) 10)
|
||||||
(setf (config :database :pool-timeout) 30)
|
(setf (config :database :pool-timeout) 30)
|
||||||
|
|
||||||
(format t "~%✅ Radiance configured for PostgreSQL~%")
|
;; (format t "~%✅ Radiance configured for PostgreSQL~%")
|
||||||
(format t "Database: asteroid@localhost:5432~%")
|
;; (format t "Database: asteroid@localhost:5432~%")
|
||||||
(format t "Connection pooling: enabled (10 connections)~%~%")
|
;; (format t "Connection pooling: enabled (10 connections)~%~%")
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,12 @@ services:
|
||||||
- asteroid-network
|
- asteroid-network
|
||||||
|
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:16-alpine
|
image: postgres:17-alpine
|
||||||
container_name: asteroid-postgres
|
container_name: asteroid-postgres
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: asteroid
|
- POSTGRES_DB=${ASTEROID_DB_NAME:-asteroid}
|
||||||
POSTGRES_USER: asteroid
|
- POSTGRES_USER=${ASTEROID_DB_USER:-asteroid}
|
||||||
POSTGRES_PASSWORD: asteroid_db_2025
|
- POSTGRES_PASSWORD=${ASTEROID_DB_PASSWORD:-asteroid_db_2025}
|
||||||
ports:
|
ports:
|
||||||
- "5432:5432"
|
- "5432:5432"
|
||||||
volumes:
|
volumes:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
export ASTEROID_STREAM_URL='http://ice.asteroid.radio'
|
||||||
|
|
||||||
|
# source this file prior to starting the asteroid containers. Set the
|
||||||
|
# DB name and access params here.
|
||||||
|
|
||||||
|
export ASTEROID_DB_NAME=asteroid
|
||||||
|
export ASTEROID_DB_USER=asteroid
|
||||||
|
export ASTEROID_DB_PASSWORD=asteroid_db_2025
|
||||||
|
|
@ -5,34 +5,36 @@
|
||||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
|
||||||
-- Users table
|
-- Users table
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS "USERS" (
|
||||||
id SERIAL PRIMARY KEY,
|
_id SERIAL PRIMARY KEY,
|
||||||
username VARCHAR(255) UNIQUE NOT NULL,
|
username VARCHAR(255) UNIQUE NOT NULL,
|
||||||
email VARCHAR(255) UNIQUE NOT NULL,
|
email VARCHAR(255) UNIQUE NOT NULL,
|
||||||
password_hash TEXT NOT NULL,
|
"password-hash" TEXT NOT NULL,
|
||||||
role VARCHAR(50) DEFAULT 'listener',
|
role VARCHAR(50) DEFAULT 'listener',
|
||||||
active BOOLEAN DEFAULT true,
|
active integer DEFAULT 1,
|
||||||
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
-- "created-date" integer DEFAULT CURRENT_TIMESTAMP,
|
||||||
last_login TIMESTAMP,
|
"created-date" integer,
|
||||||
|
"last-login" integer,
|
||||||
CONSTRAINT valid_role CHECK (role IN ('listener', 'dj', 'admin'))
|
CONSTRAINT valid_role CHECK (role IN ('listener', 'dj', 'admin'))
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Create index on username and email for faster lookups
|
-- Create index on username and email for faster lookups
|
||||||
CREATE INDEX idx_users_username ON users(username);
|
CREATE INDEX idx_users_username ON "USERS"(username);
|
||||||
CREATE INDEX idx_users_email ON users(email);
|
CREATE INDEX idx_users_email ON "USERS"(email);
|
||||||
|
|
||||||
-- Tracks table
|
-- Tracks table
|
||||||
CREATE TABLE IF NOT EXISTS tracks (
|
CREATE TABLE IF NOT EXISTS tracks (
|
||||||
id SERIAL PRIMARY KEY,
|
_id SERIAL PRIMARY KEY,
|
||||||
title VARCHAR(500) NOT NULL,
|
title VARCHAR(500) NOT NULL,
|
||||||
artist VARCHAR(500),
|
artist VARCHAR(500),
|
||||||
album VARCHAR(500),
|
album VARCHAR(500),
|
||||||
duration INTEGER DEFAULT 0,
|
duration INTEGER DEFAULT 0,
|
||||||
format VARCHAR(50),
|
format VARCHAR(50),
|
||||||
file_path TEXT NOT NULL UNIQUE,
|
bitrate integer,
|
||||||
play_count INTEGER DEFAULT 0,
|
"file-path" TEXT NOT NULL UNIQUE,
|
||||||
added_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
"play-count" INTEGER DEFAULT 0,
|
||||||
last_played TIMESTAMP
|
"added-date" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"last-played" TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Create indexes for common queries
|
-- Create indexes for common queries
|
||||||
|
|
@ -42,25 +44,25 @@ CREATE INDEX idx_tracks_title ON tracks(title);
|
||||||
|
|
||||||
-- Playlists table
|
-- Playlists table
|
||||||
CREATE TABLE IF NOT EXISTS playlists (
|
CREATE TABLE IF NOT EXISTS playlists (
|
||||||
id SERIAL PRIMARY KEY,
|
_id SERIAL PRIMARY KEY,
|
||||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
"user-id" INTEGER NOT NULL REFERENCES "USERS"(_id) ON DELETE CASCADE,
|
||||||
name VARCHAR(255) NOT NULL,
|
name VARCHAR(255) NOT NULL,
|
||||||
description TEXT,
|
description TEXT,
|
||||||
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
"created-date" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
modified_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
"modified-date" TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Create index on user_id for faster user playlist lookups
|
-- Create index on user_id for faster user playlist lookups
|
||||||
CREATE INDEX idx_playlists_user_id ON playlists(user_id);
|
CREATE INDEX idx_playlists_user_id ON playlists("user-id");
|
||||||
|
|
||||||
-- Playlist tracks junction table (many-to-many relationship)
|
-- Playlist tracks junction table (many-to-many relationship)
|
||||||
CREATE TABLE IF NOT EXISTS playlist_tracks (
|
CREATE TABLE IF NOT EXISTS playlist_tracks (
|
||||||
id SERIAL PRIMARY KEY,
|
_id SERIAL PRIMARY KEY,
|
||||||
playlist_id INTEGER NOT NULL REFERENCES playlists(id) ON DELETE CASCADE,
|
playlist_id INTEGER NOT NULL REFERENCES playlists(_id) ON DELETE CASCADE,
|
||||||
track_id INTEGER NOT NULL REFERENCES tracks(id) ON DELETE CASCADE,
|
track_id INTEGER NOT NULL REFERENCES tracks(_id) ON DELETE CASCADE,
|
||||||
position INTEGER NOT NULL,
|
position INTEGER NOT NULL,
|
||||||
added_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
added_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
UNIQUE(playlist_id, track_id, position)
|
UNIQUE(playlist_id, track_id, "position")
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Create indexes for playlist track queries
|
-- Create indexes for playlist track queries
|
||||||
|
|
@ -68,28 +70,28 @@ CREATE INDEX idx_playlist_tracks_playlist_id ON playlist_tracks(playlist_id);
|
||||||
CREATE INDEX idx_playlist_tracks_track_id ON playlist_tracks(track_id);
|
CREATE INDEX idx_playlist_tracks_track_id ON playlist_tracks(track_id);
|
||||||
|
|
||||||
-- Sessions table (for Radiance session management)
|
-- Sessions table (for Radiance session management)
|
||||||
CREATE TABLE IF NOT EXISTS sessions (
|
-- CREATE TABLE IF NOT EXISTS sessions (
|
||||||
id VARCHAR(255) PRIMARY KEY,
|
-- _id VARCHAR(255) PRIMARY KEY,
|
||||||
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
|
-- "user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
|
||||||
data JSONB,
|
-- data JSONB,
|
||||||
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
-- created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
expires_at TIMESTAMP NOT NULL
|
-- expires_at TIMESTAMP NOT NULL
|
||||||
);
|
-- );
|
||||||
|
|
||||||
-- Create index on user_id and expires_at
|
-- Create index on user_id and expires_at
|
||||||
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
|
-- CREATE INDEX idx_sessions_user_id ON sessions(user_id);
|
||||||
CREATE INDEX idx_sessions_expires_at ON sessions(expires_at);
|
-- CREATE INDEX idx_sessions_expires_at ON sessions(expires_at);
|
||||||
|
|
||||||
-- Create default admin user (password: admin - CHANGE THIS!)
|
-- Create default admin user (password: admin - CHANGE THIS!)
|
||||||
-- Password hash for 'admin' using bcrypt
|
-- Password hash for 'admin' using bcrypt
|
||||||
INSERT INTO users (username, email, password_hash, role, active)
|
INSERT INTO "USERS" (username, email, "password-hash", role, active)
|
||||||
VALUES ('admin', 'admin@asteroid.radio', '$2a$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYqYqYqYqYq', 'admin', true)
|
-- VALUES ('admin', 'admin@asteroid.radio', '$2a$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYqYqYqYqYq', 'admin', 1)
|
||||||
|
VALUES ('admin', 'admin@asteroid.radio','8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', 'admin', 1)
|
||||||
ON CONFLICT (username) DO NOTHING;
|
ON CONFLICT (username) DO NOTHING;
|
||||||
|
|
||||||
-- Create a test listener user
|
-- Create a test listener user
|
||||||
INSERT INTO users (username, email, password_hash, role, active)
|
INSERT INTO "USERS" (username, email, "password-hash", role, active)
|
||||||
VALUES ('listener', 'listener@asteroid.radio', '$2a$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYqYqYqYqYq', 'listener', true)
|
VALUES ('listener', 'listener@asteroid.radio', '$2a$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYqYqYqYqYq', 'listener', 1);
|
||||||
ON CONFLICT (username) DO NOTHING;
|
|
||||||
|
|
||||||
-- Grant necessary permissions
|
-- Grant necessary permissions
|
||||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO asteroid;
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO asteroid;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# source our environment for credentials
|
||||||
|
. environment.sh
|
||||||
|
|
||||||
# Simple start script for Docker directory
|
# Simple start script for Docker directory
|
||||||
# Run from: /home/glenn/Projects/Code/asteroid/docker/
|
# Run from: /home/glenn/Projects/Code/asteroid/docker/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,14 @@ echo "🛑 Stopping Asteroid Radio Docker Services..."
|
||||||
# Stop services
|
# Stop services
|
||||||
docker compose down
|
docker compose down
|
||||||
|
|
||||||
|
# if we really need to clean everything and start fresh, run the
|
||||||
|
# following commands:
|
||||||
|
|
||||||
|
# docker compose down postgres
|
||||||
|
# docker volume rm docker_postgres-data
|
||||||
|
|
||||||
|
# TODO - apply a getopt interface to this script.
|
||||||
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "✅ Services stopped."
|
echo "✅ Services stopped."
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
/home/fade/Media/Music
|
|
||||||
|
|
@ -7,6 +7,12 @@
|
||||||
(ps:ps*
|
(ps:ps*
|
||||||
'(progn
|
'(progn
|
||||||
|
|
||||||
|
;; Stream connection state
|
||||||
|
(defvar *stream-error-count* 0)
|
||||||
|
(defvar *last-play-attempt* 0)
|
||||||
|
(defvar *is-reconnecting* false)
|
||||||
|
(defvar *reconnect-timeout* nil)
|
||||||
|
|
||||||
;; Stream quality configuration
|
;; Stream quality configuration
|
||||||
(defun get-stream-config (stream-base-url encoding)
|
(defun get-stream-config (stream-base-url encoding)
|
||||||
(let ((config (ps:create
|
(let ((config (ps:create
|
||||||
|
|
@ -137,6 +143,249 @@
|
||||||
(ps:chain local-storage (remove-item "useFrameset"))
|
(ps:chain local-storage (remove-item "useFrameset"))
|
||||||
(setf (ps:@ window location href) "/asteroid/"))
|
(setf (ps:@ window location href) "/asteroid/"))
|
||||||
|
|
||||||
|
;; Stream status UI functions
|
||||||
|
(defun show-stream-status (message status-type)
|
||||||
|
"Show a status message to the user. status-type: 'error', 'warning', 'success', 'info'"
|
||||||
|
(let ((indicator (ps:chain document (get-element-by-id "stream-status-indicator"))))
|
||||||
|
(when indicator
|
||||||
|
(setf (ps:@ indicator inner-text) message)
|
||||||
|
(setf (ps:@ indicator style display) "block")
|
||||||
|
(setf (ps:@ indicator style background)
|
||||||
|
(cond
|
||||||
|
((= status-type "error") "#550000")
|
||||||
|
((= status-type "warning") "#554400")
|
||||||
|
((= status-type "success") "#005500")
|
||||||
|
(t "#003355")))
|
||||||
|
(setf (ps:@ indicator style border)
|
||||||
|
(cond
|
||||||
|
((= status-type "error") "1px solid #ff0000")
|
||||||
|
((= status-type "warning") "1px solid #ffaa00")
|
||||||
|
((= status-type "success") "1px solid #00ff00")
|
||||||
|
(t "1px solid #00aaff"))))))
|
||||||
|
|
||||||
|
(defun hide-stream-status ()
|
||||||
|
"Hide the status indicator"
|
||||||
|
(let ((indicator (ps:chain document (get-element-by-id "stream-status-indicator"))))
|
||||||
|
(when indicator
|
||||||
|
(setf (ps:@ indicator style display) "none"))))
|
||||||
|
|
||||||
|
(defun show-reconnect-button ()
|
||||||
|
"Show the reconnect button"
|
||||||
|
(let ((btn (ps:chain document (get-element-by-id "reconnect-btn"))))
|
||||||
|
(when btn
|
||||||
|
(setf (ps:@ btn style display) "inline-block"))))
|
||||||
|
|
||||||
|
(defun hide-reconnect-button ()
|
||||||
|
"Hide the reconnect button"
|
||||||
|
(let ((btn (ps:chain document (get-element-by-id "reconnect-btn"))))
|
||||||
|
(when btn
|
||||||
|
(setf (ps:@ btn style display) "none"))))
|
||||||
|
|
||||||
|
;; Recreate audio element to fix wedged state
|
||||||
|
(defun recreate-audio-element ()
|
||||||
|
"Recreate the audio element entirely to fix wedged MediaElementSource"
|
||||||
|
(let* ((container (ps:chain document (get-element-by-id "audio-container")))
|
||||||
|
(old-audio (ps:chain document (get-element-by-id "live-audio")))
|
||||||
|
(stream-base-url (ps:chain document (get-element-by-id "stream-base-url")))
|
||||||
|
(stream-quality (or (ps:chain local-storage (get-item "stream-quality")) "aac"))
|
||||||
|
(config (get-stream-config (ps:@ stream-base-url value) stream-quality)))
|
||||||
|
|
||||||
|
(when (and container old-audio)
|
||||||
|
;; Reset spectrum analyzer before removing audio
|
||||||
|
(when (ps:@ window |resetSpectrumAnalyzer|)
|
||||||
|
(ps:chain window (reset-spectrum-analyzer)))
|
||||||
|
|
||||||
|
;; Remove old audio element
|
||||||
|
(ps:chain old-audio (pause))
|
||||||
|
(setf (ps:@ old-audio src) "")
|
||||||
|
(ps:chain old-audio (remove))
|
||||||
|
|
||||||
|
;; Create new audio element
|
||||||
|
(let ((new-audio (ps:chain document (create-element "audio"))))
|
||||||
|
(setf (ps:@ new-audio id) "live-audio")
|
||||||
|
(setf (ps:@ new-audio controls) t)
|
||||||
|
(setf (ps:@ new-audio crossorigin) "anonymous")
|
||||||
|
(setf (ps:@ new-audio style width) "100%")
|
||||||
|
(setf (ps:@ new-audio style margin) "10px 0")
|
||||||
|
|
||||||
|
;; Create source element
|
||||||
|
(let ((source (ps:chain document (create-element "source"))))
|
||||||
|
(setf (ps:@ source id) "audio-source")
|
||||||
|
(setf (ps:@ source src) (ps:@ config url))
|
||||||
|
(setf (ps:@ source type) (ps:@ config type))
|
||||||
|
(ps:chain new-audio (append-child source)))
|
||||||
|
|
||||||
|
;; Add to container
|
||||||
|
(ps:chain container (append-child new-audio))
|
||||||
|
|
||||||
|
;; Re-attach event listeners
|
||||||
|
(attach-audio-event-listeners new-audio)
|
||||||
|
|
||||||
|
(ps:chain console (log "Audio element recreated"))
|
||||||
|
new-audio))))
|
||||||
|
|
||||||
|
;; Main reconnect function
|
||||||
|
(defun reconnect-stream ()
|
||||||
|
"Reconnect the stream - called by user or automatically"
|
||||||
|
(when *is-reconnecting*
|
||||||
|
(return))
|
||||||
|
|
||||||
|
(setf *is-reconnecting* t)
|
||||||
|
(show-stream-status "🔄 Reconnecting to stream..." "info")
|
||||||
|
(hide-reconnect-button)
|
||||||
|
|
||||||
|
;; Clear any pending reconnect timeout
|
||||||
|
(when *reconnect-timeout*
|
||||||
|
(clear-timeout *reconnect-timeout*)
|
||||||
|
(setf *reconnect-timeout* nil))
|
||||||
|
|
||||||
|
(let ((audio-element (ps:chain document (get-element-by-id "live-audio"))))
|
||||||
|
(if audio-element
|
||||||
|
;; Try simple reload first
|
||||||
|
(progn
|
||||||
|
(ps:chain audio-element (pause))
|
||||||
|
(ps:chain audio-element (load))
|
||||||
|
|
||||||
|
;; Resume AudioContext if suspended
|
||||||
|
(when (ps:@ window |resetSpectrumAnalyzer|)
|
||||||
|
(ps:chain window (reset-spectrum-analyzer)))
|
||||||
|
|
||||||
|
;; Try to play after a short delay
|
||||||
|
(set-timeout
|
||||||
|
(lambda ()
|
||||||
|
(ps:chain audio-element (play)
|
||||||
|
(then (lambda ()
|
||||||
|
(setf *stream-error-count* 0)
|
||||||
|
(setf *is-reconnecting* false)
|
||||||
|
(show-stream-status "✓ Stream reconnected!" "success")
|
||||||
|
(set-timeout hide-stream-status 3000)
|
||||||
|
|
||||||
|
;; Reinitialize spectrum analyzer
|
||||||
|
(when (ps:@ window |initSpectrumAnalyzer|)
|
||||||
|
(set-timeout
|
||||||
|
(lambda ()
|
||||||
|
(ps:chain window (init-spectrum-analyzer)))
|
||||||
|
500))))
|
||||||
|
(catch (lambda (err)
|
||||||
|
(ps:chain console (log "Simple reconnect failed, recreating audio element:" err))
|
||||||
|
;; Simple reload failed, recreate the audio element
|
||||||
|
(let ((new-audio (recreate-audio-element)))
|
||||||
|
(when new-audio
|
||||||
|
(set-timeout
|
||||||
|
(lambda ()
|
||||||
|
(ps:chain new-audio (play)
|
||||||
|
(then (lambda ()
|
||||||
|
(setf *stream-error-count* 0)
|
||||||
|
(setf *is-reconnecting* false)
|
||||||
|
(show-stream-status "✓ Stream reconnected!" "success")
|
||||||
|
(set-timeout hide-stream-status 3000)))
|
||||||
|
(catch (lambda (err2)
|
||||||
|
(setf *is-reconnecting* false)
|
||||||
|
(incf *stream-error-count*)
|
||||||
|
(show-stream-status "❌ Could not reconnect. Click play to try again." "error")
|
||||||
|
(show-reconnect-button)
|
||||||
|
(ps:chain console (log "Reconnect failed:" err2))))))
|
||||||
|
500)))))))
|
||||||
|
500))
|
||||||
|
|
||||||
|
;; No audio element found, try to recreate
|
||||||
|
(let ((new-audio (recreate-audio-element)))
|
||||||
|
(if new-audio
|
||||||
|
(set-timeout
|
||||||
|
(lambda ()
|
||||||
|
(ps:chain new-audio (play)
|
||||||
|
(then (lambda ()
|
||||||
|
(setf *is-reconnecting* false)
|
||||||
|
(show-stream-status "✓ Stream connected!" "success")
|
||||||
|
(set-timeout hide-stream-status 3000)))
|
||||||
|
(catch (lambda (err)
|
||||||
|
(setf *is-reconnecting* false)
|
||||||
|
(show-stream-status "❌ Could not connect. Click play to try again." "error")
|
||||||
|
(show-reconnect-button)))))
|
||||||
|
500)
|
||||||
|
(progn
|
||||||
|
(setf *is-reconnecting* false)
|
||||||
|
(show-stream-status "❌ Could not create audio player. Please reload the page." "error")))))))
|
||||||
|
|
||||||
|
;; Attach event listeners to audio element
|
||||||
|
(defun attach-audio-event-listeners (audio-element)
|
||||||
|
"Attach all necessary event listeners to an audio element"
|
||||||
|
|
||||||
|
;; Error handler
|
||||||
|
(ps:chain audio-element
|
||||||
|
(add-event-listener "error"
|
||||||
|
(lambda (err)
|
||||||
|
(incf *stream-error-count*)
|
||||||
|
(ps:chain console (log "Stream error:" err))
|
||||||
|
|
||||||
|
(if (< *stream-error-count* 3)
|
||||||
|
;; Auto-retry for first few errors
|
||||||
|
(progn
|
||||||
|
(show-stream-status (+ "⚠️ Stream error. Reconnecting... (attempt " *stream-error-count* ")") "warning")
|
||||||
|
(setf *reconnect-timeout*
|
||||||
|
(set-timeout reconnect-stream 3000)))
|
||||||
|
;; Too many errors, show manual reconnect
|
||||||
|
(progn
|
||||||
|
(show-stream-status "❌ Stream connection lost. Click Reconnect to try again." "error")
|
||||||
|
(show-reconnect-button))))))
|
||||||
|
|
||||||
|
;; Stalled handler
|
||||||
|
(ps:chain audio-element
|
||||||
|
(add-event-listener "stalled"
|
||||||
|
(lambda ()
|
||||||
|
(ps:chain console (log "Stream stalled"))
|
||||||
|
(show-stream-status "⚠️ Stream stalled. Attempting to recover..." "warning")
|
||||||
|
(setf *reconnect-timeout*
|
||||||
|
(set-timeout
|
||||||
|
(lambda ()
|
||||||
|
;; Only reconnect if still stalled
|
||||||
|
(when (ps:@ audio-element paused)
|
||||||
|
(reconnect-stream)))
|
||||||
|
5000)))))
|
||||||
|
|
||||||
|
;; Waiting handler (buffering)
|
||||||
|
(ps:chain audio-element
|
||||||
|
(add-event-listener "waiting"
|
||||||
|
(lambda ()
|
||||||
|
(ps:chain console (log "Stream buffering..."))
|
||||||
|
(show-stream-status "⏳ Buffering..." "info"))))
|
||||||
|
|
||||||
|
;; Playing handler - clear any error states
|
||||||
|
(ps:chain audio-element
|
||||||
|
(add-event-listener "playing"
|
||||||
|
(lambda ()
|
||||||
|
(setf *stream-error-count* 0)
|
||||||
|
(hide-stream-status)
|
||||||
|
(hide-reconnect-button)
|
||||||
|
(when *reconnect-timeout*
|
||||||
|
(clear-timeout *reconnect-timeout*)
|
||||||
|
(setf *reconnect-timeout* nil)))))
|
||||||
|
|
||||||
|
;; Pause handler - track when paused for long pause detection
|
||||||
|
(ps:chain audio-element
|
||||||
|
(add-event-listener "pause"
|
||||||
|
(lambda ()
|
||||||
|
(setf *last-play-attempt* (ps:chain |Date| (now))))))
|
||||||
|
|
||||||
|
;; Play handler - detect long pauses that need reconnection
|
||||||
|
(ps:chain audio-element
|
||||||
|
(add-event-listener "play"
|
||||||
|
(lambda ()
|
||||||
|
(let ((pause-duration (- (ps:chain |Date| (now)) *last-play-attempt*)))
|
||||||
|
;; If paused for more than 30 seconds, reconnect to get fresh stream
|
||||||
|
(when (> pause-duration 30000)
|
||||||
|
(ps:chain console (log "Long pause detected, reconnecting for fresh stream..."))
|
||||||
|
(reconnect-stream))))))
|
||||||
|
|
||||||
|
;; Spectrum analyzer hooks
|
||||||
|
(when (ps:@ window |initSpectrumAnalyzer|)
|
||||||
|
(ps:chain audio-element (add-event-listener "play"
|
||||||
|
(lambda () (ps:chain window (init-spectrum-analyzer))))))
|
||||||
|
|
||||||
|
(when (ps:@ window |stopSpectrumAnalyzer|)
|
||||||
|
(ps:chain audio-element (add-event-listener "pause"
|
||||||
|
(lambda () (ps:chain window (stop-spectrum-analyzer)))))))
|
||||||
|
|
||||||
(defun redirect-when-frame ()
|
(defun redirect-when-frame ()
|
||||||
(let* ((path (ps:@ window location pathname))
|
(let* ((path (ps:@ window location pathname))
|
||||||
(is-frameset-page (not (= (ps:@ window parent) (ps:@ window self))))
|
(is-frameset-page (not (= (ps:@ window parent) (ps:@ window self))))
|
||||||
|
|
@ -164,80 +413,10 @@
|
||||||
;; Update now playing
|
;; Update now playing
|
||||||
(update-now-playing)
|
(update-now-playing)
|
||||||
|
|
||||||
;; Auto-reconnect on stream errors
|
;; Attach event listeners to audio element
|
||||||
(let ((audio-element (ps:chain document (get-element-by-id "live-audio"))))
|
(let ((audio-element (ps:chain document (get-element-by-id "live-audio"))))
|
||||||
(when audio-element
|
(when audio-element
|
||||||
(ps:chain audio-element
|
(attach-audio-event-listeners audio-element)))
|
||||||
(add-event-listener
|
|
||||||
"error"
|
|
||||||
(lambda (err)
|
|
||||||
(ps:chain console (log "Stream error, attempting reconnect in 3 seconds..." err))
|
|
||||||
(set-timeout
|
|
||||||
(lambda ()
|
|
||||||
(ps:chain audio-element (load))
|
|
||||||
(ps:chain (ps:chain audio-element (play))
|
|
||||||
(catch (lambda (err)
|
|
||||||
(ps:chain console (log "Reconnect failed:" err))))))
|
|
||||||
3000))))
|
|
||||||
|
|
||||||
(ps:chain audio-element
|
|
||||||
(add-event-listener
|
|
||||||
"stalled"
|
|
||||||
(lambda ()
|
|
||||||
(ps:chain console (log "Stream stalled, reloading..."))
|
|
||||||
(ps:chain audio-element (load))
|
|
||||||
(ps:chain (ps:chain audio-element (play))
|
|
||||||
(catch (lambda (err)
|
|
||||||
(ps:chain console (log "Reload failed:" err))))))))
|
|
||||||
|
|
||||||
(let ((pause-timestamp nil)
|
|
||||||
(is-reconnecting false)
|
|
||||||
(needs-reconnect false)
|
|
||||||
(pause-reconnect-threshold 10000))
|
|
||||||
|
|
||||||
(ps:chain audio-element
|
|
||||||
(add-event-listener "pause"
|
|
||||||
(lambda ()
|
|
||||||
(setf pause-timestamp (ps:chain |Date| (now)))
|
|
||||||
(ps:chain console (log "Stream paused at:" pause-timestamp)))))
|
|
||||||
|
|
||||||
(ps:chain audio-element
|
|
||||||
(add-event-listener "play"
|
|
||||||
(lambda ()
|
|
||||||
(when (and (not is-reconnecting)
|
|
||||||
pause-timestamp
|
|
||||||
(> (- (ps:chain |Date| (now)) pause-timestamp) pause-reconnect-threshold))
|
|
||||||
(setf needs-reconnect true)
|
|
||||||
(ps:chain console (log "Long pause detected, will reconnect when playing starts...")))
|
|
||||||
(setf pause-timestamp nil))))
|
|
||||||
|
|
||||||
(ps:chain audio-element
|
|
||||||
(add-event-listener "playing"
|
|
||||||
(lambda ()
|
|
||||||
(when (and needs-reconnect (not is-reconnecting))
|
|
||||||
(setf is-reconnecting true)
|
|
||||||
(setf needs-reconnect false)
|
|
||||||
(ps:chain console (log "Reconnecting stream after long pause to clear stale buffers..."))
|
|
||||||
|
|
||||||
(ps:chain audio-element (pause))
|
|
||||||
|
|
||||||
(when (ps:@ window |resetSpectrumAnalyzer|)
|
|
||||||
(ps:chain window (reset-spectrum-analyzer)))
|
|
||||||
|
|
||||||
(ps:chain audio-element (load))
|
|
||||||
|
|
||||||
(set-timeout
|
|
||||||
(lambda ()
|
|
||||||
(ps:chain audio-element (play)
|
|
||||||
(catch (lambda (err)
|
|
||||||
(ps:chain console (log "Reconnect play failed:" err)))))
|
|
||||||
|
|
||||||
(when (ps:@ window |initSpectrumAnalyzer|)
|
|
||||||
(ps:chain window (init-spectrum-analyzer))
|
|
||||||
(ps:chain console (log "Spectrum analyzer reinitialized after reconnect")))
|
|
||||||
|
|
||||||
(setf is-reconnecting false))
|
|
||||||
200))))))))
|
|
||||||
|
|
||||||
;; Check frameset preference
|
;; Check frameset preference
|
||||||
(let ((path (ps:@ window location pathname))
|
(let ((path (ps:@ window location pathname))
|
||||||
|
|
@ -249,8 +428,8 @@
|
||||||
|
|
||||||
(redirect-when-frame)))))
|
(redirect-when-frame)))))
|
||||||
|
|
||||||
;; Update now playing every 10 seconds
|
;; Update now playing every 5 seconds
|
||||||
(set-interval update-now-playing 10000)
|
(set-interval update-now-playing 5000)
|
||||||
|
|
||||||
;; Listen for messages from popout window
|
;; Listen for messages from popout window
|
||||||
(ps:chain window
|
(ps:chain window
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,16 @@
|
||||||
(when *animation-id*
|
(when *animation-id*
|
||||||
(cancel-animation-frame *animation-id*)
|
(cancel-animation-frame *animation-id*)
|
||||||
(setf *animation-id* nil))
|
(setf *animation-id* nil))
|
||||||
|
;; Close the old AudioContext if it exists
|
||||||
|
(when *audio-context*
|
||||||
|
(ps:try
|
||||||
|
(ps:chain *audio-context* (close))
|
||||||
|
(:catch (e)
|
||||||
|
(ps:chain console (log "Error closing AudioContext:" e)))))
|
||||||
(setf *audio-context* nil)
|
(setf *audio-context* nil)
|
||||||
(setf *analyser* nil)
|
(setf *analyser* nil)
|
||||||
(setf *media-source* nil)
|
(setf *media-source* nil)
|
||||||
|
(setf *current-audio-element* nil)
|
||||||
(ps:chain console (log "Spectrum analyzer reset for reconnection")))
|
(ps:chain console (log "Spectrum analyzer reset for reconnection")))
|
||||||
|
|
||||||
(defun init-spectrum-analyzer ()
|
(defun init-spectrum-analyzer ()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXTINF:370,Vector Lovers - City Lights From a Train
|
||||||
|
/app/music/Vector Lovers/City Lights From a Train.flac
|
||||||
|
#EXTINF:400,The Black Dog - Psil-Cosyin
|
||||||
|
/app/music/The Black Dog/Psil-Cosyin.flac
|
||||||
|
#EXTINF:320,Plaid - Eyen
|
||||||
|
/app/music/Plaid/Eyen.flac
|
||||||
|
#EXTINF:330,ISAN - Birds Over Barges
|
||||||
|
/app/music/ISAN/Birds Over Barges.flac
|
||||||
|
#EXTINF:360,Ochre - Bluebottle Farm
|
||||||
|
/app/music/Ochre/Bluebottle Farm.flac
|
||||||
|
#EXTINF:390,Arovane - Theme
|
||||||
|
/app/music/Arovane/Theme.flac
|
||||||
|
#EXTINF:380,Proem - Deep Like Airline Failure
|
||||||
|
/app/music/Proem/Deep Like Airline Failure.flac
|
||||||
|
#EXTINF:310,Solvent - My Radio (Remix)
|
||||||
|
/app/music/Solvent/My Radio (Remix).flac
|
||||||
|
#EXTINF:350,Bochum Welt - Marylebone (7th)
|
||||||
|
/app/music/Bochum Welt/Marylebone (7th).flac
|
||||||
|
#EXTINF:290,Mrs Jynx - Shibuya Lullaby
|
||||||
|
/app/music/Mrs Jynx/Shibuya Lullaby.flac
|
||||||
|
#EXTINF:340,Kettel - Whisper Me Wishes
|
||||||
|
/app/music/Kettel/Whisper Me Wishes.flac
|
||||||
|
#EXTINF:360,Christ. - Perlandine Friday
|
||||||
|
/app/music/Christ./Perlandine Friday.flac
|
||||||
|
#EXTINF:330,Cepia - Ithaca
|
||||||
|
/app/music/Cepia/Ithaca.flac
|
||||||
|
#EXTINF:340,Datassette - Vacuform
|
||||||
|
/app/music/Datassette/Vacuform.flac
|
||||||
|
#EXTINF:390,Plant43 - Dreams of the Sentient City
|
||||||
|
/app/music/Plant43/Dreams of the Sentient City.flac
|
||||||
|
#EXTINF:410,Claro Intelecto - Peace of Mind (Electrosoul)
|
||||||
|
/app/music/Claro Intelecto/Peace of Mind (Electrosoul).flac
|
||||||
|
#EXTINF:430,E.R.P. - Evoked
|
||||||
|
/app/music/E.R.P./Evoked.flac
|
||||||
|
#EXTINF:310,Der Zyklus - Formenverwandler
|
||||||
|
/app/music/Der Zyklus/Formenverwandler.flac
|
||||||
|
#EXTINF:330,Dopplereffekt - Infophysix
|
||||||
|
/app/music/Dopplereffekt/Infophysix.flac
|
||||||
|
#EXTINF:350,Drexciya - Wavejumper
|
||||||
|
/app/music/Drexciya/Wavejumper.flac
|
||||||
|
#EXTINF:375,The Other People Place - Sorrow & A Cup of Joe
|
||||||
|
/app/music/The Other People Place/Sorrow & A Cup of Joe.flac
|
||||||
|
#EXTINF:340,Arpanet - Wireless Internet
|
||||||
|
/app/music/Arpanet/Wireless Internet.flac
|
||||||
|
#EXTINF:380,Legowelt - Sturmvogel
|
||||||
|
/app/music/Legowelt/Sturmvogel.flac
|
||||||
|
#EXTINF:310,DMX Krew - Space Paranoia
|
||||||
|
/app/music/DMX Krew/Space Paranoia.flac
|
||||||
|
#EXTINF:360,Skywave Theory - Nova Drift
|
||||||
|
/app/music/Skywave Theory/Nova Drift.flac
|
||||||
|
#EXTINF:460,Pye Corner Audio - Transmission Four
|
||||||
|
/app/music/Pye Corner Audio/Transmission Four.flac
|
||||||
|
#EXTINF:390,B12 - Heaven Sent
|
||||||
|
/app/music/B12/Heaven Sent.flac
|
||||||
|
#EXTINF:450,Higher Intelligence Agency - Tortoise
|
||||||
|
/app/music/Higher Intelligence Agency/Tortoise.flac
|
||||||
|
#EXTINF:420,Biosphere - Kobresia
|
||||||
|
/app/music/Biosphere/Kobresia.flac
|
||||||
|
#EXTINF:870,Global Communication - 14:31
|
||||||
|
/app/music/Global Communication/14:31.flac
|
||||||
|
#EXTINF:500,Monolake - Cyan
|
||||||
|
/app/music/Monolake/Cyan.flac
|
||||||
|
#EXTINF:660,Deepchord - Electromagnetic
|
||||||
|
/app/music/Deepchord/Electromagnetic.flac
|
||||||
|
#EXTINF:1020,GAS - Pop 4
|
||||||
|
/app/music/GAS/Pop 4.flac
|
||||||
|
#EXTINF:600,Yagya - Rigning Nýju
|
||||||
|
/app/music/Yagya/Rigning Nýju.flac
|
||||||
|
#EXTINF:990,Voices From The Lake - Velo di Maya
|
||||||
|
/app/music/Voices From The Lake/Velo di Maya.flac
|
||||||
|
#EXTINF:3720,ASC - Time Heals All
|
||||||
|
/app/music/ASC/Time Heals All.flac
|
||||||
|
#EXTINF:540,36 - Room 237
|
||||||
|
/app/music/36/Room 237.flac
|
||||||
|
#EXTINF:900,Loscil - Endless Falls
|
||||||
|
/app/music/Loscil/Endless Falls.flac
|
||||||
|
#EXTINF:450,Kiasmos - Looped
|
||||||
|
/app/music/Kiasmos/Looped.flac
|
||||||
|
#EXTINF:590,Underworld - Rez
|
||||||
|
/app/music/Underworld/Rez.flac
|
||||||
|
#EXTINF:570,Orbital - Halcyon + On + On
|
||||||
|
/app/music/Orbital/Halcyon + On + On.flac
|
||||||
|
#EXTINF:1080,The Orb - A Huge Ever Growing Pulsating Brain
|
||||||
|
/app/music/The Orb/A Huge Ever Growing Pulsating Brain.flac
|
||||||
|
#EXTINF:360,Autechre - Slip
|
||||||
|
/app/music/Autechre/Slip.flac
|
||||||
|
#EXTINF:400,Labradford - S (Mi Media Naranja)
|
||||||
|
/app/music/Labradford/S (Mi Media Naranja).flac
|
||||||
|
#EXTINF:350,Vector Lovers - Rusting Cars and Wildflowers
|
||||||
|
/app/music/Vector Lovers/Rusting Cars and Wildflowers.flac
|
||||||
|
#EXTINF:390,The Black Dog - Raxmus
|
||||||
|
/app/music/The Black Dog/Raxmus.flac
|
||||||
|
#EXTINF:315,Plaid - Hawkmoth
|
||||||
|
/app/music/Plaid/Hawkmoth.flac
|
||||||
|
#EXTINF:320,ISAN - What This Button Did
|
||||||
|
/app/music/ISAN/What This Button Did.flac
|
||||||
|
#EXTINF:370,Ochre - Circadies
|
||||||
|
/app/music/Ochre/Circadies.flac
|
||||||
|
#EXTINF:420,Arovane - Tides
|
||||||
|
/app/music/Arovane/Tides.flac
|
||||||
|
#EXTINF:370,Proem - Nothing is as It Seems
|
||||||
|
/app/music/Proem/Nothing is as It Seems.flac
|
||||||
|
#EXTINF:300,Solvent - Loss For Words
|
||||||
|
/app/music/Solvent/Loss For Words.flac
|
||||||
|
#EXTINF:340,Bochum Welt - Saint (77sunset)
|
||||||
|
/app/music/Bochum Welt/Saint (77sunset).flac
|
||||||
|
#EXTINF:280,Mrs Jynx - Stay Home
|
||||||
|
/app/music/Mrs Jynx/Stay Home.flac
|
||||||
|
#EXTINF:330,Kettel - Church
|
||||||
|
/app/music/Kettel/Church.flac
|
||||||
|
#EXTINF:370,Christ. - Cordate
|
||||||
|
/app/music/Christ./Cordate.flac
|
||||||
|
#EXTINF:350,Datassette - Computers Elevate
|
||||||
|
/app/music/Datassette/Computers Elevate.flac
|
||||||
|
#EXTINF:420,Plant43 - The Cold Surveyor
|
||||||
|
/app/music/Plant43/The Cold Surveyor.flac
|
||||||
|
#EXTINF:380,Claro Intelecto - Section
|
||||||
|
/app/music/Claro Intelecto/Section.flac
|
||||||
|
#EXTINF:440,E.R.P. - Vox Automaton
|
||||||
|
/app/music/E.R.P./Vox Automaton.flac
|
||||||
|
#EXTINF:300,Dopplereffekt - Z-Boson
|
||||||
|
/app/music/Dopplereffekt/Z-Boson.flac
|
||||||
|
#EXTINF:380,Drexciya - Digital Tsunami
|
||||||
|
/app/music/Drexciya/Digital Tsunami.flac
|
||||||
|
#EXTINF:350,The Other People Place - You Said You Want Me
|
||||||
|
/app/music/The Other People Place/You Said You Want Me.flac
|
||||||
|
#EXTINF:370,Legowelt - Star Gazing
|
||||||
|
/app/music/Legowelt/Star Gazing.flac
|
||||||
|
#EXTINF:440,Pye Corner Audio - Electronic Rhythm Number 3
|
||||||
|
/app/music/Pye Corner Audio/Electronic Rhythm Number 3.flac
|
||||||
|
#EXTINF:460,B12 - Infinite Lites (Classic Mix)
|
||||||
|
/app/music/B12/Infinite Lites (Classic Mix).flac
|
||||||
|
#EXTINF:390,Biosphere - The Things I Tell You
|
||||||
|
/app/music/Biosphere/The Things I Tell You.flac
|
||||||
|
#EXTINF:580,Global Communication - 9:39
|
||||||
|
/app/music/Global Communication/9:39.flac
|
||||||
|
#EXTINF:460,Monolake - T-Channel
|
||||||
|
/app/music/Monolake/T-Channel.flac
|
||||||
|
#EXTINF:690,Deepchord - Vantage Isle (Variant)
|
||||||
|
/app/music/Deepchord/Vantage Isle (Variant).flac
|
||||||
|
#EXTINF:840,GAS - Königsforst 5
|
||||||
|
/app/music/GAS/Königsforst 5.flac
|
||||||
|
#EXTINF:520,Yagya - The Salt on Her Cheeks
|
||||||
|
/app/music/Yagya/The Salt on Her Cheeks.flac
|
||||||
|
#EXTINF:720,Voices From The Lake - Dream State
|
||||||
|
/app/music/Voices From The Lake/Dream State.flac
|
||||||
|
#EXTINF:510,36 - Night Rain
|
||||||
|
/app/music/36/Night Rain.flac
|
||||||
|
#EXTINF:470,Loscil - First Narrows
|
||||||
|
/app/music/Loscil/First Narrows.flac
|
||||||
|
#EXTINF:400,Kiasmos - Burnt
|
||||||
|
/app/music/Kiasmos/Burnt.flac
|
||||||
|
#EXTINF:570,Underworld - Jumbo (Extended)
|
||||||
|
/app/music/Underworld/Jumbo (Extended).flac
|
||||||
|
#EXTINF:480,Orbital - Belfast
|
||||||
|
/app/music/Orbital/Belfast.flac
|
||||||
|
#EXTINF:540,The Orb - Little Fluffy Clouds (Ambient Mix)
|
||||||
|
/app/music/The Orb/Little Fluffy Clouds (Ambient Mix).flac
|
||||||
|
#EXTINF:390,Autechre - Nine
|
||||||
|
/app/music/Autechre/Nine.flac
|
||||||
|
#EXTINF:380,Labradford - G (Mi Media Naranja)
|
||||||
|
/app/music/Labradford/G (Mi Media Naranja).flac
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
#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
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
#EXTM3U
|
||||||
|
#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
|
||||||
|
|
@ -0,0 +1,371 @@
|
||||||
|
#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
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1041,6 +1041,20 @@
|
||||||
:flex 1
|
:flex 1
|
||||||
:min-width "300px")
|
:min-width "300px")
|
||||||
|
|
||||||
|
(.persistent-reconnect-btn
|
||||||
|
:background transparent
|
||||||
|
:color "#00ff00"
|
||||||
|
:border "1px solid #00ff00"
|
||||||
|
:padding "5px 10px"
|
||||||
|
:cursor "pointer"
|
||||||
|
:font-family #(main-font)
|
||||||
|
:font-size "0.85em"
|
||||||
|
:white-space nowrap
|
||||||
|
:margin-right "5px")
|
||||||
|
|
||||||
|
((:and .persistent-reconnect-btn :hover)
|
||||||
|
:background "#2a3441")
|
||||||
|
|
||||||
(.persistent-disable-btn
|
(.persistent-disable-btn
|
||||||
:background transparent
|
:background transparent
|
||||||
:color "#00ff00"
|
:color "#00ff00"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>About - Asteroid Radio</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" type="text/css" href="/asteroid/static/asteroid.css">
|
||||||
|
<script src="/asteroid/static/js/auth-ui.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<header>
|
||||||
|
<h1 style="display: flex; align-items: center; justify-content: center; gap: 15px;">
|
||||||
|
<img src="/asteroid/static/asteroid.png" alt="Asteroid" style="height: 50px; width: auto;">
|
||||||
|
<span>ABOUT ASTEROID RADIO</span>
|
||||||
|
<img src="/asteroid/static/asteroid.png" alt="Asteroid" style="height: 50px; width: auto;">
|
||||||
|
</h1>
|
||||||
|
<nav class="nav">
|
||||||
|
<a href="/asteroid/content" target="_self">Home</a>
|
||||||
|
<a href="/asteroid/player-content" target="_self">Player</a>
|
||||||
|
<a href="/asteroid/about-content" target="_self">About</a>
|
||||||
|
<a href="/asteroid/status" target="_self">Status</a>
|
||||||
|
<a href="/asteroid/profile" target="_self" data-show-if-logged-in>Profile</a>
|
||||||
|
<a href="/asteroid/admin" target="_self" data-show-if-admin>Admin</a>
|
||||||
|
<a href="/asteroid/login" target="_self" data-show-if-logged-out>Login</a>
|
||||||
|
<a href="/asteroid/register" target="_self" data-show-if-logged-out>Register</a>
|
||||||
|
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout">Logout</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<main style="max-width: 800px; margin: 0 auto; padding: 20px;">
|
||||||
|
<section style="margin-bottom: 30px;">
|
||||||
|
<h2 style="color: #00ff00; border-bottom: 2px solid #00ff00; padding-bottom: 10px;">🎵 Asteroid Music for Hackers</h2>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
Asteroid Radio is a community-driven internet radio station born from the SystemCrafters community.
|
||||||
|
We celebrate the intersection of music, technology, and hacker culture—broadcasting for those who
|
||||||
|
appreciate both great code and great music.
|
||||||
|
</p>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
We met through a shared set of technical biases and a love for building systems from first principles.
|
||||||
|
Asteroid Radio embodies that ethos: <strong>music for hackers, built by hackers</strong>.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section style="margin-bottom: 30px;">
|
||||||
|
<h2 style="color: #00ff00; border-bottom: 2px solid #00ff00; padding-bottom: 10px;">🛠️ Built with Common Lisp</h2>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
This entire platform is built using <strong>Common Lisp</strong>, demonstrating the power and elegance
|
||||||
|
of Lisp for modern web applications. We use:
|
||||||
|
</p>
|
||||||
|
<ul style="line-height: 1.8; margin-left: 20px;">
|
||||||
|
<li><strong><a href="https://codeberg.org/shirakumo/radiance" style="color: #00ff00;">Radiance</a></strong> - Web application framework</li>
|
||||||
|
<li><strong><a href="https://codeberg.org/shinmera/clip" style="color: #00ff00;">Clip</a></strong> - HTML5-compliant template engine</li>
|
||||||
|
<li><strong><a href="https://codeberg.org/shinmera/LASS" style="color: #00ff00;">LASS</a></strong> - Lisp Augmented Style Sheets</li>
|
||||||
|
<li><strong><a href="https://gitlab.common-lisp.net/parenscript/parenscript" style="color: #00ff00;">ParenScript</a></strong> - Lisp-to-JavaScript compiler</li>
|
||||||
|
<li><strong><a href="https://icecast.org/" style="color: #00ff00;">Icecast</a></strong> - Streaming media server</li>
|
||||||
|
<li><strong><a href="https://www.liquidsoap.info/" style="color: #00ff00;">Liquidsoap</a></strong> - Audio stream generation</li>
|
||||||
|
</ul>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
By building in Common Lisp, we're doubling down on our technical values and creating features
|
||||||
|
for "our people"—those who appreciate the elegance of Lisp and the power of understanding your tools deeply.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section style="margin-bottom: 30px;">
|
||||||
|
<h2 style="color: #00ff00; border-bottom: 2px solid #00ff00; padding-bottom: 10px;">📖 Open Source & AGPL Licensed</h2>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
Asteroid Radio is <strong>free and open source software</strong>, licensed under the
|
||||||
|
<strong><a href="https://www.gnu.org/licenses/agpl-3.0.en.html" style="color: #00ff00;">GNU Affero General Public License v3.0 (AGPL)</a></strong>.
|
||||||
|
</p>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
The source code is available at:
|
||||||
|
<a href="https://github.com/Fade/asteroid" style="color: #00ff00; font-weight: bold;">https://github.com/Fade/asteroid</a>
|
||||||
|
</p>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
We believe in transparency, collaboration, and the freedom to study, modify, and share the software we use.
|
||||||
|
The AGPL ensures that improvements to Asteroid Radio remain free and available to everyone.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section style="margin-bottom: 30px;">
|
||||||
|
<h2 style="color: #00ff00; border-bottom: 2px solid #00ff00; padding-bottom: 10px;">🎧 Features</h2>
|
||||||
|
<ul style="line-height: 1.8; margin-left: 20px;">
|
||||||
|
<li><strong>Live Streaming</strong> - Multiple quality options (AAC, MP3)</li>
|
||||||
|
<li><strong>Persistent Player</strong> - Frameset mode for uninterrupted playback while browsing</li>
|
||||||
|
<li><strong>Spectrum Analyzer</strong> - Real-time audio visualization with customizable themes</li>
|
||||||
|
<li><strong>Track Library</strong> - Browse and search the music collection</li>
|
||||||
|
<li><strong>User Profiles</strong> - Track your listening history</li>
|
||||||
|
<li><strong>Admin Tools</strong> - Manage tracks, users, and playlists</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section style="margin-bottom: 30px;">
|
||||||
|
<h2 style="color: #00ff00; border-bottom: 2px solid #00ff00; padding-bottom: 10px;">🤝 Community</h2>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
We're part of the <strong><a href="https://systemcrafters.net/" style="color: #00ff00;">SystemCrafters</a></strong>
|
||||||
|
community—a group of developers, hackers, and enthusiasts who believe in building systems from first principles,
|
||||||
|
understanding our tools deeply, and sharing knowledge freely.
|
||||||
|
</p>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
Join us in celebrating the intersection of great music and great code!
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>About - Asteroid Radio</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="/asteroid/static/favicon.ico">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/asteroid/static/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/asteroid/static/favicon-16x16.png">
|
||||||
|
<link rel="stylesheet" type="text/css" href="/asteroid/static/asteroid.css">
|
||||||
|
<script src="/asteroid/static/js/auth-ui.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<header>
|
||||||
|
<h1 style="display: flex; align-items: center; justify-content: center; gap: 15px;">
|
||||||
|
<img src="/asteroid/static/asteroid.png" alt="Asteroid" style="height: 50px; width: auto;">
|
||||||
|
<span>ABOUT ASTEROID RADIO</span>
|
||||||
|
<img src="/asteroid/static/asteroid.png" alt="Asteroid" style="height: 50px; width: auto;">
|
||||||
|
</h1>
|
||||||
|
<nav class="nav">
|
||||||
|
<a href="/asteroid/">Home</a>
|
||||||
|
<a href="/asteroid/player">Player</a>
|
||||||
|
<a href="/asteroid/about">About</a>
|
||||||
|
<a href="/asteroid/status">Status</a>
|
||||||
|
<a href="/asteroid/profile" data-show-if-logged-in>Profile</a>
|
||||||
|
<a href="/asteroid/admin" data-show-if-admin>Admin</a>
|
||||||
|
<a href="/asteroid/login" data-show-if-logged-out>Login</a>
|
||||||
|
<a href="/asteroid/register" data-show-if-logged-out>Register</a>
|
||||||
|
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout">Logout</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<main style="max-width: 800px; margin: 0 auto; padding: 20px;">
|
||||||
|
<section style="margin-bottom: 30px;">
|
||||||
|
<h2 style="color: #00ff00; border-bottom: 2px solid #00ff00; padding-bottom: 10px;">🎵 Asteroid Music for Hackers</h2>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
Asteroid Radio is a community-driven internet radio station born from the SystemCrafters community.
|
||||||
|
We celebrate the intersection of music, technology, and hacker culture—broadcasting for those who
|
||||||
|
appreciate both great code and great music.
|
||||||
|
</p>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
We met through a shared set of technical biases and a love for building systems from first principles.
|
||||||
|
Asteroid Radio embodies that ethos: <strong>music for hackers, built by hackers</strong>.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section style="margin-bottom: 30px;">
|
||||||
|
<h2 style="color: #00ff00; border-bottom: 2px solid #00ff00; padding-bottom: 10px;">🛠️ Built with Common Lisp</h2>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
This entire platform is built using <strong>Common Lisp</strong>, demonstrating the power and elegance
|
||||||
|
of Lisp for modern web applications. We use:
|
||||||
|
</p>
|
||||||
|
<ul style="line-height: 1.8; margin-left: 20px;">
|
||||||
|
<li><strong><a href="https://codeberg.org/shirakumo/radiance" style="color: #00ff00;">Radiance</a></strong> - Web application framework</li>
|
||||||
|
<li><strong><a href="https://codeberg.org/shinmera/clip" style="color: #00ff00;">Clip</a></strong> - HTML5-compliant template engine</li>
|
||||||
|
<li><strong><a href="https://codeberg.org/shinmera/LASS" style="color: #00ff00;">LASS</a></strong> - Lisp Augmented Style Sheets</li>
|
||||||
|
<li><strong><a href="https://gitlab.common-lisp.net/parenscript/parenscript" style="color: #00ff00;">ParenScript</a></strong> - Lisp-to-JavaScript compiler</li>
|
||||||
|
<li><strong><a href="https://icecast.org/" style="color: #00ff00;">Icecast</a></strong> - Streaming media server</li>
|
||||||
|
<li><strong><a href="https://www.liquidsoap.info/" style="color: #00ff00;">Liquidsoap</a></strong> - Audio stream generation</li>
|
||||||
|
</ul>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
By building in Common Lisp, we're doubling down on our technical values and creating features
|
||||||
|
for "our people"—those who appreciate the elegance of Lisp and the power of understanding your tools deeply.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section style="margin-bottom: 30px;">
|
||||||
|
<h2 style="color: #00ff00; border-bottom: 2px solid #00ff00; padding-bottom: 10px;">📖 Open Source & AGPL Licensed</h2>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
Asteroid Radio is <strong>free and open source software</strong>, licensed under the
|
||||||
|
<strong><a href="https://www.gnu.org/licenses/agpl-3.0.en.html" style="color: #00ff00;">GNU Affero General Public License v3.0 (AGPL)</a></strong>.
|
||||||
|
</p>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
The source code is available at:
|
||||||
|
<a href="https://github.com/Fade/asteroid" style="color: #00ff00; font-weight: bold;">https://github.com/Fade/asteroid</a>
|
||||||
|
</p>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
We believe in transparency, collaboration, and the freedom to study, modify, and share the software we use.
|
||||||
|
The AGPL ensures that improvements to Asteroid Radio remain free and available to everyone.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section style="margin-bottom: 30px;">
|
||||||
|
<h2 style="color: #00ff00; border-bottom: 2px solid #00ff00; padding-bottom: 10px;">🎧 Features</h2>
|
||||||
|
<ul style="line-height: 1.8; margin-left: 20px;">
|
||||||
|
<li><strong>Live Streaming</strong> - Multiple quality options (AAC, MP3)</li>
|
||||||
|
<li><strong>Persistent Player</strong> - Frameset mode for uninterrupted playback while browsing</li>
|
||||||
|
<li><strong>Spectrum Analyzer</strong> - Real-time audio visualization with customizable themes</li>
|
||||||
|
<li><strong>Track Library</strong> - Browse and search the music collection</li>
|
||||||
|
<li><strong>User Profiles</strong> - Track your listening history</li>
|
||||||
|
<li><strong>Admin Tools</strong> - Manage tracks, users, and playlists</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section style="margin-bottom: 30px;">
|
||||||
|
<h2 style="color: #00ff00; border-bottom: 2px solid #00ff00; padding-bottom: 10px;">🤝 Community</h2>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
We're part of the <strong><a href="https://systemcrafters.net/" style="color: #00ff00;">SystemCrafters</a></strong>
|
||||||
|
community—a group of developers, hackers, and enthusiasts who believe in building systems from first principles,
|
||||||
|
understanding our tools deeply, and sharing knowledge freely.
|
||||||
|
</p>
|
||||||
|
<p style="line-height: 1.6;">
|
||||||
|
Join us in celebrating the intersection of great music and great code!
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -28,11 +28,18 @@
|
||||||
|
|
||||||
<span class="now-playing-mini" id="mini-now-playing">Loading...</span>
|
<span class="now-playing-mini" id="mini-now-playing">Loading...</span>
|
||||||
|
|
||||||
|
<button id="reconnect-btn" onclick="reconnectStream()" class="persistent-reconnect-btn" title="Reconnect if audio stops working">
|
||||||
|
🔄
|
||||||
|
</button>
|
||||||
|
|
||||||
<button onclick="disableFramesetMode()" class="persistent-disable-btn">
|
<button onclick="disableFramesetMode()" class="persistent-disable-btn">
|
||||||
✕ Disable
|
✕ Disable
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Status indicator for connection issues -->
|
||||||
|
<div id="stream-status" style="display: none; background: #550000; color: #ff6666; padding: 4px 10px; text-align: center; font-size: 0.85em;"></div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Configure audio element for better streaming
|
// Configure audio element for better streaming
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
|
@ -134,6 +141,145 @@
|
||||||
// Redirect parent window to regular view
|
// Redirect parent window to regular view
|
||||||
window.parent.location.href = '/asteroid/';
|
window.parent.location.href = '/asteroid/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show status message
|
||||||
|
function showStatus(message, isError) {
|
||||||
|
const status = document.getElementById('stream-status');
|
||||||
|
if (status) {
|
||||||
|
status.textContent = message;
|
||||||
|
status.style.display = 'block';
|
||||||
|
status.style.background = isError ? '#550000' : '#005500';
|
||||||
|
status.style.color = isError ? '#ff6666' : '#66ff66';
|
||||||
|
if (!isError) {
|
||||||
|
setTimeout(() => { status.style.display = 'none'; }, 3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideStatus() {
|
||||||
|
const status = document.getElementById('stream-status');
|
||||||
|
if (status) {
|
||||||
|
status.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconnect stream - recreates audio element to fix wedged state
|
||||||
|
function reconnectStream() {
|
||||||
|
console.log('Reconnecting stream...');
|
||||||
|
showStatus('🔄 Reconnecting...', false);
|
||||||
|
|
||||||
|
const container = document.querySelector('.persistent-player');
|
||||||
|
const oldAudio = document.getElementById('persistent-audio');
|
||||||
|
const streamBaseUrl = document.getElementById('stream-base-url').value;
|
||||||
|
const streamQuality = localStorage.getItem('stream-quality') || 'aac';
|
||||||
|
const config = getStreamConfig(streamBaseUrl, streamQuality);
|
||||||
|
|
||||||
|
if (!container || !oldAudio) {
|
||||||
|
showStatus('❌ Could not reconnect - reload page', true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save current volume and muted state
|
||||||
|
const savedVolume = oldAudio.volume;
|
||||||
|
const savedMuted = oldAudio.muted;
|
||||||
|
console.log('Saving volume:', savedVolume, 'muted:', savedMuted);
|
||||||
|
|
||||||
|
// Reset spectrum analyzer if it exists
|
||||||
|
if (window.resetSpectrumAnalyzer) {
|
||||||
|
window.resetSpectrumAnalyzer();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop and remove old audio
|
||||||
|
oldAudio.pause();
|
||||||
|
oldAudio.src = '';
|
||||||
|
oldAudio.load();
|
||||||
|
|
||||||
|
// Create new audio element
|
||||||
|
const newAudio = document.createElement('audio');
|
||||||
|
newAudio.id = 'persistent-audio';
|
||||||
|
newAudio.controls = true;
|
||||||
|
newAudio.preload = 'metadata';
|
||||||
|
newAudio.crossOrigin = 'anonymous';
|
||||||
|
|
||||||
|
// Restore volume and muted state
|
||||||
|
newAudio.volume = savedVolume;
|
||||||
|
newAudio.muted = savedMuted;
|
||||||
|
|
||||||
|
// Create source
|
||||||
|
const source = document.createElement('source');
|
||||||
|
source.id = 'audio-source';
|
||||||
|
source.src = config.url;
|
||||||
|
source.type = config.type;
|
||||||
|
newAudio.appendChild(source);
|
||||||
|
|
||||||
|
// Replace old audio with new
|
||||||
|
oldAudio.replaceWith(newAudio);
|
||||||
|
|
||||||
|
// Re-attach event listeners
|
||||||
|
attachAudioListeners(newAudio);
|
||||||
|
|
||||||
|
// Try to play
|
||||||
|
setTimeout(() => {
|
||||||
|
newAudio.play()
|
||||||
|
.then(() => {
|
||||||
|
console.log('Reconnected successfully');
|
||||||
|
showStatus('✓ Reconnected!', false);
|
||||||
|
// Reinitialize spectrum analyzer - try in this frame first
|
||||||
|
if (window.initSpectrumAnalyzer) {
|
||||||
|
setTimeout(() => window.initSpectrumAnalyzer(), 500);
|
||||||
|
}
|
||||||
|
// Also try in content frame (where spectrum canvas usually is)
|
||||||
|
try {
|
||||||
|
const contentFrame = window.parent.frames['content-frame'];
|
||||||
|
if (contentFrame && contentFrame.initSpectrumAnalyzer) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (contentFrame.resetSpectrumAnalyzer) {
|
||||||
|
contentFrame.resetSpectrumAnalyzer();
|
||||||
|
}
|
||||||
|
contentFrame.initSpectrumAnalyzer();
|
||||||
|
console.log('Spectrum analyzer reinitialized in content frame');
|
||||||
|
}, 600);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.log('Could not reinit spectrum in content frame:', e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log('Reconnect play failed:', err);
|
||||||
|
showStatus('Click play to start stream', false);
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach event listeners to audio element
|
||||||
|
function attachAudioListeners(audioElement) {
|
||||||
|
audioElement.addEventListener('waiting', function() {
|
||||||
|
console.log('Audio buffering...');
|
||||||
|
});
|
||||||
|
|
||||||
|
audioElement.addEventListener('playing', function() {
|
||||||
|
console.log('Audio playing');
|
||||||
|
hideStatus();
|
||||||
|
});
|
||||||
|
|
||||||
|
audioElement.addEventListener('error', function(e) {
|
||||||
|
console.error('Audio error:', e);
|
||||||
|
showStatus('⚠️ Stream error - click 🔄 to reconnect', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
audioElement.addEventListener('stalled', function() {
|
||||||
|
console.log('Audio stalled');
|
||||||
|
showStatus('⚠️ Stream stalled - click 🔄 if no audio', true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach listeners to initial audio element
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const audioElement = document.getElementById('persistent-audio');
|
||||||
|
if (audioElement) {
|
||||||
|
attachAudioListeners(audioElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -51,25 +51,26 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav class="nav">
|
<nav class="nav">
|
||||||
<a href="/asteroid/content" target="content-frame">Home</a>
|
<a href="/asteroid/content" target="_self">Home</a>
|
||||||
<a href="/asteroid/player-content" target="content-frame">Player</a>
|
<a href="/asteroid/player-content" target="_self">Player</a>
|
||||||
<a href="/asteroid/status" target="content-frame">Status</a>
|
<a href="/asteroid/about-content" target="_self">About</a>
|
||||||
<a href="/asteroid/profile" target="content-frame" data-show-if-logged-in>Profile</a>
|
<a href="/asteroid/status" target="_self">Status</a>
|
||||||
<a href="/asteroid/admin" target="content-frame" data-show-if-admin>Admin</a>
|
<a href="/asteroid/profile" target="_self" data-show-if-logged-in>Profile</a>
|
||||||
<a href="/asteroid/login" target="content-frame" data-show-if-logged-out>Login</a>
|
<a href="/asteroid/admin" target="_self" data-show-if-admin>Admin</a>
|
||||||
<a href="/asteroid/register" target="content-frame" data-show-if-logged-out>Register</a>
|
<a href="/asteroid/login" target="_self" data-show-if-logged-out>Login</a>
|
||||||
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout">Logout</a>
|
<a href="/asteroid/register" target="_self" data-show-if-logged-out>Register</a>
|
||||||
|
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout">Logout</a>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="live-stream">
|
<div class="live-stream">
|
||||||
<h2 style="color: #00ff00; margin: 0;"><span class="live-stream-indicator" style="font-size: 1rem;">🟢</span> LIVE STREAM</h2>
|
<h2 style="color: #00ff00; margin: 0;"><span class="live-stream-indicator" style="font-size: 1rem;">🟢</span> LIVE STREAM</h2>
|
||||||
<input type="hidden" id="stream-base-url" lquery="(val stream-base-url)">
|
<input type="hidden" id="stream-base-url" lquery="(val stream-base-url)">
|
||||||
<p><strong class="live-stream-label">Stream URL:</strong> <code id="stream-url" lquery="(text default-stream-url)"></code></p>
|
<p><strong class="live-stream-label">Stream URL:</strong> <code id="stream-url" lquery="(text default-stream-url)"></code></p>
|
||||||
<p><strong class="live-stream-label">Stream Quality:</strong> <span id="stream-format" lquery="(text default-stream-encoding-desc)"></span></p>
|
<p><strong class="live-stream-label">Stream Quality:</strong> <span id="stream-format" lquery="(text default-stream-encoding-desc)"></span></p>
|
||||||
<p><strong class="live-stream-label">BROADCASTING:</strong> <span id="stream-status" style="">Asteroid music for Hackers</span></p>
|
<p><strong class="live-stream-label">BROADCASTING:</strong> <span id="stream-status" style="">Asteroid music for Hackers</span></p>
|
||||||
<p class="frame-enable-message"><em>The live stream player is now in the persistent bar at the bottom of the page</em></p>
|
<p class="frame-enable-message"><em>The live stream player is now in the persistent bar at the bottom of the page</em></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="now-playing" class="now-playing"></div>
|
<div id="now-playing" class="now-playing"></div>
|
||||||
|
|
|
||||||
|
|
@ -51,21 +51,22 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav class="nav">
|
<nav class="nav">
|
||||||
<a href="/asteroid/">Home</a>
|
<a href="/asteroid/">Home</a>
|
||||||
<a href="/asteroid/player">Player</a>
|
<a href="/asteroid/player">Player</a>
|
||||||
<a href="/asteroid/status">Status</a>
|
<a href="/asteroid/about">About</a>
|
||||||
<a href="/asteroid/profile" data-show-if-logged-in>Profile</a>
|
<a href="/asteroid/status">Status</a>
|
||||||
<a href="/asteroid/admin" data-show-if-admin>Admin</a>
|
<a href="/asteroid/profile" data-show-if-logged-in>Profile</a>
|
||||||
<a href="/asteroid/login" data-show-if-logged-out>Login</a>
|
<a href="/asteroid/admin" data-show-if-admin>Admin</a>
|
||||||
<a href="/asteroid/register" data-show-if-logged-out>Register</a>
|
<a href="/asteroid/login" data-show-if-logged-out>Login</a>
|
||||||
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout">Logout</a>
|
<a href="/asteroid/register" data-show-if-logged-out>Register</a>
|
||||||
|
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout">Logout</a>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="live-stream">
|
<div class="live-stream">
|
||||||
<div style="margin-bottom: 20px;">
|
<div style="margin-bottom: 20px;">
|
||||||
<h2 style="color: #00ff00; margin: 0;"><span class="live-stream-indicator" style="font-size: 1rem;">🟢</span> LIVE STREAM</h2>
|
<h2 style="color: #00ff00; margin: 0;"><span class="live-stream-indicator" style="font-size: 1rem;">🟢</span> LIVE STREAM</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Stream Quality Selector -->
|
<!-- Stream Quality Selector -->
|
||||||
|
|
@ -84,6 +85,9 @@
|
||||||
<p><strong class="live-stream-label" class="live-stream-label">BROADCASTING:</strong> <span id="stream-status" style="">Asteroid music for Hackers</span></p>
|
<p><strong class="live-stream-label" class="live-stream-label">BROADCASTING:</strong> <span id="stream-status" style="">Asteroid music for Hackers</span></p>
|
||||||
|
|
||||||
<div style="display: flex; gap: 10px; justify-content: end; margin-bottom: 20px;">
|
<div style="display: flex; gap: 10px; justify-content: end; margin-bottom: 20px;">
|
||||||
|
<button id="reconnect-btn" class="btn btn-warning" onclick="reconnectStream()" style="font-size: 0.9em; display: none;">
|
||||||
|
🔄 Reconnect Stream
|
||||||
|
</button>
|
||||||
<button id="popout-btn" class="btn btn-info" onclick="openPopoutPlayer()" style="font-size: 0.9em;">
|
<button id="popout-btn" class="btn btn-info" onclick="openPopoutPlayer()" style="font-size: 0.9em;">
|
||||||
🗗 Pop Out Player
|
🗗 Pop Out Player
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -92,10 +96,15 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<audio id="live-audio" controls crossorigin="anonymous" style="width: 100%; margin: 10px 0;">
|
<!-- Stream connection status -->
|
||||||
<source id="audio-source" lquery="(attr :src default-stream-url :type default-stream-encoding)">
|
<div id="stream-status-indicator" style="display: none; padding: 8px; margin-bottom: 10px; border-radius: 4px; text-align: center;"></div>
|
||||||
Your browser does not support the audio element.
|
|
||||||
</audio>
|
<div id="audio-container">
|
||||||
|
<audio id="live-audio" controls crossorigin="anonymous" style="width: 100%; margin: 10px 0;">
|
||||||
|
<source id="audio-source" lquery="(attr :src default-stream-url :type default-stream-encoding)">
|
||||||
|
Your browser does not support the audio element.
|
||||||
|
</audio>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="now-playing" class="now-playing"></div>
|
<div id="now-playing" class="now-playing"></div>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" type="text/css" href="/asteroid/static/asteroid.css">
|
<link rel="stylesheet" type="text/css" href="/asteroid/static/asteroid.css">
|
||||||
<script src="/asteroid/static/js/auth-ui.js"></script>
|
<script src="/asteroid/static/js/auth-ui.js"></script>
|
||||||
|
<script src="/asteroid/static/js/front-page.js"></script>
|
||||||
<script src="/asteroid/static/js/player.js"></script>
|
<script src="/asteroid/static/js/player.js"></script>
|
||||||
<script src="/api/asteroid/spectrum-analyzer.js"></script>
|
<script src="/api/asteroid/spectrum-analyzer.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/asteroid/static/favicon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="/asteroid/static/favicon-16x16.png">
|
||||||
<link rel="stylesheet" type="text/css" href="/asteroid/static/asteroid.css">
|
<link rel="stylesheet" type="text/css" href="/asteroid/static/asteroid.css">
|
||||||
<script src="/asteroid/static/js/auth-ui.js"></script>
|
<script src="/asteroid/static/js/auth-ui.js"></script>
|
||||||
|
<script src="/asteroid/static/js/front-page.js"></script>
|
||||||
<script src="/asteroid/static/js/player.js"></script>
|
<script src="/asteroid/static/js/player.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
|
|
@ -311,3 +311,49 @@
|
||||||
(error (e)
|
(error (e)
|
||||||
(format t "Error initializing user system: ~a~%" e)))))
|
(format t "Error initializing user system: ~a~%" e)))))
|
||||||
:name "user-init"))))
|
:name "user-init"))))
|
||||||
|
|
||||||
|
(defun dump-users (users)
|
||||||
|
(with-open-file (s "userdump.csv" :direction :output :if-exists :supersede)
|
||||||
|
(loop for user in users
|
||||||
|
do
|
||||||
|
(let* ((_id (dm:field user "_id"))
|
||||||
|
(username (dm:field user "username"))
|
||||||
|
(email (dm:field user "email"))
|
||||||
|
(password-hash (dm:field user "password-hash"))
|
||||||
|
(role (dm:field user "role"))
|
||||||
|
(active (dm:field user "active"))
|
||||||
|
(created-date (dm:field user "created-date"))
|
||||||
|
(last-login (dm:field user "last-login")))
|
||||||
|
(format s "~&~{~A~^,~}~%" (list _id username email password-hash role active created-date last-login))
|
||||||
|
(finish-output s)))))
|
||||||
|
|
||||||
|
(defun get-users-from-csv (filename)
|
||||||
|
(with-open-file (s filename :direction :input)
|
||||||
|
(let ((csv-data (cl-csv:read-csv s)))
|
||||||
|
csv-data)))
|
||||||
|
|
||||||
|
(defun ensure-users (filename)
|
||||||
|
(let* ((users (get-users-from-csv filename)))
|
||||||
|
(princ users)
|
||||||
|
(loop
|
||||||
|
for (_id username email password-hash role active created-date last-login) in users
|
||||||
|
do
|
||||||
|
(progn
|
||||||
|
(format t "~&_id: ~A, username: ~A, email: ~A password-hash: ~A role: ~A active: ~A created-date: ~A last-login: ~A" _id username email password-hash role active created-date last-login)
|
||||||
|
(let ((user (dm:hull "USERS")))
|
||||||
|
(setf (dm:field user "username") username)
|
||||||
|
(setf (dm:field user "email") email)
|
||||||
|
(setf (dm:field user "password-hash") password-hash)
|
||||||
|
(setf (dm:field user "role") role)
|
||||||
|
(setf (dm:field user "active") active)
|
||||||
|
(setf (dm:field user "created-date") created-date)
|
||||||
|
(setf (dm:field user "last-login") nil)
|
||||||
|
|
||||||
|
(handler-case
|
||||||
|
(db:with-transaction ()
|
||||||
|
(format t "Inserting user: ~A~%" user)
|
||||||
|
(let ((result (dm:insert user)))
|
||||||
|
(format t "Insert result: ~A~%" result)
|
||||||
|
(format t "User created: ~A (~A)~%" username role)))
|
||||||
|
(error (e)
|
||||||
|
(format t "Error creating user ~A: ~A~%" username e))))))))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue