Skip to content

Commit f1b7e3e

Browse files
merge: resolve conflicts with tauri-migration versions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2 parents a96bf94 + 51c80bf commit f1b7e3e

5 files changed

Lines changed: 798 additions & 28 deletions

File tree

β€ŽAGENTS.mdβ€Ž

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,9 @@ Worktrunk automatically detects remote branches and creates worktrees at compute
462462
**Basic worktree operations:**
463463

464464
```bash
465+
# list existing worktrees
466+
wt list
467+
465468
# Switch to existing worktree for a branch
466469
wt switch feature
467470

β€Ždocs/README.mdβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This directory contains comprehensive documentation for the MT music player proj
1313
- [**Custom Playlists**](custom-playlists.md) - Implementation plan for user-created playlists
1414
- [**Current Status**](status.md) - Implementation progress, outstanding tasks, and known issues
1515
- [**Web Migration Guide**](web-migration.md) - Strategy for porting to FastAPI/Flask web application
16+
- [**Tauri Architecture**](tauri-architecture.md) - Target architecture for Tauri migration (Rust audio, Python sidecar, Alpine.js frontend)
1617

1718
## Quick Start
1819

β€Ždocs/python-architecture.mdβ€Ž

Lines changed: 224 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,46 @@ The application entry point follows a structured initialization sequence:
1717
5. **Component Setup** - All subsystem initialization and connection
1818
6. **Event Loop** - Tkinter main loop with error handling
1919

20-
### Central Orchestrator (`core/player.py`)
20+
### Central Orchestrator (`core/player/`)
2121

22-
The `MusicPlayer` class serves as the central orchestrator, managing:
22+
The `core/player/` package contains the `MusicPlayer` class and its composed managers, serving as the central orchestrator. The package uses a **manager composition pattern** to separate concerns:
2323

24-
- **Window Management**: Size, position, and platform-specific styling (macOS integration)
25-
- **Component Lifecycle**: Initialization order and dependency injection
26-
- **UI Layout**: PanedWindow-based two-panel design (library + content)
27-
- **Event Coordination**: User interactions, media keys, and file system events
28-
- **State Persistence**: Window preferences and application settings
24+
#### Package Structure
2925

30-
#### Key Components Integration
26+
```
27+
core/player/
28+
β”œβ”€β”€ __init__.py # MusicPlayer class - main orchestrator
29+
β”œβ”€β”€ handlers.py # PlayerEventHandlers - event callbacks
30+
β”œβ”€β”€ library.py # PlayerLibraryManager - library operations
31+
β”œβ”€β”€ progress.py # PlayerProgressController - playback progress
32+
β”œβ”€β”€ queue.py # PlayerQueueHandler - queue operations
33+
β”œβ”€β”€ ui.py # PlayerUIManager - UI component management
34+
└── window.py # PlayerWindowManager - window lifecycle
35+
```
36+
37+
#### Manager Composition Pattern
38+
39+
The `MusicPlayer` class composes specialized manager classes, each handling a specific domain:
40+
41+
```python
42+
# Manager classes composed into MusicPlayer
43+
PlayerWindowManager # Window size, position, macOS styling
44+
PlayerUIManager # UI component lifecycle and layout
45+
PlayerEventHandlers # User interactions, media keys, file events
46+
PlayerLibraryManager # Library scanning, filtering, display
47+
PlayerQueueHandler # Queue operations and playback order
48+
PlayerProgressController # Progress tracking and seeking
49+
```
50+
51+
#### Core Subsystems
3152

3253
```python
3354
# Core subsystems initialized in setup_components()
34-
self.db = MusicDatabase() # SQLite data layer
35-
self.queue_manager = QueueManager() # Queue operations
36-
self.library_manager = LibraryManager() # Library scanning/management
37-
self.player_core = PlayerCore() # Audio playback engine
55+
self.db = MusicDatabase(DB_NAME, DB_TABLES) # SQLite data layer (facade)
56+
self.queue_manager = QueueManager(self.db) # Queue operations
57+
self.library_manager = LibraryManager(self.db) # Library scanning
58+
self.favorites_manager = FavoritesManager(self.db) # Favorites/likes
59+
self.player_core = PlayerCore() # VLC audio engine
3860
```
3961

4062
#### UI Component Architecture
@@ -44,30 +66,60 @@ self.player_core = PlayerCore() # Audio playback engine
4466
self.library_view = LibraryView() # Left panel library browser
4567
self.queue_view = QueueView() # Right panel queue display
4668
self.progress_bar = ProgressBar() # Bottom progress/controls
69+
self.search_bar = SearchBar() # Library search interface
70+
self.status_bar = StatusBar() # Status display
4771
```
4872

49-
## Data Layer (`core/db.py`)
73+
## Data Layer (`core/db/`)
74+
75+
The `core/db/` package implements a **facade pattern** for database operations, with specialized modules for each domain:
5076

51-
### Database Design
77+
### Package Structure
5278

53-
SQLite-based persistence with two main tables:
79+
```
80+
core/db/
81+
β”œβ”€β”€ __init__.py # Facade exports (MusicDatabase, DB_TABLES)
82+
β”œβ”€β”€ database.py # MusicDatabase class - core operations
83+
β”œβ”€β”€ library.py # Library track CRUD operations
84+
β”œβ”€β”€ queue.py # Queue management operations
85+
β”œβ”€β”€ favorites.py # Favorites and dynamic playlist views
86+
β”œβ”€β”€ playlists.py # Custom playlist operations
87+
└── preferences.py # User preferences persistence
88+
```
89+
90+
### Database Schema
91+
92+
SQLite-based persistence with the following tables:
5493

5594
- **`library`**: Music file metadata and indexing
5695
- File paths, metadata (artist, album, title, duration)
57-
- Content hashing for deduplication
58-
- Last modified timestamps for incremental scanning
96+
- Play count and last played timestamps
97+
- Added date for "Recently Added" views
5998

6099
- **`queue`**: Current playback queue state
61-
- Track references, position, play order
62-
- Shuffle state and loop configuration
100+
- Track references by filepath
63101
- Session persistence across app restarts
64102

103+
- **`favorites`**: Liked tracks
104+
- Foreign key to library with timestamps
105+
- Unique constraint prevents duplicates
106+
107+
- **`playlists`** / **`playlist_items`**: Custom playlists
108+
- Playlist metadata with creation timestamps
109+
- Ordered track references with position tracking
110+
111+
- **`settings`**: Key-value preference storage
112+
- Window geometry, volume, loop/shuffle state
113+
114+
- **`lyrics_cache`**: Cached lyrics data
115+
- Artist/title lookup with source URLs
116+
65117
### Database Operations
66118

67-
The `MusicDatabase` class provides:
119+
The `MusicDatabase` facade provides:
68120

69-
- **Schema Management**: Automatic table creation and migration
70-
- **Query Interface**: High-level operations for library and queue
121+
- **Schema Management**: Automatic table creation via `DB_TABLES` dict
122+
- **Query Interface**: High-level operations delegated to domain modules
71123
- **Preference Storage**: JSON-serialized configuration data
72124
- **Transaction Safety**: Atomic operations for data consistency
73125

@@ -84,10 +136,67 @@ The `LibraryManager` handles:
84136

85137
### Performance Optimizations
86138

87-
- **Zig Integration**: High-performance directory scanning via `core/_scan.py`
139+
- **Zig Integration**: High-performance directory scanning via `src/scan.zig`
88140
- **Batch Operations**: Bulk database insertions for large libraries
89141
- **Background Processing**: Non-blocking UI during scan operations
90142

143+
## Zig Performance Extension (`src/`)
144+
145+
The `src/` directory contains a Zig-based native extension for high-performance file system operations, built using [ziggy-pydust](https://github.com/spiraldb/ziggy-pydust) for Python FFI.
146+
147+
### Module Structure
148+
149+
```
150+
src/
151+
β”œβ”€β”€ build.zig # Zig build configuration
152+
β”œβ”€β”€ pydust.build.zig # Pydust integration
153+
└── scan.zig # Music directory scanner
154+
```
155+
156+
### scan.zig - Directory Scanner
157+
158+
High-performance recursive directory scanner for audio files:
159+
160+
```zig
161+
// Exposed to Python
162+
pub fn scan_music_directory(args: struct { root_path: []const u8 }) u64
163+
```
164+
165+
**Features:**
166+
- **Audio Detection**: Recognizes `.mp3`, `.flac`, `.m4a`, `.ogg`, `.wav`, `.wma`, `.aac`, `.opus`, `.m4p`, `.mp4`
167+
- **Recursive Walking**: Uses `std.fs.Dir.walk()` for efficient traversal
168+
- **Smart Filtering**: Skips hidden directories, `__pycache__`, `.DS_Store`
169+
- **Memory Safety**: Uses Zig's `GeneralPurposeAllocator` with leak detection
170+
171+
### Build Process
172+
173+
```bash
174+
# Build via Python script
175+
uv run python build.py
176+
177+
# Or via hatch during package installation
178+
hatch build
179+
180+
# Output: core/_scan.so (Python extension)
181+
```
182+
183+
### Python Integration
184+
185+
```python
186+
# Import the Zig extension
187+
from core._scan import scan_music_directory
188+
189+
# Count audio files in directory
190+
count = scan_music_directory("/path/to/music")
191+
```
192+
193+
### Why Zig?
194+
195+
- **Performance**: 10-100x faster than pure Python for large directory trees
196+
- **Memory Efficiency**: Zero-copy string handling, no GC pressure
197+
- **Safety**: Compile-time memory safety without runtime overhead
198+
- **Cross-Platform**: Single codebase for macOS/Linux
199+
91200
## Queue System (`core/queue.py`)
92201

93202
### Queue Management
@@ -122,14 +231,101 @@ The `PlayerCore` class wraps VLC functionality:
122231
- **Thread Safety**: UI updates via `window.after()` for main thread execution
123232
- **Event Handling**: VLC event callbacks with proper synchronization
124233

125-
## User Interface (`core/gui.py`)
234+
## API Server (`api/server.py`)
235+
236+
The `APIServer` class provides programmatic control of the music player via a socket-based JSON protocol, enabling LLM and automation tool integration.
237+
238+
### Architecture
239+
240+
```
241+
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” JSON/Socket β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
242+
β”‚ External Tool β”‚ ◄──────────────────► β”‚ APIServer β”‚
243+
β”‚ (LLM, Script) β”‚ localhost:5555 β”‚ (Background) β”‚
244+
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
245+
β”‚
246+
window.after()
247+
β”‚
248+
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
249+
β”‚ MusicPlayer β”‚
250+
β”‚ (Main Thread) β”‚
251+
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
252+
```
253+
254+
### Threading Model
255+
256+
- **Server Thread**: Daemon thread handles socket connections
257+
- **Client Threads**: Each client request spawns a handler thread
258+
- **Main Thread Execution**: Commands execute via `window.after()` for thread safety
259+
- **Timeout Handling**: 1-second socket timeout for graceful shutdown
260+
261+
### Command Surface
262+
263+
```python
264+
# Playback controls
265+
'play_pause', 'play', 'pause', 'stop', 'next', 'previous'
266+
267+
# Track selection
268+
'select_track', 'play_track_at_index'
269+
270+
# Queue management
271+
'add_to_queue', 'clear_queue', 'remove_from_queue'
272+
273+
# UI navigation
274+
'switch_view', 'select_library_item', 'select_queue_item'
275+
276+
# Slider controls
277+
'set_volume', 'seek', 'seek_to_position'
278+
279+
# Utility controls
280+
'toggle_loop', 'toggle_shuffle', 'toggle_favorite'
281+
282+
# Media key simulation
283+
'media_key'
284+
285+
# Search
286+
'search', 'clear_search'
287+
288+
# Info queries
289+
'get_status', 'get_current_track', 'get_queue', 'get_library'
290+
```
291+
292+
### Configuration
293+
294+
```bash
295+
# Enable API server
296+
MT_API_SERVER_ENABLED=true uv run main.py
297+
298+
# Custom port (default: 5555)
299+
MT_API_SERVER_PORT=5555 uv run main.py
300+
```
301+
302+
### Security
303+
304+
- **Localhost Only**: Binds to `localhost` only, not exposed externally
305+
- **No Authentication**: Designed for local automation, not network access
306+
307+
## User Interface (`core/gui/`)
308+
309+
The `core/gui/` package contains modular UI components built with Tkinter/ttk.
310+
311+
### Package Structure
312+
313+
```
314+
core/gui/
315+
β”œβ”€β”€ __init__.py # Exports (LibraryView, QueueView, etc.)
316+
β”œβ”€β”€ library_search.py # LibraryView - left panel browser
317+
β”œβ”€β”€ queue_view.py # QueueView - right panel queue display
318+
β”œβ”€β”€ player_controls.py # PlayerControls - transport buttons
319+
β”œβ”€β”€ progress_status.py # ProgressBar, StatusBar
320+
└── music_player.py # Legacy stub (deprecated)
321+
```
126322

127323
### Component Structure
128324

129-
- **LibraryView**: Left panel with collapsible sections for different library views
130-
- **QueueView**: Right panel tree display of current playback queue
131-
- **PlayerControls**: Bottom panel transport controls and volume
132-
- **ProgressBar**: Custom canvas-based progress indication with seeking
325+
- **LibraryView** (`library_search.py`): Left panel with collapsible sections for library views, search, and playlists
326+
- **QueueView** (`queue_view.py`): Right panel tree display with drag-and-drop reordering
327+
- **PlayerControls** (`player_controls.py`): Bottom panel transport controls (play/pause, prev/next, loop, shuffle)
328+
- **ProgressBar** (`progress_status.py`): Custom canvas-based progress indication with click-to-seek
133329

134330
### Theming System (`core/theme.py`)
135331

0 commit comments

Comments
Β (0)