Commit Graph
7014 Commits
Author SHA1 Message Date
vicrodh 93ba7584b0 fix(qt): polish purchases queue and search loading
cx
2026-09-05 14:39:07 -06:00
vicrodh 9cbe58c7d8 merge: integrate purchases local copy fixes
cx
2026-09-05 12:11:07 -06:00
vicrodh f01950571d fix(purchases): restore local copy and download semantics
Restore downward stream-format downloads while keeping purchased masters on the download grant. Make Purchases playback prefer the highest complete local copy, repair duplicate copy inventory, and move copy management into a bounded modal with safe library and record actions.

cx
2026-09-05 12:10:55 -06:00
vicrodh 92c87d190f merge: integrate SACD raw and DST ISO support
cx
2026-09-05 10:01:37 -06:00
vicrodh 4bb4982312 feat(sacd): support raw and DST-compressed ISO playback
Parse resilient SACD images, decode DST, scan ISO releases into the local library, and keep explicit opens ephemeral.

Ship decoder notices across distribution formats and align DSD album filtering and version selection.

cx
2026-09-05 10:00:24 -06:00
vicrodh b4c706b828 merge: integrate distribution and artist library release work
cx
2026-09-04 14:21:20 -06:00
vicrodh c7cee95ac2 merge: integrate artist library fixes into release branch
cx
2026-09-04 14:04:10 -06:00
vicrodh 2fdf8878dc i18n: add the artist-page and Qobuz-links strings to all eight locales
"Play random", "Play selected", "Cancel selection", "QOBUZ LINKS", "Open
Qobuz links in QBZ" and the toggle's description. msgfmt --check clean.

cc
2026-09-04 13:10:42 -06:00
vicrodh 4ac6b4006e feat(integrations): make the qobuzapp:// handler a setting
Claiming the official client's `qobuzapp://` scheme was a side effect
of installing. On Linux that displaces nobody; on macOS and Windows the
official client registers the same scheme, and on Windows — where QBZ
is only starting to be adopted — taking the browser's links over at
install time is not a reasonable default. `qbz://` (our own scheme)
stays registered unconditionally.

Settings > Integrations > "Open Qobuz links in QBZ" (link_handler_qt,
pref `qobuz_links_enabled` beside the other Integrations opt-ins),
default on for Linux/macOS and OFF on Windows. The registration moves
only when the toggle is flipped; the one startup reconciliation is
conservative — a claim pointing at this executable while the setting is
off (the 2.0.x MSI wrote one) is dropped, nothing is ever claimed on its
own.

Windows writes/removes HKCU\Software\Classes\qobuzapp (deleting only a
tree whose command names this exe); macOS uses Launch Services and hands
the default back to the first other handler on off; Linux runs xdg-mime
on. The MSI no longer registers qobuzapp and the workflow's protocol
checks cover qbz only. The Windows and macOS arms build on their
platform gates, not on this box.

cc
2026-09-04 13:10:42 -06:00
vicrodh 6d07dfdf4d feat(artist): sort for the in-library albums and a split play button on every album section
The "In library" Albums section gains the release buckets' sort select
(same five keys, persisted by artist_prefs under the pseudo release type
"library"; rows sorted in QML off the document's seed). Every album
section — each catalog bucket and the library grid — gains a split
button right of its sort (controls/QbzSplitButton.qml, sized like the
sm select): the body plays the whole section in its sort order as one
queue replacing the current one (`QbzPlayer.playAlbums` ->
`playback_qt::play_albums`, each album resolved through the single-album
path, failures skipped), the chevron offers Play random (one album of
the section) and Play selected, which arms a per-section select mode:
the cards show their check bottom-right inside the art
(`AlbumCard.selectMarkBottom`), the button reads "Play selected (n)" and
plays the checked albums in sort order, and the menu swaps that row for
Cancel selection. One section is armed at a time; changing artist or
tab disarms. No queue options on purpose.

cc
2026-09-04 13:10:42 -06:00
vicrodh c85fbac4c7 fix(artist): keep the jump-nav mounted in library mode and park the filters past the magnifier
With both source switches on over an artist whose purchases are not
hearted, the library tab's section set was empty, the strip unmounted,
and the switches — which live in the strip — went with it, leaving no
way to reset the filter. "About" (the strip's back-to-top) is now always
present in library mode, landing on the page top since the library
column carries no bio anchor; the active tab on a mode switch is still
the first real section.

The trailing slot moves to the far right of the bar, past the search
toggle: the field grows LEFT over the tabs when it opens, so controls
left of the magnifier were covered while typing.

cc
2026-09-04 11:51:59 -06:00
vicrodh 32109e4ca4 ci(release): require RPM repository dispatch
cx
2026-09-04 10:48:12 -06:00
vicrodh 3bce452f6d fix(packaging): prevent qbz and qbzd file conflicts
cx
2026-09-04 10:45:52 -06:00
vicrodh 89b621264e fix(artist): in-library tab queues its own list, gets a Tracks section and a mode-aware jump-nav (#737)
A track clicked under "In library" played the artist's POPULAR queue:
every row of the page went through `QbzPlayer.playArtistTrack`, whose
queue is TOP_QUEUE and which starts that list at row 0 for any id it
does not hold — the exact symptom in #737, including "it works only when
the song is also popular". The library rows now play through
`QbzLibrary.libraryPlayVisible` with the tab's full filtered list, the
source-aware seam LibraryView uses; `PopularTrackRow` takes a
`playHandler` instead of knowing which tab it is in.

The tab itself becomes a first-class view over `artist.libraryItems`:

- Tracks section modelled on Popular Tracks — header action cluster
  (Play all, select mode, the shared ⋯ menu re-pointed at the library
  list), 10-row preview built from a numeric model, Load more / View
  less opening the whole list.
- JUMP TO follows the mode: in library only the Tracks / Albums sections
  that have rows, resolving anchors against the library column (the
  catalog set stayed up before and "Popular Tracks" scrolled to a section
  that was not drawn).
- Purchases / favourites switches float in the strip while the tab is
  active, with the Library > Albums/Tracks semantics (neither = union,
  one = that source, both = intersection) and page-local state.
- A cleared heart fades the row (purchases stay); the settle republishes
  the document and the row leaves. When the last row goes the page
  returns to the catalog instead of an empty tab.
- Selection and bulk actions run over the active mode's lists; a mode
  switch clears the selection and re-arms the warm from cache.

The view no longer parses `QbzLibrary.libraryJson` per binding.

cc
2026-09-04 10:41:52 -06:00
vicrodh 010b1da8d8 feat(qt): warmLibrary invokable and a trailing slot on the jump-nav bar
`QbzArtist.warmLibrary` lets the artist page's "In library" toggle re-arm
the Library feed warm (a fetch only if the session never loaded it, a
cache repaint otherwise). `QbzJumpNavBar.trailing` is a host-filled slot
between the tab strip and the magnifier, sized by its children and
costing nothing when empty, so a page can float mode-specific controls
in the strip without reflowing the tabs.

cc
2026-09-04 10:41:51 -06:00
vicrodh 40df0d83be feat(library): keep the artist page's in-library rows live
The artist page's "In library" count was a snapshot of the Library feed
taken when the document was built, over a feed that only loads when the
Library view is opened and that never gains a row for a favourite created
afterwards. On a cold session, or after an account switch, every artist
opened with an invisible toggle; hearting an album on the page moved
nothing until the next session.

- library_qt: `artist_library_items` computes the tab's rows with the
  Library > Albums/Tracks rule (favourites ∪ purchases, one row per
  entity, purchase row representative, `is_favorite` = also hearted);
  local/Plex and `following` rows never enter. A track is a member
  through its performer OR its album's main artist (new
  `FeedItem::album_artist_id`, fed by the new `AlbumSummary::artist`,
  which the wire carries — search-results capture).
- library_qt: `reconcile_qobuz_favorite` inserts the row of a freshly
  hearted track/album (one `/track/get` or `/album/get`, mapped by the
  same producers the full load uses) and drops the `favorites` rows of a
  cleared one, keeping a purchase row with its heart cleared.
- artist_qt: the rows ride inside the artist document (`libraryItems`),
  and `refresh_library_items` / `apply_favorite_change` republish them
  through `publish_patch` when the feed lands or a heart settles. A
  debug-level log prints the membership split for the open artist.
- main: `settle_favorite` is the one settle point (reconcile, fan out,
  republish on membership change) for the Library and queue-panel
  hearts; `open_artist` warms the feed in the background; `reload_library`
  hands the open page its rows; `warm_library` serves the toggle from
  cache.

Tests: membership by performer or album artist, exclusion of local /
following, dedup on the purchase row, and the `top_queue` contract that
a foreign id starts the popular list at row 0 (the #737 defect class).

cc
2026-09-04 10:41:51 -06:00
vicrodh 49227b49e8 ci(release): harden remaining artifact workflows
cx
2026-09-04 09:16:21 -06:00
vicrodh 3705c0592c fix(packaging): update Nix package for Qt frontend
cx
2026-09-04 09:16:15 -06:00
vicrodh a9a849c1ec fix(packaging): harden Snap release inputs
cx
2026-09-04 09:16:10 -06:00
vicrodh 41fb509f09 fix(packaging): align Flatpak permissions and assets
cx
2026-09-04 09:16:04 -06:00
vicrodh 0d1cdb5e89 feat(packaging): complete Linux release assets
cx
2026-09-04 09:06:02 -06:00
vicrodh ad9378e1d1 feat(packaging): add complete Gentoo package set
cx
2026-09-04 09:05:19 -06:00
vicrodh 56059e6814 feat(packaging): add complete AUR package set
cx
2026-09-04 08:27:17 -06:00
vicrodh c85908e262 docs(qbzd): document non-systemd services
cx
2026-09-04 08:27:05 -06:00
vicrodh 30912962d3 feat(library): refine track source controls
Preserve the remaining queue when shuffle is disabled, expose clear transport state tooltips, retain Library source filters for the session, and add independent track-artwork preferences for Queue and Library.

cx
2026-09-03 14:53:22 -06:00
vicrodh f833a5a401 fix(tooling): audit the active Qt tree by default
cx
2026-09-03 09:34:31 -06:00
vicrodh fb928df2ff fix(library): retain source filters for session
cx
2026-09-03 09:07:22 -06:00
vicrodh 23941a0958 feat(purchases): refine purchased album presentation
cx
2026-09-03 09:07:18 -06:00
vicrodh 38263d2bc0 fix(playback): fence late purchase materialization
cx
2026-09-03 05:52:13 -06:00
vicrodh 639fdc082d feat(playback): honor album purchase preference
cx
2026-09-03 05:41:22 -06:00
vicrodh 8566b68411 feat(purchases): persist copy coverage manifests
cx
2026-09-03 05:18:22 -06:00
vicrodh c0a37e6b87 feat(purchases): manage independent download copies
cx
2026-09-03 05:13:05 -06:00
vicrodh 59bd3ab6b2 feat(purchases): add copy-aware download receipts
cx
2026-09-03 04:36:41 -06:00
vicrodh 561b3c25c7 feat(purchases): gate album actions by entitlement
cx
2026-09-03 04:32:23 -06:00
vicrodh 247c0403b7 feat(library): type folder registration and queue scans
cx
2026-09-03 03:58:44 -06:00
vicrodh 03e55684e0 feat(library): persist distinct purchase copies
cx
2026-09-03 03:45:21 -06:00
vicrodh 8eb2afe4db fix(library): preserve unreachable purchase records
cx
2026-09-03 03:40:14 -06:00
vicrodh bb5172812a merge: repair test Track fixtures
cx
2026-09-03 03:05:32 -06:00
vicrodh 7f5e28ccac test(models): update Track availability fixtures
cx
2026-09-03 03:05:20 -06:00
vicrodh de82962ed2 merge: local library fixes and direct DSD seek
cx
2026-09-03 02:33:01 -06:00
vicrodh 8aab112afe feat(dsd): support seeking in direct playback
Add random access for DSF, DFF, and SACD demuxers, replace live DoP/native sources without releasing ALSA, and expose seek through Qt, MPRIS, and the daemon API.

cx
2026-09-03 02:32:52 -06:00
vicrodh ea92f07b66 fix(local-library): restore responsive source-aware browsing
Show SACD images in folder grouping, keep track details responsive, avoid repeated album reload work, and exclude disabled or unconfigured media servers from filters and sync.

cx
2026-09-03 02:32:37 -06:00
vicrodh 6afcfad4f4 merge: local mp3 duration, dlna end-stall, dsd chip, sacd scan and memory trims
cc
2026-09-02 20:35:37 -06:00
vicrodh 478a80a5d7 perf(qt): cap malloc arenas, eight tokio workers, idle L1 trim
Measured on a 24-core box: 52 threads held 82 glibc malloc arenas, 257 MB
of fragmented anonymous mappings at idle, and the 400 MB in-memory audio
cache kept every played track until another evicted it. main now calls
mallopt(M_ARENA_MAX, 2) before the first thread (an explicit
MALLOC_ARENA_MAX wins), the tokio runtime runs eight workers instead of
one per core, and the playback poll moves the L1 audio cache to the L2
disk cache after 300 s with nothing audible locally, remotely or on a
cast. Idle RSS went from 728 MB to 537 MB; the trim verified at exactly
300 s after a pause.

cc
2026-09-02 20:34:59 -06:00
vicrodh 024cc121a9 feat(library): adopt SACD images found by the folder scan
The scan never treated an .iso as audio; images only entered the library
through Open > disc image. Each root's scan now walks its .iso files,
asks qbz_disc::sacd::is_sacd_image for the SACDMTOC signature (PVD plus
Master TOC sector, four 2 KB reads at most, no directory parsing) so a DVD
or data ISO leaves silently, skips images already imported with the same
size and mtime without any I/O, and adopts the rest through the
generation-based import. The row builder moved from sacd_qt into
qbz_library::sacd_scan and the manual open is now its client, with the
translated fallback labels. Parser and import rejections are scan errors.

cc
2026-09-02 20:34:59 -06:00
vicrodh 1f54fd9fcb fix(qt): Local Library header gear opens Settings > Local Library
It landed on the Audio root; the row now sets section 4 through the same
invokable the settings sub-navigation uses before navigating.

cc
2026-09-02 20:34:59 -06:00
vicrodh baf0dc2bb9 feat(local-library): DSD quality chip
DSD gets its own Quality chip and Hi-Res goes back to 24-bit PCM only, in
the MediaFilter, the native catalog SQL (tracks CASE and the materialized
album quality_tier) and the legacy QML filters. A Format chip would be the
same predicate, so there is none. Schema version 6 re-derives the album
tiers that were materialized as hires.

cc
2026-09-02 20:34:59 -06:00
vicrodh 35ff1818f6 feat(qt): say "not yet available" on pre-release tracks
/album/get sends streamable_at and release_date_stream per track: a future
value marks a pre-release, null a pulled track. Track carries both fields
and Track::is_upcoming applies the one rule (future streamable_at wins,
then a future release date); the album, playlist, search and label rows
publish qobuzUpcoming and the unavailable glyph reads "This track is not
yet available" instead of "no longer". Artist page rows carry no dates and
keep the generic copy. New msgid in the seven translated catalogs.

cc
2026-09-02 20:34:58 -06:00
vicrodh feb2c9de12 fix(qt): pin the quality stamp tooltip to its text
The now-playing stamp bubble came out wider than its lines with the text
offset, and never reproduced in isolation. The three stamp ToolTips now
bind width/height straight to the content's implicit size with zero
paddings, insets and margins, leaving nothing for the style to add.

cc
2026-09-02 20:34:58 -06:00
vicrodh ca0aa0e6bf fix(cast): survive a DLNA renderer that never reports STOPPED
A KEF LSX reached the end of every track and never advanced (#733); its
poll answers were swallowed, so an INFO log could not tell a mute renderer
from one that never reports STOPPED. The DLNA poll now logs a failed
position read, GetTransportInfo faults degrade to the last transport
command instead of failing the whole read, and a RelTime frozen inside the
end guard for five polls without STOPPED counts as end-of-track. A user
pause never counts. Pure helper with unit tests.

cc
2026-09-02 20:34:58 -06:00