mytunes-pro 2.1.0__py3-none-any.whl → 2.1.3__py3-none-any.whl

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.
mytunes/app.py CHANGED
@@ -44,7 +44,7 @@ MPV_SOCKET = "/tmp/mpv_socket"
44
44
  LOG_FILE = "/tmp/mytunes_mpv.log"
45
45
  PID_FILE = "/tmp/mytunes_mpv.pid"
46
46
  APP_NAME = "MyTunes Pro"
47
- APP_VERSION = "2.1.0"
47
+ APP_VERSION = "2.1.3"
48
48
 
49
49
  # Initial Locale Setup for WSL/Windows Multibyte/Emoji Harmony
50
50
  try:
@@ -461,7 +461,9 @@ class Player:
461
461
  # 3. Pre-check: Skip if socket file doesn't exist (e.g. killed elsewhere)
462
462
  if not os.path.exists(MPV_SOCKET):
463
463
  self.socket_fail_count += 1
464
- if self.socket_fail_count >= 2:
464
+ # Be more patient during loading (mpv takes time to create socket)
465
+ threshold = 15 if self.loading else 2
466
+ if self.socket_fail_count >= threshold:
465
467
  self.socket_ok = False
466
468
  self.socket_retry_ts = now + 1.5 # 1.5s cool-down
467
469
  return None
@@ -488,7 +490,8 @@ class Player:
488
490
  return json.loads(response.decode('utf-8'))
489
491
  except:
490
492
  self.socket_fail_count += 1
491
- if self.socket_fail_count >= 2:
493
+ threshold = 15 if self.loading else 2
494
+ if self.socket_fail_count >= threshold:
492
495
  self.socket_ok = False
493
496
  self.socket_retry_ts = now + 1.5 # 1.5s cool-down
494
497
  return None
@@ -678,7 +681,15 @@ class MyTunesApp:
678
681
  def update_playback_state(self):
679
682
  # Poll MPV for state with throttling to reduce CPU/IPC overhead
680
683
  try:
681
- # 0. Health Check: If socket is known-bad, exit immediately to keep TUI responsive
684
+ # A. Safety: If loading takes too long (> 8s), force reset to allow error handling/skip
685
+ # Must check this even if socket_ok is False!
686
+ now = time.time()
687
+ if self.player.loading and (now - self.player.loading_ts > 8):
688
+ self.player.loading = False
689
+ self.player.socket_ok = True # Reset health to try again
690
+ self.show_feedback("⚠️ Load timed out. Skipping...")
691
+
692
+ # B. Health Check: If socket is known-bad, exit immediately to keep TUI responsive
682
693
  if not self.player.socket_ok:
683
694
  return
684
695
 
@@ -700,12 +711,6 @@ class MyTunesApp:
700
711
  self.dm.set_progress(self.current_track['url'], self.playback_time)
701
712
 
702
713
 
703
- # Safety: If loading takes too long (> 8s), force reset to allow error handling/skip
704
- now = time.time()
705
- if self.player.loading and (now - self.player.loading_ts > 8):
706
- self.player.loading = False
707
- self.show_feedback("⚠️ Load timed out. Skipping...")
708
-
709
714
  # 2. Frequent: Pause state (Every 2 loops ~400ms)
710
715
  if self.loop_count % 2 == 0:
711
716
  p = self.player.get_property("pause")
@@ -911,7 +916,10 @@ class MyTunesApp:
911
916
  self.stop_on_exit = False; self.running = False
912
917
 
913
918
  elif cmd == "CYCLE_EQ":
914
- self.cycle_equalizer()
919
+ if IS_WSL:
920
+ self.show_feedback("⚠️ EQ is disabled on WSL for stability" if self.lang=="en" else "⚠️ WSL 안정성을 위해 EQ 기능이 비활성화되었습니다")
921
+ else:
922
+ self.cycle_equalizer()
915
923
 
916
924
  elif isinstance(cmd, tuple) and cmd[0] == "UNKNOWN":
917
925
  key = cmd[1]
@@ -1198,7 +1206,7 @@ class MyTunesApp:
1198
1206
  else:
1199
1207
  start_pos = 0
1200
1208
 
1201
- self.player.play(item['url'], start_pos)
1209
+ self.player.play(item['url'], start_pos, initial_eq_preset=target_eq_preset)
1202
1210
 
1203
1211
  # Re-apply EQ logic (double check: mpv restart wipes af property?)
1204
1212
  # Yes, play() might restart mpv if socket fails.
@@ -1218,10 +1226,6 @@ class MyTunesApp:
1218
1226
  self.playback_time = start_pos
1219
1227
  self.playback_duration = 0
1220
1228
  self.is_paused = False
1221
- self.stdscr.nodelay(False) # Blocking input for dialog
1222
- h, w = self.stdscr.getmaxyx()
1223
- box_h, box_w = 8, 60
1224
- box_y, box_x = (h - box_h) // 2, (w - box_w) // 2
1225
1229
 
1226
1230
  def ask_resume(self, saved_time, track_title):
1227
1231
  self.stdscr.nodelay(False) # Blocking input for dialog
@@ -1665,6 +1669,10 @@ class MyTunesApp:
1665
1669
 
1666
1670
  # Row 2: Actions
1667
1671
  r2 = self.t("header_r2")
1672
+ if IS_WSL:
1673
+ # Remove "[E]이퀄라이저" or "[E]EQ"
1674
+ r2 = r2.replace("[E]이퀄라이저 ", "").replace("[E]이퀄라이저", "").replace("[E]EQ ", "").replace("[E]EQ", "")
1675
+
1668
1676
  gap2 = w - 4 - self.get_display_width(r2)
1669
1677
  if gap2 < 2: gap2 = 2
1670
1678
  line2 = f"{' '*gap2}{r2}"
@@ -1691,17 +1699,15 @@ class MyTunesApp:
1691
1699
  status_icon = "❚❚" if self.is_paused else "▶"
1692
1700
 
1693
1701
  # Prepare EQ Info for Title Line
1694
- current_eq = EQUALIZER_KEYS[self.current_eq_index]
1695
-
1696
- # Show effective EQ with Mode Indicator
1697
- # Auto Mode: "🎚 Auto: Jazz"
1698
- # Manual Mode: "🎚 EQ: Pop"
1699
- if current_eq == "Auto":
1700
- eq_display = f"🎚 Auto: {self.auto_preset_name}"
1701
- else:
1702
- eq_display = f"🎚 EQ: {current_eq}"
1702
+ eq_display = ""
1703
+ if not IS_WSL:
1704
+ current_eq = EQUALIZER_KEYS[self.current_eq_index]
1705
+ if current_eq == "Auto":
1706
+ eq_display = f"🎚 Auto: {self.auto_preset_name}"
1707
+ else:
1708
+ eq_display = f"🎚 EQ: {current_eq}"
1703
1709
 
1704
- eq_info = f" [{eq_display}]" # Right side content
1710
+ eq_info = f" [{eq_display}]" if eq_display else "" # Right side content
1705
1711
 
1706
1712
  # Calculate space for Title
1707
1713
  # Total Width - margins(2) - Icon(2) - Space(1) - EQ Info - Branding(Maybe separate line, but here we just need fit)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mytunes-pro
3
- Version: 2.1.0
3
+ Version: 2.1.3
4
4
  Summary: A lightweight, keyboard-centric terminal player for streaming YouTube music.
5
5
  Author-email: loxo <loxo5432@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/postgresql-co-kr/mytunes
@@ -18,9 +18,9 @@ Requires-Dist: yt-dlp
18
18
  Requires-Dist: pusher
19
19
  Dynamic: license-file
20
20
 
21
- # 🎵 MyTunes Pro - Professional TUI Edition v2.1.0
21
+ # 🎵 MyTunes Pro - Professional TUI Edition v2.1.3
22
22
 
23
- ## 🚀 Terminal-based Media Workflow Experiment v2.1.0
23
+ ## 🚀 Terminal-based Media Workflow Experiment v2.1.3
24
24
 
25
25
  > [!IMPORTANT]
26
26
  > **Legal Disclaimer:** This project is a personal, non-commercial research experiment for developer education.
@@ -390,6 +390,18 @@ Windows 환경에서 한글 검색이 안 되거나 설치가 어려운 분들
390
390
 
391
391
  ## 🔄 Changelog
392
392
 
393
+ ### v2.1.3 (2026-02-02)
394
+ - **Resolved TUI Freeze on Song Launch**: Fixed a critical regression from v2.0.6 where misplaced blocking input code caused the TUI to freeze on "Loading" during song transitions or resume until a key was pressed.
395
+ - **Fixed EQ Application**: Restored correct Auto EQ initialization during `play_music` in `app.py`.
396
+
397
+ ### v2.1.2 (2026-02-02)
398
+ - **Fix "Loading" Stuck**: Improved IPC resilience to prevent the TUI from being stuck on "Loading" during song transitions or resume, by increasing the initial socket connection timeout patience.
399
+ - **Fail-Safe Loading**: Implemented a hard reset for the loading state if mpv takes longer than 8 seconds to respond, ensuring the TUI remains interactive.
400
+
401
+ ### v2.1.1 (2026-02-02)
402
+ - **WSL UI Polish**: Hides Equalizer (EQ) labels and status in the TUI when running on WSL to avoid confusion, as the feature is disabled in that environment for stability.
403
+ - **Improved Feedback**: Provides a clear status message when the 'E' key is pressed on WSL.
404
+
393
405
  ### v2.1.0 (2026-02-02)
394
406
  - **Zero-Freeze IPC Resilience**: Implemented a "Fast-Fail" mechanism that detects mpv process death within 0.1ms via `poll()`, preventing TUI freezes.
395
407
  - **Fail-Early Polling**: Main loop now aborts all remaining IPC property checks immediately if any call fails, maintaining a smooth 5fps even on broken connections.
@@ -0,0 +1,8 @@
1
+ mytunes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ mytunes/app.py,sha256=zvWU5l6DRT3i61bMhRQWFE1-dkahf7FZwGRI-UhdLhg,84436
3
+ mytunes_pro-2.1.3.dist-info/licenses/LICENSE,sha256=lOrP0EIjxcgJia__W3f3PVDZkRd2oRzFkyH2g3LRRCg,1063
4
+ mytunes_pro-2.1.3.dist-info/METADATA,sha256=bpCbf07PEXhVYnaDx1g9bb6GXMJRyuaxmEjm8lrG_3Q,30766
5
+ mytunes_pro-2.1.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
6
+ mytunes_pro-2.1.3.dist-info/entry_points.txt,sha256=6-MsC13nIgzLvrREaGotc32FgxHx_Iuu1z2qCzJs1_4,65
7
+ mytunes_pro-2.1.3.dist-info/top_level.txt,sha256=KWzdFyNNG_sO7GT83-sN5fYArP4_DL5I8HYIwgazXyY,8
8
+ mytunes_pro-2.1.3.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- mytunes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- mytunes/app.py,sha256=h3HseVdqdM03G5AX1TGghi7rs5FVDxBcZeooXSiyd6U,83870
3
- mytunes_pro-2.1.0.dist-info/licenses/LICENSE,sha256=lOrP0EIjxcgJia__W3f3PVDZkRd2oRzFkyH2g3LRRCg,1063
4
- mytunes_pro-2.1.0.dist-info/METADATA,sha256=ieQwUOTyg6pfC2lBY6VHk_GE_-6JgG396xK_8ISh3l4,29755
5
- mytunes_pro-2.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
6
- mytunes_pro-2.1.0.dist-info/entry_points.txt,sha256=6-MsC13nIgzLvrREaGotc32FgxHx_Iuu1z2qCzJs1_4,65
7
- mytunes_pro-2.1.0.dist-info/top_level.txt,sha256=KWzdFyNNG_sO7GT83-sN5fYArP4_DL5I8HYIwgazXyY,8
8
- mytunes_pro-2.1.0.dist-info/RECORD,,