mytunes-pro 2.0.3__py3-none-any.whl → 2.0.5__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 +61 -52
- {mytunes_pro-2.0.3.dist-info → mytunes_pro-2.0.5.dist-info}/METADATA +60 -113
- mytunes_pro-2.0.5.dist-info/RECORD +8 -0
- mytunes_pro-2.0.3.dist-info/RECORD +0 -8
- {mytunes_pro-2.0.3.dist-info → mytunes_pro-2.0.5.dist-info}/WHEEL +0 -0
- {mytunes_pro-2.0.3.dist-info → mytunes_pro-2.0.5.dist-info}/entry_points.txt +0 -0
- {mytunes_pro-2.0.3.dist-info → mytunes_pro-2.0.5.dist-info}/licenses/LICENSE +0 -0
- {mytunes_pro-2.0.3.dist-info → mytunes_pro-2.0.5.dist-info}/top_level.txt +0 -0
mytunes/app.py
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""
|
|
3
3
|
MyTunes Pro - Professional TUI Edition v1.0
|
|
4
|
-
Premium CLI
|
|
4
|
+
# Premium CLI Media Workflow Experiment with Curses Interface
|
|
5
5
|
Enhanced with Context7-researched MPV IPC & Resize Handling
|
|
6
6
|
"""
|
|
7
|
+
import warnings
|
|
8
|
+
# Suppress urllib3 NotOpenSSLWarning (LibreSSL compatibility)
|
|
9
|
+
# This must be defined before ANY imports that might trigger urllib3
|
|
10
|
+
warnings.filterwarnings("ignore", message=".*urllib3 v2 only supports OpenSSL 1.1.1+.*")
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
import urllib3
|
|
14
|
+
# Optional: also ignore by category if already imported
|
|
15
|
+
from urllib3.exceptions import NotOpenSSLWarning
|
|
16
|
+
warnings.filterwarnings("ignore", category=NotOpenSSLWarning)
|
|
17
|
+
except: pass
|
|
18
|
+
|
|
7
19
|
import curses
|
|
8
20
|
import curses.textpad
|
|
9
21
|
import json
|
|
@@ -32,7 +44,7 @@ MPV_SOCKET = "/tmp/mpv_socket"
|
|
|
32
44
|
LOG_FILE = "/tmp/mytunes_mpv.log"
|
|
33
45
|
PID_FILE = "/tmp/mytunes_mpv.pid"
|
|
34
46
|
APP_NAME = "MyTunes Pro"
|
|
35
|
-
APP_VERSION = "2.0.
|
|
47
|
+
APP_VERSION = "2.0.5"
|
|
36
48
|
|
|
37
49
|
# === [Strings & Localization] ===
|
|
38
50
|
STRINGS = {
|
|
@@ -52,10 +64,10 @@ STRINGS = {
|
|
|
52
64
|
"fav_added": "★ 즐겨찾기에 추가됨",
|
|
53
65
|
"fav_removed": "☆ 즐겨찾기 해제됨",
|
|
54
66
|
"header_r1": "[S/1]검색 [F/2]즐겨찾기 [R/3]기록 [M/4]메인 [A/5]즐겨찾기추가 [Q/6]뒤로",
|
|
55
|
-
"header_r2": "[F7]유튜브 [
|
|
56
|
-
"help_guide": "[j/k]이동 [En]선택 [h/q]뒤로 [S/1]검색 [F/2]즐겨찾기 [R/3]기록 [M/4]메인 [F7]유튜브
|
|
67
|
+
"header_r2": "[F7]유튜브 [SPC]Play/Stop [+/-]볼륨 [<>]빨리감기 [D/Del]삭제",
|
|
68
|
+
"help_guide": "[j/k]이동 [En]선택 [h/q]뒤로 [S/1]검색 [F/2]즐겨찾기 [R/3]기록 [M/4]메인 [F7]유튜브",
|
|
57
69
|
"menu_main": "☰ 메인 메뉴",
|
|
58
|
-
"menu_search_results": "⌕
|
|
70
|
+
"menu_search_results": "⌕ 미디어 콘텐츠 검색",
|
|
59
71
|
"menu_favorites": "★ 나의 즐겨찾기",
|
|
60
72
|
"menu_history": "◷ 재생 기록",
|
|
61
73
|
"menu_bg_play": "⧉ 백그라운드 재생 (나가기)",
|
|
@@ -63,7 +75,9 @@ STRINGS = {
|
|
|
63
75
|
"favorites_info": "즐겨찾기 저장 위치: {}",
|
|
64
76
|
"hist_info": "최근 재생 기록 (최대 100곡)",
|
|
65
77
|
"time_fmt": "{}/{}",
|
|
66
|
-
"vol_fmt": "볼륨: {}%"
|
|
78
|
+
"vol_fmt": "볼륨: {}%",
|
|
79
|
+
"ime_warning": "영문 모드로 전환 후 단축키를 눌러주세요.",
|
|
80
|
+
"invalid_key": "잘못된 키 입력: '{}'"
|
|
67
81
|
},
|
|
68
82
|
"en": {
|
|
69
83
|
"title": "MyTunes Pro v{}",
|
|
@@ -81,10 +95,10 @@ STRINGS = {
|
|
|
81
95
|
"fav_added": "★ Added to Favorites",
|
|
82
96
|
"fav_removed": "☆ Removed from Favorites",
|
|
83
97
|
"header_r1": "[S/1]Srch [F/2]Favs [R/3]Hist [M/4]Main [A/5]AddFav [Q/6]Back",
|
|
84
|
-
"header_r2": "[F7]YT [
|
|
85
|
-
"help_guide": "[j/k]Move [En]Select [h/q]Back [S/1]Srch [F/2]Fav [R/3]Hist [M/4]Main [F7]YT
|
|
98
|
+
"header_r2": "[F7]YT [SPC]Play/Stop [+/-]Vol [<>]Seek [D/Del]Del",
|
|
99
|
+
"help_guide": "[j/k]Move [En]Select [h/q]Back [S/1]Srch [F/2]Fav [R/3]Hist [M/4]Main [F7]YT",
|
|
86
100
|
"menu_main": "☰ Main Menu",
|
|
87
|
-
"menu_search_results": "⌕ Search
|
|
101
|
+
"menu_search_results": "⌕ Search Media Content",
|
|
88
102
|
"menu_favorites": "★ My Favorites",
|
|
89
103
|
"menu_history": "◷ History",
|
|
90
104
|
"menu_bg_play": "⧉ Background Play (Leave)",
|
|
@@ -92,7 +106,9 @@ STRINGS = {
|
|
|
92
106
|
"favorites_info": "Favorites stored at: {}",
|
|
93
107
|
"hist_info": "Recent Playback History (Max 100)",
|
|
94
108
|
"time_fmt": "{}/{}",
|
|
95
|
-
"vol_fmt": "Vol: {}%"
|
|
109
|
+
"vol_fmt": "Vol: {}%",
|
|
110
|
+
"ime_warning": "Switch to English for shortcuts.",
|
|
111
|
+
"invalid_key": "Invalid key: '{}'"
|
|
96
112
|
}
|
|
97
113
|
}
|
|
98
114
|
|
|
@@ -311,7 +327,7 @@ class Player:
|
|
|
311
327
|
# 'accessory' hides Dock but allows system resources
|
|
312
328
|
cmd.append("--macos-app-activation-policy=accessory")
|
|
313
329
|
|
|
314
|
-
# C.
|
|
330
|
+
# C. Media Source 403 Forbidden Bypass (Cross-platform robustness)
|
|
315
331
|
# This uses the Android player client which is currently the most stable
|
|
316
332
|
# and avoids HLS segment blocks on both Linux and macOS.
|
|
317
333
|
cmd.extend([
|
|
@@ -437,7 +453,7 @@ class MyTunesApp:
|
|
|
437
453
|
self.playback_duration = 0
|
|
438
454
|
self.is_paused = False
|
|
439
455
|
self.last_save_time = time.time()
|
|
440
|
-
self.
|
|
456
|
+
self.status_set_time = 0
|
|
441
457
|
|
|
442
458
|
# Throttling Counters
|
|
443
459
|
self.loop_count = 0
|
|
@@ -467,9 +483,6 @@ class MyTunesApp:
|
|
|
467
483
|
curses.mousemask(curses.ALL_MOUSE_EVENTS | curses.REPORT_MOUSE_POSITION)
|
|
468
484
|
print("\033[?1003h") # Enable mouse tracking
|
|
469
485
|
|
|
470
|
-
# Sharing Client (Serverless Proxy)
|
|
471
|
-
self.pusher = None # Deprecated: Direct Pusher client removed for security
|
|
472
|
-
self.share_api_url = "https://postgresql.co.kr/api/pusher/mytunes"
|
|
473
486
|
self.sent_history = {}
|
|
474
487
|
|
|
475
488
|
|
|
@@ -647,17 +660,22 @@ class MyTunesApp:
|
|
|
647
660
|
"<": "SEEK_BACK_30", ">": "SEEK_FWD_30",
|
|
648
661
|
"a": "TOGGLE_FAV", "5": "TOGGLE_FAV",
|
|
649
662
|
str(curses.KEY_F7): "OPEN_BROWSER",
|
|
650
|
-
str(curses.KEY_F8): "OPEN_HOME_APP",
|
|
651
|
-
str(curses.KEY_F9): "SHARE",
|
|
652
663
|
str(curses.KEY_DC): "DELETE", "d": "DELETE"
|
|
653
664
|
}
|
|
654
|
-
|
|
665
|
+
cmd = mapping.get(k_char)
|
|
666
|
+
if cmd: return cmd
|
|
667
|
+
return ("UNKNOWN", key)
|
|
655
668
|
|
|
656
669
|
def handle_input(self):
|
|
657
670
|
"""Clean dispatcher: Get normalized command and execute it."""
|
|
658
671
|
cmd = self.get_next_event()
|
|
659
672
|
if not cmd: return
|
|
660
673
|
|
|
674
|
+
# Reset transient state for valid commands
|
|
675
|
+
is_transient = any(kw in self.status_msg for kw in ["Invalid key", "잘못된 키", "영문", "English"])
|
|
676
|
+
if is_transient:
|
|
677
|
+
self.status_msg = ""
|
|
678
|
+
|
|
661
679
|
current_list = self.get_current_list()
|
|
662
680
|
|
|
663
681
|
# 1. Functional Commands (Require Logic)
|
|
@@ -732,9 +750,9 @@ class MyTunesApp:
|
|
|
732
750
|
elif cmd == "OPEN_BROWSER":
|
|
733
751
|
if current_list and 0 <= self.selection_idx < len(current_list):
|
|
734
752
|
url = current_list[self.selection_idx].get('url')
|
|
735
|
-
if url: (self.show_copy_dialog("
|
|
753
|
+
if url: (self.show_copy_dialog("Media", url) if self.is_remote() else self.open_browser(url))
|
|
736
754
|
|
|
737
|
-
elif cmd in ["
|
|
755
|
+
elif cmd in ["OPEN_HOME"]:
|
|
738
756
|
url = "https://mytunes-pro.com"
|
|
739
757
|
if self.is_remote(): self.show_copy_dialog("MyTunes Home", url)
|
|
740
758
|
else: self.open_browser(url, app_mode=False)
|
|
@@ -742,8 +760,6 @@ class MyTunesApp:
|
|
|
742
760
|
elif cmd == "OPEN_PARTNER":
|
|
743
761
|
self.open_browser("https://postgresql.co.kr")
|
|
744
762
|
|
|
745
|
-
elif cmd == "SHARE":
|
|
746
|
-
self.handle_share(current_list)
|
|
747
763
|
|
|
748
764
|
elif cmd == "RESIZE":
|
|
749
765
|
self.stdscr.clear()
|
|
@@ -752,6 +768,17 @@ class MyTunesApp:
|
|
|
752
768
|
elif cmd == "EXIT_BKG":
|
|
753
769
|
self.stop_on_exit = False; self.running = False
|
|
754
770
|
|
|
771
|
+
elif isinstance(cmd, tuple) and cmd[0] == "UNKNOWN":
|
|
772
|
+
key = cmd[1]
|
|
773
|
+
if isinstance(key, str) and ord(key[0]) > 127:
|
|
774
|
+
self.status_msg = self.t("ime_warning")
|
|
775
|
+
self.status_set_time = time.time()
|
|
776
|
+
self.draw() # Internal redraw for instant feedback
|
|
777
|
+
elif isinstance(key, str) and key.isprintable():
|
|
778
|
+
self.status_msg = self.t("invalid_key", key)
|
|
779
|
+
self.status_set_time = time.time()
|
|
780
|
+
self.draw() # Internal redraw for instant feedback
|
|
781
|
+
|
|
755
782
|
def handle_deletion(self, current_list):
|
|
756
783
|
"""Sub-logic for DELETE command to keep dispatcher clean."""
|
|
757
784
|
if not current_list or not (0 <= self.selection_idx < len(current_list)): return
|
|
@@ -774,30 +801,6 @@ class MyTunesApp:
|
|
|
774
801
|
if success:
|
|
775
802
|
self.selection_idx = max(0, min(self.selection_idx, len(self.get_current_list()) - 1))
|
|
776
803
|
|
|
777
|
-
def handle_share(self, current_list):
|
|
778
|
-
"""Sub-logic for SHARE command."""
|
|
779
|
-
if not current_list or not (0 <= self.selection_idx < len(current_list)): return
|
|
780
|
-
target_item = current_list[self.selection_idx]
|
|
781
|
-
url = target_item.get('url')
|
|
782
|
-
title = target_item.get('title', 'Unknown Title')
|
|
783
|
-
|
|
784
|
-
if not url: return
|
|
785
|
-
if time.time() - self.sent_history.get(url, 0) < 5:
|
|
786
|
-
self.status_msg = "⚠️ Already Shared Recently!"; return
|
|
787
|
-
|
|
788
|
-
def send_share_async(payload, headers, url_to_share, title_to_share):
|
|
789
|
-
try:
|
|
790
|
-
resp = requests.post(self.share_api_url, json=payload, headers=headers, timeout=3)
|
|
791
|
-
if resp.status_code == 200:
|
|
792
|
-
self.sent_history[url_to_share] = time.time()
|
|
793
|
-
self.status_msg = f"🚀 Shared: {self.truncate(title_to_share, 40)}..."
|
|
794
|
-
else: self.status_msg = f"❌ Share Error: {resp.status_code}"
|
|
795
|
-
except: self.status_msg = "❌ Network Error (API)"
|
|
796
|
-
|
|
797
|
-
payload = {"title": title, "url": url, "duration": target_item.get('duration', '--:--'),
|
|
798
|
-
"country": self.dm.get_country(), "timestamp": time.time()}
|
|
799
|
-
headers = {"Content-Type": "application/json", "x-mytunes-secret": "mytunes-v1-secret-8822"}
|
|
800
|
-
threading.Thread(target=send_share_async, args=(payload, headers, url, title), daemon=True).start()
|
|
801
804
|
|
|
802
805
|
|
|
803
806
|
|
|
@@ -1309,12 +1312,18 @@ class MyTunesApp:
|
|
|
1309
1312
|
if self.player.loading:
|
|
1310
1313
|
self.stdscr.addstr(h - 2, 2, f"⏳ Loading...", curses.color_pair(6) | curses.A_BLINK)
|
|
1311
1314
|
elif self.status_msg:
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1315
|
+
# Auto-clear transient warnings after 5 seconds
|
|
1316
|
+
is_transient = "Invalid key" in self.status_msg or "잘못된 키" in self.status_msg or "영문" in self.status_msg or "English" in self.status_msg
|
|
1317
|
+
if time.time() - self.status_set_time > 5 and is_transient:
|
|
1318
|
+
self.status_msg = ""
|
|
1319
|
+
|
|
1320
|
+
if self.status_msg:
|
|
1321
|
+
avail_w = branding_x - 4
|
|
1322
|
+
if avail_w > 5:
|
|
1323
|
+
msg = self.truncate(self.status_msg, avail_w)
|
|
1324
|
+
# Use Bold Yellow (Pair 3) for premium static warning
|
|
1325
|
+
attr = curses.color_pair(3) | curses.A_BOLD
|
|
1326
|
+
self.stdscr.addstr(h - 2, 2, f"📢 {msg}", attr)
|
|
1318
1327
|
|
|
1319
1328
|
# List Area (Remaining Middle)
|
|
1320
1329
|
list_top = 4
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mytunes-pro
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.5
|
|
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
|
|
@@ -13,22 +13,28 @@ Requires-Python: >=3.9
|
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
15
|
Requires-Dist: requests
|
|
16
|
+
Requires-Dist: urllib3<2.0.0
|
|
16
17
|
Requires-Dist: yt-dlp
|
|
17
18
|
Requires-Dist: pusher
|
|
18
19
|
Dynamic: license-file
|
|
19
20
|
|
|
20
|
-
# 🎵 MyTunes Pro
|
|
21
|
+
# 🎵 MyTunes Pro - Professional TUI Edition v2.0.5
|
|
21
22
|
|
|
22
|
-
## 🚀
|
|
23
|
+
## 🚀 Terminal-based Media Workflow Experiment v2.0.5
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
> [!IMPORTANT]
|
|
26
|
+
> **Legal Disclaimer:** This project is a personal, non-commercial research experiment for developer education.
|
|
27
|
+
> It does not host, provide, or distribute any media content.
|
|
28
|
+
> All media sources are independently accessed and configured by the user.
|
|
29
|
+
> Users are solely responsible for ensuring that their usage complies with the terms of service of any third-party platforms accessed via this tool.
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
MyTunes Pro is a developer-focused **CLI Media Tool** for experimenting with terminal-based media workflows.
|
|
32
|
+
It utilizes the Python `curses` library to provide a structured TUI (Terminal User Interface) for handling media URLs,
|
|
33
|
+
leveraging the `mpv` engine for local media processing and playback.
|
|
34
|
+
|
|
35
|
+
> **💡 Project Note**
|
|
36
|
+
> This tool was designed for personal research into how terminal users can interact with media sources without interrupting their developer workflow.
|
|
37
|
+
> It explores the integration between local CLI environments (like Headless Debian Servers) and external media handling utilities.
|
|
32
38
|
|
|
33
39
|

|
|
34
40
|

|
|
@@ -41,27 +47,24 @@ Python `curses` 라이브러리를 사용하여 터미널 환경에서도 **GUI
|
|
|
41
47
|
|
|
42
48
|
---
|
|
43
49
|
|
|
44
|
-
## ✨
|
|
50
|
+
## ✨ Core Features
|
|
45
51
|
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
- **라이브 (F8)**: 전 세계 유저들과 함께 듣는 **실시간 음악 대시보드** (전용 팝업).
|
|
53
|
-
- **공유 (F9)**: 내가 듣는 곡을 **라이브 스테이션에 즉시 송출**하여 함께 즐깁니다.
|
|
54
|
-
- **비주얼**: 현대적인 심볼 아이콘(⌕, ★, ◷)과 깔끔한 디자인.
|
|
52
|
+
- **Media Handling**: Support for loading and processing media URLs using external extraction tools.
|
|
53
|
+
- **TUI Workflow**: Efficient, low-latency interface built on the `curses` library.
|
|
54
|
+
- **Workflow Persistence**: Handles sequential media loading and state restoration.
|
|
55
|
+
- **Terminal Optimization**: Performance-focused design that prioritizes keyboard-driven interactions.
|
|
56
|
+
- **Smart Management**: Optional user-configured collections, interaction history, and metadata handling.
|
|
57
|
+
- **External Integration**: Capabilities to load media links into external viewer/player environments.
|
|
55
58
|
|
|
56
59
|
---
|
|
57
60
|
|
|
58
|
-
## 💻
|
|
61
|
+
## 💻 Environment & Integration
|
|
59
62
|
|
|
60
|
-
**MyTunes Pro
|
|
63
|
+
**MyTunes Pro** is a CLI-based tool. It can integrate with externally installed media processing tools.
|
|
61
64
|
|
|
62
|
-
- **
|
|
63
|
-
- **Linux**:
|
|
64
|
-
- **Windows**: **WSL(Windows Subsystem for Linux)
|
|
65
|
+
- **External Tools**: This project can interface with user-installed utilities like `mpv` and media extraction tools. No third-party tools are bundled with this software.
|
|
66
|
+
- **macOS/Linux**: Native terminal support.
|
|
67
|
+
- **Windows**: Recommended to use with **WSL (Windows Subsystem for Linux)**.
|
|
65
68
|
|
|
66
69
|
---
|
|
67
70
|
|
|
@@ -182,8 +185,6 @@ Windows 환경에서 한글 검색이 안 되거나 설치가 어려운 분들
|
|
|
182
185
|
| **`+`** | **볼륨 UP** | 볼륨 +5% (단축키 `=`와 동일) |
|
|
183
186
|
| **`-`** | **볼륨 DOWN** | 볼륨 -5% (단축키 `_`와 동일) |
|
|
184
187
|
| **`F7`** | **유튜브 열기** | 현재 곡을 브라우저에서 보기 |
|
|
185
|
-
| **`F8`** | **라이브 (Live)** | **실시간 음악 대시보드 열기** (전용 팝업창) |
|
|
186
|
-
| **`F9`** | **공유 (Share)** | **현재 곡을 라이브 스테이션에 즉시 공유** |
|
|
187
188
|
| **`6`** | **뒤로가기** | 이전 화면으로 이동 (단축키 `Q`, `h`와 동일) |
|
|
188
189
|
| **`L`** | **앞으로** | 이전 화면에서 앞화면으로 다시 이동 (`Right Arrow`) |
|
|
189
190
|
| **`ESC`** | **배경재생** | **음악 끄지 않고 나가기** (백그라운드 재생) |
|
|
@@ -210,107 +211,55 @@ Windows 환경에서 한글 검색이 안 되거나 설치가 어려운 분들
|
|
|
210
211
|
---
|
|
211
212
|
---
|
|
212
213
|
|
|
213
|
-
# 🎵 MyTunes Pro (English)
|
|
214
|
-
|
|
215
|
-
**Modern CLI YouTube Music Player (v2.0.3)**
|
|
216
|
-
A lightweight, keyboard-centric terminal player for streaming YouTube music.
|
|
217
|
-
|
|
218
|
-
---
|
|
219
|
-
|
|
220
|
-
## 💻 Environment Support
|
|
221
|
-
|
|
222
|
-
**MyTunes Pro** is a Terminal-native application.
|
|
223
|
-
|
|
224
|
-
- **macOS**: Native Terminal support. Python 3.9+ required.
|
|
225
|
-
- **Linux**: Supports all distributions (Ubuntu, Debian, etc.).
|
|
226
|
-
- **Windows**: Requires **WSL (Windows Subsystem for Linux)**.
|
|
227
|
-
|
|
228
|
-
---
|
|
229
|
-
|
|
230
|
-
## 🚀 Quick Start
|
|
231
|
-
|
|
232
|
-
On modern macOS/Linux systems (PEP 668), using **`pipx`** is highly recommended.
|
|
233
|
-
|
|
234
|
-
### 1. Recommended (pipx)
|
|
235
|
-
```bash
|
|
236
|
-
pipx install mytunes-pro
|
|
237
|
-
pipx ensurepath
|
|
238
|
-
source ~/.zshrc # or source ~/.bashrc to apply changes immediately
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
### 2. Standard pip
|
|
242
|
-
```bash
|
|
243
|
-
pip install mytunes-pro --break-system-packages
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
Run simply by typing **`mp`** in your terminal!
|
|
247
|
-
|
|
248
214
|
---
|
|
249
215
|
|
|
250
|
-
|
|
216
|
+
# 🎵 MyTunes Pro (Experimental Media Tool - KR)
|
|
251
217
|
|
|
252
|
-
|
|
253
|
-
```bash
|
|
254
|
-
brew install mpv python3 pipx
|
|
255
|
-
```
|
|
218
|
+
## 🚀 터미널 기반 미디어 워크플로우 실험 v2.0.5
|
|
256
219
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
```
|
|
220
|
+
> [!IMPORTANT]
|
|
221
|
+
> **법적 면책 고지:** 본 프로젝트는 개발자 교육 및 연구를 목적으로 하는 개인적, 비상업적 실험입니다.
|
|
222
|
+
> 본 소프트웨어는 어떠한 미디어 콘텐츠도 직접 호스팅하거나 배포하지 않습니다.
|
|
223
|
+
> 모든 미디어 소스는 사용자의 로컬 환경에서 직접 구성되고 접근되며, 사용자는 외부 플랫폼의 이용 약관을 준수할 책임이 있습니다.
|
|
262
224
|
|
|
263
|
-
|
|
225
|
+
MyTunes Pro는 개발자를 위해 설계된 **CLI 미디어 실험 도구**입니다.
|
|
226
|
+
Python `curses` 라이브러리를 통해 터미널 환경에서 미디어 URL을 로드하고 관리하며,
|
|
227
|
+
사용자가 설치한 `mpv` 등의 외부 도구와 연동하여 미디어 워크플로우를 테스트할 수 있습니다.
|
|
264
228
|
|
|
265
|
-
|
|
266
|
-
```powershell
|
|
267
|
-
wsl --install -d Debian
|
|
268
|
-
```
|
|
269
|
-
**Restart your computer** after installation.
|
|
270
|
-
|
|
271
|
-
2. **Install Core Tools**:
|
|
272
|
-
```bash
|
|
273
|
-
sudo apt update && sudo apt install mpv python3-pip pipx -y
|
|
274
|
-
```
|
|
229
|
+
## ✨ 주요 특징
|
|
275
230
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
source ~/.bashrc
|
|
281
|
-
```
|
|
231
|
+
- **미디어 핸들링**: 외부 추출 도구를 사용한 미디어 URL 로드 및 처리 지원.
|
|
232
|
+
- **TUI 워크플로우**: `curses` 라이브러리 기반의 효율적인 터미널 인터페이스.
|
|
233
|
+
- **작업 유지**: 순차적 미디어 로딩 및 마지막 작업 상태 복원 기능.
|
|
234
|
+
- **환경 연동**: 사용자에 의해 구성된 외부 미디어 도구와의 연동 지원. (본 소프트웨어는 외부 도구를 포함하여 배포하지 않습니다.)
|
|
282
235
|
|
|
283
236
|
---
|
|
284
237
|
|
|
285
|
-
##
|
|
238
|
+
## 🔄 Changelog
|
|
286
239
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
| **`5`** | **Add/Del** | Toggle Favorite (Same as `A`) |
|
|
294
|
-
| **`+`** | **Vol Up** | Volume +5% (Same as `=`) |
|
|
295
|
-
| **`-`** | **Vol Down** | Volume -5% (Same as `_`) |
|
|
296
|
-
| **`6`** | **Back** | Go back (Same as `Q`, `h`) |
|
|
297
|
-
| **`L`** | **Forward** | Go forward (`Right Arrow`) |
|
|
298
|
-
| **`ESC`** | **Bg Play** | **Exit app but keep music playing** |
|
|
240
|
+
### v2.0.5 (2026-02-01)
|
|
241
|
+
- **Input Feedback Refinement**: Transitioned from blinking warnings to a static Bold Yellow status message for better accessibility and premium feel.
|
|
242
|
+
- **Auto-clear Optimization**: Implemented a 5-second auto-clear timer for all transient status messages.
|
|
243
|
+
- **Zero Latency Feedback**: Added instant redraw mechanisms to ensure input warnings appear immediately upon key press.
|
|
244
|
+
- **Stability Fixes**: Resolved a critical attribute error that caused crashes when selecting menu items.
|
|
245
|
+
- **SSL Compatibility**: Improved `urllib3` compatibility for macOS systems using LibreSSL.
|
|
299
246
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
247
|
+
### v2.0.4 (2026-02-01)
|
|
248
|
+
- **Legal Polish**: Comprehensive scrubbing of brand identifiers and service-oriented terminology across the ecosystem.
|
|
249
|
+
- **Localization**: Fully localized Korean landing page and technical experiment descriptions.
|
|
250
|
+
- **Educational Focus**: Added explicit project disclaimers to all web footers.
|
|
251
|
+
- **Project Scope**: Solidified positioning as a "Media Handling Experiment" rather than a music player.
|
|
303
252
|
|
|
304
253
|
### v2.0.3 (Input Handling & Unicode Stability)
|
|
305
254
|
|
|
306
255
|
- **Input Logic**: Replaced legacy `getch()` with `get_wch()` in all UI dialogs (`ask_resume`, `show_copy_dialog`) for robust wide-character and Unicode support.
|
|
307
|
-
- **Architecture**: Refactored the input handling system into a modular, command-based architecture (v2.0.3).
|
|
256
|
+
- **Architecture**: Refactored the input handling system into a modular, command-based architecture (v2.0.3).
|
|
308
257
|
- **Decoupling**: Separated input collection (`get_next_event`), event normalization, and command execution.
|
|
309
258
|
- **Improved ESC Handling**: Enhanced detection of ESC and multi-byte sequences (including Option+Backspace) for smoother navigation.
|
|
310
259
|
|
|
311
260
|
### v2.0.2 (Stability & Browser Optimization)
|
|
312
261
|
|
|
313
|
-
- **Browser Launch**: Switched to fully decoupled `subprocess.Popen` logic for browser opening. This eliminates occasional TUI freezes when launching
|
|
262
|
+
- **Browser Launch**: Switched to fully decoupled `subprocess.Popen` logic for browser opening. This eliminates occasional TUI freezes when launching Media Links (F7) or Dashboard (F8) by bypassing `webbrowser` library limitations.
|
|
314
263
|
- **App Mode Restore**: Fixed and improved Chrome/Brave App Mode (Popup) for the Live Station on macOS.
|
|
315
264
|
- **Improved Remote Detection**: Refined SSH/WSL detection to ensure local browser features are correctly enabled where possible.
|
|
316
265
|
|
|
@@ -325,7 +274,6 @@ sudo apt install mpv python3 python3-pip pipx python3-venv -y
|
|
|
325
274
|
|
|
326
275
|
- **Domain Migration**: Updated all branding and internal links to support `mytunes-pro.com`.
|
|
327
276
|
- **Realtime Stability**: Fixed critical state-management bugs in the live dashboard that caused list clearing and duplicated track entries.
|
|
328
|
-
- **Pusher Channel Synchronization**: Unified communication across the transition to ensure zero-latency sharing on the new `mytunes-pro` channel.
|
|
329
277
|
- **Improved Empty State**: Redesigned the "SIGNAL LOST" screen into a more descriptive "READY TO RECEIVE" interface for better UX.
|
|
330
278
|
|
|
331
279
|
### v1.9.8 (Realtime Stabilization)
|
|
@@ -333,7 +281,7 @@ sudo apt install mpv python3 python3-pip pipx python3-venv -y
|
|
|
333
281
|
- **UI Refinement**: Implemented in-list "Now Playing" sticky behavior with auto-scroll synchronization for a seamless browsing experience.
|
|
334
282
|
- **Queue System Optimization**: Capped incoming track queue at 200 items with a "200+" notification indicator for high-traffic stability.
|
|
335
283
|
- **Popup UI Consistency**: Unified Live Station popup dimensions to 620x900 across Web and TUI.
|
|
336
|
-
- **Improved
|
|
284
|
+
- **Improved Media Playback**: Optimized the media player hook to resolve initialization race conditions and syntax edge cases.
|
|
337
285
|
|
|
338
286
|
### v1.9.7 (Analytics)
|
|
339
287
|
|
|
@@ -393,7 +341,7 @@ sudo apt install mpv python3 python3-pip pipx python3-venv -y
|
|
|
393
341
|
### v1.8.4
|
|
394
342
|
|
|
395
343
|
- **Python Crash Fix (WSL)**: Eliminated premature termination by implementing `start_new_session=True` for browser launches, isolating them from the TUI process group.
|
|
396
|
-
- **Hybrid Browser Strategy**: Switched to the standard `webbrowser` library for F7 (
|
|
344
|
+
- **Hybrid Browser Strategy**: Switched to the standard `webbrowser` library for F7 (Media links) for maximum internal stability.
|
|
397
345
|
- **Global Error Protection**: Wrapped the main application loop in an exception guard to catch and log transient OS errors without crashing the entire app.
|
|
398
346
|
- **Refined Process Cleanup**: Specialized the `pkill` logic to prevent accidental self-termination while maintaining reliable MPV management.
|
|
399
347
|
|
|
@@ -440,7 +388,7 @@ sudo apt install mpv python3 python3-pip pipx python3-venv -y
|
|
|
440
388
|
### v1.7.5
|
|
441
389
|
|
|
442
390
|
- **WSL Integration**: Fully optimized browser launch from WSL by utilizing `cmd.exe` to trigger native Windows browsers.
|
|
443
|
-
- **F7 Windows Resolve**: Fixed an issue where
|
|
391
|
+
- **F7 Windows Resolve**: Fixed an issue where Media links (F7) wouldn't open in WSL environments.
|
|
444
392
|
- **F8 App Mode (WSL/Win)**: Enhanced flags to ensure "App Mode" (no address bar) works consistently even when launched from WSL.
|
|
445
393
|
|
|
446
394
|
### v1.7.4
|
|
@@ -450,7 +398,7 @@ sudo apt install mpv python3 python3-pip pipx python3-venv -y
|
|
|
450
398
|
|
|
451
399
|
### v1.7.3
|
|
452
400
|
|
|
453
|
-
- **Windows Fixes**: Resolved issue where F7 (
|
|
401
|
+
- **Windows Fixes**: Resolved issue where F7 (Media) failed to open browsers on Windows by implementing `os.startfile` logic.
|
|
454
402
|
- **F8 Initialization**: Improved Live Station (F8) window sizing on Windows by forcing a clean session state.
|
|
455
403
|
- **Robustness**: Enhanced cross-platform browser redirection logic to ensure consistent behavior.
|
|
456
404
|
|
|
@@ -470,7 +418,6 @@ sudo apt install mpv python3 python3-pip pipx python3-venv -y
|
|
|
470
418
|
### v1.6.0
|
|
471
419
|
|
|
472
420
|
- **Global Version Synchronization**: Synchronized version 1.6.0 across CLI, README, and Web interface.
|
|
473
|
-
- **Dependency Fix**: Ensured `pusher` dependency is correctly included for real-time features.
|
|
474
421
|
|
|
475
422
|
### v1.5.6
|
|
476
423
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
mytunes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
mytunes/app.py,sha256=-vJSyC0gF0rj0Q3LkJWwlDH0c75OHZRxQ3l4Nxj19Ps,59412
|
|
3
|
+
mytunes_pro-2.0.5.dist-info/licenses/LICENSE,sha256=lOrP0EIjxcgJia__W3f3PVDZkRd2oRzFkyH2g3LRRCg,1063
|
|
4
|
+
mytunes_pro-2.0.5.dist-info/METADATA,sha256=GelVLtHE3uFp4s76DylYNpNFF4lgz8hY4hokILwIE6g,23172
|
|
5
|
+
mytunes_pro-2.0.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
6
|
+
mytunes_pro-2.0.5.dist-info/entry_points.txt,sha256=6-MsC13nIgzLvrREaGotc32FgxHx_Iuu1z2qCzJs1_4,65
|
|
7
|
+
mytunes_pro-2.0.5.dist-info/top_level.txt,sha256=KWzdFyNNG_sO7GT83-sN5fYArP4_DL5I8HYIwgazXyY,8
|
|
8
|
+
mytunes_pro-2.0.5.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
mytunes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
mytunes/app.py,sha256=LQY9p6w25cIz1WBJ4LIWmX4BsvfHotZ_FVZffqjGy7A,59351
|
|
3
|
-
mytunes_pro-2.0.3.dist-info/licenses/LICENSE,sha256=lOrP0EIjxcgJia__W3f3PVDZkRd2oRzFkyH2g3LRRCg,1063
|
|
4
|
-
mytunes_pro-2.0.3.dist-info/METADATA,sha256=xQW9fpXYf9jho1a3RBirqRHy6xYoeiUCWeHtzXeoL-g,23396
|
|
5
|
-
mytunes_pro-2.0.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
6
|
-
mytunes_pro-2.0.3.dist-info/entry_points.txt,sha256=6-MsC13nIgzLvrREaGotc32FgxHx_Iuu1z2qCzJs1_4,65
|
|
7
|
-
mytunes_pro-2.0.3.dist-info/top_level.txt,sha256=KWzdFyNNG_sO7GT83-sN5fYArP4_DL5I8HYIwgazXyY,8
|
|
8
|
-
mytunes_pro-2.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|