| .github | ||
| .vscode | ||
| backend | ||
| frontend | ||
| locales | ||
| plugins | ||
| scripts | ||
| tests | ||
| .aider.conf.yml | ||
| .cursorrules | ||
| .gitignore | ||
| config.json | ||
| I18N_EXAMPLES.md | ||
| I18N_GUIDE.md | ||
| I18N_QUICKREF.md | ||
| IDENTIFIER_REFACTOR_SUMMARY.md | ||
| LICENSE | ||
| LOCALIZATION_COMPLETE.md | ||
| LOCALIZATION_STATUS.md | ||
| migrate_data.py | ||
| migrate_to_identifier.py | ||
| PROJECT_GUIDE.md | ||
| pyproject.toml | ||
| README.md | ||
| requirements.txt | ||
| setup-pi-client.sh | ||
| setup-pi-server.sh | ||
| SONG_LIBRARY_CHANGES.md | ||
| test_identifier_fixes.py | ||
| test_output.txt | ||
| uv.lock | ||
| VERIFICATION_CHECKLIST.md | ||
Organist - Music Player for Religious Services
A real-time synchronized music player server application built with Python, FastAPI, and Socket.IO. Designed for live music playback in religious services with multi-device synchronization.
Features
- Real-time Synchronization: All connected clients see the same state instantly
- Song Library Management: Upload, tag, and edit songs with identifiers
- Flexible Playlist Editor: Build playlists with auto-stop flags; search and add songs dynamically
- Smart Quick-Play: Live-search dropdown to find and play songs by identifier, filename, or tags
- Auto-Advance: Automatically progress through playlists with customizable stop points
- Full-Width Controls: Large, touch-friendly player buttons with clear visual feedback
- Responsive Layout: Flexible panes for songs/playlists (scrollable list + fixed editor)
- Volume Synchronization: Real-time volume control synchronized across server and clients
- Multi-Language Support: Internationalized UI with language selector
- Plugin System: Extend functionality with local plugins for emergency control
- Remote Control: Control playback from any connected browser on any device
Architecture
Backend (Python)
- FastAPI: Modern, async web framework
- Socket.IO: Real-time bidirectional communication with fallbacks
- python-vlc: Server-side audio playback through system audio interface
- Async I/O: Non-blocking operations for smooth real-time updates
Frontend (Vanilla JavaScript)
- No build tools: Plain JavaScript, HTML, and CSS—works in any browser
- No browser audio playback: All audio plays only on the server
- Client-side rendering: Dynamic UI with i18n support
- Socket.IO client: Real-time state synchronization
- Responsive design: Mobile-friendly, touch-optimized interface
Key Design Principles
- Server-authoritative state: All state changes happen on the server and broadcast to clients
- Single source of truth: No conflicting local state between clients
- Immediate UI sync: All connected clients update within milliseconds
- Touch-friendly: Large buttons, clear labels, and responsive spacing for live service use
Installation
Prerequisites
- Python 3.8+
- VLC media player installed on the system
- uv - Fast Python package installer
Setup
- Clone the repository:
git clone https://github.com/your-organization/Organist.git
cd Organist
- Install uv (if not already installed):
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
- Install dependencies and create virtual environment:
uv sync
- Run the server:
uv run python -m backend.main
- Open your browser to:
http://localhost:8000
Alternative: Quick Start
# One command to install and run
uv run python -m backend.main
Installation on Raspberry Pi 5 with Raspbian Trixie
Two automated setup scripts are provided to deploy Organist on a Raspberry Pi 5:
setup-pi-server.sh- WiFi hotspot/access point mode (10.76.x.x subnet)setup-pi-client.sh- WiFi client mode (connects to existing network)
Prerequisites
- Raspberry Pi 5 with Raspbian Trixie (Debian Trixie derivative)
- Micro-SD card (32GB recommended)
- Power supply
- Organist repository checked out on the Pi
Quick Setup (Automated)
- Clone the repository (or copy it to the Pi):
cd ~
git clone https://github.com/your-organization/Organist.git
cd Organist
- Run the appropriate setup script:
For WiFi Hotspot/Server Mode (creates "Organist" WiFi network):
sudo bash setup-pi-server.sh
For WiFi Client Mode (connects to existing WiFi):
sudo bash setup-pi-client.sh
-
Follow the prompts to configure:
- WiFi SSID and password
- IP address (server mode only)
- DHCP range (server mode only)
- System user (default:
organist)
-
Reboot when prompted.
What the Scripts Install
Both scripts automatically:
- Update system packages
- Install dependencies (Python, VLC, uv, networking tools)
- Create system user
- Copy Organist to
/opt/organist - Install Python dependencies with uv
- Create systemd service for auto-start
- Enable and configure services
Server Mode (setup-pi-server.sh) additionally:
- Configures WiFi access point (hostapd)
- Sets up DHCP server (dnsmasq)
- Assigns static IP (default: 10.76.0.1)
- Enables IP forwarding
Client Mode (setup-pi-client.sh) additionally:
- Configures wpa_supplicant for WiFi client
- Connects to existing network
- Uses DHCP-assigned IP from your router
Verify Installation
For Server Mode:
- Look for WiFi network: Organist (or your chosen SSID)
- Connect with the password you configured
- Open browser:
http://10.76.0.1:8000(or your chosen IP)
For Client Mode:
- Find the Pi's IP from your router (or use
organist.local) - Open browser:
http://<pi-ip>:8000
Check service status on the Pi:
sudo systemctl status organist
sudo journalctl -u organist -f
Manual Setup (Advanced)
If you prefer manual setup or need to customize beyond the script options, follow the detailed steps in the script source code or contact the maintainers.
Network Details (Server Mode Default)
- WiFi SSID: Organist
- WiFi Password: (configured during setup)
- AP IP Address: 10.76.0.1
- DHCP Range: 10.76.0.2 – 10.76.0.254
- App URL: http://10.76.0.1:8000
Troubleshooting
WiFi not appearing (server mode):
sudo rfkill list
sudo rfkill unblock all # If blocked
sudo systemctl restart hostapd
Cannot connect to app:
# Check Organist status
sudo systemctl status organist
# Restart all services
sudo systemctl restart organist hostapd dnsmasq # server mode
sudo systemctl restart organist # client mode
# View logs
sudo journalctl -u organist -n 50 -f
Find IP address (client mode):
hostname -I # Shows all IP addresses
ip addr show wlan0 # WiFi interface details
Change WiFi password (server mode):
Edit /etc/hostapd/hostapd.conf, change wpa_passphrase, then:
sudo systemctl restart hostapd
Usage
Player View
- Play/Pause Button (green when ready to play): Start or resume playback
- Stop Button (red): Stop playback and clear current song
- Previous/Next Buttons: Navigate through loaded playlist
- Volume Slider: Adjust volume with live feedback (synchronized across all clients)
- Quick-Play Search: Type to search songs by identifier, filename, or tags; click a result to fill the field, then press Play
Song Library
- Navigate to the Library section
- Upload audio files individually, as folders, or as ZIP archives
- Optionally add identifiers and tags during upload
- Click the Edit button next to any song to modify filename, identifier, or tags
- Songs appear as a scrollable list; editor panel stays fixed at bottom
Playlist Editor
- Navigate to the Playlists section
- Create a new playlist using the form
- Click Edit on a playlist to open the editor:
- Search results appear on the left (searchable by identifier, filename, or tags)
- Your playlist entries appear on the right
- Drag-add songs from search results to your playlist
- Mark songs with "Stop After" to pause at that point
- Save your changes
- On the player, use the dropdown to load a playlist and press Play
Auto-Advance
- When a song ends and has the "Stop After" flag set, Organist automatically advances to the next song in the playlist
- If it's the last song in the playlist, it wraps to the first song
- Manual stop (clicking the Stop button) does not trigger auto-advance
Multi-Client Synchronization
- Open the app on multiple devices connected to the same network
- All clients mirror each other's state in real-time
- Any client can control playback; all others update simultaneously
- Perfect for distributed service leadership and coordination
Plugin Development
Create custom plugins in the plugins/ directory:
class Plugin:
def __init__(self):
self.name = "My Plugin"
def setup(self):
# Initialize plugin
pass
See plugins/local_interface.py for an emergency control example.
Configuration
Edit config.json to customize:
- Server host and port
- Data directories
- Default audio settings
- Plugin settings
Project Structure
Organist/
├── backend/
│ ├── main.py # FastAPI + Socket.IO server, HTTP endpoints
│ ├── audio_player.py # VLC audio interface
│ ├── song_manager.py # Song library and metadata management
│ ├── playlist_manager.py # Playlist CRUD and lifecycle
│ └── plugin_manager.py # Plugin loading and management
├── frontend/
│ ├── index.html # Single-page application markup
│ └── static/
│ ├── app.js # Socket.IO client, UI logic, state management
│ ├── style.css # Dark theme styling, responsive layout
│ └── i18n.js # Internationalization engine
├── locales/ # Translation JSON files
│ ├── en.json
│ ├── es.json
│ └── ...
├── plugins/
│ └── local_interface.py # Example plugin: emergency local control
├── data/ # Runtime data (created on first run)
│ ├── songs/ # Uploaded audio files
│ ├── songs.json # Song metadata with identifiers and tags
│ └── playlists.json # Playlist definitions
├── pyproject.toml # Python dependencies (uv)
├── config.json # Application configuration
└── README.md
HTTP API Endpoints
Songs
GET /api/songs- List all songs with metadataGET /api/tags- List all unique tags across songsPOST /api/songs/upload- Upload a single song filePOST /api/songs/bulk-upload- Upload multiple files (folder or ZIP)PUT /api/songs/{song_id}- Update song metadata (identifier, tags)
Playlists
GET /api/playlists- List all playlistsPOST /api/playlists- Create a new playlistPUT /api/playlists/{playlist_id}- Update playlist entries
Health & Status
GET /- Main application interfaceGET /health- Server health check
Socket.IO Events
Client → Server
play_song(song_id)- Play a song by IDplay_next()- Advance to next song in playlistpause_playback()- Toggle play/pausestop_playback()- Stop and clear current songload_playlist(playlist_id)- Load a playlistload_song_at_index(playlist_index, auto_play)- Load song at playlist positionchange_view(view)- Switch UI section (synced across all clients)set_volume(volume)- Set volume (0–100)
Server → Client
state_update(state)- Full application statesongs_updated(songs)- Song library changedplaylists_updated(playlists)- Playlists changed
Data Models
Song
{
"id": "uuid",
"filename": "My Song.mp3",
"identifier": "101",
"tags": ["hymn", "morning"],
"file_path": "data/songs/101_My Song.mp3",
"uploaded_at": "2025-12-21T10:30:00Z",
"duration": 180000
}
Playlist
{
"id": "uuid",
"name": "Sunday Service",
"created_at": "2025-12-21T09:00:00Z",
"modified_at": "2025-12-21T10:00:00Z",
"entries": [
{
"song_id": "uuid",
"stop_after": false
},
{
"song_id": "uuid",
"stop_after": true
}
]
}
Troubleshooting
VLC Not Found
Ensure VLC media player is installed on your system. The python-vlc library requires the VLC executable.
Audio Not Playing
- Check the server console for VLC errors
- Verify audio file paths and supported formats (MP3, WAV, FLAC, OGG, M4A, AAC, WMA)
- Test VLC playback directly to confirm system audio setup
Clients Out of Sync
- Refresh the browser page
- Check browser console for Socket.IO connection errors
- Ensure all clients can reach the server IP/port
Bulk Upload Fails
- Verify ZIP or folder contains only supported audio files
- Check file permissions and disk space
- Ensure identifiers are unique or generated correctly
Future Enhancements
- Keyboard shortcuts for playback control
- Drag-and-drop playlist reordering
- Playback position tracking
- Volume fade in/out
- Song search within playlists
- Multiple audio output device selection
- Playlist import/export
- Song editing UI (currently API only)
License
See LICENSE file for details.
Support
For issues or questions, please open an issue in the repository.