From c770801af794615d0e294de609e9d5731a396b94 Mon Sep 17 00:00:00 2001 From: Justin Donofrio Date: Sun, 10 Nov 2024 20:20:39 -0500 Subject: [PATCH] Add back 'Mirror Spotify Playback' and minor tweaks to the ui --- src/onthespot/api/spotify.py | 80 +++++++++++++++++++++++- src/onthespot/downloader.py | 2 +- src/onthespot/gui/mainui.py | 17 +++-- src/onthespot/gui/qtui/main.ui | 73 ++++++++++++++++++--- src/onthespot/gui/settings.py | 2 + src/onthespot/otsconfig.py | 1 + src/onthespot/resources/themes/dark.qss | 3 - src/onthespot/resources/themes/light.qss | 3 - 8 files changed, 161 insertions(+), 20 deletions(-) diff --git a/src/onthespot/api/spotify.py b/src/onthespot/api/spotify.py index b73302a..22ef21e 100644 --- a/src/onthespot/api/spotify.py +++ b/src/onthespot/api/spotify.py @@ -3,17 +3,95 @@ import time import uuid import json +import threading import requests from librespot.audio.decoders import AudioQuality from librespot.core import Session from librespot.zeroconf import ZeroconfServer +from PyQt6.QtCore import QObject from ..otsconfig import config, cache_dir -from ..runtimedata import get_logger, account_pool +from ..runtimedata import get_logger, account_pool, pending, download_queue from ..utils import make_call, conv_list_format logger = get_logger("api.spotify") +class MirrorSpotifyPlayback(QObject): + def __init__(self): + super().__init__() + self.thread = None + self.is_running = False + + def start(self): + if self.thread is None: + logger.info('Starting SpotifyMirrorPlayback') + self.is_running = True + self.thread = threading.Thread(target=self.run) + self.thread.start() + else: + logger.warning('SpotifyMirrorPlayback is already running.') + + def stop(self): + if self.thread is not None: + logger.info('Stopping SpotifyMirrorPlayback') + self.is_running = False + self.thread.join() + self.thread = None + else: + logger.warning('SpotifyMirrorPlayback is not running.') + + def run(self): + while self.is_running: + time.sleep(3) + try: + parsing_index = config.get('parsing_acc_sn') + if account_pool[parsing_index]['service'] != 'spotify': + continue + token = account_pool[parsing_index]['login']['session'].tokens().get("user-read-currently-playing") + except IndexError: + time.sleep(2) + continue + except Exception: + spotify_re_init_session(account_pool[parsing_index]) + token = account_pool[parsing_index]['login']['session'].tokens().get("user-read-currently-playing") + url = "https://api.spotify.com/v1/me/player/currently-playing" + resp = requests.get(url, headers={"Authorization": f"Bearer {token}"}) + if resp.status_code == 200: + data = resp.json() + if data['currently_playing_type'] == 'track': + item_id = data['item']['id'] + if item_id not in pending and item_id not in download_queue: + parent_category = 'track' + playlist_name = '' + playlist_by = '' + if data['context']['type'] == 'playlist': + token = account_pool[parsing_index]['login']['session'].tokens().get("user-read-email") + playlist_name, playlist_by = spotify_get_playlist_data(token, data['item']['id']) + parent_category = 'playlist' + elif data['context']['type'] == 'collection': + playlist_name = 'Liked Songs' + playlist_by = 'me' + parent_category = 'playlist' + elif data['context']['type'] in ('album', 'artist'): + parent_category = 'album' + + pending[item_id] = { + 'item_service': 'spotify', + 'item_type': 'track', + 'item_id': item_id, + 'parent_category': parent_category, + 'playlist_name': playlist_name, + 'playlist_by': playlist_by + } + logger.info(f'Mirror Spotify Playback added track to download queue: https://open.spotify.com/track/{item_id}') + continue + else: + logger.info('Spotify API does not return enough data to parse currently playing episodes.') + continue + else: + continue + + def spotify_new_session(): os.makedirs(os.path.join(cache_dir(), 'onthespot', 'sessions'), exist_ok=True) diff --git a/src/onthespot/downloader.py b/src/onthespot/downloader.py index c3cf6dc..4928701 100644 --- a/src/onthespot/downloader.py +++ b/src/onthespot/downloader.py @@ -28,7 +28,7 @@ def __init__(self, gui=False): self.is_running = True def start(self): - self.thread.start() # Start the thread + self.thread.start() def readd_item_to_download_queue(self, item): diff --git a/src/onthespot/gui/mainui.py b/src/onthespot/gui/mainui.py index b45ce04..ec3a723 100644 --- a/src/onthespot/gui/mainui.py +++ b/src/onthespot/gui/mainui.py @@ -12,7 +12,7 @@ from ..otsconfig import config from ..runtimedata import get_logger, parsing, pending, download_queue, account_pool, download_queue_lock from .thumb_listitem import LabelWithThumb -from ..api.spotify import spotify_get_token, spotify_get_track_metadata, spotify_get_episode_metadata, spotify_new_session +from ..api.spotify import spotify_get_token, spotify_get_track_metadata, spotify_get_episode_metadata, spotify_new_session, MirrorSpotifyPlayback from ..api.soundcloud import soundcloud_get_token, soundcloud_get_track_metadata from ..api.deezer import deezer_get_track_metadata, deezer_add_account from ..accounts import get_account_token, FillAccountPool @@ -68,7 +68,6 @@ def __init__(self, _dialog, start_url=''): # Bind button click self.bind_button_inputs() - self.__users = [] self.last_search = None @@ -84,7 +83,6 @@ def __init__(self, _dialog, start_url=''): fillaccountpool.progress.connect(self.__show_popup_dialog) fillaccountpool.start() - queueworker = QueueWorker() queueworker.add_item_to_download_list.connect(self.add_item_to_download_list) # Connect signal to update_table method queueworker.start() @@ -93,6 +91,10 @@ def __init__(self, _dialog, start_url=''): downloadworker.progress.connect(self.update_item_in_download_list) # Connect the signal to the update method downloadworker.start() # Start the download worker thread + self.mirrorplayback = MirrorSpotifyPlayback() + if config.get('mirror_spotify_playback'): + self.mirrorplayback.start() + # Set application theme self.toggle_theme_button.clicked.connect(self.toggle_theme) self.theme = config.get("theme") @@ -176,6 +178,8 @@ def bind_button_inputs(self): self.inp_download_queue_show_unavailable.stateChanged.connect(self.update_table_visibility) self.inp_download_queue_show_completed.stateChanged.connect(self.update_table_visibility) + self.inp_mirror_spotify_playback.stateChanged.connect(self.manage_mirror_spotify_playback) + def set_table_props(self): window_width = self.width() logger.info(f"Setting table item properties {window_width}") @@ -216,7 +220,6 @@ def set_table_props(self): self.set_login_fields() return True - def reset_app_config(self): config.rollback() self.__show_popup_dialog("The application setting was cleared successfully !\n Please restart the application.") @@ -716,3 +719,9 @@ def update_table_visibility(self): self.tbl_dl_progress.hideRow(row) # Hide the row else: self.tbl_dl_progress.showRow(row) # Show the row if the status is allowed + + def manage_mirror_spotify_playback(self): + if self.inp_mirror_spotify_playback.isChecked(): + self.mirrorplayback.start() + else: + self.mirrorplayback.stop() diff --git a/src/onthespot/gui/qtui/main.ui b/src/onthespot/gui/qtui/main.ui index 21bf298..4a2c213 100644 --- a/src/onthespot/gui/qtui/main.ui +++ b/src/onthespot/gui/qtui/main.ui @@ -21,7 +21,7 @@ ../../resources/icon.png../../resources/icon.png - + QGroupBox #group_login_form_3, #gb0_0, #gb0_1, #gb0_2, #gb0_3, #gb0_4, #gb0_5, #gb1_0, #gb1_1, #gb1_2, #gb1_3, #gb1_4, #gb1_5, #gb1_6, #gb1_7, #gb1_8, #gb1_9, #gb1_10, #gb1_11, #gb1_12, #gb1_13, #gb2_0, #gb2_1, #gb2_2, #gb2_3, #gb2_4, #gb2_5, #gb2_6, #gb2_7, #gb2_8, #gb2_9, #gb2_10, #gb2_11, #gb2_12, #gb2_13, #gb2_14, #gb2_15, #gb2_16, #gb2_17 { border: 0;} @@ -656,9 +656,9 @@ 0 - -1158 - 630 - 3263 + 0 + 627 + 3010 @@ -1251,6 +1251,50 @@ + + + + + + + + + + Qt::RightToLeft + + + Mirror Spotify Playback + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + true + + @@ -1286,6 +1330,19 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -1776,7 +1833,7 @@ - + @@ -1911,7 +1968,7 @@ - + @@ -2019,7 +2076,7 @@ - + @@ -2124,7 +2181,7 @@ - + diff --git a/src/onthespot/gui/settings.py b/src/onthespot/gui/settings.py index 03df0f2..78632d8 100644 --- a/src/onthespot/gui/settings.py +++ b/src/onthespot/gui/settings.py @@ -120,6 +120,7 @@ def load_config(self): self.inp_embed_loudness.setChecked(config.get('embed_loudness')) self.inp_embed_speechiness.setChecked(config.get('embed_speechiness')) self.inp_embed_valence.setChecked(config.get('embed_valence')) + self.inp_mirror_spotify_playback.setChecked(config.get('mirror_spotify_playback')) def save_config(self): # Missing Theme @@ -200,4 +201,5 @@ def save_config(self): config.set_('embed_loudness', self.inp_embed_loudness.isChecked()) config.set_('embed_speechiness', self.inp_embed_speechiness.isChecked()) config.set_('embed_valence', self.inp_embed_valence.isChecked()) + config.set_('mirror_spotify_playback', self.inp_mirror_spotify_playback.isChecked()) config.update() diff --git a/src/onthespot/otsconfig.py b/src/onthespot/otsconfig.py index efbdeb3..8fc1e36 100755 --- a/src/onthespot/otsconfig.py +++ b/src/onthespot/otsconfig.py @@ -79,6 +79,7 @@ def __init__(self, cfg_path=None): "explicit_label": "🅴", # Explicit label in app and download path "search_thumb_height": 60, # Thumbnail height ( they are of equal width and height ) "metadata_seperator": "; ", # Seperator used for metadata fields that have multiple values + "mirror_spotify_playback": False, # Mirror spotify playback "embed_branding": False, "embed_cover": True, "embed_artist": True, diff --git a/src/onthespot/resources/themes/dark.qss b/src/onthespot/resources/themes/dark.qss index 8745c64..e97c1f1 100644 --- a/src/onthespot/resources/themes/dark.qss +++ b/src/onthespot/resources/themes/dark.qss @@ -7,9 +7,6 @@ QWidget:item:selected background-color: #2596BE; color: #fff; } -QGroupBox #gb0_0, #gb0_1, #gb0_2, #gb0_3, #gb1_0, #gb1_1, #gb1_2, #gb1_3, #gb1_4, #gb1_5, #gb1_6, #gb1_7, #gb1_8, #gb1_9, #gb2_0, #gb2_1, #gb2_2, #gb2_3, #gb2_4, #gb2_5, #gb2_6, #gb2_7, #gb2_8, #gb2_9, #gb2_10, #gb2_11, #gb2_12, #gb2_13, #gb2_14, #gb2_15, #gb2_16, #gb_17 { - border: 0; -} QToolTip { background-color: #282828; color: #fff; diff --git a/src/onthespot/resources/themes/light.qss b/src/onthespot/resources/themes/light.qss index 9035918..59da6bb 100644 --- a/src/onthespot/resources/themes/light.qss +++ b/src/onthespot/resources/themes/light.qss @@ -7,9 +7,6 @@ QWidget:item:selected background-color: #81D4FA; color: #000; } -QGroupBox #gb0_0, #gb0_1, #gb0_2, #gb0_3, #gb1_0, #gb1_1, #gb1_2, #gb1_3, #gb1_4, #gb1_5, #gb1_6, #gb1_7, #gb1_8, #gb1_9, #gb2_0, #gb2_1, #gb2_2, #gb2_3, #gb2_4, #gb2_5, #gb2_6, #gb2_7, #gb2_8, #gb2_9, #gb2_10, #gb2_11, #gb2_12, #gb2_13, #gb2_14, #gb2_15, #gb2_16, #gb2_17 { - border: 0; -} QToolTip { background-color: #fff; color: #000;