From decd1f39394279bf2f5307549a63cce1fefe3e59 Mon Sep 17 00:00:00 2001 From: Broque Thomas Date: Sun, 20 Jul 2025 18:15:39 -0700 Subject: [PATCH] Create PLAYLIST_DOWNLOAD_IMPLEMENTATION.md --- PLAYLIST_DOWNLOAD_IMPLEMENTATION.md | 368 ++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 PLAYLIST_DOWNLOAD_IMPLEMENTATION.md diff --git a/PLAYLIST_DOWNLOAD_IMPLEMENTATION.md b/PLAYLIST_DOWNLOAD_IMPLEMENTATION.md new file mode 100644 index 00000000..f73e2325 --- /dev/null +++ b/PLAYLIST_DOWNLOAD_IMPLEMENTATION.md @@ -0,0 +1,368 @@ +# Playlist Download Implementation Plan + +## Overview + +This document outlines the implementation plan for the "Download Missing Tracks" feature that enables intelligent playlist downloads with Plex integration and Soulseek source matching. + +## Feature Requirements + +### Core Functionality +- **Plex Integration**: Check track existence before downloading (if Plex connected) +- **Fallback Mode**: Download all tracks if no Plex connection +- **Intelligent Matching**: Use Spotify metadata to match Soulseek results +- **File Organization**: Create playlist-based folder structure in Transfer directory +- **Metadata Enhancement**: Apply Spotify metadata to downloaded tracks +- **Progress Tracking**: Real-time download progress and status updates + +### User Experience Flow +1. User clicks "Download Missing Tracks" in playlist details modal +2. System checks Plex connection status +3. If Plex connected: analyze playlist and identify missing tracks +4. If no Plex: queue all tracks for download +5. Use existing Spotify matching for artist/track identification +6. Download tracks to Transfer/[PLAYLIST_NAME]/ folder structure +7. Apply Spotify metadata to downloaded files + +## Current Architecture Analysis + +### Downloads.py Strengths +- **Robust download workflow** with `start_download()`, `start_matched_download()` patterns +- **Sophisticated track matching** via `SpotifyMatchingModal` and `MusicMatchingEngine` +- **File organization system** with Transfer folder structure (Artist/Album/Track) +- **Queue management** with progress tracking and status monitoring +- **Metadata enhancement** from Spotify API integration +- **Thread-safe operations** with background workers + +### Plex Integration Capabilities +- **Track existence checking** via `PlexClient._find_track()` method +- **Bulk track retrieval** with `search_tracks()` (up to 10K tracks) +- **Matching engine integration** with confidence scoring (0.7+ threshold) +- **Lazy connection pattern** prevents UI blocking + +### Extension Points Identified +- `start_matched_download()` pattern can be extended for playlist context +- Existing `SpotifyMatchingModal` can handle batch artist selection +- Current Transfer folder organization supports playlist grouping +- Thread management patterns support playlist-scale operations + +## Implementation Plan + +### Phase 1: Core Infrastructure + +#### 1. Create Playlist Download Service +**File**: `/services/playlist_download_service.py` (NEW) + +**Purpose**: Orchestrate playlist-wide download operations + +**Key Components**: +```python +class PlaylistDownloadService: + def __init__(self, spotify_client, plex_client, soulseek_client, downloads_page): + self.spotify_client = spotify_client + self.plex_client = plex_client + self.soulseek_client = soulseek_client + self.downloads_page = downloads_page + + async def download_missing_tracks(self, playlist: PlaylistInfo): + """Main entry point for playlist downloads""" + + def _check_plex_existence(self, tracks: List[SpotifyTrack]) -> List[SpotifyTrack]: + """Check which tracks are missing from Plex""" + + def _queue_playlist_downloads(self, tracks: List[SpotifyTrack], playlist_name: str): + """Add tracks to download queue with playlist organization""" + + def _create_playlist_folder_structure(self, playlist_name: str) -> str: + """Create Transfer/[PLAYLIST_NAME]/ directory structure""" +``` + +**Estimated Lines**: 300-400 + +#### 2. Extend Downloads Page Integration +**File**: `/ui/pages/downloads.py` (MODIFY) + +**Changes Required**: +- Add `start_playlist_download()` method following existing patterns +- Extend download queue to support playlist containers +- Add playlist-level progress tracking +- Integrate with existing `SpotifyMatchingModal` for batch operations + +**New Methods**: +```python +def start_playlist_download(self, playlist: PlaylistInfo): + """Initiate playlist-wide download operation""" + +def _handle_playlist_download_progress(self, playlist_id: str, progress: dict): + """Track progress across multiple playlist downloads""" + +def _organize_playlist_download(self, track_result: TrackResult, playlist_name: str): + """Apply playlist-specific folder organization""" +``` + +**Estimated Lines Added**: 100-150 + +#### 3. Enhance Sync Page Modal +**File**: `/ui/pages/sync.py` (MODIFY) + +**Changes Required**: +- Connect "Download Missing Tracks" button to playlist download service +- Add playlist download progress indicators +- Handle user feedback for Plex vs. non-Plex scenarios + +**New Methods**: +```python +def on_download_missing_tracks_clicked(self): + """Handle Download Missing Tracks button click""" + +def _show_playlist_download_progress(self, playlist_id: str): + """Display download progress in modal""" + +def _handle_download_completion(self, playlist_id: str, results: dict): + """Process playlist download completion""" +``` + +**Button Integration**: +```python +# In create_buttons() method +download_btn.clicked.connect(self.on_download_missing_tracks_clicked) +``` + +**Estimated Lines Added**: 50-75 + +### Phase 2: Plex Integration Optimization + +#### 1. Enhance Track Existence Checking +**File**: `/core/plex_client.py` (MODIFY) + +**New Methods**: +```python +def check_tracks_existence_batch(self, spotify_tracks: List[SpotifyTrack]) -> Dict[str, PlexTrackInfo]: + """Efficiently check existence of multiple tracks""" + +def _build_track_cache(self) -> Dict[str, PlexTrackInfo]: + """Create in-memory cache of all Plex tracks for fast lookup""" + +def _normalize_track_key(self, title: str, artist: str) -> str: + """Create normalized key for track matching""" +``` + +**Optimization Strategy**: +- Cache all Plex tracks in memory for O(1) lookup +- Use normalized title+artist keys for matching +- Leverage existing `MusicMatchingEngine` for confidence scoring +- Implement batch processing for large playlists + +**Estimated Lines Added**: 75-100 + +#### 2. Smart Download Logic Implementation + +**Core Algorithm**: +```python +def determine_tracks_to_download(self, playlist_tracks: List[SpotifyTrack]) -> Tuple[List[SpotifyTrack], Dict[str, str]]: + """ + Returns: + - List of tracks to download + - Dictionary of skipped tracks with reasons + """ + if not self.plex_client.is_connected(): + return playlist_tracks, {} + + tracks_to_download = [] + skipped_tracks = {} + plex_cache = self.plex_client._build_track_cache() + + for track in playlist_tracks: + existing_track = self._find_in_cache(track, plex_cache) + if existing_track and self._calculate_confidence(track, existing_track) >= 0.8: + skipped_tracks[track.id] = f"Already exists in Plex: {existing_track.title}" + else: + tracks_to_download.append(track) + + return tracks_to_download, skipped_tracks +``` + +### Phase 3: Enhanced Matching & Metadata + +#### 1. Leverage Existing Spotify Matching +**Files**: `/ui/pages/downloads.py`, `/core/matching_engine.py` (MODIFY) + +**Extensions Required**: +- Extend `SpotifyMatchingModal` for playlist context +- Add batch artist suggestion for album-heavy playlists +- Use existing confidence scoring algorithms +- Apply Spotify metadata to matched downloads + +**Playlist Context Enhancement**: +```python +class PlaylistSpotifyMatchingModal(SpotifyMatchingModal): + def __init__(self, track_results: List[TrackResult], playlist_context: PlaylistInfo): + super().__init__(track_results) + self.playlist_context = playlist_context + + def _generate_playlist_aware_suggestions(self): + """Generate suggestions considering playlist context (album groupings, etc.)""" +``` + +#### 2. Soulseek Result Matching Integration + +**Leverage Existing Systems**: +- Use existing search and matching algorithms from downloads.py +- Apply track info from Spotify API (title, artist, album, duration) +- Leverage existing `TrackResult` parsing and scoring +- Maintain current quality filtering and selection logic + +### Phase 4: File Organization & Metadata + +#### 1. Transfer Folder Structure +**Pattern Implementation**: +``` +Transfer/ + [PLAYLIST_NAME]/ + ARTIST_NAME/ + ARTIST_NAME - ALBUM_NAME/ + 01 - TRACK_NAME.flac + cover.jpg + ARTIST_NAME/ + ARTIST_NAME - SINGLE_NAME/ + SINGLE_NAME.flac + cover.jpg +``` + +**Organization Logic**: +```python +def _create_playlist_folder_structure(self, playlist_name: str, track: SpotifyTrack) -> str: + """Create appropriate folder structure within playlist directory""" + base_path = os.path.join(config_manager.get('soulseek.transfer_path'), playlist_name) + + if self._is_part_of_album(track): + return os.path.join(base_path, track.artist, f"{track.artist} - {track.album}") + else: + return os.path.join(base_path, track.artist, f"{track.artist} - {track.title}") +``` + +#### 2. Metadata Enhancement +**Integration with Existing Systems**: +- Apply Spotify track metadata to downloaded files +- Use existing metadata writing functionality from downloads.py +- Preserve track numbers, album info, cover art +- Maintain existing file naming conventions + +## Technical Implementation Details + +### Performance Optimizations +- **Plex Track Caching**: Load all Plex tracks once, cache in memory for O(1) lookups +- **Batch Processing**: Process large playlists (>100 tracks) in chunks +- **Progressive Downloads**: Use existing thread pool patterns for concurrent downloads +- **Background Processing**: Leverage existing worker thread architecture + +### Error Handling Strategies +- **Plex Connection Failures**: Graceful fallback to "download all tracks" mode +- **Soulseek Search Failures**: Use existing retry mechanisms and error handling +- **Download Failures**: Leverage existing queue management and retry logic +- **Metadata Failures**: Graceful degradation with basic file naming + +### User Experience Enhancements +- **Progress Indicators**: Real-time progress for playlist analysis and downloads +- **Skip Existing Option**: Clear feedback when tracks exist in Plex +- **Batch Operations**: Efficient handling of large playlists +- **Status Feedback**: Clear messaging for Plex vs. non-Plex scenarios + +### Thread Safety Considerations +- **Queue Thread Safety**: Use existing `ThreadSafeQueueManager` patterns +- **UI Updates**: Leverage existing signal/slot patterns for thread-safe UI updates +- **Resource Management**: Follow existing thread cleanup and management patterns + +## Integration Points + +### Existing Service Integration +- **SyncService**: Extend existing playlist sync workflows +- **Downloads Page**: Integrate with current download management +- **Spotify Client**: Use existing OAuth and API integration +- **Plex Client**: Extend current track lookup and library access + +### Signal/Slot Connections +```python +# In sync.py - PlaylistDetailsModal +self.download_btn.clicked.connect(self.on_download_missing_tracks_clicked) + +# Progress tracking +self.playlist_download_service.progress_updated.connect(self.update_download_progress) +self.playlist_download_service.download_completed.connect(self.on_playlist_download_complete) +``` + +## Testing Strategy + +### Unit Testing +- **Track Existence Checking**: Test Plex integration with various track matching scenarios +- **Download Logic**: Test playlist download workflow with and without Plex +- **File Organization**: Test folder structure creation and metadata application + +### Integration Testing +- **End-to-End Workflow**: Test complete playlist download from button click to completion +- **Error Scenarios**: Test Plex disconnection, Soulseek failures, network issues +- **Large Playlist Handling**: Test performance with 100+ track playlists + +### User Acceptance Testing +- **Plex Integration**: Verify correct skip behavior for existing tracks +- **Progress Tracking**: Ensure clear feedback during long download operations +- **File Organization**: Verify correct Transfer folder structure and metadata + +## Future Enhancements (Post-MVP) + +### Database Integration +- **Download History**: Track download history and statistics +- **Playlist Sync Status**: Store playlist sync timestamps and status +- **Quality Tracking**: Record download quality and source information +- **User Preferences**: Store user settings and preferences + +### Advanced Features +- **Selective Download**: Allow users to manually select tracks from playlist +- **Quality Preferences**: Automatic quality selection based on user preferences +- **Duplicate Detection**: Advanced duplicate handling across playlists +- **Sync Scheduling**: Automatic periodic playlist synchronization + +## Estimated Implementation Timeline + +### Phase 1: Core Infrastructure (2-3 days) +- Create `PlaylistDownloadService` +- Basic downloads.py integration +- Sync page button connection + +### Phase 2: Plex Integration (1-2 days) +- Optimize track existence checking +- Implement smart download logic +- Add playlist analysis + +### Phase 3: Enhanced Matching (1-2 days) +- Extend Spotify matching for playlists +- Integrate with existing Soulseek matching +- Add metadata enhancement + +### Phase 4: File Organization & Polish (1-2 days) +- Implement Transfer folder structure +- Add progress tracking and error handling +- User experience refinements + +**Total Estimated Effort**: 5-9 days + +## Success Criteria + +### Functional Requirements +- ✅ Playlist tracks download to Transfer/[PLAYLIST_NAME]/ structure +- ✅ Plex integration skips existing tracks (confidence ≥ 0.8) +- ✅ Fallback to download all tracks when Plex not connected +- ✅ Spotify metadata applied to downloaded files +- ✅ Progress tracking and error handling + +### Performance Requirements +- ✅ Playlist analysis completes within 10 seconds for 100-track playlists +- ✅ Download initiation within 5 seconds of button click +- ✅ UI remains responsive during playlist processing + +### User Experience Requirements +- ✅ Clear feedback for Plex vs. non-Plex scenarios +- ✅ Progress indicators for long-running operations +- ✅ Intuitive folder organization in Transfer directory +- ✅ Error handling with clear user messaging + +This implementation plan leverages the existing robust architecture while adding intelligent Plex checking and playlist-based download functionality in a maintainable and extensible way. \ No newline at end of file