When gapless is off, the AudioOutput is dropped after each track ends
naturally, producing a real gap on the next play. When on, the output
stays alive so tracks transition seamlessly. Also re-adds URL prefetch
gating behind the same toggle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add EV_PLAYLIST_TRACK_ADDED (22) — emitted when a track is
successfully added to a playlist
- If the currently-open playlist is the one modified, re-fetch it
so the track appears in the list immediately
- After creating a playlist, open it automatically so the user
lands in the new (empty) playlist view right away
- Sidebar already refreshes on create/delete; this ensures the
track list view also stays in sync
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Playlist management:
- Add/remove tracks from playlists via right-click context menu
- Create new playlists (right-click Playlists sidebar header)
- Delete playlists with confirmation dialog (right-click playlist item)
- Playlist view removes track immediately on delete (optimistic)
- Deleting currently-open playlist clears the track view
Gapless playback:
- Single long-running audio thread owns AudioOutput; CPAL stream stays
open between tracks eliminating device teardown/startup gap
- Decode runs inline on the audio thread; command channel polled via
try_recv() so Pause/Resume/Seek/Stop/Play all work without spawning
- New Play command arriving mid-decode is handled immediately,
reusing the same audio output for zero-gap transition
- Position timer reduced from 500 ms to 50 ms for faster track-end detection
- URL/metadata prefetch: when gapless is enabled Qt pre-fetches the next
track while the current one is still playing
ReplayGain:
- Toggled in Settings → Playback
- replaygain_track_gain (dB) from track audio_info converted to linear
gain factor and applied per-sample alongside volume
Qobuz dark theme:
- Background #191919, base #141414, accent #FFB232 (yellow-orange)
- Selection highlight, slider fill, scrollbar hover all use #FFB232
- Links use Qobuz blue #46B3EE
- Hi-res H badges updated to #FFB232 (from #FFD700)
- Now-playing row uses #FFB232 (was Spotify green)
- QSS stylesheet for scrollbars, menus, inputs, buttons, groups
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Seeking:
- Rust player: seek_requested/seek_target_secs atomics on PlayerStatus
- Decoder loop checks for seek each iteration, calls format.seek() and resets decoder
- New qobuz_backend_seek C FFI + QobuzBackend::seek(quint64)
- Progress slider onProgressReleased now seeks to the dragged position
Last.fm:
- LastFmScrobbler: now-playing + scrobble (50% or 240s threshold, min 30s)
- API signature follows Last.fm spec (sorted params, md5)
- Settings dialog: API key/secret, username/password, Connect button with status
- AppSettings: lastfm/enabled, api_key, api_secret, session_key
- Scrobbler wired to trackChanged, positionChanged, trackFinished in MainWindow
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>