# SwingMusic Project Structure and Architecture This document provides a comprehensive overview of how SwingMusic is structured, how its components interact, and the application lifecycle from startup to ready state. > [!IMPORTANT] > Disclaimer: This document was drafted with the help of an LLM. Last updated on July 14th, 2025. ## Project Overview SwingMusic is a modern music streaming server built with Python (Flask) on the backend and Vue.js on the frontend. It provides a self-hosted music library management system with features like audio streaming, playlist management, favorite tracking, and metadata extraction. ## High-Level Architecture ```mermaid graph TB subgraph "Client Layer" WEB[Web Client
Vue.js SPA] MOBILE[Mobile Apps
Third-party clients] end subgraph "API Layer" FLASK[Flask-OpenAPI3
REST API Server] AUTH[JWT Authentication
Middleware] CORS[CORS & Compression
Middleware] end subgraph "Business Logic" STORES[In-Memory Stores
Fast Data Access] LIBS[Library Functions
Core Business Logic] PLUGINS[Plugin System
Extensible Features] end subgraph "Data Layer" SQLITE[SQLite Database
Persistent Storage] FILES[File System
Audio Files & Images] CONFIG[JSON Config
User Settings] end WEB --> FLASK MOBILE --> FLASK FLASK --> AUTH AUTH --> STORES STORES --> LIBS LIBS --> SQLITE LIBS --> FILES FLASK --> CONFIG ``` ## Directory Structure ```sh swingmusic/ ├── client/ # Built Vue.js frontend (static files) ├── swingmusic/ # Main Python package │ ├── __main__.py # CLI entry point │ ├── api/ # REST API endpoints │ │ ├── __init__.py # Flask app creation & blueprint registration │ │ ├── album.py # Album-related endpoints │ │ ├── artist.py # Artist-related endpoints │ │ ├── auth.py # Authentication & user management │ │ ├── stream.py # Audio streaming & transcoding │ │ ├── search.py # Search functionality │ │ ├── playlist.py # Playlist management │ │ ├── settings.py # Configuration endpoints │ │ └── ... # Other API modules │ ├── models/ # Data models (dataclasses) │ │ ├── album.py # Album model with type detection │ │ ├── artist.py # Artist model with image handling │ │ ├── track.py # Track model with metadata processing │ │ ├── playlist.py # Playlist model │ │ └── user.py # User model │ ├── store/ # In-memory data stores │ │ ├── albums.py # Album store with hash-based lookup │ │ ├── artists.py # Artist store with relationship mapping │ │ ├── tracks.py # Track store with grouping by hash │ │ └── folder.py # Folder structure store │ ├── db/ # Database layer │ │ ├── engine.py # SQLAlchemy engine & session management │ │ ├── libdata.py # Library data tables (tracks, albums, etc.) │ │ ├── userdata.py # User data tables (favorites, playlists) │ │ └── sqlite/ # SQLite-specific utilities & migrations │ ├── lib/ # Core business logic │ │ ├── populate.py # Media scanning & indexing │ │ ├── trackslib.py # Track processing utilities │ │ ├── albumslib.py # Album processing utilities │ │ ├── artistlib.py # Artist processing utilities │ │ ├── searchlib.py # Search algorithms │ │ ├── tagger.py # Metadata extraction & processing │ │ └── transcoder.py # Audio format conversion │ ├── utils/ # Utility functions │ │ ├── hashing.py # Hash generation for entities │ │ ├── auth.py # Authentication utilities │ │ ├── parsers.py # Text parsing (artists, titles, etc.) │ │ └── ... # Other utilities │ ├── plugins/ # Plugin system │ │ ├── lyrics.py # Lyrics fetching │ │ ├── mixes.py # Auto-generated playlists │ │ └── lastfm.py # Last.fm integration │ ├── crons/ # Background tasks │ │ ├── cron.py # Cron job scheduler │ │ └── mixes.py # Automated playlist generation │ ├── config.py # Configuration management │ ├── settings.py # Path and system settings │ └── start_swingmusic.py # Application startup ├── run.py # Application launcher ├── requirements.txt # Python dependencies └── docs/ # Documentation ``` ## Core Components Deep Dive ### 1. Data Models (`models/`) SwingMusic uses dataclasses for its core data models, providing type safety and automatic serialization: #### Track Model (`models/track.py`) - **Purpose**: Represents individual audio files with rich metadata - **Key Features**: - Artist splitting and featured artist extraction - Genre processing with configurable separators - Hash-based unique identification - Play statistics tracking - User-specific favorite status #### Album Model (`models/album.py`) - **Purpose**: Groups tracks into albums - **Key Features**: - Automatic album type classification (album, single, EP, compilation, live, soundtrack) - Version detection (deluxe, remastered, etc.) - Artist relationship management #### Artist Model (`models/artist.py`) - **Purpose**: Represents music artists with aggregated statistics - **Key Features**: - Album and track counting - Genre aggregation - Image management - Play statistics ### 2. In-Memory Stores (`store/`) The store layer provides fast O(1) access to frequently used data: ```mermaid graph LR subgraph "Store Architecture" TS[TrackStore
trackhash → TrackGroup] AS[AlbumStore
albumhash → AlbumMapEntry] ARS[ArtistStore
artisthash → ArtistMapEntry] FS[FolderStore
File path mapping] end subgraph "Relationships" TS --> AS AS --> ARS ARS --> TS end ``` #### TrackStore - **Structure**: `dict[trackhash, TrackGroup]` - **Purpose**: Groups duplicate tracks (same content, different quality) - **Key Methods**: `get_tracks_by_trackhashes()`, `get_tracks_by_albumhash()` #### AlbumStore - **Structure**: `dict[albumhash, AlbumMapEntry]` - **Purpose**: Maps albums to their track collections - **Key Methods**: `get_album_by_hash()`, `get_albums_by_artisthash()` #### ArtistStore - **Structure**: `dict[artisthash, ArtistMapEntry]` - **Purpose**: Maps artists to their albums and tracks - **Key Methods**: `get_artist_by_hash()`, `get_artist_tracks()` ### 3. Database Layer (`db/`) Uses SQLAlchemy with SQLite for persistent storage: #### Engine Configuration (`db/engine.py`) ```python # Optimized SQLite settings PRAGMA journal_mode=WAL # Write-Ahead Logging for concurrency PRAGMA synchronous=NORMAL # Balanced durability/performance PRAGMA cache_size=10000 # Large memory cache PRAGMA foreign_keys=ON # Referential integrity ``` #### Table Structure - **Library Data**: Tracks, albums, artists, genres - **User Data**: Favorites, playlists, play statistics, user accounts - **Metadata**: Similar artists, color palettes, plugin data ### 4. API Layer (`api/`) Built with Flask-OpenAPI3 for automatic documentation and validation: #### Authentication System (`api/auth.py`) - **JWT-based**: 30-day tokens with automatic refresh - **Multiple auth methods**: Username/password, pairing codes for mobile - **Role-based access**: Admin and regular user roles - **Guest support**: Limited access without authentication #### Core Endpoints - **`/album`**: Album information, tracks, versions, similar albums - **`/artist`**: Artist details, discography, top tracks - **`/search`**: Fuzzy search across all content types - **`/file`**: Audio streaming with transcoding support - **`/playlist`**: CRUD operations for playlists #### Streaming (`api/stream.py`) - **Format support**: MP3, AAC, FLAC, WebM, OGG - **Quality options**: 96kbps to lossless - **Range requests**: Efficient seeking and partial downloads - **Real-time transcoding**: On-demand format conversion (broken) ## Application Startup Sequence ```mermaid sequenceDiagram participant CLI as run.py participant Main as __main__.py participant Setup as setup/ participant DB as Database participant Stores as Memory Stores participant Flask as Flask App participant BG as Background Tasks CLI->>Main: start_swingmusic(host, port) Main->>Setup: run_setup() Setup->>DB: Create directories, setup SQLite Setup->>DB: Run migrations Main->>Flask: create_api() Flask->>Flask: Register blueprints & middleware Main->>Stores: load_into_mem() Stores->>DB: Load all tracks Stores->>Stores: Build hash maps Stores->>Stores: Map relationships Main->>BG: Start background tasks BG->>BG: Register plugins BG->>BG: Start cron jobs Main->>Flask: Run server (bjoern/waitress) ``` ### Detailed Startup Process 1. **CLI Initialization** (`run.py`, `__main__.py`) - Parse command line arguments - Set configuration directory - Initialize multiprocessing 2. **Setup Phase** (`setup/__init__.py`) - **Directory Creation**: Config, database, cache directories - **Database Setup**: SQLite file creation and optimization - **Migrations**: Schema updates and data transformations - **Config Loading**: User preferences and default settings 3. **Memory Loading** (`setup/__init__.py:load_into_mem()`) ```python # Load sequence (order matters!) TrackStore.load_all_tracks() # ~15-30s for large libraries AlbumStore.load_albums() # Depends on tracks ArtistStore.load_artists() # Depends on tracks/albums FolderStore.load_filepaths() # File system mapping # Map additional data map_scrobble_data() # Play statistics map_favorites() # User favorites map_artist_colors() # UI color themes map_album_colors() # Album artwork colors ``` 4. **Flask Application Setup** (`start_swingmusic.py`) - **API Creation**: Blueprint registration, OpenAPI docs - **Middleware Setup**: JWT authentication, CORS, compression - **Static Files**: Client serving with gzip support - **Route Protection**: Authentication requirements 5. **Background Services** (`start_swingmusic.py`) - **Plugin Registration**: Load and initialize plugins - **Cron Jobs**: Periodic tasks (scanning, cleanup) - **Process Management**: Set process title, resource limits 6. **Server Launch** - **WSGI Server**: Bjoern (preferred) or Waitress fallback - **Configuration**: Threading, IPv4/IPv6 support - **Ready State**: API accepting requests ## Data Flow Examples ### Track Lookup Flow ```mermaid graph LR API[API Request
GET /track/abc123] --> Store[TrackStore.get_tracks_by_trackhashes] Store --> Group[TrackGroup.get_best] Group --> Track[Track Object
Highest bitrate version] Track --> Serialize[Serialize for API] Serialize --> Response[JSON Response] ``` ### Search Flow ```mermaid graph LR API[API Request
POST /search] --> Search[SearchLib.search_all] Search --> Tracks[Search TrackStore] Search --> Albums[Search AlbumStore] Search --> Artists[Search ArtistStore] Tracks --> Merge[Merge & Rank Results] Albums --> Merge Artists --> Merge Merge --> Paginate[Apply Pagination] Paginate --> Response[JSON Response] ``` ### Audio Streaming Flow ```mermaid graph LR API[GET /file/trackhash] --> Auth[Verify JWT Token] Auth --> Lookup[TrackStore Lookup] Lookup --> File[Check File Exists] File --> Transcode{Transcoding
Needed?} Transcode -->|Yes| Convert[FFmpeg Conversion] Transcode -->|No| Direct[Direct File Stream] Convert --> Stream[HTTP Response
with Range Support] Direct --> Stream ``` ## Component Coordination ### Hash-Based Entity System SwingMusic uses hashes for entity identification: - **Track Hash**: `hash(title + album + artists)` - Content-based deduplication - **Album Hash**: `hash(title + album_artists)` - Album identification - **Artist Hash**: `hash(artist_name)` - Artist identification - **Weak Hash**: Fuzzy matching for similar content ### Relationship Management ```mermaid graph TB subgraph "Entity Relationships" Track --> Album Track --> Artists[Multiple Artists] Album --> AlbumArtists[Album Artists] Album --> Tracks[Track Collection] Artist --> Albums[Artist Albums] Artist --> ArtistTracks[Artist Tracks] end subgraph "Store Coordination" TrackStore -.-> AlbumStore AlbumStore -.-> ArtistStore ArtistStore -.-> TrackStore end ``` ### Configuration System - **JSON Config**: User preferences stored in `config.json` - **Runtime Settings**: Database-backed settings for admin features - **Environment Variables**: System-level configuration - **Default Values**: Sensible defaults for new installations ## Key Workflows ### Music Library Scanning 1. **Directory Walking**: Recursive file discovery 2. **Metadata Extraction**: ID3, FLAC, etc. tag reading 3. **Artist Splitting**: Configurable separator handling 4. **Duplicate Detection**: Hash-based deduplication 5. **Database Updates**: Incremental changes only 6. **Store Refresh**: Update in-memory caches ### User Authentication 1. **Login Request**: Username/password or pairing code 2. **Credential Validation**: Database lookup and verification 3. **JWT Generation**: 30-day token with user claims 4. **Cookie Setting**: Secure HTTP-only cookies 5. **Request Middleware**: Token validation on each request 6. **Auto Refresh**: Transparent token renewal ### Plugin System 1. **Plugin Discovery**: Scan plugins directory 2. **Registration**: Import and validate plugin modules 3. **Hook Integration**: Connect to application events 4. **Configuration**: Plugin-specific settings 5. **Background Tasks**: Scheduled plugin execution ## Monitoring and Logging - **Application Logs**: Structured logging with severity levels - **Performance Metrics**: Response times, memory usage - **Error Tracking**: Exception logging and stack traces - **User Analytics**: Play counts, popular content (optional) ## Security Considerations - **Input Validation**: Pydantic schemas for API requests - **File Path Safety**: Prevent directory traversal attacks - **JWT Security**: Secure token generation and validation - **CORS Configuration**: Controlled cross-origin access - **Rate Limiting**: Protection against abuse (configurable) This architecture provides a robust, scalable foundation for music streaming while maintaining simplicity and ease of deployment. The separation of concerns between stores, business logic, and API layers ensures maintainability and extensibility as the project grows.