This commit is contained in:
Broque Thomas 2025-07-23 23:21:09 -07:00
parent ffabf9889d
commit aedfdbd867
4 changed files with 98 additions and 15 deletions

View file

@ -1 +1 @@
{"access_token": "BQBcawhTowBatKdkvO7n3N80j8Pe7sZlSAoUGyWlT6Iyz-SHjUBxehwq0FomzdFUGEkJk2pQ3RKNoCY60Kvd9mDjgmh3rSFYphYE0LAEq71j1i0SR0vZnhpKV_5Ia7DdLWS3Z5em2t1XTe0dsnJoRHlvfguCDGFTGrgzOEUUtzJ6rUMqcWlgQTqWcqif0xAKij8l4hwiPI5fsWbRVQUdD-MXLqBveArU3tcJunylwDbqJfqSJ_8HxRNLDQoxtqfn", "token_type": "Bearer", "expires_in": 3600, "scope": "user-library-read user-read-private playlist-read-private playlist-read-collaborative user-read-email", "expires_at": 1753338014, "refresh_token": "AQDmfQkPCGObfJeTUIbW1hAAwhSqkuHRA3Qh2dqVYMRh0eCkFMQgPNJDDzF8y-BiaVbj80zePkK_XSfYH1aJutMtNbnsqRKWuxP31BTrMc7pdUdbE7Fma4oH8wpDUKdG3MM"}
{"access_token": "BQCLT_slOYLk3v2BHMORcGETcy_0zWC43NqlAHsNvKZg6YnGZwlW3U98evnFP_mlm-PRC5LjSZc39mtX9Z5ikNILw13_nCpCLAYD5Qh0ZP4tUtCwlbmkCyDrhnzFXRgv7BaiFhCmxz4QV63j1YMhgk_NM95Bg8cMy8_K7jcdgNP5ApVC6LXbhNK4ytYFhuicULb-fTbJna2DAmp37QduR9dc1LHazfFYGb7Um_fAYfo7CjipUhyFI54NH3zy32aQ", "token_type": "Bearer", "expires_in": 3600, "scope": "user-library-read user-read-private playlist-read-private playlist-read-collaborative user-read-email", "expires_at": 1753341652, "refresh_token": "AQDmfQkPCGObfJeTUIbW1hAAwhSqkuHRA3Qh2dqVYMRh0eCkFMQgPNJDDzF8y-BiaVbj80zePkK_XSfYH1aJutMtNbnsqRKWuxP31BTrMc7pdUdbE7Fma4oH8wpDUKdG3MM"}

View file

@ -446604,3 +446604,33 @@
2025-07-23 22:21:16 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'}
2025-07-23 22:21:16 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200
2025-07-23 22:21:16 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"username":"DuckinthePond","directories":[{"directory":"@@qkrmw\\Music\\Flac Files\\Chart\\Billboard Top 100\\Billboard Top 100 - Hits of 2000-2009\\Billboard Top 100 - Hits of 2006","fileCount":1,"files":[{"id":"1c1afe3d-46fb-4d8a-ba73-1d1af559489c","username":"DuckinthePond","direction":"Download","filename":"@@qkrmw\\Music\\Flac Files\\Chart\\Billboard Top 100\\Billboard Top 100 - Hits of 2000-2009\\Billboard Top 100 - Hits of 2006\\035 - Ludacris feat Pharrell - Money Maker.flac","size":30...
2025-07-23 23:17:01 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG
2025-07-23 23:17:01 - newmusic.main - INFO - main:211 - Starting NewMusic application
2025-07-23 23:17:01 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed)
2025-07-23 23:17:01 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030
2025-07-23 23:17:01 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed)
2025-07-23 23:17:02 - newmusic.main - INFO - change_page:163 - Changed to page: dashboard
2025-07-23 23:17:02 - newmusic.main - INFO - setup_media_player_connections:150 - Media player connections established between sidebar and downloads page
2025-07-23 23:17:02 - newmusic.plex_client - INFO - _find_music_library:116 - Found music library: Music
2025-07-23 23:17:02 - newmusic.plex_client - INFO - _setup_client:102 - Successfully connected to Plex server: PLEX-MACHINE
2025-07-23 23:17:10 - newmusic.main - INFO - change_page:163 - Changed to page: downloads
2025-07-23 23:17:10 - newmusic.main - INFO - change_page:163 - Changed to page: sync
2025-07-23 23:17:10 - newmusic.spotify_client - INFO - _ensure_user_id:195 - Successfully authenticated with Spotify as broquethomas
2025-07-23 23:17:11 - newmusic.spotify_client - INFO - get_user_playlists_metadata_only:256 - Retrieved 7 playlist metadata (first batch)
2025-07-23 23:20:35 - newmusic.main - INFO - closeEvent:176 - Closing application...
2025-07-23 23:20:35 - newmusic.main - INFO - closeEvent:181 - Cleaning up Downloads page threads...
2025-07-23 23:20:35 - newmusic.main - INFO - closeEvent:186 - Stopping status monitoring thread...
2025-07-23 23:20:36 - newmusic.main - INFO - closeEvent:191 - Closing Soulseek client...
2025-07-23 23:20:36 - newmusic.main - INFO - closeEvent:197 - Application closed successfully
2025-07-23 23:20:38 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG
2025-07-23 23:20:38 - newmusic.main - INFO - main:211 - Starting NewMusic application
2025-07-23 23:20:38 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed)
2025-07-23 23:20:38 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030
2025-07-23 23:20:38 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed)
2025-07-23 23:20:39 - newmusic.main - INFO - change_page:163 - Changed to page: dashboard
2025-07-23 23:20:39 - newmusic.main - INFO - setup_media_player_connections:150 - Media player connections established between sidebar and downloads page
2025-07-23 23:20:39 - newmusic.plex_client - INFO - _find_music_library:116 - Found music library: Music
2025-07-23 23:20:39 - newmusic.plex_client - INFO - _setup_client:102 - Successfully connected to Plex server: PLEX-MACHINE
2025-07-23 23:20:52 - newmusic.main - INFO - change_page:163 - Changed to page: sync
2025-07-23 23:20:52 - newmusic.spotify_client - INFO - _ensure_user_id:195 - Successfully authenticated with Spotify as broquethomas
2025-07-23 23:20:52 - newmusic.spotify_client - INFO - get_user_playlists_metadata_only:256 - Retrieved 7 playlist metadata (first batch)

View file

@ -811,7 +811,9 @@ class PlaylistDetailsModal(QDialog):
playlist_item_widget.download_modal = modal
self.parent_page.on_download_process_started(self.playlist.id, playlist_item_widget)
# --- FIX ---
# The call to on_download_process_started has been removed from here
# and moved to the modal's "Begin Search" button.
self.accept()
modal.show()
@ -1425,18 +1427,22 @@ class SyncPage(QWidget):
playlist_item_widget.show_operation_status()
self.refresh_btn.setEnabled(False)
self.refresh_btn.setText("🔄 Working...")
# Connect the finished signal from the modal
playlist_item_widget.download_modal.process_finished.connect(
lambda: self.on_download_process_finished(playlist_id)
)
# --- FIX: Connect the finished signal from the modal ---
# This ensures that when the modal is finished (or cancelled), the cleanup function is called.
if playlist_item_widget.download_modal:
playlist_item_widget.download_modal.process_finished.connect(
lambda: self.on_download_process_finished(playlist_id)
)
def on_download_process_finished(self, playlist_id):
"""Re-enables refresh button if no other downloads are active."""
print(f"Download process finished for playlist: {playlist_id}.")
print(f"Download process finished or cancelled for playlist: {playlist_id}.")
if playlist_id in self.active_download_processes:
playlist_item_widget = self.active_download_processes.pop(playlist_id)
playlist_item_widget.download_modal = None
playlist_item_widget.hide_operation_status()
# --- FIX: Reset the UI state of the playlist item ---
if playlist_item_widget:
playlist_item_widget.download_modal = None
playlist_item_widget.hide_operation_status()
if not self.active_download_processes:
print("All download processes finished. Re-enabling refresh.")
@ -2833,6 +2839,10 @@ class DownloadMissingTracksModal(QDialog):
def on_begin_search_clicked(self):
"""Handle Begin Search button click - starts Plex analysis"""
# --- FIX: Trigger the UI change on the main page ---
# This is the correct point to signal that the process has started.
self.parent_page.on_download_process_started(self.playlist.id, self.playlist_item)
self.begin_search_btn.hide()
self.cancel_btn.show()
self.analysis_progress.setVisible(True)
@ -2840,6 +2850,7 @@ class DownloadMissingTracksModal(QDialog):
self.analysis_progress.setValue(0)
self.download_in_progress = True # Set flag
self.start_plex_analysis()
def start_plex_analysis(self):
"""Start Plex analysis using existing worker"""
@ -3179,24 +3190,66 @@ class DownloadMissingTracksModal(QDialog):
f"Completed downloading {self.successful_downloads}/{len(self.missing_tracks)} missing tracks!")
def on_cancel_clicked(self):
"""Handle Cancel button - cancels operations and closes modal"""
"""Handle Cancel button - cancels operations, emits finished signal, and closes modal."""
# --- FIX: The full cancellation logic is now centralized here. ---
self.cancel_operations()
self.reject()
self.process_finished.emit() # Signal the main page to clean up and reset the button.
self.reject() # Close the modal.
def on_close_clicked(self):
self.reject()
def cancel_operations(self):
"""Cancel any ongoing operations"""
self.cancel_requested = True
"""Cancel any ongoing operations, including active slskd downloads."""
print("🛑 Cancelling all operations for this playlist...")
self.cancel_requested = True # Flag to stop any new workers from starting.
# --- FIX: Actively cancel downloads on the slskd server ---
if self.active_downloads:
print(f"Requesting cancellation for {len(self.active_downloads)} active download(s)...")
import asyncio
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
soulseek_client = self.parent_page.soulseek_client
# Create tasks to cancel all active downloads concurrently
tasks = []
for download_info in self.active_downloads:
download_id = download_info.get('download_id')
# Assumes the soulseek_client has a method to make raw API calls.
# A DELETE request is standard for cancellation in RESTful APIs like slskd's.
if download_id and hasattr(soulseek_client, '_make_request'):
tasks.append(
soulseek_client._make_request('DELETE', f'transfers/downloads/{download_id}')
)
if tasks:
try:
# Wait for all cancellation requests to be sent
loop.run_until_complete(asyncio.gather(*tasks, return_exceptions=True))
print("All cancellation requests sent to slskd.")
except Exception as e:
print(f"An error occurred while sending cancellation requests: {e}")
# Cancel background workers (like the initial Plex analysis)
for worker in self.active_workers:
if hasattr(worker, 'cancel'): worker.cancel()
if hasattr(worker, 'cancel'):
worker.cancel()
self.active_workers.clear()
# Clean up any fallback thread pools
for pool in self.fallback_pools:
pool.waitForDone(1000)
self.fallback_pools.clear()
# Stop the status polling timer to prevent further checks
self.download_status_timer.stop()
print("🛑 All operations cancelled successfully")
print("🛑 Modal operations cancelled successfully.")
def closeEvent(self, event):
"""