fixed case where user could start multiple syncs at once and would not display ui correclty.
This commit is contained in:
parent
cecbd539a6
commit
46c519a27e
2 changed files with 44 additions and 22 deletions
|
|
@ -44,13 +44,29 @@ class PlaylistSyncService:
|
||||||
self.spotify_client = spotify_client
|
self.spotify_client = spotify_client
|
||||||
self.plex_client = plex_client
|
self.plex_client = plex_client
|
||||||
self.soulseek_client = soulseek_client
|
self.soulseek_client = soulseek_client
|
||||||
self.progress_callback = None
|
self.progress_callbacks = {} # Playlist-specific progress callbacks
|
||||||
self.is_syncing = False
|
self.syncing_playlists = set() # Track multiple syncing playlists
|
||||||
self._cancelled = False
|
self._cancelled = False
|
||||||
self.matching_engine = MusicMatchingEngine()
|
self.matching_engine = MusicMatchingEngine()
|
||||||
|
|
||||||
def set_progress_callback(self, callback):
|
@property
|
||||||
self.progress_callback = callback
|
def is_syncing(self):
|
||||||
|
"""Check if any playlist is currently syncing"""
|
||||||
|
return len(self.syncing_playlists) > 0
|
||||||
|
|
||||||
|
def set_progress_callback(self, callback, playlist_name=None):
|
||||||
|
"""Set progress callback for specific playlist or global if no playlist specified"""
|
||||||
|
if playlist_name:
|
||||||
|
self.progress_callbacks[playlist_name] = callback
|
||||||
|
else:
|
||||||
|
# Legacy support - set for all current syncing playlists
|
||||||
|
for playlist in self.syncing_playlists:
|
||||||
|
self.progress_callbacks[playlist] = callback
|
||||||
|
|
||||||
|
def clear_progress_callback(self, playlist_name):
|
||||||
|
"""Clear progress callback for specific playlist"""
|
||||||
|
if playlist_name in self.progress_callbacks:
|
||||||
|
del self.progress_callbacks[playlist_name]
|
||||||
|
|
||||||
def cancel_sync(self):
|
def cancel_sync(self):
|
||||||
"""Cancel the current sync operation"""
|
"""Cancel the current sync operation"""
|
||||||
|
|
@ -58,10 +74,12 @@ class PlaylistSyncService:
|
||||||
self._cancelled = True
|
self._cancelled = True
|
||||||
self.is_syncing = False
|
self.is_syncing = False
|
||||||
|
|
||||||
def _update_progress(self, step: str, track: str, progress: float, total_steps: int, current_step: int,
|
def _update_progress(self, playlist_name: str, step: str, track: str, progress: float, total_steps: int, current_step: int,
|
||||||
total_tracks: int = 0, matched_tracks: int = 0, failed_tracks: int = 0):
|
total_tracks: int = 0, matched_tracks: int = 0, failed_tracks: int = 0):
|
||||||
if self.progress_callback:
|
# Send progress update to the specific playlist's callback
|
||||||
self.progress_callback(SyncProgress(
|
callback = self.progress_callbacks.get(playlist_name)
|
||||||
|
if callback:
|
||||||
|
callback(SyncProgress(
|
||||||
current_step=step,
|
current_step=step,
|
||||||
current_track=track,
|
current_track=track,
|
||||||
progress=progress,
|
progress=progress,
|
||||||
|
|
@ -73,8 +91,9 @@ class PlaylistSyncService:
|
||||||
))
|
))
|
||||||
|
|
||||||
async def sync_playlist(self, playlist: SpotifyPlaylist, download_missing: bool = False) -> SyncResult:
|
async def sync_playlist(self, playlist: SpotifyPlaylist, download_missing: bool = False) -> SyncResult:
|
||||||
if self.is_syncing:
|
# Check if THIS specific playlist is already syncing
|
||||||
logger.warning("Sync already in progress")
|
if playlist.name in self.syncing_playlists:
|
||||||
|
logger.warning(f"Sync already in progress for playlist: {playlist.name}")
|
||||||
return SyncResult(
|
return SyncResult(
|
||||||
playlist_name=playlist.name,
|
playlist_name=playlist.name,
|
||||||
total_tracks=0,
|
total_tracks=0,
|
||||||
|
|
@ -83,10 +102,11 @@ class PlaylistSyncService:
|
||||||
downloaded_tracks=0,
|
downloaded_tracks=0,
|
||||||
failed_tracks=0,
|
failed_tracks=0,
|
||||||
sync_time=datetime.now(),
|
sync_time=datetime.now(),
|
||||||
errors=["Sync already in progress"]
|
errors=[f"Sync already in progress for playlist: {playlist.name}"]
|
||||||
)
|
)
|
||||||
|
|
||||||
self.is_syncing = True
|
# Add this playlist to syncing set
|
||||||
|
self.syncing_playlists.add(playlist.name)
|
||||||
self._cancelled = False
|
self._cancelled = False
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
|
|
@ -97,7 +117,7 @@ class PlaylistSyncService:
|
||||||
return self._create_error_result(playlist.name, ["Sync cancelled"])
|
return self._create_error_result(playlist.name, ["Sync cancelled"])
|
||||||
|
|
||||||
# Skip fetching playlist since we already have it
|
# Skip fetching playlist since we already have it
|
||||||
self._update_progress("Preparing playlist sync", "", 10, 5, 1)
|
self._update_progress(playlist.name, "Preparing playlist sync", "", 10, 5, 1)
|
||||||
|
|
||||||
if not playlist.tracks:
|
if not playlist.tracks:
|
||||||
errors.append(f"Playlist '{playlist.name}' has no tracks")
|
errors.append(f"Playlist '{playlist.name}' has no tracks")
|
||||||
|
|
@ -108,7 +128,7 @@ class PlaylistSyncService:
|
||||||
|
|
||||||
total_tracks = len(playlist.tracks)
|
total_tracks = len(playlist.tracks)
|
||||||
|
|
||||||
self._update_progress("Matching tracks against Plex library", "", 20, 5, 2, total_tracks=total_tracks)
|
self._update_progress(playlist.name, "Matching tracks against Plex library", "", 20, 5, 2, total_tracks=total_tracks)
|
||||||
|
|
||||||
# Use the same robust matching approach as "Download Missing Tracks"
|
# Use the same robust matching approach as "Download Missing Tracks"
|
||||||
match_results = []
|
match_results = []
|
||||||
|
|
@ -119,7 +139,7 @@ class PlaylistSyncService:
|
||||||
# Update progress for each track
|
# Update progress for each track
|
||||||
progress_percent = 20 + (40 * (i + 1) / total_tracks) # 20-60% for matching
|
progress_percent = 20 + (40 * (i + 1) / total_tracks) # 20-60% for matching
|
||||||
current_track_name = f"{track.artists[0]} - {track.name}" if track.artists else track.name
|
current_track_name = f"{track.artists[0]} - {track.name}" if track.artists else track.name
|
||||||
self._update_progress("Matching tracks", current_track_name, progress_percent, 5, 2,
|
self._update_progress(playlist.name, "Matching tracks", current_track_name, progress_percent, 5, 2,
|
||||||
total_tracks=total_tracks,
|
total_tracks=total_tracks,
|
||||||
matched_tracks=len([r for r in match_results if r.is_match]),
|
matched_tracks=len([r for r in match_results if r.is_match]),
|
||||||
failed_tracks=len([r for r in match_results if not r.is_match]))
|
failed_tracks=len([r for r in match_results if not r.is_match]))
|
||||||
|
|
@ -145,7 +165,7 @@ class PlaylistSyncService:
|
||||||
return self._create_error_result(playlist.name, ["Sync cancelled"])
|
return self._create_error_result(playlist.name, ["Sync cancelled"])
|
||||||
|
|
||||||
# Update progress with match results
|
# Update progress with match results
|
||||||
self._update_progress("Matching completed", "", 60, 5, 3,
|
self._update_progress(playlist.name, "Matching completed", "", 60, 5, 3,
|
||||||
total_tracks=total_tracks,
|
total_tracks=total_tracks,
|
||||||
matched_tracks=len(matched_tracks),
|
matched_tracks=len(matched_tracks),
|
||||||
failed_tracks=len(unmatched_tracks))
|
failed_tracks=len(unmatched_tracks))
|
||||||
|
|
@ -154,7 +174,7 @@ class PlaylistSyncService:
|
||||||
if download_missing and unmatched_tracks:
|
if download_missing and unmatched_tracks:
|
||||||
if self._cancelled:
|
if self._cancelled:
|
||||||
return self._create_error_result(playlist.name, ["Sync cancelled"])
|
return self._create_error_result(playlist.name, ["Sync cancelled"])
|
||||||
self._update_progress("Downloading missing tracks", "", 70, 5, 4,
|
self._update_progress(playlist.name, "Downloading missing tracks", "", 70, 5, 4,
|
||||||
total_tracks=total_tracks,
|
total_tracks=total_tracks,
|
||||||
matched_tracks=len(matched_tracks),
|
matched_tracks=len(matched_tracks),
|
||||||
failed_tracks=len(unmatched_tracks))
|
failed_tracks=len(unmatched_tracks))
|
||||||
|
|
@ -163,7 +183,7 @@ class PlaylistSyncService:
|
||||||
if self._cancelled:
|
if self._cancelled:
|
||||||
return self._create_error_result(playlist.name, ["Sync cancelled"])
|
return self._create_error_result(playlist.name, ["Sync cancelled"])
|
||||||
|
|
||||||
self._update_progress("Creating/updating Plex playlist", "", 80, 5, 4,
|
self._update_progress(playlist.name, "Creating/updating Plex playlist", "", 80, 5, 4,
|
||||||
total_tracks=total_tracks,
|
total_tracks=total_tracks,
|
||||||
matched_tracks=len(matched_tracks),
|
matched_tracks=len(matched_tracks),
|
||||||
failed_tracks=len(unmatched_tracks))
|
failed_tracks=len(unmatched_tracks))
|
||||||
|
|
@ -189,7 +209,7 @@ class PlaylistSyncService:
|
||||||
synced_tracks = len(plex_tracks) if sync_success else 0
|
synced_tracks = len(plex_tracks) if sync_success else 0
|
||||||
failed_tracks = len(playlist.tracks) - synced_tracks - downloaded_tracks
|
failed_tracks = len(playlist.tracks) - synced_tracks - downloaded_tracks
|
||||||
|
|
||||||
self._update_progress("Sync completed", "", 100, 5, 5,
|
self._update_progress(playlist.name, "Sync completed", "", 100, 5, 5,
|
||||||
total_tracks=total_tracks,
|
total_tracks=total_tracks,
|
||||||
matched_tracks=len(matched_tracks),
|
matched_tracks=len(matched_tracks),
|
||||||
failed_tracks=failed_tracks)
|
failed_tracks=failed_tracks)
|
||||||
|
|
@ -214,7 +234,9 @@ class PlaylistSyncService:
|
||||||
return self._create_error_result(playlist.name, errors)
|
return self._create_error_result(playlist.name, errors)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
self.is_syncing = False
|
# Remove this playlist from syncing set and clear its callback
|
||||||
|
self.syncing_playlists.discard(playlist.name)
|
||||||
|
self.clear_progress_callback(playlist.name)
|
||||||
self._cancelled = False
|
self._cancelled = False
|
||||||
|
|
||||||
async def _find_track_in_plex(self, spotify_track: SpotifyTrack) -> Tuple[Optional[PlexTrackInfo], float]:
|
async def _find_track_in_plex(self, spotify_track: SpotifyTrack) -> Tuple[Optional[PlexTrackInfo], float]:
|
||||||
|
|
|
||||||
|
|
@ -569,8 +569,8 @@ class SyncWorker(QRunnable):
|
||||||
self.sync_service.cancel_sync()
|
self.sync_service.cancel_sync()
|
||||||
|
|
||||||
# Clear the progress callback to stop further progress updates
|
# Clear the progress callback to stop further progress updates
|
||||||
if hasattr(self.sync_service, 'set_progress_callback'):
|
if hasattr(self.sync_service, 'clear_progress_callback'):
|
||||||
self.sync_service.set_progress_callback(None)
|
self.sync_service.clear_progress_callback(self.playlist.name)
|
||||||
|
|
||||||
# Log the cancellation request
|
# Log the cancellation request
|
||||||
print(f"DEBUG: SyncWorker.cancel() called for playlist {getattr(self.playlist, 'name', 'unknown')}")
|
print(f"DEBUG: SyncWorker.cancel() called for playlist {getattr(self.playlist, 'name', 'unknown')}")
|
||||||
|
|
@ -587,7 +587,7 @@ class SyncWorker(QRunnable):
|
||||||
if not self._cancelled:
|
if not self._cancelled:
|
||||||
self.signals.progress.emit(progress)
|
self.signals.progress.emit(progress)
|
||||||
|
|
||||||
self.sync_service.set_progress_callback(on_progress)
|
self.sync_service.set_progress_callback(on_progress, self.playlist.name)
|
||||||
|
|
||||||
# Create new event loop for this thread
|
# Create new event loop for this thread
|
||||||
loop = asyncio.new_event_loop()
|
loop = asyncio.new_event_loop()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue