spolyrics 1.2.2__tar.gz → 1.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {spolyrics-1.2.2/spolyrics.egg-info → spolyrics-1.2.4}/PKG-INFO +1 -1
- {spolyrics-1.2.2 → spolyrics-1.2.4}/main.py +63 -24
- {spolyrics-1.2.2 → spolyrics-1.2.4}/setup.py +1 -1
- {spolyrics-1.2.2 → spolyrics-1.2.4/spolyrics.egg-info}/PKG-INFO +1 -1
- {spolyrics-1.2.2 → spolyrics-1.2.4}/LICENSE +0 -0
- {spolyrics-1.2.2 → spolyrics-1.2.4}/README.md +0 -0
- {spolyrics-1.2.2 → spolyrics-1.2.4}/assets.py +0 -0
- {spolyrics-1.2.2 → spolyrics-1.2.4}/setup.cfg +0 -0
- {spolyrics-1.2.2 → spolyrics-1.2.4}/spolyrics.egg-info/SOURCES.txt +0 -0
- {spolyrics-1.2.2 → spolyrics-1.2.4}/spolyrics.egg-info/dependency_links.txt +0 -0
- {spolyrics-1.2.2 → spolyrics-1.2.4}/spolyrics.egg-info/entry_points.txt +0 -0
- {spolyrics-1.2.2 → spolyrics-1.2.4}/spolyrics.egg-info/requires.txt +0 -0
- {spolyrics-1.2.2 → spolyrics-1.2.4}/spolyrics.egg-info/top_level.txt +0 -0
|
@@ -15,7 +15,7 @@ from assets import ICON_B64
|
|
|
15
15
|
from tkinter import messagebox
|
|
16
16
|
from winsdk.windows.media.control import GlobalSystemMediaTransportControlsSessionManager as MediaManager
|
|
17
17
|
|
|
18
|
-
CURRENT_VERSION = "1.2.
|
|
18
|
+
CURRENT_VERSION = "1.2.4"
|
|
19
19
|
CONFIG_PATH = os.path.join(os.environ.get("APPDATA", ""), "SpoLyrics", "config.json")
|
|
20
20
|
APP_DIR = os.path.join(os.environ.get("APPDATA", ""), "SpoLyrics")
|
|
21
21
|
os.makedirs(APP_DIR, exist_ok=True)
|
|
@@ -94,6 +94,10 @@ def get_exe_path():
|
|
|
94
94
|
script_exe = os.path.join(sys.prefix, 'Scripts', 'spolyrics.exe')
|
|
95
95
|
if os.path.exists(script_exe):
|
|
96
96
|
return script_exe
|
|
97
|
+
|
|
98
|
+
pythonw = os.path.join(sys.prefix, 'pythonw.exe')
|
|
99
|
+
if os.path.exists(pythonw):
|
|
100
|
+
return (pythonw, os.path.abspath(__file__))
|
|
97
101
|
return sys.executable
|
|
98
102
|
|
|
99
103
|
def set_auto_start(enable, force_update=False):
|
|
@@ -104,7 +108,11 @@ def set_auto_start(enable, force_update=False):
|
|
|
104
108
|
exe_path = get_exe_path()
|
|
105
109
|
if exe_path and os.path.exists(icon_path):
|
|
106
110
|
if force_update or not os.path.exists(STARTUP_SHORTCUT):
|
|
107
|
-
|
|
111
|
+
if isinstance(exe_path, tuple):
|
|
112
|
+
target, args = exe_path
|
|
113
|
+
ps_script = f"$s=(New-Object -COM WScript.Shell).CreateShortcut('{STARTUP_SHORTCUT}');$s.TargetPath='{target}';$s.Arguments='\"{args}\"';$s.IconLocation='{icon_path}';$s.Save()"
|
|
114
|
+
else:
|
|
115
|
+
ps_script = f"$s=(New-Object -COM WScript.Shell).CreateShortcut('{STARTUP_SHORTCUT}');$s.TargetPath='{exe_path}';$s.IconLocation='{icon_path}';$s.Save()"
|
|
108
116
|
subprocess.run(["powershell", "-Command", ps_script], creationflags=0x08000000)
|
|
109
117
|
else:
|
|
110
118
|
if os.path.exists(STARTUP_SHORTCUT):
|
|
@@ -186,6 +194,20 @@ class MiniLyrics:
|
|
|
186
194
|
self.render_lyrics()
|
|
187
195
|
threading.Thread(target=self.poll_song, daemon=True).start()
|
|
188
196
|
|
|
197
|
+
def get_tray_menu(self):
|
|
198
|
+
import pystray
|
|
199
|
+
items = [
|
|
200
|
+
pystray.MenuItem("Shortcuts & Info", self.tray_callbacks['on_info']),
|
|
201
|
+
pystray.MenuItem("Settings", self.tray_callbacks['on_settings']),
|
|
202
|
+
pystray.MenuItem("Toggle Visibility", self.tray_callbacks['on_toggle_lyrics']),
|
|
203
|
+
pystray.MenuItem("Quit", self.tray_callbacks['on_quit']),
|
|
204
|
+
pystray.MenuItem(f"v{CURRENT_VERSION}", lambda: None, enabled=False)
|
|
205
|
+
]
|
|
206
|
+
if getattr(self, 'update_available', False):
|
|
207
|
+
items.insert(0, pystray.MenuItem("🔥 Update Available!", lambda: self.root.after(0, self.prompt_update)))
|
|
208
|
+
return pystray.Menu(*items)
|
|
209
|
+
|
|
210
|
+
|
|
189
211
|
def render_lyrics(self):
|
|
190
212
|
if self.synced_lyrics:
|
|
191
213
|
pos = self.base_pos
|
|
@@ -769,21 +791,31 @@ class MiniLyrics:
|
|
|
769
791
|
def show_update_prompt(self, latest):
|
|
770
792
|
self.update_available = latest
|
|
771
793
|
if getattr(self, 'tray_icon', None):
|
|
772
|
-
self.tray_icon.
|
|
794
|
+
self.tray_icon.menu = self.get_tray_menu()
|
|
773
795
|
|
|
774
796
|
res = messagebox.askyesno("Update Available", f"A new version of SpoLyrics (v{latest}) is available!\n\nYou are currently on v{CURRENT_VERSION}.\nWould you like to update now?")
|
|
775
797
|
if res:
|
|
776
798
|
import tempfile
|
|
777
799
|
bat_path = os.path.join(tempfile.gettempdir(), "update_spolyrics.bat")
|
|
778
800
|
exe_path = get_exe_path()
|
|
801
|
+
|
|
802
|
+
# Extract arguments if get_exe_path returns pythonw.exe + main.py
|
|
803
|
+
exe_cmd = f'"{exe_path}"'
|
|
804
|
+
if isinstance(exe_path, tuple):
|
|
805
|
+
exe_cmd = f'"{exe_path[0]}" "{exe_path[1]}"'
|
|
806
|
+
|
|
779
807
|
with open(bat_path, 'w') as f:
|
|
780
808
|
f.write('@echo off\n')
|
|
781
809
|
f.write('echo Updating SpoLyrics...\n')
|
|
782
810
|
f.write('ping 127.0.0.1 -n 3 > nul\n')
|
|
783
|
-
|
|
784
|
-
f.write(f'
|
|
811
|
+
import sys
|
|
812
|
+
f.write(f'"{sys.executable}" -m pip install --upgrade --no-cache-dir spolyrics\n')
|
|
813
|
+
f.write(f'start "" {exe_cmd}\n')
|
|
785
814
|
f.write('del "%~f0"\n')
|
|
786
|
-
|
|
815
|
+
|
|
816
|
+
# Run bat silently without creating a window
|
|
817
|
+
import subprocess
|
|
818
|
+
subprocess.Popen(['cmd.exe', '/c', bat_path], creationflags=0x08000000)
|
|
787
819
|
if getattr(self, 'tray_icon', None):
|
|
788
820
|
self.tray_icon.stop()
|
|
789
821
|
self.root.quit()
|
|
@@ -815,15 +847,19 @@ def create_shortcut():
|
|
|
815
847
|
with open(path_file, 'r') as f:
|
|
816
848
|
saved_path = f.read().strip()
|
|
817
849
|
|
|
818
|
-
if saved_path != exe_path:
|
|
850
|
+
if saved_path != str(exe_path):
|
|
819
851
|
needs_update = True
|
|
820
852
|
path_changed = True
|
|
821
853
|
with open(path_file, 'w') as f:
|
|
822
|
-
f.write(exe_path)
|
|
854
|
+
f.write(str(exe_path))
|
|
823
855
|
|
|
824
856
|
if needs_update:
|
|
825
857
|
if exe_path:
|
|
826
|
-
|
|
858
|
+
if isinstance(exe_path, tuple):
|
|
859
|
+
target, args = exe_path
|
|
860
|
+
ps_script = f"$s=(New-Object -COM WScript.Shell).CreateShortcut('{shortcut_path}');$s.TargetPath='{target}';$s.Arguments='\"{args}\"';$s.IconLocation='{icon_path}';$s.Save()"
|
|
861
|
+
else:
|
|
862
|
+
ps_script = f"$s=(New-Object -COM WScript.Shell).CreateShortcut('{shortcut_path}');$s.TargetPath='{exe_path}';$s.IconLocation='{icon_path}';$s.Save()"
|
|
827
863
|
subprocess.run(["powershell", "-Command", ps_script], creationflags=0x08000000)
|
|
828
864
|
except Exception as e:
|
|
829
865
|
logging.error("Failed to create shortcut", exc_info=e)
|
|
@@ -835,8 +871,7 @@ def setup_tray(app):
|
|
|
835
871
|
from PIL import Image
|
|
836
872
|
|
|
837
873
|
def on_quit(icon, item):
|
|
838
|
-
|
|
839
|
-
app.root.quit()
|
|
874
|
+
app.root.after(0, app.root.quit)
|
|
840
875
|
|
|
841
876
|
def on_settings(icon, item):
|
|
842
877
|
app.root.after(0, app.open_settings)
|
|
@@ -856,19 +891,23 @@ def setup_tray(app):
|
|
|
856
891
|
logging.error("Failed to open tray icon image, using fallback", exc_info=e)
|
|
857
892
|
image = Image.new('RGB', (64, 64), color = (29, 185, 84))
|
|
858
893
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
894
|
+
app.tray_callbacks = {
|
|
895
|
+
'on_quit': on_quit,
|
|
896
|
+
'on_settings': on_settings,
|
|
897
|
+
'on_toggle_lyrics': on_toggle_lyrics,
|
|
898
|
+
'on_info': on_info
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
app_dir = os.path.join(os.environ.get("APPDATA", ""), "SpoLyrics")
|
|
902
|
+
icon_path = os.path.join(app_dir, 'icon.ico')
|
|
903
|
+
|
|
904
|
+
try:
|
|
905
|
+
image = Image.open(icon_path)
|
|
906
|
+
except Exception as e:
|
|
907
|
+
logging.error("Failed to open tray icon image, using fallback", exc_info=e)
|
|
908
|
+
image = Image.new('RGB', (64, 64), color = (29, 185, 84))
|
|
909
|
+
|
|
910
|
+
icon = pystray.Icon("SpoLyrics", image, "SpoLyrics", menu=app.get_tray_menu())
|
|
872
911
|
app.tray_icon = icon
|
|
873
912
|
threading.Thread(target=icon.run, daemon=True).start()
|
|
874
913
|
except Exception as e:
|
|
@@ -2,7 +2,7 @@ from setuptools import setup
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name='spolyrics',
|
|
5
|
-
version='1.2.
|
|
5
|
+
version='1.2.4',
|
|
6
6
|
description='A minimalist, borderless, zero-delay synced lyrics miniplayer for Spotify on Windows.',
|
|
7
7
|
long_description=open('README.md', 'r', encoding='utf-8').read(),
|
|
8
8
|
long_description_content_type='text/markdown',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|