feat: v0.0.2 — Visualizer, transitions, mini-player, metadata editor, media control#2
feat: v0.0.2 — Visualizer, transitions, mini-player, metadata editor, media control#2devohmycode merged 12 commits intomainfrom
Conversation
Mirror visualizer using NAudio FFT on pre-decoded audio data. Configurable 30/60 FPS in settings. Fix expand showing wrong view. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ata editor Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Slide+fade transitions (120ms exit, 150ms enter) between Library/Playlists/Queue/Visualizer - 3-state collapse cycling: expanded (710px) → compact (220px) → mini (60px) - Mini-player shows cover art, title — artist, play/pause button - Ctrl+L cycles through all three states Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New MetadataWriter service for TagLibSharp write-back - Edit title, artist, album directly from track context menu - Change or remove artwork via file picker - Updates database and refreshes UI on save - Error handling for locked files during playback Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The CustomTitleBar (32px) was consuming vertical space in the 60px mini-player, pushing the play/pause button off screen. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Queue restore now only updates track info display without setting the Pause icon, since no playback is active at startup. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Integrates SMTC (System Media Transport Controls) to detect and control all active system media sessions. Includes per-session cards with thumbnail, metadata, timeline scrubbing, and playback controls. Also optimizes spectrum analyzer to use sliding window cache instead of full decode, and refactors SMTC artwork update. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis pull request introduces three major features to Audiomatic: a spectrum-based audio visualizer with configurable frame rates, a system media session control panel for monitoring active media playback, and an inline metadata editor for track tags and artwork. Supporting changes include a mini-player ultra-compact display mode, animated view transitions, enhanced album art handling, and new services for spectrum analysis, metadata writing, and media session management. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant MainWindow
participant SpectrumAnalyzer
participant Canvas
participant Audio[Audio Subsystem]
User->>MainWindow: Click Visualizer button
MainWindow->>SpectrumAnalyzer: PrepareAsync(currentTrackPath)
SpectrumAnalyzer->>Audio: Pre-decode audio to memory
Audio-->>SpectrumAnalyzer: Mono float samples + sample rate
SpectrumAnalyzer-->>MainWindow: Ready signal
loop Every frame (30/60 fps)
MainWindow->>SpectrumAnalyzer: GetSpectrum(currentPosition, bandCount)
SpectrumAnalyzer->>SpectrumAnalyzer: Compute FFT + log-spaced bands
SpectrumAnalyzer-->>MainWindow: float[] spectrum data
MainWindow->>Canvas: Draw bars for each band
Canvas-->>User: Visual spectrum display
end
sequenceDiagram
participant User
participant MainWindow
participant MediaSessionPanel
participant SMTC[System Media Transport Controls]
participant System[System Media App]
MainWindow->>SMTC: Initialize SessionManager
loop Monitor active sessions
SMTC-->>MainWindow: Session state changes
MainWindow->>MediaSessionPanel: Create panel for session
MediaSessionPanel->>SMTC: Subscribe to session events
User->>MediaSessionPanel: Click play/pause
MediaSessionPanel->>SMTC: TryTogglePlayPauseAsync()
SMTC->>System: Toggle playback
System-->>SMTC: Status updated
SMTC-->>MediaSessionPanel: MediaPropertiesChanged event
MediaSessionPanel->>MediaSessionPanel: Update UI (title, art, timeline)
MediaSessionPanel-->>User: Refresh display
end
sequenceDiagram
participant User
participant MainWindow
participant MetadataWriter
participant FileSystem
participant LibraryManager
participant Database
User->>MainWindow: Click Edit Tags in context menu
MainWindow->>MainWindow: BuildMetadataEditorContent
MainWindow-->>User: Show inline editor (Title, Artist, Album, Artwork)
User->>MainWindow: Edit fields + Click Save
MainWindow->>MetadataWriter: WriteTags(filePath, title, artist, album)
MetadataWriter->>FileSystem: Open audio file via TagLib
FileSystem-->>MetadataWriter: File handle
MetadataWriter->>MetadataWriter: Set ID3/metadata tags
MetadataWriter->>FileSystem: Save file
FileSystem-->>MetadataWriter: Success
MetadataWriter-->>MainWindow: WriteResult(Success=true)
MainWindow->>LibraryManager: UpdateTrackMetadata(trackId, title, artist, album)
LibraryManager->>Database: UPDATE tracks table
Database-->>LibraryManager: Rows affected
MainWindow->>MainWindow: Refresh UI + Now Playing display
MainWindow-->>User: Show updated metadata
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review Summary by Qodov0.0.2 — Visualizer, transitions, mini-player, metadata editor, and media control
WalkthroughsDescription• **Audio visualizer** — real-time FFT spectrum analyzer with logarithmic frequency mapping, Hamming window, and configurable FPS (30/60) • **Animated view transitions** — Fluent slide+fade Storyboard animations (CubicEase) between all navigation views • **Mini-player mode** — ultra-compact 60px window state with album art, track info, and play/pause button; 3-state collapse cycling via Ctrl+L (Expanded → Compact → Mini) • **Inline metadata editor** — edit title, artist, album, and artwork directly from track context menu with TagLibSharp tag write-back • **Media control tab** — monitor and control system media sessions (SMTC) with per-session cards, timeline scrubbing, and playback controls • **Cover art detection** — automatic folder cover art discovery and SMTC artwork synchronization • **Installer update** — per-user installation (no admin required), version bump to 0.0.2 • **Settings enhancement** — visualizer FPS preference persistence (30 or 60 FPS) Diagramflowchart LR
A["Audio Player"] -->|"FFT Analysis"| B["Spectrum Analyzer"]
B -->|"Magnitude Data"| C["Visualizer Tab"]
A -->|"Metadata"| D["Metadata Writer"]
D -->|"Tag Updates"| E["Library Manager"]
A -->|"SMTC Events"| F["Media Session Panel"]
F -->|"Playback Control"| A
G["MainWindow"] -->|"State Management"| H["Mini-Player Mode"]
G -->|"Animated Transitions"| I["Navigation Views"]
J["Settings Manager"] -->|"FPS Config"| C
File Changes1. Audiomatic/MainWindow.xaml.cs
|
Code Review by Qodo
1. Media timer keeps running
|
| private void SuspendTimers() | ||
| { | ||
| _player.SuspendPositionTimer(); | ||
| _spectrumTimer?.Stop(); | ||
| } |
There was a problem hiding this comment.
1. Media timer keeps running 🐞 Bug ➹ Performance
When the window is hidden to tray, SuspendTimers stops only the player position timer and spectrum timer, leaving the MediaControl 1s tick timer running. Additionally, when sessions drop to zero, RebuildMediaSessionList clears panels but never calls UpdateMediaTimer, so an already-running media timer may never stop.
Agent Prompt
### Issue description
The Media Control timeline tick (`_mediaTickTimer`) is not suspended when the window is hidden to tray, and it may keep running even after sessions drop to zero because `RebuildMediaSessionList()` doesn’t call `UpdateMediaTimer()`.
### Issue Context
- `_mediaTickTimer` is created/started in `UpdateMediaTimer()`.
- `SuspendTimers()`/`ResumeTimers()` currently only manage `_player` position timer and `_spectrumTimer`.
- `RebuildMediaSessionList()` clears `_mediaSessionPanels`, which should cause `needsTimer` to become false, but the stop logic only runs if `UpdateMediaTimer()` is called.
### Fix Focus Areas
- Audiomatic/MainWindow.xaml.cs[1643-1699]
- Audiomatic/MainWindow.xaml.cs[1701-1719]
- Audiomatic/MainWindow.xaml.cs[2643-2654]
### Implementation notes
- In `SuspendTimers()`: stop `_mediaTickTimer` (or call `UpdateMediaTimer()` after setting a flag like `_isVisible=false`).
- In `ResumeTimers()`: call `UpdateMediaTimer()` to restart if `_viewMode == MediaControl` and panels exist.
- At the end of `RebuildMediaSessionList()`: call `UpdateMediaTimer()` so the timer starts/stops based on the new panel count.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream(); | ||
| var writer = new Windows.Storage.Streams.DataWriter(stream.GetOutputStreamAt(0)); | ||
| writer.WriteBytes(pic.Data.Data); | ||
| _ = writer.StoreAsync().AsTask().Result; | ||
| stream.Seek(0); |
There was a problem hiding this comment.
2. Metadata editor ui freeze 🐞 Bug ⛯ Reliability
BuildMetadataEditorContent blocks the UI thread by calling writer.StoreAsync().AsTask().Result while constructing the flyout, which can hang or severely stall the UI when embedded artwork is present. The method also doesn’t dispose the DataWriter/stream it creates for the preview.
Agent Prompt
### Issue description
The metadata editor flyout content builder synchronously blocks on `writer.StoreAsync().AsTask().Result` while on the UI thread, which can freeze the app when opening the editor for tracks with embedded artwork.
### Issue Context
`BuildMetadataEditorContent()` is called directly from a context-menu button click and constructs UI elements synchronously. It should not perform blocking waits.
### Fix Focus Areas
- Audiomatic/MainWindow.xaml.cs[1352-1377]
### Implementation notes
- Replace the synchronous wait with an async flow. Two viable approaches:
1) Defer the artwork preview load:
- Build the panel with placeholder initially.
- Kick off an async method like `LoadArtworkPreviewAsync(track.Path, artPreview, artPlaceholder)` that `await`s `writer.StoreAsync()` and then updates the UI via `DispatcherQueue.TryEnqueue`.
2) Avoid DataWriter/StoreAsync entirely for preview by using an alternative that doesn’t require blocking (still must remain non-blocking on UI).
- Dispose/close the `DataWriter` and stream (`using`/`await using` where applicable) after `BitmapImage.SetSource`.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Summary
Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Chores