mytunes-pro 2.0.7__tar.gz → 2.1.1__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.
- {mytunes_pro-2.0.7/src/mytunes_pro.egg-info → mytunes_pro-2.1.1}/PKG-INFO +20 -4
- {mytunes_pro-2.0.7 → mytunes_pro-2.1.1}/README.md +19 -3
- {mytunes_pro-2.0.7 → mytunes_pro-2.1.1}/pyproject.toml +1 -1
- {mytunes_pro-2.0.7 → mytunes_pro-2.1.1}/src/mytunes/app.py +100 -31
- {mytunes_pro-2.0.7 → mytunes_pro-2.1.1/src/mytunes_pro.egg-info}/PKG-INFO +20 -4
- {mytunes_pro-2.0.7 → mytunes_pro-2.1.1}/LICENSE +0 -0
- {mytunes_pro-2.0.7 → mytunes_pro-2.1.1}/setup.cfg +0 -0
- {mytunes_pro-2.0.7 → mytunes_pro-2.1.1}/src/mytunes/__init__.py +0 -0
- {mytunes_pro-2.0.7 → mytunes_pro-2.1.1}/src/mytunes_pro.egg-info/SOURCES.txt +0 -0
- {mytunes_pro-2.0.7 → mytunes_pro-2.1.1}/src/mytunes_pro.egg-info/dependency_links.txt +0 -0
- {mytunes_pro-2.0.7 → mytunes_pro-2.1.1}/src/mytunes_pro.egg-info/entry_points.txt +0 -0
- {mytunes_pro-2.0.7 → mytunes_pro-2.1.1}/src/mytunes_pro.egg-info/requires.txt +0 -0
- {mytunes_pro-2.0.7 → mytunes_pro-2.1.1}/src/mytunes_pro.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mytunes-pro
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
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.
|
|
21
|
+
# 🎵 MyTunes Pro - Professional TUI Edition v2.1.1
|
|
22
22
|
|
|
23
|
-
## 🚀 Terminal-based Media Workflow Experiment v2.
|
|
23
|
+
## 🚀 Terminal-based Media Workflow Experiment v2.1.1
|
|
24
24
|
|
|
25
25
|
> [!IMPORTANT]
|
|
26
26
|
> **Legal Disclaimer:** This project is a personal, non-commercial research experiment for developer education.
|
|
@@ -216,7 +216,7 @@ Executes immediately without worrying about input language status.
|
|
|
216
216
|
|
|
217
217
|
# 🎵 MyTunes Pro (Experimental Media Tool - KR)
|
|
218
218
|
|
|
219
|
-
## 🚀 터미널 기반 미디어 워크플로우 실험 v2.0
|
|
219
|
+
## 🚀 터미널 기반 미디어 워크플로우 실험 v2.1.0
|
|
220
220
|
|
|
221
221
|
> [!IMPORTANT]
|
|
222
222
|
> **법적 면책 고지:** 본 프로젝트는 개발자 교육 및 연구를 목적으로 하는 개인적, 비상업적 실험입니다.
|
|
@@ -390,6 +390,22 @@ Windows 환경에서 한글 검색이 안 되거나 설치가 어려운 분들
|
|
|
390
390
|
|
|
391
391
|
## 🔄 Changelog
|
|
392
392
|
|
|
393
|
+
### v2.1.1 (2026-02-02)
|
|
394
|
+
- **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.
|
|
395
|
+
- **Improved Feedback**: Provides a clear status message when the 'E' key is pressed on WSL.
|
|
396
|
+
|
|
397
|
+
### v2.1.0 (2026-02-02)
|
|
398
|
+
- **Zero-Freeze IPC Resilience**: Implemented a "Fast-Fail" mechanism that detects mpv process death within 0.1ms via `poll()`, preventing TUI freezes.
|
|
399
|
+
- **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.
|
|
400
|
+
- **Connection Throttling**: Added a 1.5-second "cool-down" period for reconnection attempts to minimize blocking time on Windows/WSL environments.
|
|
401
|
+
- **Multibyte Harmony**: Explicitly configured `locale.setlocale` to ensure stable emoji and CJK character rendering across different terminal environments.
|
|
402
|
+
- **Improved Autoplay Stability**: Autoplay logic now skips status checks when the socket is unhealthy to prevent feedback loops.
|
|
403
|
+
|
|
404
|
+
### v2.0.8 (2026-02-02)
|
|
405
|
+
- **Windows/WSL Socket Recovery**: Fixed UI freezing when mpv socket disconnects during window switching.
|
|
406
|
+
- **IPC Resilience**: Added socket pre-check and failure counter to prevent blocking on broken connections.
|
|
407
|
+
- **Automatic Recovery**: New playback automatically restarts mpv if socket is unhealthy.
|
|
408
|
+
|
|
393
409
|
### v2.0.7 (2026-02-02)
|
|
394
410
|
- **Performance Optimization**: Improved keyboard responsiveness on Windows/WSL by implementing EQ detection caching.
|
|
395
411
|
- **Data Management**: Limited resume data to 500 entries with automatic FIFO cleanup to prevent JSON bloat.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# 🎵 MyTunes Pro - Professional TUI Edition v2.
|
|
1
|
+
# 🎵 MyTunes Pro - Professional TUI Edition v2.1.1
|
|
2
2
|
|
|
3
|
-
## 🚀 Terminal-based Media Workflow Experiment v2.
|
|
3
|
+
## 🚀 Terminal-based Media Workflow Experiment v2.1.1
|
|
4
4
|
|
|
5
5
|
> [!IMPORTANT]
|
|
6
6
|
> **Legal Disclaimer:** This project is a personal, non-commercial research experiment for developer education.
|
|
@@ -196,7 +196,7 @@ Executes immediately without worrying about input language status.
|
|
|
196
196
|
|
|
197
197
|
# 🎵 MyTunes Pro (Experimental Media Tool - KR)
|
|
198
198
|
|
|
199
|
-
## 🚀 터미널 기반 미디어 워크플로우 실험 v2.0
|
|
199
|
+
## 🚀 터미널 기반 미디어 워크플로우 실험 v2.1.0
|
|
200
200
|
|
|
201
201
|
> [!IMPORTANT]
|
|
202
202
|
> **법적 면책 고지:** 본 프로젝트는 개발자 교육 및 연구를 목적으로 하는 개인적, 비상업적 실험입니다.
|
|
@@ -370,6 +370,22 @@ Windows 환경에서 한글 검색이 안 되거나 설치가 어려운 분들
|
|
|
370
370
|
|
|
371
371
|
## 🔄 Changelog
|
|
372
372
|
|
|
373
|
+
### v2.1.1 (2026-02-02)
|
|
374
|
+
- **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.
|
|
375
|
+
- **Improved Feedback**: Provides a clear status message when the 'E' key is pressed on WSL.
|
|
376
|
+
|
|
377
|
+
### v2.1.0 (2026-02-02)
|
|
378
|
+
- **Zero-Freeze IPC Resilience**: Implemented a "Fast-Fail" mechanism that detects mpv process death within 0.1ms via `poll()`, preventing TUI freezes.
|
|
379
|
+
- **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.
|
|
380
|
+
- **Connection Throttling**: Added a 1.5-second "cool-down" period for reconnection attempts to minimize blocking time on Windows/WSL environments.
|
|
381
|
+
- **Multibyte Harmony**: Explicitly configured `locale.setlocale` to ensure stable emoji and CJK character rendering across different terminal environments.
|
|
382
|
+
- **Improved Autoplay Stability**: Autoplay logic now skips status checks when the socket is unhealthy to prevent feedback loops.
|
|
383
|
+
|
|
384
|
+
### v2.0.8 (2026-02-02)
|
|
385
|
+
- **Windows/WSL Socket Recovery**: Fixed UI freezing when mpv socket disconnects during window switching.
|
|
386
|
+
- **IPC Resilience**: Added socket pre-check and failure counter to prevent blocking on broken connections.
|
|
387
|
+
- **Automatic Recovery**: New playback automatically restarts mpv if socket is unhealthy.
|
|
388
|
+
|
|
373
389
|
### v2.0.7 (2026-02-02)
|
|
374
390
|
- **Performance Optimization**: Improved keyboard responsiveness on Windows/WSL by implementing EQ detection caching.
|
|
375
391
|
- **Data Management**: Limited resume data to 500 entries with automatic FIFO cleanup to prevent JSON bloat.
|
|
@@ -44,7 +44,21 @@ 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.
|
|
47
|
+
APP_VERSION = "2.1.1"
|
|
48
|
+
|
|
49
|
+
# Initial Locale Setup for WSL/Windows Multibyte/Emoji Harmony
|
|
50
|
+
try:
|
|
51
|
+
locale.setlocale(locale.LC_ALL, '')
|
|
52
|
+
except:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
# WSL Detection: EQ/IPC robustness logic
|
|
56
|
+
IS_WSL = False
|
|
57
|
+
if hasattr(os, 'uname'):
|
|
58
|
+
try:
|
|
59
|
+
IS_WSL = "microsoft" in os.uname().release.lower()
|
|
60
|
+
except: pass
|
|
61
|
+
|
|
48
62
|
|
|
49
63
|
# === [Strings & Localization] ===
|
|
50
64
|
STRINGS = {
|
|
@@ -304,6 +318,11 @@ class Player:
|
|
|
304
318
|
self.current_proc = None
|
|
305
319
|
self.loading = False
|
|
306
320
|
self.loading_ts = 0
|
|
321
|
+
self.socket_fail_count = 0 # Track consecutive IPC failures
|
|
322
|
+
self.socket_ok = True # Socket health flag
|
|
323
|
+
self.last_socket_warn = 0 # Rate limit for socket error warnings
|
|
324
|
+
self.socket_retry_ts = 0 # Cool-down for reconnection attempts
|
|
325
|
+
|
|
307
326
|
|
|
308
327
|
# Cleanup pre-existing instance if any
|
|
309
328
|
# self.cleanup_orphaned_mpv() # Moved to play() per user request
|
|
@@ -339,6 +358,9 @@ class Player:
|
|
|
339
358
|
|
|
340
359
|
# 2. Fallback: Clean up and start fresh (Aggressive)
|
|
341
360
|
self.cleanup_orphaned_mpv()
|
|
361
|
+
# Reset socket health for fresh start
|
|
362
|
+
self.socket_fail_count = 0
|
|
363
|
+
self.socket_ok = True
|
|
342
364
|
|
|
343
365
|
self.stop()
|
|
344
366
|
self.loading = True
|
|
@@ -355,10 +377,11 @@ class Player:
|
|
|
355
377
|
"--idle=yes"
|
|
356
378
|
]
|
|
357
379
|
|
|
358
|
-
# Inject Initial EQ (0ms Latency)
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
380
|
+
# Inject Initial EQ (0ms Latency) - Skip on WSL (causes freezing)
|
|
381
|
+
if not IS_WSL:
|
|
382
|
+
eq_af = self._get_eq_af_string(initial_eq_preset)
|
|
383
|
+
if eq_af:
|
|
384
|
+
cmd.append(f"--af={eq_af}")
|
|
362
385
|
|
|
363
386
|
cmd.append(url)
|
|
364
387
|
|
|
@@ -423,10 +446,29 @@ class Player:
|
|
|
423
446
|
self.send_cmd(["add", "volume", delta])
|
|
424
447
|
|
|
425
448
|
def send_cmd(self, command):
|
|
426
|
-
"""Send raw command list to MPV via JSON IPC."""
|
|
449
|
+
"""Send raw command list to MPV via JSON IPC with resilience."""
|
|
450
|
+
# 1. Fast-Detect Process Death
|
|
451
|
+
if self.current_proc and self.current_proc.poll() is not None:
|
|
452
|
+
self.socket_ok = False
|
|
453
|
+
self.current_proc = None
|
|
454
|
+
return None
|
|
455
|
+
|
|
456
|
+
# 2. Re-connection Cool-down (Throttle blocking connect() calls)
|
|
457
|
+
now = time.time()
|
|
458
|
+
if not self.socket_ok and now < self.socket_retry_ts:
|
|
459
|
+
return None
|
|
460
|
+
|
|
461
|
+
# 3. Pre-check: Skip if socket file doesn't exist (e.g. killed elsewhere)
|
|
462
|
+
if not os.path.exists(MPV_SOCKET):
|
|
463
|
+
self.socket_fail_count += 1
|
|
464
|
+
if self.socket_fail_count >= 2:
|
|
465
|
+
self.socket_ok = False
|
|
466
|
+
self.socket_retry_ts = now + 1.5 # 1.5s cool-down
|
|
467
|
+
return None
|
|
468
|
+
|
|
427
469
|
try:
|
|
428
470
|
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
429
|
-
client.settimeout(0.5) # Fast timeout (Optimization for Sleep/Wake resilience)
|
|
471
|
+
client.settimeout(0.5) # Fast timeout (Optimization for Sleep/Wake/WSL resilience)
|
|
430
472
|
client.connect(MPV_SOCKET)
|
|
431
473
|
cmd_str = json.dumps({"command": command}) + "\n"
|
|
432
474
|
client.send(cmd_str.encode('utf-8'))
|
|
@@ -440,17 +482,29 @@ class Player:
|
|
|
440
482
|
if b"\n" in chunk: break
|
|
441
483
|
|
|
442
484
|
client.close()
|
|
485
|
+
# Success: Fully Restore health
|
|
486
|
+
self.socket_fail_count = 0
|
|
487
|
+
self.socket_ok = True
|
|
443
488
|
return json.loads(response.decode('utf-8'))
|
|
444
489
|
except:
|
|
490
|
+
self.socket_fail_count += 1
|
|
491
|
+
if self.socket_fail_count >= 2:
|
|
492
|
+
self.socket_ok = False
|
|
493
|
+
self.socket_retry_ts = now + 1.5 # 1.5s cool-down
|
|
445
494
|
return None
|
|
446
495
|
|
|
447
496
|
def get_property(self, prop):
|
|
497
|
+
"""Skip IPC if health is bad to prevent TUI freezing."""
|
|
498
|
+
if not self.socket_ok:
|
|
499
|
+
return None
|
|
448
500
|
res = self.send_cmd(["get_property", prop])
|
|
449
501
|
if res and "data" in res:
|
|
450
502
|
return res["data"]
|
|
451
503
|
return None
|
|
452
504
|
|
|
453
505
|
def set_property(self, prop, value):
|
|
506
|
+
if not self.socket_ok:
|
|
507
|
+
return
|
|
454
508
|
self.send_cmd(["set_property", prop, value])
|
|
455
509
|
|
|
456
510
|
def toggle_pause(self):
|
|
@@ -476,6 +530,8 @@ class Player:
|
|
|
476
530
|
|
|
477
531
|
def set_equalizer(self, preset_name):
|
|
478
532
|
"""Apply 10-band equalizer preset using lavfi."""
|
|
533
|
+
if IS_WSL:
|
|
534
|
+
return # Skip EQ on WSL (causes freezing)
|
|
479
535
|
af_str = self._get_eq_af_string(preset_name)
|
|
480
536
|
self.set_property("af", af_str)
|
|
481
537
|
|
|
@@ -622,24 +678,29 @@ class MyTunesApp:
|
|
|
622
678
|
def update_playback_state(self):
|
|
623
679
|
# Poll MPV for state with throttling to reduce CPU/IPC overhead
|
|
624
680
|
try:
|
|
681
|
+
# 0. Health Check: If socket is known-bad, exit immediately to keep TUI responsive
|
|
682
|
+
if not self.player.socket_ok:
|
|
683
|
+
return
|
|
684
|
+
|
|
625
685
|
# 1. Mandatory every loop: Current time (for progress bar)
|
|
626
686
|
t = self.player.get_property("time-pos")
|
|
627
|
-
if t is
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
self.player.loading = False
|
|
631
|
-
|
|
632
|
-
# Update Resume Data (Memory) - Throttle save logic
|
|
633
|
-
if self.current_track and self.playback_duration > 30:
|
|
634
|
-
if self.playback_time / self.playback_duration > 0.99:
|
|
635
|
-
self.dm.set_progress(self.current_track['url'], 0)
|
|
636
|
-
elif self.playback_time > 10:
|
|
637
|
-
self.dm.set_progress(self.current_track['url'], self.playback_time)
|
|
687
|
+
if t is None:
|
|
688
|
+
# If even time-pos fails, bail out immediately to prevent cascaded delay
|
|
689
|
+
return
|
|
638
690
|
|
|
691
|
+
self.playback_time = float(t)
|
|
692
|
+
if self.player.loading and self.playback_time >= 0:
|
|
693
|
+
self.player.loading = False
|
|
694
|
+
|
|
695
|
+
# Update Resume Data (Memory) - Throttle save logic
|
|
696
|
+
if self.current_track and self.playback_duration > 30:
|
|
697
|
+
if self.playback_time / self.playback_duration > 0.99:
|
|
698
|
+
self.dm.set_progress(self.current_track['url'], 0)
|
|
699
|
+
elif self.playback_time > 10:
|
|
700
|
+
self.dm.set_progress(self.current_track['url'], self.playback_time)
|
|
639
701
|
|
|
640
702
|
|
|
641
703
|
# Safety: If loading takes too long (> 8s), force reset to allow error handling/skip
|
|
642
|
-
# Consolidated redundancy checks into a single clean block
|
|
643
704
|
now = time.time()
|
|
644
705
|
if self.player.loading and (now - self.player.loading_ts > 8):
|
|
645
706
|
self.player.loading = False
|
|
@@ -669,6 +730,7 @@ class MyTunesApp:
|
|
|
669
730
|
if time.time() - getattr(self, 'last_save_time', 0) > 10:
|
|
670
731
|
self.dm.save_data()
|
|
671
732
|
self.last_save_time = time.time()
|
|
733
|
+
|
|
672
734
|
|
|
673
735
|
except: pass
|
|
674
736
|
|
|
@@ -849,7 +911,10 @@ class MyTunesApp:
|
|
|
849
911
|
self.stop_on_exit = False; self.running = False
|
|
850
912
|
|
|
851
913
|
elif cmd == "CYCLE_EQ":
|
|
852
|
-
|
|
914
|
+
if IS_WSL:
|
|
915
|
+
self.show_feedback("⚠️ EQ is disabled on WSL for stability" if self.lang=="en" else "⚠️ WSL 안정성을 위해 EQ 기능이 비활성화되었습니다")
|
|
916
|
+
else:
|
|
917
|
+
self.cycle_equalizer()
|
|
853
918
|
|
|
854
919
|
elif isinstance(cmd, tuple) and cmd[0] == "UNKNOWN":
|
|
855
920
|
key = cmd[1]
|
|
@@ -1603,6 +1668,10 @@ class MyTunesApp:
|
|
|
1603
1668
|
|
|
1604
1669
|
# Row 2: Actions
|
|
1605
1670
|
r2 = self.t("header_r2")
|
|
1671
|
+
if IS_WSL:
|
|
1672
|
+
# Remove "[E]이퀄라이저" or "[E]EQ"
|
|
1673
|
+
r2 = r2.replace("[E]이퀄라이저 ", "").replace("[E]이퀄라이저", "").replace("[E]EQ ", "").replace("[E]EQ", "")
|
|
1674
|
+
|
|
1606
1675
|
gap2 = w - 4 - self.get_display_width(r2)
|
|
1607
1676
|
if gap2 < 2: gap2 = 2
|
|
1608
1677
|
line2 = f"{' '*gap2}{r2}"
|
|
@@ -1629,17 +1698,15 @@ class MyTunesApp:
|
|
|
1629
1698
|
status_icon = "❚❚" if self.is_paused else "▶"
|
|
1630
1699
|
|
|
1631
1700
|
# Prepare EQ Info for Title Line
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
else:
|
|
1640
|
-
eq_display = f"🎚 EQ: {current_eq}"
|
|
1701
|
+
eq_display = ""
|
|
1702
|
+
if not IS_WSL:
|
|
1703
|
+
current_eq = EQUALIZER_KEYS[self.current_eq_index]
|
|
1704
|
+
if current_eq == "Auto":
|
|
1705
|
+
eq_display = f"🎚 Auto: {self.auto_preset_name}"
|
|
1706
|
+
else:
|
|
1707
|
+
eq_display = f"🎚 EQ: {current_eq}"
|
|
1641
1708
|
|
|
1642
|
-
eq_info = f" [{eq_display}]" # Right side content
|
|
1709
|
+
eq_info = f" [{eq_display}]" if eq_display else "" # Right side content
|
|
1643
1710
|
|
|
1644
1711
|
# Calculate space for Title
|
|
1645
1712
|
# Total Width - margins(2) - Icon(2) - Space(1) - EQ Info - Branding(Maybe separate line, but here we just need fit)
|
|
@@ -1804,8 +1871,10 @@ class MyTunesApp:
|
|
|
1804
1871
|
|
|
1805
1872
|
def check_autoplay(self):
|
|
1806
1873
|
# Auto-play next track from Global Queue
|
|
1807
|
-
|
|
1874
|
+
if not self.running: return
|
|
1808
1875
|
if self.player.loading: return
|
|
1876
|
+
# Logic check: Skip if playback just started or socket is dead to prevent feedback loops
|
|
1877
|
+
if not self.player.socket_ok: return
|
|
1809
1878
|
|
|
1810
1879
|
try:
|
|
1811
1880
|
is_idle = self.player.get_property("idle-active")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mytunes-pro
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
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.
|
|
21
|
+
# 🎵 MyTunes Pro - Professional TUI Edition v2.1.1
|
|
22
22
|
|
|
23
|
-
## 🚀 Terminal-based Media Workflow Experiment v2.
|
|
23
|
+
## 🚀 Terminal-based Media Workflow Experiment v2.1.1
|
|
24
24
|
|
|
25
25
|
> [!IMPORTANT]
|
|
26
26
|
> **Legal Disclaimer:** This project is a personal, non-commercial research experiment for developer education.
|
|
@@ -216,7 +216,7 @@ Executes immediately without worrying about input language status.
|
|
|
216
216
|
|
|
217
217
|
# 🎵 MyTunes Pro (Experimental Media Tool - KR)
|
|
218
218
|
|
|
219
|
-
## 🚀 터미널 기반 미디어 워크플로우 실험 v2.0
|
|
219
|
+
## 🚀 터미널 기반 미디어 워크플로우 실험 v2.1.0
|
|
220
220
|
|
|
221
221
|
> [!IMPORTANT]
|
|
222
222
|
> **법적 면책 고지:** 본 프로젝트는 개발자 교육 및 연구를 목적으로 하는 개인적, 비상업적 실험입니다.
|
|
@@ -390,6 +390,22 @@ Windows 환경에서 한글 검색이 안 되거나 설치가 어려운 분들
|
|
|
390
390
|
|
|
391
391
|
## 🔄 Changelog
|
|
392
392
|
|
|
393
|
+
### v2.1.1 (2026-02-02)
|
|
394
|
+
- **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.
|
|
395
|
+
- **Improved Feedback**: Provides a clear status message when the 'E' key is pressed on WSL.
|
|
396
|
+
|
|
397
|
+
### v2.1.0 (2026-02-02)
|
|
398
|
+
- **Zero-Freeze IPC Resilience**: Implemented a "Fast-Fail" mechanism that detects mpv process death within 0.1ms via `poll()`, preventing TUI freezes.
|
|
399
|
+
- **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.
|
|
400
|
+
- **Connection Throttling**: Added a 1.5-second "cool-down" period for reconnection attempts to minimize blocking time on Windows/WSL environments.
|
|
401
|
+
- **Multibyte Harmony**: Explicitly configured `locale.setlocale` to ensure stable emoji and CJK character rendering across different terminal environments.
|
|
402
|
+
- **Improved Autoplay Stability**: Autoplay logic now skips status checks when the socket is unhealthy to prevent feedback loops.
|
|
403
|
+
|
|
404
|
+
### v2.0.8 (2026-02-02)
|
|
405
|
+
- **Windows/WSL Socket Recovery**: Fixed UI freezing when mpv socket disconnects during window switching.
|
|
406
|
+
- **IPC Resilience**: Added socket pre-check and failure counter to prevent blocking on broken connections.
|
|
407
|
+
- **Automatic Recovery**: New playback automatically restarts mpv if socket is unhealthy.
|
|
408
|
+
|
|
393
409
|
### v2.0.7 (2026-02-02)
|
|
394
410
|
- **Performance Optimization**: Improved keyboard responsiveness on Windows/WSL by implementing EQ detection caching.
|
|
395
411
|
- **Data Management**: Limited resume data to 500 entries with automatic FIFO cleanup to prevent JSON bloat.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|