Commit Graph

253 Commits

Author SHA1 Message Date
Glenn Thompson 1186214770 Implement playlist management MVP for player page
Features:
- Create, view, load, and delete playlists
- Add tracks to playlists via dropdown menu (📋 button)
- View playlist contents (👁️ button)
- Load playlist to queue with auto-play (📂 button)
- Delete playlist with confirmation (🗑️ button)

Backend changes:
- Move get-db-connection-params to database.lisp for proper load order
- Update playlist functions to use playlist_tracks junction table
- Add get-playlist-tracks and get-playlist-track-count functions
- Add delete and remove-track API endpoints
- Fix stream-track endpoint to not wrap errors in JSON

Frontend changes (ParenScript):
- Add playlist display with action buttons
- Add showAddToPlaylistMenu dropdown
- Add deletePlaylist and viewPlaylist functions
- Fix forEach chaining with progn
- Fix let* scoping for sequential bindings
- Fix ps:regex syntax for string escaping
- Add console logging for playlist debugging
2025-12-09 17:50:21 +03:00
Glenn Thompson 00bcf46c27 Apply easilok's ParenScript fixes and fix playlist creation
ParenScript player.lisp fixes (from easilok):
- Replace == with = for JavaScript equality
- Replace inner-html with inner-h-t-m-l
- Replace parseInt with parse-int
- Replace let with let* where needed for sequential bindings
- Replace new "FormData" with new -Form-data
- Fix audio event listener chaining
- Replace Promise chains with setTimeout callbacks

playlist-management.lisp:
- Remove track-ids field (column doesn't exist, using junction table)
2025-12-09 16:38:45 +03:00
Glenn Thompson a8b681621d Fix timestamp consistency across all tables
- Update USERS table schema to use TIMESTAMP instead of integer
- Add migration 003 to convert existing integer timestamps to TIMESTAMP
- Remove timestamp-to-unix calls in playlist-management.lisp (use DB default)
- Update user-management.lisp to use postmodern:execute for last-login update
- All timestamp columns now consistently use PostgreSQL TIMESTAMP type
2025-12-09 12:34:38 +03:00
Glenn Thompson 9c308066c5 Add Liquidsoap/Icecast controls, fix library scan
- Add Liquidsoap control panel: status display, skip track, reload playlist, restart container
- Add Icecast restart button to System Status section
- Remove redundant Web Player Control section from admin
- Fix music library scan to follow symlinks (truename resolution)
- Fix database timestamp error (let PostgreSQL default handle added-date)
- Update docker-compose mount for stream-queue.m3u
- Clean up playlist path handling
2025-12-09 09:32:30 +03:00
Glenn Thompson be31bd678b Fix player.js bugs and update admin panel
- Remove Live Stream Monitor section (redundant with frame player)
- Fix player.lisp pagination start-index calculation
- Fix track property access (remove erroneous index 0)
- Fix if/else paren structure in play-next function
- Fix indentation in play-track function
- Update Music Library Management section to reflect Docker setup
- Add geostationary playlist file
2025-12-09 06:33:28 +03:00
Glenn Thompson 21275693c1 Add geo stats collection and improve admin dashboard UI
- Add geo IP lookup for listener locations (ip-api.com)
- Add geo stats table with country flags to admin dashboard
- Fix listener stats table alignment with proper centering
- Fix Now Playing display to update without requiring audio playback
- Add caching for geo lookups to reduce API calls
2025-12-08 09:08:24 +03:00
Glenn Thompson c4120de9fc Add listener statistics feature
- Add database schema for listener snapshots, sessions, and aggregates
- Implement background polling of Icecast admin XML stats
- Add API endpoints for current, daily, and geo stats
- Add listener stats section to admin dashboard with auto-refresh
- GDPR compliant: IP hashing, data retention cleanup
2025-12-08 08:25:06 +03:00
Glenn Thompson c182c79353 Add listener statistics feature design document 2025-12-08 07:03:18 +03:00
Glenn Thompson 373ca04eb0 Add status page for frameset mode and fix navigation 2025-12-08 07:01:46 +03:00
Glenn Thompson 2ed92ba003 Fix wedged player with reconnect button and volume preservation
- Add reconnect button (🔄) to frameset player bar
- Recreate audio element on reconnect to fix wedged MediaElementSource
- Properly close and reinitialize AudioContext for spectrum analyzer
- Preserve volume and muted state when reconnecting
- Show status messages for connection issues
- Reduce Now Playing update interval to 5 seconds
- Add front-page.js to player-content.ctml for Now Playing updates
- Create About pages (about.ctml and about-content.ctml)
- Add About link to navigation in both modes
2025-12-08 05:01:15 +03:00
Brian O'Reilly 8fd0b06b69 dump users in db to csv, and restore them from same
this is (hopefully) a write once run once utility, but we're moving
from sqlite to postgres, and I don't want to lose the users that have
already signed up for the site.
2025-12-07 19:44:04 -05:00
Brian O'Reilly 4ca6570d5e correct the database creation script for the expected fields. 2025-12-07 19:44:04 -05:00
Brian O'Reilly c9f6cb2aa7 ... And then we ask: How did this *ever* work??
(It did. On my machine.)
2025-12-07 19:44:04 -05:00
Brian O'Reilly 6c6732d1e0 as far as I'm concerned, this is version 1.
Bump the major version number in the asdf system definition file, for
great ceremony.
2025-12-07 19:44:04 -05:00
Brian O'Reilly 8754e7261f pull creds from the enclosing environment
When we stand up, we establish the configuration for database
authentication in the postgres docker container. Put these credentials
into environment variables for production, and default to known values
for development.
2025-12-07 19:44:04 -05:00
Brian O'Reilly e55210c332 Source database auth creds from the environment
Defaults to known values for development.
source the environment credentials so they're available at container build.
2025-12-07 19:44:04 -05:00
Brian O'Reilly d66b7b8053 this effectively reverts the previous case change of the USERS table name
I guess for now we'll leave this quirk in
2025-12-07 19:44:04 -05:00
Brian O'Reilly 44096dfb4b move m3u files into dedicated directory.
These playlist files are useful only to the installation at
https://asteroid.radio, because they reference tracks that likely do
not exist in any other library where this code might be run.
Regardless, it's useful to me, and saving this work somewhere durable
has intrinsic value to me, operationally. If nothing else, this shows
the structure of a plalist for use with this code.
2025-12-07 19:44:04 -05:00
Brian O'Reilly 9cbc0a7780 the db is connected, so init the users. 2025-12-07 19:44:04 -05:00
Brian O'Reilly 7a4e9c208a creating the users table all caps style gives us duplicates in postgres. 2025-12-07 19:44:04 -05:00
Luis Pereira aa84ff4470 fix: improve live stream text proportions
Conflicts:
	static/asteroid.css
2025-12-07 19:44:04 -05:00
Brian O'Reilly 9bb31ec88c many things, almost working, but not quite. 2025-12-07 19:44:04 -05:00
Brian O'Reilly 6c2ed75b15 include i-postgmodern interface for postgres.
Conflicts:
	asteroid.asd
2025-12-07 19:44:04 -05:00
Brian O'Reilly d2508451d0 Delete the music/library directory which held an erroneous path to a softlink that doesn't exist in prod. 2025-12-07 19:44:04 -05:00
Glenn Thompson efe993e0c1 Fix HTML entity decoding in now playing titles
- Use plump:decode-entities to decode HTML entities (&, ", etc.) in track titles from Icecast XML
- Fixes display of artist names and track titles containing ampersands and other special characters
- One-line fix using existing plump library dependency
2025-12-06 11:55:24 -05:00
Glenn Thompson 2fa03e447a Update dropdown colors to match spectrum analyzer theme
- Dropdown boxes now dynamically update their text and border colors to match selected theme
- Prevents color clashing between UI elements and spectrum analyzer
- Colors update both on theme change and on page load
2025-12-06 11:55:24 -05:00
Glenn Thompson c08b5f73de Add monotone theme and dynamic border color
- Add monotone theme with deep blue to cobalt gradient
- Update canvas border color dynamically to match selected theme
- Set initial border color on page load based on saved preference
2025-12-06 11:55:24 -05:00
Glenn Thompson 16a69dc6e9 Rename recently-played.js to recently-played.js.original
Match naming convention of other original JS files now replaced by parenscript
2025-12-06 11:55:24 -05:00
Glenn Thompson 51387bddba Add spectrum analyzer theming and visualization styles
- Add 6 color themes: green, blue, purple, red, amber, rainbow
- Add 3 visualization styles: bars, wave, dots
- Add UI controls (dropdowns) to change theme and style
- Persist user preferences in localStorage
- Remove debug logging from parenscript serving and Icecast stats
- Fix dots visualization with proper Math.PI handling
2025-12-06 11:55:24 -05:00
Glenn Thompson b6be0ebab1 feat: Convert JavaScript to Parenscript with stream fixes and UX improvements
Major Changes:
- Convert all JavaScript files to Parenscript for better maintainability
- Move spectrum-analyzer to parenscript/ directory structure
- Add parenscript-utils.lisp for shared utilities
- Convert admin.js, player.js, front-page.js, auth-ui.js to Parenscript
- Convert profile.js, users.js, recently-played.js to Parenscript

Stream Reconnect Fixes (from merged PR):
- Add reset-spectrum-analyzer function to properly clean up Web Audio API
- Implement reconnect logic for pauses longer than 10 seconds
- Detect stale audio in 'playing' event and force stream reconnection
- Prevent 'Now Playing' updates while stream is paused
- Reduce reconnect delay to 200ms for faster response
- Add proper spectrum analyzer reset/reinit during reconnection

UX Improvements:
- Change live indicator from blink to smooth pulse (2s ease-in-out)
- Pulse animation like old PowerBook/MacBook sleep indicator
- Add MUTED indicator to spectrum analyzer when audio is muted
- Spectrum continues to flow even when muted (data still streaming)
- Red 'MUTED' text displayed in top-right corner of canvas

Technical Details:
- Parenscript files generate JavaScript via API endpoints
- All player modes updated: main player, front page, popout, frame player
- Improved audio context handling to only create once per element
- Added comprehensive error handling and logging
- Updated asteroid.asd to include parenscript module structure

Documentation:
- Updated all documentation dates to 2025-12-06
- Added PARENSCRIPT-EXPERIMENT.org documenting the conversion
- Updated PROJECT-HISTORY.org with Phase 9 (Visual Audio Features)
- Added comprehensive project statistics (408 commits, 9,300 LOC)

This conversion improves code maintainability by using Lisp throughout
the stack and makes it easier to share code between frontend and backend.
2025-12-06 11:55:24 -05:00
Brian O'Reilly f68c85f0cd asteroid.css is generated on every start. delete it from repository. 2025-12-06 10:25:26 -05:00
Glenn Thompson 4ec90c0f27 perf: Reduce reconnect delay from 500ms to 200ms for faster response
Optimized the timeout after stream reconnection to make the pause/unpause
experience more responsive. The 200ms delay is sufficient for the browser
to clear buffers and start the fresh stream while minimizing perceived lag.
2025-12-06 08:36:30 -05:00
Glenn Thompson 7c7b2c921e fix: Prevent stale audio playback after long pause and reorganize spectrum analyzer
- Detect pauses longer than 10 seconds across all player modes
- Intercept 'playing' event to stop stale buffered audio
- Force stream reconnect to get live audio after long pause
- Reset and reinitialize spectrum analyzer during reconnect
- Prevent 'Now Playing' updates while stream is paused
- Move spectrum-analyzer.lisp to parenscript/ directory
- Update all documentation dates to 2025-12-06
- Add comprehensive project statistics (408 commits, 9,300 LOC)
- Add Phase 9 (Visual Audio Features) to project history

Fixes issue where resuming playback after a long pause would play
old buffered audio instead of the current live stream. The fix uses
the 'playing' event to detect when stale audio starts and immediately
stops it, then reconnects to get fresh stream data.

All player modes updated: main player, front page, popout, and frame player.
2025-12-06 08:36:30 -05:00
Glenn Thompson 6e8260172f fix: Reduce Icecast burst size and prevent now-playing updates during pause
- Reduced Icecast burst-size from 64KB to 8KB to minimize buffer accumulation
- Fixed spectrum analyzer to only create MediaElementSource once
- Added resetSpectrumAnalyzer() function to allow reconnection
- Prevent now-playing info updates when stream is paused across all players:
  * Player page
  * Front page
  * Pop-out player
  * Frame player
  * Admin page
- After pause >10s, reconnect stream and reinitialize spectrum analyzer
- Preserves spectrum analyzer functionality after pause/unpause
- Eliminates stuttering and buffer accumulation issues
2025-12-06 08:36:30 -05:00
Glenn Thompson 924f6498de Add real-time spectrum analyzer using Parenscript
- Implement Web Audio API-based spectrum analyzer with green gradient bars
- Add spectrum analyzer to front page and persistent player content frames
- Support cross-frame audio element access for frameset mode
- Add CORS headers to Icecast configuration for Web Audio API
- Serve Parenscript-generated JavaScript dynamically via API endpoint
- Canvas visualization appears below page title, above navigation
2025-12-03 19:00:13 -05:00
Glenn Thompson 090e8e9898 fix: Serve spectrum analyzer JavaScript dynamically via API
Changed from static file generation to Radiance API endpoint.
Parenscript now generates JavaScript in-memory at runtime when
the /api/asteroid/spectrum-analyzer.js endpoint is requested.

This is the correct approach for Parenscript integration with Radiance.
2025-12-03 19:00:13 -05:00
Glenn Thompson a1257af16f feat: Add spectrum analyzer using Parenscript
Implements real-time audio visualization for the main page:
- Added Parenscript dependency to asteroid.asd
- Created spectrum-analyzer.lisp with Parenscript code
- Added canvas element to front-page.ctml above nav buttons
- Auto-generates JavaScript at compile time
- Green gradient bars matching Asteroid aesthetic
- Uses Web Audio API for FFT analysis

This is the first Parenscript component in Asteroid Radio,
demonstrating the approach for future JavaScript conversions.
2025-12-03 19:00:13 -05:00
Glenn Thompson 280b8f0690 fix: Use 'normal' mode instead of 'sequential' for playlist playback
The 'sequential' mode in Liquidsoap starts playback at a random position
in the playlist, causing tracks to play out of order. Switching to 'normal'
mode ensures the playlist starts from the beginning and plays sequentially
through all tracks in order.
2025-12-03 19:00:13 -05:00
Glenn Thompson c668a5f40f Add phase metadata to stream-queue.m3u 2025-12-03 19:00:13 -05:00
Luis Pereira 4c534a0a4f feat: add blinking live cursor 2025-11-23 18:43:45 -05:00
Luis Pereira 709affa957 fix: improve live stream text proportions 2025-11-23 18:43:45 -05:00
Glenn Thompson 57af5663ab style: Match audio player color to app panels
- Change audio player background from #1a1a1a to #1a2332
- Matches the blue-grey color used throughout the app
- Addresses Fade's feedback about brownish grey appearance
2025-11-22 09:06:05 -05:00
Glenn Thompson 9a7b5eb50f style: Update recently played track styling
- Change track link colors: cyan default, green hover, blue visited
- Add equal left/right padding (12px) to track-list for centered separators
- Increase track-item top/bottom padding from 6px to 10px for better spacing
- Move track-list and track-item inside recently-played-list block for proper CSS nesting
- Addresses feedback from easilok on symmetry and breathing room
2025-11-22 09:06:05 -05:00
Glenn Thompson 2fae9f80f4 fix: Correct LASS hover syntax for track links
- Move track-link styles inside recently-played-list block for proper CSS nesting
- Use (:and .track-link :hover) at correct nesting level per LASS documentation
- Fixes hover color change to green when mousing over track names
- Generates correct CSS selector: .recently-played-list .track-link:hover
2025-11-22 09:06:05 -05:00
Glenn Thompson ea3cd4a8f6 refactor: Make track name clickable with external link icon
- Replace separate MusicBrainz link with clickable track name
- Add external link icon next to track name
- Simplify grid layout by removing track-meta column
- Update CSS styling for track-link with hover effects
- Improves UX by making the primary action (clicking track) more intuitive
2025-11-22 09:06:05 -05:00
Glenn Thompson 6bf19ade01 Add recently played tracks feature with MusicBrainz integration
- Display last 3 played tracks on front page
- Auto-updates every 30 seconds
- Shows track title, artist, and time ago
- Links to MusicBrainz search for each track
- Thread-safe in-memory storage
- Works in both normal and frameset modes
- Hacker-themed green styling

Implements feature request from fade to show recently played tracks
with linkage to track info at music database.
2025-11-22 09:06:05 -05:00
Luis Pereira 34ca61809b feat: add user role update routes 2025-11-21 18:06:49 -05:00
Luis Pereira ded376d971 feat: add user activate and deactivate routes 2025-11-21 18:06:49 -05:00
Glenn Thompson 66d013d7d1 feat: Add recently-played.ctml partial template
Add modular partial template for recently-played section that can be included in other templates
2025-11-20 17:05:35 -05:00
Glenn Thompson 3a08ff61c0 feat: Add favicon and asteroid.png graphics to front page
- Add favicon.ico, favicon-16x16.png, and favicon-32x32.png
- Add asteroid.png graphic to header on both front-page.ctml and front-page-content.ctml
- Update header styling to display asteroid graphics flanking the station name
2025-11-20 17:05:35 -05:00