This commit is contained in:
Broque Thomas 2025-09-11 18:14:20 -07:00
parent d746729c02
commit e718069f8b
6 changed files with 84 additions and 1354 deletions

469
README.md
View file

@ -1,421 +1,120 @@
# 🎵 SoulSync - Automated Music Discovery & Collection Manager
<p align="center">
<img src="./assets/trans.png" alt="Logo">
</p>
# 🎵 SoulSync - Automated Music Discovery and Collection Manager
SoulSync is a powerful desktop application designed to bridge the gap between your music streaming habits on Spotify and your personal, high-quality music library in Plex or Jellyfin. It automates the process of discovering new music, finding missing tracks from your favorite playlists, and sourcing them from the Soulseek network via slskd.
The core philosophy of SoulSync is to let you enjoy music discovery on Spotify while it handles the tedious work of building and maintaining a pristine, locally-hosted music collection for you in your media server. Both Plex and Jellyfin are supported as media servers (though neither is required for the app to function), while slskd and Spotify API are required.
## ☕ Support Development
If you find SoulSync useful, consider supporting its development:
Bridge the gap between streaming services and your local music library. Automatically sync Spotify/Tidal playlists to Plex/Jellyfin via Soulseek.
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/boulderbadgedad)
![A screenshot of SoulSync](./assets/dashboard.png)
## ✨ What It Does
## ⚠️ Docker Support
Docker is unlikely since this is a fully GUI based app. The unique setup would be difficult for most users and my knowledge of docker is sad.
- **Auto-sync playlists** from Spotify/Tidal to your media server
- **Smart matching** finds what you're missing vs what you own
- **Download missing tracks** from Soulseek with FLAC priority
- **Metadata enhancement** adds proper tags and album art
- **File organization** creates clean folder structures
- **Artist discovery** browse complete discographies
- **Background automation** retries failed downloads every hour
## ✨ Core Features
## 🚀 Three Ways to Run
### 🤖 **Automation Engine**
SoulSync handles everything automatically once you set it up. You can sync multiple Spotify / Youtube / Tidal playlists at the same time, and it'll prioritize FLAC files and reliable sources. When downloads finish, it organizes them into clean folder structures and updates your Plex library automatically.
The app runs a background process every 60 minutes to retry failed downloads - so if a track wasn't available earlier, it'll keep trying until it finds it. It also auto-detects your Plex or Jellyfin server and slskd on your network, backs up your playlists before making changes, and reconnects to services if they go down.
Once it's running, SoulSync basically acts like a personal music librarian that works in the background.
### 🎬 **Spotify & YouTube & Tidal Integration**
Works with both Spotify / Youtube / Tidal playlists. For YouTube, it extracts clean track names by removing stuff like "(Official Music Video)" and other junk from titles. For Spotify, it tracks playlist changes so it only downloads new tracks instead of re-scanning everything.
Both get the same smart matching system with color-coded confidence scores, and you can bulk download all missing tracks with progress tracking.
### 🎯 **Artist Discovery**
Search for any artist and see their complete discography with indicators showing what you already own vs what's missing. You can download entire missing discographies with one click, or just grab specific albums/tracks. It shows releases chronologically and highlights gaps in your collection.
### 🔍 **Search & Download**
The search page lets you manually hunt for specific albums or singles. Every result has a preview button so you can stream before downloading. It keeps your search history and has detailed progress tracking for downloads. Failed downloads automatically go to a wishlist for retry later.
### 🧠 **Smart Matching**
The matching engine is pretty sophisticated - it prioritizes original versions over remixes, handles weird characters (like КоЯn → Korn), and removes album names from track titles for cleaner matching. It generates multiple search variations per track to find more results and scores each match so you know how confident it is.
### 🗄️ **Local Database**
Keeps a complete SQLite database of your media server library (Plex or Jellyfin) locally, so matching is instant instead of making slow API calls. Updates automatically when files change and handles thousands of songs without slowing down.
### 📁 **File Organization**
Downloads get organized automatically based on whether they're album tracks or singles. Creates clean folder structures like `Transfer/Artist/Artist - Album/01 - Track.flac`. Supports all common audio formats and automatically tags everything with proper metadata and album art from Spotify.
### 🎵 **Built-in Player**
You can stream tracks directly from Soulseek before downloading to make sure they're the right ones. Supports all common audio formats and the player works across all pages in the app.
### 📋 **Wishlist System**
Failed downloads automatically get saved to a wishlist with context about where they came from. The app tries to download wishlist items every hour automatically. You can also manually retry or bulk manage failed downloads.
### 👀 **Watchlist Monitoring**
Track your favorite artists automatically by adding them to your watchlist. SoulSync monitors watched artists for new releases and automatically scans their latest albums and singles against your library. When new tracks are found missing, they're added to your wishlist for download. The system runs comprehensive scans with intelligent rate limiting to avoid API bans, and you can view real-time progress with detailed status updates for each artist being scanned.
### 📊 **Dashboard & Monitoring**
Real-time status for all your connections (Spotify, Plex/Jellyfin, Soulseek), download statistics, and system performance. Activity feed shows everything that's happening with timestamps.
### 🎯 **Five Main Pages**
**Downloads**: Search for music manually, preview before downloading, see progress in real-time.
**Sync**: Load Spotify/YouTube playlists, see what's missing with confidence scores, bulk download missing tracks.
**Artists**: Browse complete artist catalogs, see what you own vs missing, bulk download entire discographies.
**Dashboard**: Overview of all connections and activity, quick access to common functions.
**Settings**: Configure all your API keys and preferences, database management, performance tuning.
### 🚀 **Performance**
Multi-threaded so it stays responsive during heavy operations. Automatically manages resources, prevents Soulseek bans with rate limiting, and handles errors gracefully with automatic recovery.
## ⚙️ How It Works
The application follows a clear, automated workflow to enhance and expand your music library:
1. **Connect Services**: First, you authenticate with your Spotify account, connect to your media server (Plex or Jellyfin), and connect to your running slskd instance through the settings panel. This gives SoulSync the access it needs to work its magic.
2. **Analyze**: Navigate to the Sync page and select a Spotify playlist. SoulSync fetches all tracks and compares them against your media server library. This comparison uses a sophisticated matching engine that looks at track title, artist, album, and duration to make an accurate assessment.
3. **Identify Missing**: After the analysis, the application generates a clear, actionable list of tracks that are present in the Spotify playlist but are not found in your media server library.
4. **Search & Download**: For each missing track, SoulSync generates multiple optimized search queries to increase the likelihood of finding a high-quality match. It then uses the slskd API to search the Soulseek network, prioritizing FLAC files and reliable users, and automatically queues them for download.
5. **Organize & Enhance**: Once a download is complete, SoulSync automatically organizes the file from the download directory into the transfer directory, creating a clean folder structure based on the artist and album (`/Transfer/Artist Name/Artist Name - Album Name/Track.flac`). Immediately after organization, the metadata enhancement system enriches the file with accurate Spotify data including proper artist/album names, track numbers, release dates, genres, and high-quality embedded album art. This ensures every file emerges perfectly tagged and ready for your media server, requiring no manual metadata editing.
## 🚀 Getting Started
Follow these steps to get SoulSync up and running on your system.
### ⚠️ Important Soulseek Sharing Requirement
**CRITICAL**: Before using SoulSync, you MUST set up a shared folder in slskd. Users who only download without sharing are typically banned by other Soulseek users, which will severely limit your ability to find and download music.
1. In your slskd web interface (`http://localhost:5030`), go to the **Shares** section
2. Add at least one folder containing music files to share with the network
3. The more you share, the better your reputation and download success rate will be
4. Consider sharing your organized music collection from your Plex library
### Prerequisites
Before you begin, ensure you have the following installed and configured:
- **Python 3.8+**: The core runtime for the application.
- **Media Server (OPTIONAL)**: Either Plex Media Server or Jellyfin is optional but recommended. If connected, SoulSync will scan your existing music library to identify missing tracks. Without a media server, all tracks will be considered "missing" and automatically downloaded.
- **slskd**: A headless Soulseek client. This is the engine that powers the downloading feature. See detailed setup instructions below.
- **Spotify Account**: A regular or premium Spotify account is required to access your playlists and artist data.
### Setting Up slskd
This application requires **slskd**, a web-based Soulseek client, to handle music downloads. Here's how to set it up:
#### Installing slskd
**Option 1: Manual Installation (RECOMMENDED)**
1. Download the latest release from [slskd GitHub releases](https://github.com/slskd/slskd/releases)
2. Extract and run the executable
3. Default web interface will be available at `http://localhost:5030`
**Option 2: Docker (MAYBE? UNTESTED)**
### 1. Desktop GUI (Original)
Full PyQt6 desktop application with all features.
```bash
# Create directories for slskd
mkdir -p ~/slskd/{config,downloads,incomplete}
# Run slskd container
docker run -d \
--name slskd \
-p 5030:5030 \
-p 50300:50300 \
-v ~/slskd/config:/app/config \
-v ~/slskd/downloads:/app/downloads \
-v ~/slskd/incomplete:/app/incomplete \
slskd/slskd:latest
git clone https://github.com/Nezreka/SoulSync
cd SoulSync
pip install -r requirements.txt
python main.py
```
#### Configuring slskd
### 2. Web UI (New!)
Browser-based interface - same features, runs anywhere.
```bash
python web_server.py
# Open http://localhost:8008
```
1. **Initial Setup**: Open `http://localhost:5030` in your browser
2. **Create Account**: Set up your admin username and password
3. **Soulseek Credentials**: Enter your Soulseek username and password
4. **API Key**: Create a random 16-character API key:
- Generate a random string (letters and numbers) like `abc123def456ghi7`
- Add this to your slskd configuration file as the API key
- Use the same key in SoulSync configuration
5. **CONFIG SETUP**: An application directory will be created in either ~/.local/share/slskd (on Linux and macOS) or %localappdata%/slskd (on Windows). In the root of this directory the file slskd.yml will be created the first time the application runs. Edit this file to enter your credentials for the Soulseek network, and tweak any additional settings using the
### 3. Docker (New!)
Containerized web UI with persistent database.
```bash
docker-compose up -d
# Open http://localhost:8008
```
**Important Notes:**
- slskd must be running before starting SoulSync
- Make sure your Soulseek account has sharing enabled to avoid connection issues
- The default port 5030 can be changed in slskd settings if needed
## ⚡ Quick Setup
### Installation
### Prerequisites
- **slskd**: Download from [GitHub](https://github.com/slskd/slskd/releases), run on port 5030
- **Spotify API**: Create app at [Spotify Dashboard](https://developer.spotify.com/dashboard)
- **Media Server**: Plex or Jellyfin (optional but recommended)
1. **Clone the repository**:
```bash
git clone https://github.com/Nezreka/SoulSync
cd soulsync-app
```
### Essential Config
1. Get Spotify Client ID/Secret from developer dashboard
2. Set up slskd with downloads folder and API key
3. Launch SoulSync, go to Settings, enter your credentials
4. **Important**: Share music in slskd to avoid bans
2. **Install dependencies**:
```bash
pip install -r requirements.txt
```
### Docker Notes
- Database persists between rebuilds via named volume
- Mount drives containing your download/transfer folders:
```yaml
volumes:
- /mnt/c:/host/mnt/c:rw # For C: drive paths
- /mnt/d:/host/mnt/d:rw # For D: drive paths
```
- Uses separate database from GUI/WebUI versions
### ⚠️ First-Time Setup: A Critical Step
## 🎯 Core Features
**IMPORTANT**: SoulSync will not function until you provide your API keys and service details. You must do this before you start using the app's features. You have two options for this initial setup:
**Search & Download**: Manual track search with preview streaming
**Playlist Sync**: Spotify/Tidal playlist analysis and batch downloads
**Artist Explorer**: Complete discography browsing with missing indicators
**Smart Matching**: Advanced algorithm prioritizes originals over remixes
**Automation**: Hourly retry of failed downloads, metadata enhancement
**Wishlist**: Failed downloads saved for automatic retry
**Watchlist**: Monitor favorite artists for new releases automatically
**Activity Feed**: Real-time status and progress tracking
#### Option 1 (Recommended): Use the In-App Settings Page
## 📁 File Flow
1. Launch the application (`python main.py`).
2. The very first thing you should do is navigate to the **Settings** page using the sidebar.
3. Fill in the required fields for Spotify and Soulseek. Media server configuration (Plex or Jellyfin) is optional but recommended.
4. Click "Save Settings". The app is now ready to use.
5. Restart the app for good luck.
1. **Search**: Query Soulseek via slskd API
2. **Download**: Files saved to configured download folder
3. **Process**: Auto-organize to transfer folder with metadata
4. **Structure**: `Transfer/Artist/Artist - Album/01 - Track.flac`
5. **Import**: Media server picks up organized files
#### Option 2: Edit the config.json File Manually
1. **Locate the Configuration File**: Before launching the app, find the `config.json` file in the `config/` directory of the project.
2. **Configure API Keys and URLs**: Open the file and fill in the details as described below.
### Configuration Details
Open the `config.json` file and fill in the details for Spotify, your media server (Plex or Jellyfin), and Soulseek.
#### 🔑 Obtaining Required API Credentials
Before configuring SoulSync, you'll need to obtain API credentials from Spotify and your media server. Here's how:
##### Spotify Client ID and Secret
**Step 1: Create a Spotify App**
1. Go to the [Spotify Developer Dashboard](https://developer.spotify.com/dashboard)
2. Log in with your Spotify account
3. Click "Create App"
4. Fill in the required information:
- **App name**: "SoulSync" (or any name you prefer)
- **App description**: "Music library sync application"
- **Redirect URI**: `http://127.0.0.1:8888/callback`
- Check the boxes to agree to the Terms of Service
5. Click "Save"
**Step 2: Get Your Credentials**
1. In your newly created app, click "Settings"
2. Copy the **Client ID** - this is your `client_id`
3. Click "View client secret" to reveal and copy the **Client Secret** - this is your `client_secret`
##### Tidal ID and Secret
**Step 1: Create a Tidal App**
1. Go to the [Tidal Developer Dashboard](https://developer.tidal.com/dashboard)
2. Log in with your Tidal account
3. Click "Create New App"
4. Fill in the required information:
- **App name**: "SoulSync" (or any name you prefer)
- **App description**: "Music library sync application"
- **Redirect URI**: `http://127.0.0.1:8889/tidal/callback`
- **Required Scopes:**
- user.read (Read access to a user's account information, such as country and email address.)
- playlists.read (Required to list playlists created by a user.)
5. Click "Save"
**Step 2: Get Your Credentials**
1. In your newly created app, click "Settings"
2. Copy the **Client ID** - this is your `client_id`
3. Click "View client secret" to reveal and copy the **Client Secret** - this is your `client_secret`
##### Plex Token
**Method 1: Through Plex Web Interface (Recommended)**
1. Open Plex in your web browser and sign in
2. Right-click anywhere on the page and select "Inspect" or press F12
3. Go to the **Network** tab in Developer Tools
4. Reload the page
5. Look for requests to `plex.tv` or your Plex server
6. In the request headers, find `X-Plex-Token` - copy this value
**Method 2: Using Browser Console**
1. Go to [plex.tv](https://plex.tv) and sign in
2. Open Developer Tools (F12) and go to the **Console** tab
3. Type: `localStorage.myPlexAccessToken` and press Enter
4. Copy the returned token value (without quotes)
**Method 3: Through Media Item XML (Easy)**
1. Open Plex in your web browser and navigate to any media item
2. Click on the item to view its details
3. Click "View XML" or right-click and select "View XML"
4. In the URL bar, you'll see a URL like: `http://your-server:32400/library/metadata/12345?X-Plex-Token=YOUR_TOKEN_HERE`
5. Copy the token from the `X-Plex-Token=` parameter in the URL
**Method 4: Using Plex API**
1. Make a POST request to `https://plex.tv/users/sign_in.xml`
2. Include your Plex username and password in the request
3. Extract the authentication token from the XML response
**Finding Your Plex Server URL:**
- Local network: `http://[YOUR_PLEX_SERVER_IP]:32400` (e.g., `http://192.168.1.100:32400`)
- Same machine: `http://localhost:32400`
- To find your server IP, check your Plex server settings or use your router's admin panel
##### Jellyfin API Key
**Method 1: Through Jellyfin Dashboard (Recommended)**
1. Open your Jellyfin web interface and sign in as an administrator
2. Go to **Dashboard** → **API Keys**
3. Click **New API Key**
4. Enter an **App Name** (e.g., "SoulSync")
5. Click **Create**
6. Copy the generated API key immediately (it won't be shown again)
**Method 2: Through User Settings**
1. Go to **Dashboard** → **Users**
2. Click on your user account
3. Go to the **API Keys** tab
4. Create a new API key as described above
**Finding Your Jellyfin Server URL:**
- Local network: `http://[YOUR_JELLYFIN_SERVER_IP]:8096` (e.g., `http://192.168.1.100:8096`)
- Same machine: `http://localhost:8096`
- HTTPS: `https://[YOUR_JELLYFIN_SERVER_IP]:8920` (if configured)
**Note**: SoulSync uses Jellyfin's REST API for library access. Make sure your Jellyfin user has permissions to access the music library.
#### 📁 Important: Understanding Download vs Transfer Folders
- **download_path**: This should be the exact same folder where slskd saves its downloads (e.g., the downloads folder you configured in slskd). SoulSync monitors this folder for completed downloads.
- **transfer_path**: This is where SoulSync moves and organizes the processed files. Typically, this should be your main media server music library folder, so the files are immediately available to your media server after processing.
#### ❗ Important: slskd API Key Setup
The slskd API key is crucial for the application to communicate with your Soulseek client.
1. **Find your slskd config file**: This is typically a `slskd.yml` or `slskd.json` file located where you installed slskd.
2. **Locate the API key**: Inside the slskd configuration, find the `api_key` value you have set. It will look something like this:
```yaml
# slskd.yml example
api:
key: "your-secret-api-key-goes-here"
```
3. **Copy and Paste**: Copy the exact API key from your slskd configuration.
4. **Update config.json**: Paste the key into the `api_key` field under the `soulseek` section in the SoulSync app's `config.json` file.
Alternatively, you can paste this key directly into the API Key field in the Settings menu within the application after launching it.
## 🔧 Config Example
```json
{
"active_media_server": "plex",
"spotify": {
"client_id": "CLIENT ID",
"client_secret": "CLIENT SECRET"
"client_id": "your_client_id",
"client_secret": "your_client_secret"
},
"plex": {
"base_url": "http://192.168.86.36:32400",
"token": "PLEX TOKEN",
"auto_detect": true
},
"jellyfin": {
"base_url": "http://localhost:8096",
"api_key": "JELLYFIN API KEY",
"auto_detect": true
"base_url": "http://localhost:32400",
"token": "your_plex_token"
},
"soulseek": {
"slskd_url": "http://localhost:5030",
"api_key": "SLSKD API KEY",
"download_path": "./downloads",
"transfer_path": "./transfers"
},
"logging": {
"path": "logs/app.log",
"level": "INFO"
},
"settings": {
"audio_quality": "flac"
},
"database": {
"path": "database/music_library.db",
"max_workers": 5
},
"metadata_enhancement": {
"enabled": true,
"embed_album_art": true
},
"playlist_sync": {
"create_backup": true
"slskd_url": "http://localhost:5030",
"api_key": "your_api_key",
"download_path": "/path/to/downloads",
"transfer_path": "/path/to/music/library"
}
}
```
**Note**: Set `"active_media_server"` to either `"plex"` or `"jellyfin"` depending on which media server you want to use. You only need to configure the server you plan to use.
## ⚠️ Important Notes
## 🖥️ Usage
- **Must share files in slskd** - downloaders without shares get banned
- **Docker uses separate database** from GUI/WebUI versions
- **Transfer path** should point to your media server music library
- **FLAC preferred** but supports all common formats
Run the main application file to launch the GUI:
## 🏗️ Architecture
```bash
python main.py
```
or for mac:
```bash
python3 main.py
```
- **Core**: Service clients for Spotify, Plex, Jellyfin, Soulseek
- **Database**: SQLite with full media library cache
- **UI**: PyQt6 desktop + Flask web interface
- **Matching**: Advanced text normalization and scoring
- **Background**: Multi-threaded with automatic retry logic
### Application Pages
- **Dashboard**: Real-time system overview with service connection matrix (Spotify/Plex/Jellyfin/Soulseek status), live download statistics (active transfers, speeds, queue status), database health metrics (size, sync status, last update), chronological activity feed of all application events, and quick action buttons for common operations.
- **Sync**: Advanced playlist management featuring Spotify playlist loading with snapshot-based change detection, confidence-scored track matching with color-coded indicators, bulk "Download Missing Tracks" with progress tracking, intelligent retry logic for failed downloads, and detailed match analysis showing why tracks were or weren't found in your media server library.
- **Downloads**: Comprehensive download management with unified Albums/Singles search interface, stream-before-download capability for every result, matched download system with artist/album selection modals, real-time progress monitoring with queue positions, failed download recovery via integrated wishlist access, and persistent search history across sessions.
- **Artists**: Complete discography explorer with full artist catalog browsing, ownership status indicators for every album, chronological release timeline with media server library overlay, bulk download operations for entire discographies, album-level missing track downloads, and integration with matched download system for accurate metadata assignment.
- **Settings**: Service configuration hub for Spotify/Plex/Jellyfin/Soulseek credentials, media server selection, download/transfer path management, metadata enhancement controls (enable/disable automatic tagging and album art embedding), database operations (update, rebuild, health check), performance tuning options (thread limits, cache settings), notification preferences, and application logging controls.
## 🐍 Key Components
The application is built on a modern, layered architecture with distinct separation of concerns:
- **main.py**: PyQt6 application entry point with main window management, service initialization, media player signal routing, and application lifecycle management.
- **core/**: Business logic and service integration layer
- `spotify_client.py`: Spotify Web API integration with OAuth2 authentication, playlist/artist data retrieval, and metadata normalization.
- `plex_client.py`: Plex Media Server API client with library scanning, metadata retrieval, and server status monitoring.
- `jellyfin_client.py`: Jellyfin Media Server API client with library scanning, metadata retrieval, and server status monitoring.
- `soulseek_client.py`: slskd API communication handling search operations, download management, and queue monitoring.
- `matching_engine.py`: Advanced metadata comparison engine with version-aware scoring, text normalization, and confidence calculation.
- `wishlist_service.py`: Failed download management with retry mechanisms and source context preservation.
- `media_scan_manager.py`: Intelligent media server library scan coordination with debouncing and periodic updates.
- **database/**: Data persistence and management layer
- `music_database.py`: SQLite database operations with thread-safe connections, WAL mode, and metadata synchronization.
- `music_library.db`: Local database storing complete media server library metadata for instant access.
- **ui/**: Modern PyQt6 user interface with responsive design
- `sidebar.py`: Navigation sidebar with integrated media player, service status indicators, and scrolling track info.
- `components/`: Reusable UI elements including toast notifications, loading animations, and database status widgets.
- `pages/`: Application pages (`dashboard.py`, `sync.py`, `downloads.py`, `artists.py`, `settings.py`) with specialized workflows.
- **services/**: Background service layer
- `sync_service.py`: High-level sync orchestration with playlist analysis and download coordination.
- **config/**: Configuration management
- `config.json`: Service credentials, paths, and application settings.
- `settings.py`: Configuration file handling and validation.
- **utils/**: Shared utilities
- `logging_config.py`: Centralized logging configuration with file and console output.
## 🤝 Contributing
Contributions are welcome! Please feel free to submit a pull request or open an issue for any bugs or feature requests.
## 📜 License
This project is licensed under the MIT License. See the LICENSE file for details.
Modern, clean, automated. Set it up once, let it manage your music library.

View file

@ -1,67 +0,0 @@
#!/bin/bash
# SoulSync Docker Setup Script
# This script helps set up the Docker environment for SoulSync WebUI
set -e
echo "🎵 SoulSync WebUI Docker Setup"
echo "==============================="
# Create necessary directories
echo "📁 Creating directory structure..."
mkdir -p config database logs downloads Transfer
# Create .gitkeep files for empty directories
touch downloads/.gitkeep Transfer/.gitkeep logs/.gitkeep
# Copy example config if config.json doesn't exist
if [ ! -f "config/config.json" ]; then
if [ -f "config/config.example.json" ]; then
echo "📋 Copying example configuration..."
cp config/config.example.json config/config.json
echo "⚙️ Please edit config/config.json with your API keys and settings"
else
echo "⚠️ Warning: No example config found. You'll need to create config/config.json manually"
fi
fi
# Set proper permissions
echo "🔐 Setting permissions..."
chmod -R 755 config database logs downloads Transfer
chown -R $USER:$USER config database logs downloads Transfer
# Check if Docker is installed
if ! command -v docker &> /dev/null; then
echo "❌ Docker is not installed. Please install Docker first."
echo " Visit: https://docs.docker.com/get-docker/"
exit 1
fi
# Check if Docker Compose is installed
if ! command -v docker-compose &> /dev/null; then
echo "❌ Docker Compose is not installed. Please install Docker Compose first."
echo " Visit: https://docs.docker.com/compose/install/"
exit 1
fi
echo "✅ Setup complete!"
echo ""
echo "📝 Next steps:"
echo "1. Edit config/config.json with your API keys and server settings"
echo "2. Run: docker-compose up -d"
echo "3. Access SoulSync at http://localhost:8888"
echo ""
echo "🔧 Useful commands:"
echo " docker-compose up -d # Start in background"
echo " docker-compose logs -f # View logs"
echo " docker-compose down # Stop container"
echo " docker-compose pull # Update image"
echo " docker-compose restart # Restart container"
echo ""
echo "📂 Data locations:"
echo " - Configuration: ./config/"
echo " - Database: ./database/"
echo " - Logs: ./logs/"
echo " - Downloads: ./downloads/"
echo " - Transfer: ./Transfer/"

View file

@ -1,323 +0,0 @@
# SoulSync Web UI Development Plan
## Overview
Build a complete web replica of the SoulSync PyQt6 GUI application with identical layout, styling, and visual components. This will be a single-page application (SPA) contained in `index.html` with all pages shown/hidden via JavaScript.
## Current Architecture Analysis
### Main GUI Structure (PyQt6)
- **Sidebar (240px width)**: Navigation, media player, donation widget, version info, service status
- **Main Content Area**: QStackedWidget containing 5 pages
- **Pages**: Dashboard, Sync, Downloads (Search), Artists, Settings
- **Styling**: Dark theme with Spotify green accents (#1ed760), modern gradients, rounded corners
### Key Components Identified
#### Sidebar Components:
1. **Header**: App name "SoulSync" with subtitle "Music Sync & Manager"
2. **Navigation**: 5 buttons with icons
- 📊 Dashboard
- 🔄 Sync
- 📥 Search (Downloads)
- 🎵 Artists
- ⚙️ Settings
3. **Media Player**: Collapsible with track info, play/pause, volume control, loading animation
4. **Crypto Donation**: Collapsible section with Ko-fi and crypto addresses
5. **Version Info**: Clickable version button (v.0.65)
6. **Service Status**: 3 indicators (Spotify, Media Server, Soulseek) with connection dots
#### Page Components:
1. **Dashboard**: Service stats, recent activity, quick actions, uptime tracking
2. **Sync**: Playlist management, sync operations, progress tracking, track analysis
3. **Downloads/Search**: Music search, download queue, media player, search filters
4. **Artists**: Artist browsing, album management, collection overview, completion status
5. **Settings**: Configuration forms, service setup, preferences, detection tools
## Implementation Plan
### Phase 1: Core Framework Setup ✅
**Files to Create:**
- `headless.md` (this document)
- Update `webui/index.html` (single-page structure)
- Update `webui/static/style.css` (complete styling system)
- Update `webui/static/script.js` (page management, API integration)
### Phase 2: Layout Structure
**2.1 HTML Structure (index.html)**
```html
<div id="app">
<aside id="sidebar">
<div id="sidebar-header">
<h1>SoulSync</h1>
<p>Music Sync & Manager</p>
</div>
<nav id="sidebar-nav">
<!-- Navigation buttons -->
</nav>
<div id="media-player">
<!-- Media player component -->
</div>
<div id="crypto-donation">
<!-- Donation component -->
</div>
<div id="version-info">
<!-- Version button -->
</div>
<div id="service-status">
<!-- Status indicators -->
</div>
</aside>
<main id="content">
<div id="dashboard-page" class="page active">...</div>
<div id="sync-page" class="page">...</div>
<div id="downloads-page" class="page">...</div>
<div id="artists-page" class="page">...</div>
<div id="settings-page" class="page">...</div>
</main>
</div>
```
**2.2 CSS Framework (style.css)**
- Dark theme base colors (#121212, #1e1e1e, #0d1117)
- Spotify green accent system (#1ed760, #1ed760, #1ca851)
- Modern gradient backgrounds (qlineargradient equivalents)
- Rounded corner design language (12px, 16px border-radius)
- Responsive grid systems
- Animation/transition systems (300ms ease curves)
**2.3 JavaScript Page Manager (script.js)**
- Page switching logic (show/hide with fade transitions)
- State persistence (current page, form data)
- API communication layer (fetch-based)
- Component management system
- Real-time status updates (5-second intervals)
### Phase 3: Sidebar Implementation
**3.1 Sidebar Structure**
- Fixed 240px width sidebar
- Gradient background: `linear-gradient(135deg, #0d1117, #121212, #0a0a0a)`
- Border-right: `1px solid rgba(29, 185, 84, 0.1)`
- Border-radius: `12px` (top-right, bottom-right)
**3.2 Navigation System**
- Button styling: 216px width, 52px height
- Active state: Green gradient background + left border
- Hover states with smooth transitions
- Icon + text layout with proper spacing
- Active state management with visual feedback
**3.3 Media Player Component**
- Collapsible design (85px collapsed, 145px expanded)
- Track information display with scrolling long titles
- Control buttons: play/pause (40px green circle), stop (32px)
- Volume slider: horizontal with green accent
- Loading animations: indefinite + determinate progress
- "No track" placeholder state
**3.4 Additional Sidebar Components**
- **Crypto Donation**: Show/Hide toggle, Ko-fi + crypto addresses
- **Version Info**: Clickable button with hover effects
- **Service Status**: 3 indicators with colored dots (green/red)
### Phase 4: Page Content Implementation
**4.1 Dashboard Page**
```html
<!-- Service status cards -->
<!-- Activity feed with real-time updates -->
<!-- Quick action buttons -->
<!-- Statistics displays (tracks, artists, downloads) -->
<!-- Progress indicators for ongoing operations -->
<!-- Database status and update controls -->
```
**4.2 Sync Page**
```html
<!-- Playlist selection dropdown -->
<!-- Sync progress tracking with animated bars -->
<!-- Track listing tables with status columns -->
<!-- Action buttons (sync, analyze, cancel) -->
<!-- Status indicators for sync operations -->
<!-- Missing/found track summaries -->
```
**4.3 Downloads/Search Page**
```html
<!-- Search interface with filters -->
<!-- Results grid/list with album art -->
<!-- Download queue with progress bars -->
<!-- Progress tracking for active downloads -->
<!-- Media player integration -->
<!-- Search history and suggestions -->
```
**4.4 Artists Page**
```html
<!-- Artist grid layout with images -->
<!-- Album cards with completion indicators -->
<!-- Search/filter interface -->
<!-- Collection management tools -->
<!-- Image lazy loading system -->
<!-- Artist details modal/expansion -->
```
**4.5 Settings Page**
```html
<!-- Service configuration forms (Spotify, Plex, Jellyfin, Soulseek) -->
<!-- Input validation and feedback -->
<!-- Save/test functionality -->
<!-- Configuration display and status -->
<!-- Auto-detection tools (Plex discovery) -->
<!-- Path settings and validation -->
```
### Phase 5: Backend Integration
**5.1 API Endpoints (add to main.py)**
```python
# Page-specific data APIs
@app.route('/api/dashboard') # Dashboard stats and activity
@app.route('/api/sync') # Sync status and playlists
@app.route('/api/downloads') # Download queue and history
@app.route('/api/artists') # Artist collection and albums
@app.route('/api/settings') # Current configuration
# Action APIs
@app.route('/api/search', methods=['POST']) # Music search
@app.route('/api/download', methods=['POST']) # Download tracks
@app.route('/api/sync-playlist', methods=['POST']) # Sync operations
@app.route('/api/save-settings', methods=['POST']) # Save configuration
@app.route('/api/test-connection', methods=['POST']) # Test service connections
# Real-time APIs
@app.route('/api/status') # Service status (existing)
@app.route('/api/progress') # Operation progress
@app.route('/api/activity') # Recent activity feed
```
**5.2 Data Integration**
- Connect to existing service clients (SpotifyClient, PlexClient, etc.)
- Reuse existing business logic from GUI pages
- Maintain state consistency with backend services
- Real-time updates via polling (5-second intervals)
- Error handling and user feedback
### Phase 6: Visual Polish & Testing
**6.1 Styling Refinement**
- Match exact colors and gradients from PyQt6
- Perfect spacing and typography (SF Pro fonts)
- Smooth animations and transitions (300ms standard)
- Responsive behavior for different screen sizes
**6.2 Component Testing**
- Page switching functionality and animations
- Form submissions and validation
- Real-time updates and polling
- Error handling and user feedback
- Media player controls and state management
**6.3 Integration Testing**
- Backend API connectivity and data flow
- State management across page switches
- Performance optimization and caching
- Cross-browser compatibility (Chrome, Firefox, Safari)
## Color Palette & Design System
### Primary Colors
- **Background**: `#121212` (main), `#1e1e1e` (cards), `#0d1117` (sidebar)
- **Accent**: `#1ed760` (Spotify green), `#1fdf64` (hover), `#1ca851` (pressed)
- **Text**: `#ffffff` (primary), `rgba(255, 255, 255, 0.8)` (secondary)
- **Borders**: `rgba(255, 255, 255, 0.05)` (subtle), `rgba(29, 185, 84, 0.1)` (accent)
### Typography
- **Headers**: SF Pro Display, 20px bold (app title)
- **Navigation**: SF Pro Text, 12px medium
- **Body**: SF Pro Text, 11px regular
- **Monospace**: Courier New (crypto addresses)
### Spacing System
- **Margins**: 8px, 12px, 16px, 20px, 24px
- **Padding**: 4px, 8px, 12px, 16px, 18px
- **Border Radius**: 8px (small), 12px (medium), 16px (large), 20px (buttons)
## Critical Safety Measures
### 1. Non-Breaking Approach
- ❌ NO modifications to existing PyQt6 code
- ❌ NO changes to core business logic
- ❌ NO alterations to service clients or database code
- ✅ Only add new Flask routes and web assets
### 2. Isolated Web Components
- All web code in `webui/` directory
- Separate CSS/JS files with no shared globals
- Independent state management
- No shared variables with GUI code
### 3. Shared Backend Services
- Reuse existing SpotifyClient, PlexClient, JellyfinClient, SoulseekClient
- Call same methods as GUI application
- Maintain identical configuration system via config_manager
- Preserve all existing functionality and error handling
### 4. State Isolation
- Web UI maintains its own state in JavaScript
- No persistent state shared between GUI and web
- Configuration changes affect both modes equally
- Independent session management
## Success Criteria
1. ✅ Visual replica of PyQt6 interface (95%+ visual accuracy)
2. ✅ All 5 pages functional and navigable with smooth transitions
3. ✅ Sidebar components fully operational (navigation, media player, status)
4. ✅ Backend integration complete with all major functions working
5. ✅ No disruption to existing GUI app functionality
6. ✅ Seamless switching between `python main.py` and `python main.py --headless`
7. ✅ Real-time updates and responsive user interface
8. ✅ Proper error handling and user feedback
## File Structure
```
webui/
├── index.html # Single-page application
└── static/
├── style.css # Complete styling system
├── script.js # Page management & API calls
├── components.css # Reusable component styles
└── animations.css # Transition and animation definitions
```
## Development Phases Timeline
### Phase 1: Foundation (Current) ✅
- [x] Plan document creation
- [x] Basic file structure setup
### Phase 2: Core Structure 🚧
- [ ] HTML single-page structure
- [ ] CSS foundation and color system
- [ ] JavaScript page management
### Phase 3: Sidebar Complete 📋
- [ ] Navigation component
- [ ] Media player component
- [ ] Status indicators
- [ ] Donation and version sections
### Phase 4: Page Implementation 📋
- [ ] Dashboard page
- [ ] Sync page
- [ ] Downloads/Search page
- [ ] Artists page
- [ ] Settings page
### Phase 5: Backend Integration 📋
- [ ] Flask API endpoints
- [ ] Service client integration
- [ ] Real-time data updates
### Phase 6: Polish & Testing 📋
- [ ] Visual accuracy review
- [ ] Functionality testing
- [ ] Performance optimization
This plan ensures we build an exact replica of the GUI while maintaining complete safety and isolation from the existing codebase. The web interface will provide the same functionality as the desktop app but accessible through any web browser.

View file

@ -1,197 +0,0 @@
# Multi-Server Database Update Implementation Plan
## Overview
This document outlines the plan to extend SoulSync's database update functionality to support both Plex and Jellyfin media servers, moving from the current Plex-only architecture to a unified multi-server approach.
## Current Architecture Analysis
### Existing Plex-Centric System
**DatabaseUpdateWorker** (`core/database_update_worker.py`):
- Hardcoded to accept `plex_client` parameter
- Uses Plex-specific API methods: `get_all_artists()`, `albums()`, `tracks()`
- Relies on Plex `ratingKey` attributes as primary identifiers
- Implements smart incremental updates using Plex's `recentlyAdded` and `updatedAt` sorting
**Database Schema** (`database/music_database.py`):
- `insert_or_update_artist(plex_artist)` - expects Plex artist objects with `ratingKey`
- `insert_or_update_album(plex_album, artist_id)` - expects Plex album objects
- `insert_or_update_track(plex_track, album_id, artist_id)` - expects Plex track objects
- All database operations depend on `.ratingKey`, `.title`, `.artist()`, `.album()` methods
**Dashboard Tools**:
- "Update SoulSync Database" button → `DatabaseUpdateWorker` with Plex client
- "Plex Metadata Updater" → separate tool for enhancing artist photos via Spotify API
- Both tools assume Plex connectivity and data structures
## Implementation Strategy
### Recommended Approach: Universal Database Worker
Extend the existing architecture rather than creating duplicate tools to maintain consistency and user experience.
#### Key Benefits:
- **Unified Database**: Both servers populate same tables for consistent search/sync
- **Single User Interface**: One "Update Database" button that works with active server
- **Code Reuse**: Share database logic, incremental update strategies, and UI components
- **Seamless Switching**: Users don't need to learn different tools for different servers
#### Architecture Changes:
1. **Server Abstraction Layer**:
```python
# Create common interface for both servers
class MediaServerClient(ABC):
@abstractmethod
def get_all_artists(self) -> List[MediaServerArtist]
@abstractmethod
def get_recently_added_content(self) -> List[MediaServerAlbum]
class JellyfinClient(MediaServerClient):
# Implement Jellyfin-specific API calls
class PlexClient(MediaServerClient):
# Existing implementation
```
2. **Database Worker Updates**:
```python
class DatabaseUpdateWorker(QThread):
def __init__(self, media_client: MediaServerClient, server_type: str, ...):
self.media_client = media_client
self.server_type = server_type # "plex" or "jellyfin"
```
3. **Dynamic Dashboard Tools**:
- "Update SoulSync Database" → detects active server and uses appropriate client
- "Metadata Updater" → works with both server types using abstracted artist data
## Technical Concerns & Design Decisions
### 1. Database Schema Strategy
**Option A: Shared Tables with Server Source Column** (Recommended)
```sql
-- Add server_source column to existing tables
ALTER TABLE artists ADD COLUMN server_source TEXT DEFAULT 'plex';
ALTER TABLE albums ADD COLUMN server_source TEXT DEFAULT 'plex';
ALTER TABLE tracks ADD COLUMN server_source TEXT DEFAULT 'plex';
```
**Pros**:
- Single source of truth for all music data
- Unified search and sync operations
- Easy migration path from current Plex-only setup
**Cons**:
- Potential ID conflicts between servers
- Need to handle server-switching scenarios
**Option B: Separate Tables per Server**
```sql
-- Create parallel table structures
CREATE TABLE jellyfin_artists (...);
CREATE TABLE jellyfin_albums (...);
CREATE TABLE jellyfin_tracks (...);
```
**Pros**:
- Complete isolation between server data
- No ID conflicts
**Cons**:
- Duplicate database logic
- Complex search/sync operations across multiple tables
- User confusion about data sources
### 2. ID Handling Strategy
**Challenge**: Plex uses `ratingKey` (e.g., "12345"), Jellyfin uses GUIDs (e.g., "f2a6c4e8-1234-5678-9abc-def012345678")
**Option A: Native ID Storage** (Recommended)
- Store server-specific IDs as-is in existing `id` columns
- Add `server_source` column to identify which server the ID belongs to
- Update queries to filter by both ID and server source
**Option B: Universal ID Mapping**
- Create internal UUID system that maps to server-specific IDs
- Maintain mapping tables for translation
- More complex but server-agnostic
### 3. Incremental Update Strategy
**Plex Approach**: Uses `recentlyAdded()` and `updatedAt` sorting for smart incremental updates
**Jellyfin Equivalent**:
- `/Users/{userId}/Items?SortBy=DateCreated&SortOrder=Descending` for recently added
- `/Users/{userId}/Items?SortBy=DateLastMediaAdded&SortOrder=Descending` for updated content
- Similar early-stopping logic when consecutive items are already in database
### 4. Metadata Enhancement Compatibility
**Current "Plex Metadata Updater"**:
- Scans Plex artists for missing/low-quality photos
- Uses Spotify API to find and download better artist images
- Updates Plex server with enhanced metadata
**Jellyfin Compatibility Question**:
- Can Jellyfin accept metadata updates via API?
- Should this be server-agnostic or Plex-specific?
- Recommendation: Make server-agnostic if Jellyfin supports metadata updates
### 5. Error Handling & Fallbacks
**Server Switching Scenarios**:
- What happens when user switches from Plex to Jellyfin mid-update?
- How to handle existing database with Plex data when switching to Jellyfin?
- Should we clear database on server switch or maintain both datasets?
**API Differences**:
- Different error types and handling between Plex and Jellyfin APIs
- Different rate limiting and authentication mechanisms
- Need abstraction layer for consistent error handling
## Implementation Phases
### Phase 1: Foundation
1. Create `JellyfinClient` class matching `PlexClient` interface
2. Add `server_source` column to database tables
3. Update database methods to handle server-agnostic data structures
### Phase 2: Worker Updates
1. Modify `DatabaseUpdateWorker` to accept generic media server client
2. Implement Jellyfin-specific data extraction methods
3. Update incremental update logic for Jellyfin API patterns
### Phase 3: UI Integration
1. Update dashboard tools to detect active server
2. Make tool names dynamic ("Update Database" instead of "Update Plex Database")
3. Update progress messages and activity logs to show current server
### Phase 4: Metadata Enhancement
1. Evaluate Jellyfin metadata update capabilities
2. Create server-agnostic metadata enhancement workflow
3. Update UI to reflect server-specific capabilities
## Questions Requiring Decision
1. **Database Strategy**: Shared tables with `server_source` column vs. separate tables?
2. **ID Handling**: Store native server IDs vs. create universal mapping system?
3. **Data Isolation**: Should switching servers clear existing data or maintain both?
4. **Metadata Updates**: Extend metadata enhancement to Jellyfin or keep Plex-specific?
5. **Migration Strategy**: How to handle existing Plex databases when introducing multi-server support?
## Recommended Next Steps
1. **Decide on database schema approach** (shared vs. separate tables)
2. **Create basic JellyfinClient class** with artist/album/track enumeration
3. **Test Jellyfin API** for incremental update patterns
4. **Update database schema** with chosen approach
5. **Modify DatabaseUpdateWorker** for server abstraction
This plan prioritizes maintaining the existing user experience while adding Jellyfin support seamlessly.

View file

@ -1,12 +0,0 @@
# Plans
## Additional Media Server Sources
- Include Emby support for database building phase
- Include Jellyfin support for database building phase
## Playlist Support
- Add Tidal playlist support
- Investigate Apple Music playlist support (if possible)
## Transfer Phase Enhancements
- Add lyrics during the transfer phase

View file

@ -1,370 +0,0 @@
# Multi-Server Support Feature Specification
## Overview
Add Jellyfin support alongside existing Plex functionality to provide users with media server choice and flexibility. This feature will allow SoulSync to work with either Plex or Jellyfin as the source for music library data, with the same level of functionality for both platforms.
## Goals
- **Server Choice**: Allow users to choose between Plex and Jellyfin as their media server
- **Feature Parity**: Maintain all existing functionality regardless of server choice
- **Future-Proof Architecture**: Design extensible system for additional servers (Emby, etc.)
- **Backward Compatibility**: Existing Plex users experience no disruption
- **Unified Experience**: Same SoulSync interface and features regardless of backend
## User Experience
### Settings Page UI Changes
#### Server Selection Interface
- **Toggle Buttons**: Two prominent buttons at top of API Configuration section
- `[🟦 Plex]` - Plex logo button (active state shown with filled background)
- `⬜ Jellyfin` - Jellyfin logo button (inactive state shown with outline)
- **Dynamic Settings Container**: Only show settings for selected server
- **Smooth Transitions**: Animated transitions when switching between servers
- **Clear Visual Feedback**: Active server button is highlighted, inactive is dimmed
#### Plex Settings Container (Existing)
```
Plex Configuration
├── Server URL: [text input with auto-detect button]
├── Token: [password input with help text]
└── Auto-detect: [checkbox]
```
#### Jellyfin Settings Container (New)
```
Jellyfin Configuration
├── Server URL: [text input with auto-detect button]
├── API Key: [password input with help text]
└── Auto-detect: [checkbox]
```
### Default Behavior
- **First-time users**: Default to Plex selection (maintains current onboarding)
- **Existing users**: Migrate to new system with Plex pre-selected
- **Settings validation**: Real-time validation for active server only
- **Connection status**: Show connection status for selected server only
## Configuration Change Behavior
### Restart Required for Server Changes
**Design Decision**: Changing the active media server requires application restart to take effect.
#### Implementation
- **Config Update**: Settings are saved to `config.json` immediately when changed
- **Runtime Behavior**: Application continues using current server until restart
- **User Feedback**: Clear messaging that restart is required for changes to take effect
- **Validation**: New server settings are validated before saving, but not activated
#### UI Messaging
```
Settings Page when server is changed:
┌─────────────────────────────────────────┐
│ ⚠️ Server change requires restart │
│ Click "Save Settings" then restart │
│ SoulSync to use Jellyfin │
└─────────────────────────────────────────┘
```
#### Benefits of Restart Requirement
**Stability**:
- Avoids complex runtime server switching logic
- Prevents issues with active connections and workers
- Ensures clean initialization of new server client
- No risk of mixed server data or state conflicts
**Data Integrity**:
- Clean separation between server data sources
- No risk of cross-contamination during switch
- Ensures database connections are properly established
- Prevents orphaned connections or incomplete switches
**Development Simplicity**:
- Much simpler implementation without runtime switching
- Fewer edge cases and error conditions to handle
- Cleaner architecture without complex state management
- Easier testing and debugging
**User Experience**:
- Clear expectations about when changes take effect
- Follows common application patterns for major config changes
- Prevents confusion about which server is currently active
- Allows users to review settings before committing to switch
#### User Workflow
1. User selects different server (Plex → Jellyfin)
2. User configures new server settings
3. User clicks "Save Settings"
4. Warning appears: "Restart required for server change"
5. User restarts SoulSync
6. Application loads with new server configuration
## Technical Architecture
### Database Design
#### Shared Database with Server-Specific Tables
**File**: `music_library.db` (single database file)
**Table Structure**:
```sql
-- Server-specific music data
plex_artists, plex_albums, plex_tracks
jellyfin_artists, jellyfin_albums, jellyfin_tracks
[future: emby_artists, emby_albums, emby_tracks]
-- Shared functionality tables (unchanged)
wishlist_tracks
watchlist_artists
sync_history
download_history
settings
```
**Benefits**:
- Clean separation per server type
- Easy to query specific server data
- Simple to add new servers
- Shared functionality works across servers
- Single database file for easy backup/migration
#### Data Consistency Requirements
**All servers must provide same core metadata**:
**Artist Data**:
- `id` (server-specific identifier)
- `name` (artist name)
- `genres` (array/comma-separated)
- `image_url` (artist photo)
- `server_path` (internal server path)
**Album Data**:
- `id` (server-specific identifier)
- `title` (album title)
- `artist_id` (reference to artist)
- `release_year` (integer)
- `track_count` (integer)
- `image_url` (album artwork)
- `server_path` (internal server path)
**Track Data**:
- `id` (server-specific identifier)
- `title` (track title)
- `artist_id` (reference to artist)
- `album_id` (reference to album)
- `track_number` (integer)
- `duration_ms` (integer)
- `file_path` (absolute file system path)
- `server_path` (internal server path)
**Removed from Scope**:
- Artist biographies/summaries (unnecessary complexity)
- Extended metadata (focus on core music data)
- Social features (ratings, reviews)
### Configuration System
#### Config File Structure
```json
{
"active_media_server": "plex",
"plex": {
"base_url": "http://localhost:32400",
"token": "xxx-plex-token-xxx",
"auto_detect": true
},
"jellyfin": {
"base_url": "http://localhost:8096",
"api_key": "xxx-jellyfin-api-key-xxx",
"auto_detect": true
}
}
```
#### Configuration Management
- **Active Server Setting**: `active_media_server` determines which client to use
- **Server-Specific Configs**: Each server maintains separate configuration
- **Validation**: Only validate settings for currently active server
- **Migration**: Automatic migration of existing Plex configs to new structure
- **Restart Requirement**: Server changes only take effect after application restart
### API Client Architecture
#### Abstract Base Class
```python
class MediaServerClient(ABC):
@abstractmethod
def is_connected(self) -> bool
@abstractmethod
def get_music_library(self)
@abstractmethod
def get_all_artists(self) -> List[Artist]
@abstractmethod
def get_artist_albums(self, artist_id: str) -> List[Album]
@abstractmethod
def get_album_tracks(self, album_id: str) -> List[Track]
@abstractmethod
def search_tracks(self, query: str) -> List[Track]
```
#### Implementation Classes
- **PlexClient**: Existing implementation adapted to new interface
- **JellyfinClient**: New implementation following same patterns
- **Future**: EmbyClient, KodiClient, etc.
#### Client Factory Pattern
```python
def get_media_server_client() -> MediaServerClient:
active_server = config_manager.get('active_media_server', 'plex')
if active_server == 'plex':
return PlexClient()
elif active_server == 'jellyfin':
return JellyfinClient()
else:
raise ValueError(f"Unsupported server: {active_server}")
```
## Implementation Strategy
### Phase 1: Foundation (Database & Config)
1. **Database Schema Migration**
- Create Jellyfin tables mirroring Plex structure
- Migrate existing Plex data to new `plex_*` tables
- Update database access methods to be server-aware
- Test data migration with existing user databases
2. **Configuration System Updates**
- Add `active_media_server` config option
- Create Jellyfin configuration section
- Update settings validation logic
- Implement configuration migration for existing users
- Add restart requirement logic and UI messaging
3. **Settings UI Foundation**
- Create server toggle button components
- Implement dynamic settings container switching
- Add Jellyfin settings form (URL + API Key)
- Update settings page layout and styling
- Add restart warning system
### Phase 2: Jellyfin Integration
1. **JellyfinClient Development**
- Research Jellyfin API endpoints and authentication
- Implement MediaServerClient interface
- Handle Jellyfin-specific data formats and responses
- Add comprehensive error handling and logging
2. **Database Abstraction Layer**
- Create server-agnostic database access methods
- Update existing Plex code to use abstraction layer
- Implement Jellyfin data persistence
- Ensure cross-server functionality (wishlist/watchlist)
3. **Core Service Updates**
- Update DatabaseUpdateWorker to support both servers
- Modify matching engine to handle server-specific data
- Update download/sync services for multi-server support
- Add server-aware logging and error messages
### Phase 3: Integration & Polish
1. **Dashboard Integration**
- Update connection status indicators for active server
- Modify service health checks for selected server
- Update statistics and activity feeds
- Add server type indicators in UI
2. **Feature Testing & Validation**
- Comprehensive testing with both server types
- Data consistency verification
- Performance testing and optimization
- User experience testing and refinement
3. **Documentation & Migration**
- Update user documentation for multi-server setup
- Create migration guides for existing users
- Add troubleshooting guides for each server type
- Update installation instructions
## Jellyfin Integration Requirements
### API Research Needs
- **Authentication**: API key format and usage patterns
- **Library Structure**: How Jellyfin organizes music libraries
- **Endpoint Discovery**: Artist, album, track retrieval methods
- **Search Capabilities**: Track/artist search functionality
- **Error Handling**: Common error responses and status codes
### Data Mapping
- **Field Mapping**: Jellyfin → SoulSync data field mappings
- **ID Handling**: Jellyfin ID formats and uniqueness
- **Path Resolution**: File system path access from Jellyfin
- **Image URLs**: Album art and artist image retrieval
### Connection Management
- **Auto-Detection**: Jellyfin server discovery on local network
- **Health Checks**: Connection validation and status monitoring
- **Rate Limiting**: Jellyfin API rate limits and best practices
- **Session Management**: API key validation and renewal
## Migration Strategy
### Existing User Impact
- **Zero Disruption**: Existing Plex users see no functional changes
- **Opt-in Jellyfin**: New server support is additive, not replacement
- **Data Preservation**: All existing data, settings, and functionality preserved
- **Seamless Upgrade**: Automatic config migration during app update
- **Clear Restart Process**: Users understand when changes take effect
### New User Onboarding
- **Server Choice**: Present server options during initial setup
- **Guided Configuration**: Step-by-step setup for chosen server
- **Validation Feedback**: Clear error messages and connection testing
- **Fallback Options**: Graceful handling of connection failures
## Future Extensibility
### Additional Server Support
- **Emby**: Natural next addition with similar API patterns
- **Kodi**: Potential integration for advanced users
- **Subsonic**: API-compatible servers
- **Custom Servers**: Plugin architecture for community additions
### Advanced Features
- **Multi-Server Mode**: Theoretical support for multiple active servers
- **Server Synchronization**: Cross-server library comparison
- **Server Migration**: Tools for moving between server types
- **Hybrid Workflows**: Different servers for different purposes
## Success Criteria
### Functional Requirements
- ✅ Users can switch between Plex and Jellyfin servers
- ✅ All existing features work with both server types
- ✅ Database maintains data for both servers simultaneously
- ✅ Settings UI clearly shows active server and appropriate options
- ✅ Performance is equivalent between server types
- ✅ Server changes require restart and users are clearly informed
### User Experience Requirements
- ✅ Switching servers is intuitive with clear restart messaging
- ✅ Error messages are server-specific and helpful
- ✅ Connection status is always clear and accurate
- ✅ Existing Plex users experience no disruption
- ✅ New Jellyfin users have equivalent functionality
- ✅ Restart requirement is clearly communicated and expected
### Technical Requirements
- ✅ Clean, extensible architecture for future servers
- ✅ Comprehensive error handling and logging
- ✅ Backward compatibility with existing configurations
- ✅ Efficient database design with clear separation
- ✅ Consistent API patterns across server implementations
- ✅ Stable configuration management with restart-based activation
---
*This specification provides the foundation for implementing multi-server support in SoulSync, starting with Jellyfin integration while maintaining the high-quality user experience and robust functionality that users expect.*