Commit Graph

10 Commits

Author SHA1 Message Date
joren
d1b9cb1210 refactor: centralize hardcoded color values into Colors namespace
Add src/util/colors.hpp with named constants for all QColor values
(brand accents, badge colors, text shades, surface backgrounds) and
replace scattered QColor constructor calls across 7 source files.
Stylesheet string colors are intentionally left inline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 11:01:45 +02:00
joren
2da934f3f6 feat: restore most-popular search and top results badges
Some checks failed
Build for Windows / build-windows (push) Has been cancelled
2026-03-30 22:53:41 +02:00
joren
3346b424b3 refactor: resync with qbqt baseline and restore genre browser
Some checks failed
Build for Windows / build-windows (push) Has been cancelled
2026-03-30 22:36:39 +02:00
joren
200ef39d04 feat: most-popular search as default Top Results tab
Add /most-popular/get endpoint support (discovered via Burp):
- Returns mixed artists/albums/tracks ordered by popularity for a query
- New 'Top Results' tab shown first/default in the search panel
- Badge column: A (artist, blue), H (hi-res album, gold), A (album, gray), T (track, green)
- Full context menu support on all item types in the new tab
- Both most-popular and regular search fire on submit in parallel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 20:28:13 +02:00
joren
70810bd4b1 feat: qbz-1 streaming, gapless prefetch, accurate scrobbling, Range-seek
Port proven playback architecture from qbqt fork:
- Bounded VecDeque buffer with condvar backpressure (4MB cap)
- decrypt_and_extract_frames for clean FLAC frame extraction from ISOBMFF
- Cancel+restart seeking with sub-segment sample skipping
- start_prefetch / QueueNext for gapless transitions with pre-started downloads
- track_transitioned signaling for scrobbler during gapless playback
- Range-request HTTP seeking for non-segmented (MP3) tracks
- OnceLock HTTP client singleton with cancel-aware chunked downloads
- Accumulated listening time scrobbling (prevents false scrobbles from seeking)
- Array-format Last.fm scrobble params (artist[0], track[0], etc.)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 20:12:23 +02:00
joren
6c8d032ce9 feat: context menus on search panel, track info dialog, separate shuffle buttons
- Add right-click context menus to search panel tracks (play, queue,
  favorites, playlist, go to album/artist, track info) and albums
  (open, favorite, go to artist)
- Add "Track info..." dialog showing metadata (title, performer,
  composer, album, quality, hi-res status) — available everywhere:
  playlists, albums, favorites, search results
- Split artist page shuffle into "Shuffle" (popular tracks) and
  "Shuffle All" (deep shuffle across all releases)
- Remove magnifying glass emoji from welcome text

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 23:57:42 +01:00
joren
f30e2058c1 feat: playlist management, gapless playback, ReplayGain, Qobuz theme
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>
2026-03-24 11:19:32 +01:00
joren
74e43b9713 fix: store TypeRole in col 0 for search album results
When the H badge column was added, TypeRole was accidentally stored in
col 1 but the double-click handler reads it from col 0, breaking album
navigation from search. Move TypeRole back to col 0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 10:12:22 +01:00
joren
7e2a04ecff fix: placeholder text color and H badge in search album results
- Add QPalette::PlaceholderText (#8C8C8C) to the dark palette so
  placeholder text in search box and settings fields is readable
- Add H column to search album results (same gold badge as album list view)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 01:25:42 +01:00
joren
9402dca7ed Initial implementation of qobuz-qt
- Rust backend (qobuz-backend static lib): Qobuz API client (reqwest/tokio),
  Symphonia audio decoder, CPAL audio output, extern "C" FFI bridge
- Qt 6 frontend mirroring spotify-qt layout: toolbar with playback controls,
  left library dock, central track list, right search panel
- Auth: email/password login with MD5-signed requests; session token persisted
  via QSettings
- Playback: double-click a track → Rust fetches stream URL → Symphonia decodes
  → CPAL outputs to default audio device
- Dark Fusion palette matching spotify-qt feel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 23:34:23 +01:00