173 lines
5.4 KiB
Common Lisp
173 lines
5.4 KiB
Common Lisp
;; -*-lisp-*-
|
|
;; (defpackage :asteroid
|
|
;; (:use :cl :radiance)
|
|
;; (:use :asteroid.app-utils)
|
|
|
|
;; (:export :-main :start-server :stop-server :run-server))
|
|
|
|
(in-package :asteroid)
|
|
|
|
;; Define as RADIANCE module
|
|
(define-module asteroid
|
|
(:use #:cl #:radiance #:lass)
|
|
(:domain "asteroid"))
|
|
|
|
;; Configuration
|
|
(defparameter *server-port* 8080)
|
|
|
|
;; Read and compile LASS from file
|
|
(defun generate-css ()
|
|
"Generate CSS by reading LASS from static/asteroid.lass file"
|
|
(let ((lass-file (merge-pathnames "static/asteroid.lass")))
|
|
(lass:compile-and-write
|
|
(with-open-file (in lass-file)
|
|
(read in)))))
|
|
|
|
;; Generate CSS file using LASS
|
|
(defun compile-styles ()
|
|
"Generate CSS file using LASS"
|
|
(ensure-directories-exist "static/")
|
|
(let ((css-file (merge-pathnames "static/asteroid.css")))
|
|
(with-open-file (out css-file
|
|
:direction :output
|
|
:if-exists :supersede)
|
|
(write-string (generate-css) out))))
|
|
|
|
;; Configure static file serving for other files
|
|
(define-page static #@"/static/(.*)" (:uri-groups (path))
|
|
(serve-file (merge-pathnames (concatenate 'string "static/" path)
|
|
(asdf:system-source-directory :asteroid))))
|
|
|
|
;; RADIANCE route handlers
|
|
(define-page index #@"/" ()
|
|
(spinneret:with-html-string
|
|
(:doctype)
|
|
(:html
|
|
(:head
|
|
(:title "🎵 ASTEROID RADIO 🎵")
|
|
(:meta :charset "utf-8")
|
|
(:meta :name "viewport" :content "width=device-width, initial-scale=1")
|
|
(:link :rel "stylesheet" :type "text/css" :href "/static/asteroid.css"))
|
|
(:body
|
|
(:div.container
|
|
(:h1 "🎵 ASTEROID RADIO 🎵")
|
|
(:div.status
|
|
(:h2 "Station Status")
|
|
(:p "🟢 LIVE - Broadcasting asteroid music for hackers")
|
|
(:p "Current listeners: 0")
|
|
(:p "Stream quality: 128kbps MP3"))
|
|
(:div.nav
|
|
(:a :href "/admin" "Admin Dashboard")
|
|
(:a :href "/player" "Web Player")
|
|
(:a :href "/api/status" "API Status"))
|
|
(:div
|
|
(:h2 "Now Playing")
|
|
(:p "Artist: The Void")
|
|
(:p "Track: Silence")
|
|
(:p "Album: Startup Sounds")
|
|
(:p "Duration: ∞")))))))
|
|
|
|
(define-page admin #@"/admin" ()
|
|
(spinneret:with-html-string
|
|
(:doctype)
|
|
(:html
|
|
(:head
|
|
(:title "Asteroid Radio - Admin Dashboard")
|
|
(:meta :charset "utf-8")
|
|
(:link :rel "stylesheet" :type "text/css" :href "/static/asteroid.css"))
|
|
(:body
|
|
(:div.container
|
|
(:a.back :href "/" "← Back to Main")
|
|
(:h1 "Admin Dashboard")
|
|
(:div.panel
|
|
(:h2 "Playback Control")
|
|
(:button "Play")
|
|
(:button "Pause")
|
|
(:button "Skip")
|
|
(:button "Stop"))
|
|
(:div.panel
|
|
(:h2 "Library Management")
|
|
(:button "Upload Music")
|
|
(:button "Manage Playlists")
|
|
(:button "Scan Library"))
|
|
(:div.panel
|
|
(:h2 "Live DJ")
|
|
(:button "Go Live")
|
|
(:button "End Session")
|
|
(:button "Mic Check"))
|
|
(:div.panel
|
|
(:h2 "System Status")
|
|
(:p "Server: Running")
|
|
(:p "Database: Not Connected")
|
|
(:p "Liquidsoap: Not Running")
|
|
(:p "Icecast: Not Running")))))))
|
|
|
|
(define-page player #@"/player" ()
|
|
(spinneret:with-html-string
|
|
(:doctype)
|
|
(:html
|
|
(:head
|
|
(:title "Asteroid Radio - Web Player")
|
|
(:meta :charset "utf-8")
|
|
(:link :rel "stylesheet" :type "text/css" :href "/static/asteroid.css"))
|
|
(:body
|
|
(:a.back :href "/" "← Back to Main")
|
|
(:div.player
|
|
(:h1 "🎵 ASTEROID RADIO PLAYER 🎵")
|
|
(:div.now-playing
|
|
(:div "Now Playing:")
|
|
(:div "Silence - The Sound of Startup"))
|
|
(:div.controls
|
|
(:button "▶ Play Stream")
|
|
(:button "⏸ Pause")
|
|
(:button "🔊 Volume"))
|
|
(:div
|
|
(:p "Stream URL: http://localhost:8000/asteroid")
|
|
(:p "Bitrate: 128kbps MP3")
|
|
(:p "Status: Offline")))))))
|
|
|
|
(define-page api/status #@"/api/status" ()
|
|
(setf (radiance:header "Content-Type") "application/json")
|
|
(cl-json:encode-json-to-string
|
|
`(("status" . "running")
|
|
("server" . "asteroid-radio")
|
|
("version" . "0.1.0")
|
|
("uptime" . ,(get-universal-time))
|
|
("now-playing" . (("title" . "Silence")
|
|
("artist" . "The Void")
|
|
("album" . "Startup Sounds")))
|
|
("listeners" . 0)
|
|
("stream-url" . "http://localhost:8000/asteroid"))))
|
|
|
|
;; RADIANCE server management functions
|
|
(defun start-server (&key (port *server-port*))
|
|
"Start the Asteroid Radio RADIANCE server"
|
|
(format t "Starting Asteroid Radio RADIANCE server on port ~a~%" port)
|
|
(compile-styles) ; Generate CSS file using LASS
|
|
(radiance:startup)
|
|
(format t "Server started! Visit http://localhost:~a/asteroid/~%" port))
|
|
|
|
(defun stop-server ()
|
|
"Stop the Asteroid Radio RADIANCE server"
|
|
(format t "Stopping Asteroid Radio server...~%")
|
|
(radiance:shutdown)
|
|
(format t "Server stopped.~%"))
|
|
|
|
(defun run-server (&key (port *server-port*))
|
|
"Start the server and keep it running (blocking)"
|
|
(start-server :port port)
|
|
(format t "Server running. Press Ctrl+C to stop.~%")
|
|
;; Keep the server running
|
|
(handler-case
|
|
(loop (sleep 1))
|
|
(sb-sys:interactive-interrupt ()
|
|
(format t "~%Received interrupt, stopping server...~%")
|
|
(stop-server))))
|
|
|
|
(defun -main (&optional args)
|
|
(declare (ignorable args))
|
|
(format t "~%🎵 ASTEROID RADIO - Music for Hackers 🎵~%")
|
|
(format t "Starting RADIANCE web server...~%")
|
|
(run-server))
|
|
|