- Fix find-track-by-title to parse 'Artist - Title' format from Icecast
and search both artist and title columns in tracks table
- Fix favorites API alist key mismatch (TRACK-TITLE not TRACK_TITLE)
- Fix favorites cache to update UI after loading
- Fix race condition where star reverted after clicking
- Add aget-profile helper for Postmodern uppercase key lookup
- Add user playlist creation, editing, and track management
- Add library browser for adding tracks to playlists
- Add playlist submission workflow for station airing
- Add admin review interface with preview, approve, reject
- Generate M3U files on approval in playlists/user-submissions/
- Include user-submissions in playlist scheduler dropdown
- Use playlist description as PHASE tag in M3U
- Add database migration for user_playlists table
- Update TODO-next-features.org to mark feature complete
- Add user_favorites and listening_history database tables
- Add migration 005-user-favorites-history.sql
- Create user-profile.lisp with favorites/history API endpoints
- Add star button (☆/★) to Now Playing on main page
- Add star button to frame player bar
- Add Favorites section to profile page
- Show login prompt when unauthenticated user clicks star
- Use gold color (#ffcc00) for favorited state (space theme)
- Fix require-authentication to properly detect API routes
- Support title-based favorites (no track DB required)
- Add /api/asteroid/channel-name endpoint for live channel name updates
- Update front-page.js and stream-player.js to poll server for channel name
instead of relying on localStorage (fixes issue where listeners don't see
playlist changes until page refresh)
- Add footer with Internet Radio directory link and craftering webring links
- Fix last-login display bug: use proper ISO 8601 timestamp format and
parse as Date string instead of Unix epoch
- Add shuffle source to Liquidsoap config (96kbps MP3)
- Add shuffle option to all UI quality selectors (frame, popout, front page)
- Make now-playing APIs mount-aware for correct metadata display
- Implement separate recently-played lists for curated vs shuffle streams
- Speed up now-playing and recently-played refresh on stream change
- Fix clean shutdown of stats polling thread (positional timeout arg)
- Widen quality selector dropdown for shuffle label
- 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
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.
- 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.
This commit implements three major refactorings to make the codebase more
idiomatic and maintainable:
1. Template Path Centralization
- Add *template-directory* parameter and helper functions
- Replace 11+ instances of repetitive template loading boilerplate
- New functions: template-path, load-template in template-utils.lisp
2. String Construction with FORMAT
- Replace concatenate with format for external URLs (Icecast, static files)
- Maintain Radiance URI handling for internal routes
- Applied to stream URLs, status endpoints, and API responses
3. Error Handling with Custom Conditions
- NEW FILE: conditions.lisp with comprehensive error hierarchy
- Custom conditions: not-found-error, authentication-error,
authorization-error, validation-error, database-error, asteroid-stream-error
- Helper macros: with-error-handling, with-db-error-handling
- Helper functions: signal-not-found, signal-validation-error, etc.
- Refactored 19 API endpoints and page routes
- Proper HTTP status codes: 404, 401, 403, 400, 500
Changes:
- conditions.lisp: NEW (180+ lines of error handling infrastructure)
- asteroid.asd: Add conditions.lisp to system components
- asteroid.lisp: Refactor 30+ endpoints, eliminate 200+ lines of boilerplate
- template-utils.lisp: Add centralized template loading helpers
- frontend-partials.lisp: Update template loading and string construction
Net result: -97 lines of code, significantly improved error handling,
more maintainable and idiomatic Common Lisp.
All changes tested and verified:
- Clean build
- All endpoints functional
- Error handling returns proper HTTP codes
- No regressions
- Add user password change functionality in profile page
- Add admin password reset functionality in admin dashboard
- Fix listener count to show total from Icecast root tag
- Replace concatenate with format
- Add with-error-handling to API endpoints
- Make Icecast port binding configurable via ICECAST_BIND env var
- Add comprehensive docstrings to public functions
Note: Password reset has known issue with LambdaLite db:update
not updating password-hash field. Issue reported as an issue.
This commit implements three major refactorings to make the codebase more
idiomatic and maintainable:
1. Template Path Centralization
- Add *template-directory* parameter and helper functions
- Replace 11+ instances of repetitive template loading boilerplate
- New functions: template-path, load-template in template-utils.lisp
2. String Construction with FORMAT
- Replace concatenate with format for external URLs (Icecast, static files)
- Maintain Radiance URI handling for internal routes
- Applied to stream URLs, status endpoints, and API responses
3. Error Handling with Custom Conditions
- NEW FILE: conditions.lisp with comprehensive error hierarchy
- Custom conditions: not-found-error, authentication-error,
authorization-error, validation-error, database-error, asteroid-stream-error
- Helper macros: with-error-handling, with-db-error-handling
- Helper functions: signal-not-found, signal-validation-error, etc.
- Refactored 19 API endpoints and page routes
- Proper HTTP status codes: 404, 401, 403, 400, 500
Changes:
- conditions.lisp: NEW (180+ lines of error handling infrastructure)
- asteroid.asd: Add conditions.lisp to system components
- asteroid.lisp: Refactor 30+ endpoints, eliminate 200+ lines of boilerplate
- template-utils.lisp: Add centralized template loading helpers
- frontend-partials.lisp: Update template loading and string construction
Net result: -97 lines of code, significantly improved error handling,
more maintainable and idiomatic Common Lisp.
All changes tested and verified:
- Clean build
- All endpoints functional
- Error handling returns proper HTTP codes
- No regressions
- Add /api/asteroid/partial/now-playing-inline endpoint for inline text
- Refactor admin.js to use server-side partial (removes 23 lines of JSON/XML parsing)
- Fix hardcoded path in convert-to-docker-path to use *music-library-path* variable
- Consistent with front-page and player refactoring from upstream
- Improves portability and reduces client-side JavaScript complexity