Commit Graph
2448 Commits
Author SHA1 Message Date
vicrodh c1116613b9 Merge remote-tracking branch 'origin/pre-release' into feature/internal/windows-port 2026-08-27 10:27:58 -06:00
vicrodh be3f423bc4 feat(audio): WASAPI exclusive-mode direct stream (Windows)
The render thread and the handle. COM objects are !Send, so one thread owns
every one of them for the life of the stream and this struct is a bounded
channel plus atomics - the same back-pressure snd_pcm_writei gives the ALSA
path for free.

Opens by ENDPOINT ID, never by friendly name: Windows gives several
endpoints the same name, which is what hid this DAC from the picker until
249adc77b. Walks the format ladder, pre-aligns the period to 128 bytes,
keeps the documented NOT_ALIGNED recovery for the devices that still need
it, joins MMCSS Pro Audio, and refuses S_FALSE loudly - a "closest match" is
by definition not the format we asked for.

Verified against the owner's Cambridge Audio USB Audio 2.0 with the new
example, and it matches the spike exactly:

  rate 96000, S24In32 (24/32), period 30000 hns, buffer 288 frames,
  realigned false, timing Events, mode DirectHardware,
  960000 frames, 0 underruns, 0 event timeouts

Three faults were found on the way, and all three were in the MEASUREMENT
rather than the audio - worth recording because each looked like a hardware
problem:

  - 339 "underruns" were event timeouts counted in the same counter. Split
    them; they are different faults and were hiding each other.
  - 337 event timeouts came from a 2x-period deadline. At a 3 ms period that
    expired on 10% of wakeups because Windows scheduling is not that
    punctual. The deadline exists to stop the thread hanging on a dead
    device, not to detect glitches, and the spike waited 1000 ms and saw
    none in ten minutes. It is generous now.
  - The last 2 were a drain's trailing silence. A drain emitting silence is
    the drain working.

The stub for every other platform mirrors alsa_direct's: constructors refuse,
teardown succeeds, so a caller written against this compiles and unwinds
everywhere. `cargo tree` shows exactly one windows v0.62.2 - no second
windows tree entered the graph.

cc
2026-08-27 09:10:37 -06:00
vicrodh 1a01abde60 docs(qt): correct empty Windows environment example
cx
2026-08-27 09:05:26 -06:00
vicrodh cc3a11f254 feat(audio): the pure layer of the WASAPI exclusive path
Format ladder, PCM packing and period arithmetic for phase B, with the tests
that make them provable. No COM yet: this half compiles and is tested on
every host, which matters because it is where the platform-specific mistakes
live.

The one that bites: Windows 24-in-32 is LEFT-aligned, the 24 valid bits in
the HIGH bytes, where ALSA's S24_LE is right-aligned. Porting the ALSA
packing verbatim shifts every sample down 8 bits and plays 48 dB QUIET, which
sounds like a volume bug and survives a listening test. There is a test whose
only job is to fail if that ever happens.

Scaling matches alsa_direct exactly (8_388_607 and 32767, not the power of
two), so the two backends cannot disagree about full scale. The plan's test
sketch asserted i16::MIN and -8_388_608; those follow from the OTHER scaling
choice, so the tests assert the behaviour this file actually has.

aligned_period_hns rounds the period so frames * block_align is a whole
number of 128-byte blocks, which is how AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED
stops firing rather than being recovered from. Verified against the two
periods measured on the owner's DAC: 3 ms at 192k 24-in-32 is already
aligned at 576 frames and must not move.

LADDER order comes from research/01; the spike found that this DAC accepts
only S24In32, so the ladder is one rung deep there. It stays a ladder because
other devices are not.

cc
2026-08-27 08:52:13 -06:00
vicrodh 4ccff36139 feat(qt): surface the opened stream's BitPerfectMode on the quality stamp
The mode LED is derived from SETTINGS (output_labels.rs reads
audio.exclusive_mode and the ALSA plugin), so it reports what was ASKED FOR.
Nothing reported what the opened stream actually negotiated, which means
"exclusive worked" and "we asked for exclusive" were indistinguishable - and
that distinction is what phase B's acceptance turns on.

PlaybackEvent already carries bit_perfect_mode, so this is a publish, not new
plumbing: the poll tick maps it to direct | plugin | disabled | unknown and
set_effective_stream dedupes on it alongside the delivered params, so a
steady stream still costs no Qt-thread hop. The quality tooltip appends
"stream: <mode>" on both of its paths; unknown and empty print nothing.

Four technical tokens, so no new translatable string.

cc
2026-08-27 08:49:21 -06:00
vicrodh 559f8bfce6 fix(qt): pin the FreeType font engine on Windows
Qt's default rasteriser on Windows renders text thin and jagged. The owner's
words for the lyrics panel were "como fuente de bloc de notas con extra
alias", and the supplied screenshot shows exactly that: broken strokes and
visible stair-stepping on every line.

It is the RASTERISER, not the font and not the lyrics view. Verified on the
box by launching the same build with
QT_QPA_PLATFORM=windows:fontengine=freetype and comparing the same panel:
identical font, identical sizes, clean glyphs. So the fix belongs at the
application level, where it also cleans up the rest of the UI.

Applied only when the variable carries no real value. `offscreen` is what
the release smoke gate passes here and overwriting it would make the gate
test a platform nobody ships. Empty counts as absent for the same reason the
renderer preference now does: a cleared variable is present-with-no-value,
which var_os().is_some() reports as set.

cc
2026-08-27 08:49:21 -06:00
vicrodh 4f31e8312d fix(qt): an EMPTY Qt backend env var must not disable the renderer preference
apply_renderer_preference gated on var_os("QSG_RHI_BACKEND").is_some(), which
answers YES for a variable that is present with no value. Clearing a variable
rather than unsetting it is the common way to end up there - `QSG_RHI_BACKEND=
./qbz` in a shell, and on Windows PowerShell's SetEnvironmentVariable(name,
$null), which leaves the name present and empty. The whole preference then
stopped applying, the user's persisted Settings choice included, and the only
clue was one info line claiming an explicit backend was present.

Found on the Windows box, where a test harness cleared the variable that way
and the renderer arm silently never ran. It reproduces on Linux the same way;
this is not a platform fix.

QBZ_RENDERER, read a few lines below, has always filtered the empty string.
This applies the same rule to the two Qt variables. The predicate is split
from the lookup so the three new tests exercise it without mutating
process-global env, which would race the other tests in the binary.

cc
2026-08-27 08:39:53 -06:00
vicrodh 93b506dcd6 fix(paths): route the hand-rolled file:// strips through local_path
A regression from 8baf68db8, reported from the running app: the album and
artist header gradients stopped appearing on Windows.

Six sites undid a file:// URL by hand with strip_prefix/trim_start_matches.
Before the URL builder was fixed they worked BY ACCIDENT: file_url produced
the broken "file://C:\Users\x", and stripping seven characters off that left
a valid Windows path. With the URL correct at "file:///C:/Users/x" the same
strip yields "/C:/Users/x", which opens nothing - so the fix to the QML-
facing half broke the Rust-facing half everywhere the inverse was open-coded.

atmosphere_qt.rs is the one that showed: it decodes the cover to build the
128x128 field the header gradient IS, so a failed open means no gradient at
all, with nothing logged. album_qt.rs feeds the same pipeline plus the flat
tint, ambient_qt.rs extracts the colour triad, artwork_qt.rs uses the string
as BOTH a cache key and a path, myqbz_detail_qt.rs hands a bare path to the
artwork channel, and qbz-source returns an ArtRef::File.

local_path also undoes the three percent-escapes these sites never did, so a
cover under a path holding # ? or % now opens on every platform - previously
it failed on all of them. The two sites that hash the string will miss their
cache once and regenerate.

Three strips deliberately stay: notify.rs is cfg(linux, macos); the
playlist-import one takes a filename STEM, where a leading slash cannot
matter; and qbz-theme parses a COSMIC desktop config Windows never reads.

The plan's step-8 grep could not have caught these - it searches for
starts_with('/') and format!("file://, not for the inverse.

cc
2026-08-27 04:27:13 -06:00
vicrodh 249adc77b3 fix(audio): identify Windows output devices by endpoint id, not friendly name
Windows endpoint friendly names are not unique. Measured on this box, FOUR
active render endpoints resolved to three display strings, and two were both
called "Altavoces": the onboard Realtek and a Cambridge Audio USB DAC.
device_filter dedups on the display, so the DAC was folded away and could
not be selected at all - and a DAC you cannot select cannot be sent a
bit-perfect stream, so this also blocked phase B.

device_filter.rs:20-23 states the opposite in a comment - "macOS/Windows
device names carry unique displays, so they pass through untouched". That is
the third comment in this tree asserting a mechanism that does not hold.

Nothing new is queried: cpal 0.17.3 already fills the fields this backend
ignored. name() is the ENDPOINT and repeats; driver() is the ADAPTER and is
what tells them apart; id() is the stable WASAPI endpoint GUID. On Windows
the id becomes the GUID, the display becomes "endpoint (adapter)", and the
adapter lands in the description field that was hard-coded None. The default
device is matched by id there too, since three endpoints shared a name.

Additive cfg arms only, per the protected-core rule: every other platform
takes the same (name, name, None, name == default_name) tuple it took
before, byte for byte. The open path keeps the name comparison as a fallback
so a device_id saved before this change still resolves.

Verified against the real hardware, before and after, with a standalone cpal
probe: the DAC goes from DROPPED to listed, labelled and flagged default.

cc
2026-08-27 04:07:31 -06:00
vicrodh fc0d35e295 fix(qt): platform capability flags, and hide the audio rows nothing can honour
Adds isWindows, traySupported, systemNotificationsSupported and
rendererSelectable to the settings document, so Settings QML keeps reading
ONE document the way it already does for isMacos. The two any(...) lists
flip to include Windows when plan A-2 T3/T5 land; they point at that line.

Then the Audio tab, measured on the box with the tab open:

HiFi Wizard was live on Windows. qbz-dac-wizard-core generates a
PipeWire/WirePlumber config and knows no other stack, so the wizard cannot
finish anywhere but Linux. Hidden, not disabled - a disabled row invites a
bug report. This is not the reference's backend-is-pipewire gate returning:
inside Linux every backend still sees it, per the 2026-08-11 ruling in that
file's own comment.

Reserve DAC is D-Bus org.freedesktop.ReserveDevice1, Linux only. On Windows
exclusive mode IS the reservation; on macOS it is Hog Mode.

Exclusive mode was visible with no backend able to honour it. It now follows
the backend: Linux unchanged (always visible, enabled only on ALSA), hidden
on macOS, and on Windows it appears when Phase B publishes backendIsWasapi.
QML reads an absent doc property as undefined and undefined === true is
false, so this is correct today and correct again the day the field lands.
The DSD row follows the same pair.

Main.qml no longer boots the wizard off Linux, where its row is hidden and
the audio-stack probe would reach nothing.

Linux sees no change: every gate is isLinux-true or an added || on a field
that is undefined there. Five QML audits pass.

cc
2026-08-27 04:01:13 -06:00
vicrodh 7135c841cb build(windows): embed the icon, VERSIONINFO and a longPathAware manifest
winresource, not winres: winres has been unmaintained since 2021 and this
is its maintained fork. Gated to cfg(windows) as a target build-dependency,
so no other platform resolves it at all.

The manifest declares longPathAware and NOTHING else. Qt 6 sets
PerMonitorV2 itself at startup and a manifest DPI declaration is immutable,
so the two together either log a permanent COM error 0x5 or degrade
scaling - Qt owns DPI awareness.

The .ico carries 256/128/64/48/32. The four small entries are BMP and only
256 is PNG: measured on this box, System.Drawing.Icon (GDI+) throws
ArgumentOutOfRangeException in ToBitmap() on a PNG-payload entry, while WIC
decodes it. 256 has to be PNG because the directory encodes its size as 0.
Pixels verified against the source PNG at four points including an
asymmetric one, which is what proves the BGRA order and the bottom-up flip.

cc
2026-08-27 03:46:29 -06:00
vicrodh 77f7840ae7 fix: one hostname resolver, honouring COMPUTERNAME
Three copies read HOSTNAME and then /etc/hostname. Windows has neither, so
every Windows install fell through to the same last-resort word and they
collided on Qobuz Connect. One implementation in qbz-app; HOSTNAME keeps
precedence so Linux behaviour does not move.

qbzd/src/qconnect/transport.rs was a fourth copy the plan did not list, and
the settings_qt.rs one it did list no longer exists on this branch. Both
callers keep their own last-resort word - "Desktop" here, and qbzd's own -
because they are user-visible and mean different things.

qbz-credentials/src/lib.rs:273 also reads HOSTNAME and is deliberately NOT
touched: it is a salt in the KDF fallback chain, not a device label, so
adding COMPUTERNAME there would change the derived key on Windows and make
every already-encrypted credential file undecryptable. That is W17.

cc
2026-08-27 03:46:05 -06:00
vicrodh 45e0be125e feat(qt): expose is_windows on the shell bridge
Windows was neither is_macos nor is_linux, so QML could not name it and
every two-way platform ternary handed it the Linux arm by default.
Compile-time constant like the other two.

This is infrastructure, not a fix: the audit below found NO site that
currently resolves wrong on Windows. It is the property the settings
per-platform work and the A-2 chrome slice branch on.

Every two-way platform branch, and what Windows gets today:

  Main.qml:145 chrome flags      -> Qt.Window. default_use_system_title_bar
                                    is !cfg!(macos), so systemTitleBar is
                                    true on Windows and the ternary never
                                    reaches the macOS/Linux arms. With the
                                    title bar off it takes FramelessWindowHint,
                                    which is also the right arm on Windows -
                                    ExpandedClientAreaHint paints nothing there
  Main.qml:241 macOS diagnostic  -> skipped
  Main.qml:435 macChromeTimer    -> not running
  Main.qml:640 traffic-light inset -> skipped
  ImmersiveHeader.qml:42         -> no macOS inset
  HeaderBar.qml:89 drawn cluster -> gated on showWindowControls, which the
                                    native title bar leaves off; only the
                                    native buttons are drawn (confirmed on screen)
  HeaderBar.qml:104              -> no macOS inset
  AppearanceSettings.qml:493     -> hidden (useSystemTitleBar is true)
  AppearanceSettings.qml:510,521 -> visible; both are meaningful on Windows
                                    and 521 is the route to custom chrome
  AppearanceSettings.qml:583,603 -> hidden
  AppearanceSettings.qml:630-646 -> renderer group hidden
  hotkeys_qt.rs:423,961          -> Ctrl glyphs
  main.rs:3099-3102              -> has its own Windows arm
  renderer_qt.rs:420             -> gpuSelectable false, GPU row hidden
  settings_qt.rs:469             -> system title bar on by default
  settings_qt.rs:2258            -> is_macos false

cc
2026-08-27 03:46:05 -06:00
vicrodh 0ba1b05be9 fix(paths): undo verbatim prefixes, keep the UNC authority, leave relative alone
Adversarial review of the previous commit found four defects, three of them
mine and one of them fatal to the Local Library on Windows.

fs::canonicalize RETURNS extended-length syntax on Windows and
qbz-library/src/scan.rs stores that string for every scanned file, so the
helper saw \?\C:\Music\cover.jpg, read it as a UNC path whose server was
"?", and emitted file://%3F/C:/Music/... - every local cover, gone. Both
verbatim spellings are now undone, \?\UNC\ included.

local_path dropped the // that a UNC authority stands for, so the round trip
returned nas/music/x, a path that names nothing. It now returns
//nas/music/x, which is also what QUrl::toLocalFile gives back.

file_url pushed a third slash for any path that did not start with one, so a
relative artwork_path changed from file://covers/x to file:///covers/x on
Linux. Neither resolves - a relative path is not a valid file:// URL - but
Linux behaviour does not move in a Windows port. The extra slash is now
emitted only for a drive path.

is_local_abs_path now requires a separator after the colon, so C:cover.jpg
is drive-RELATIVE and no longer claimed as absolute on either platform.

The two residual ambiguities - a Unix path whose first component is a single
letter plus a colon - are documented at the top of the module rather than
papered over: no string algorithm separates them, and deciding by host would
put the failure back on the machine that ships.

Four regression tests added, one per defect.

cc
2026-08-27 03:37:38 -06:00
vicrodh 8baf68db84 fix(paths): one file:// helper and a shape-based absolute-path test
Seven sites built format!("file://{p}") by hand or tested starts_with('/')
for "absolute path". Both are Unix-only: file://C:/... parses the drive
letter as the URL HOST, and C:\... does not start with '/'. On Windows
that silently cost every album cover, every runtime-tinted icon and the
local folder tree - a URL that resolves to nothing renders as an empty
rectangle, not as an error, so nothing complained.

qbz_models::fs_url now owns file_url / local_path / is_local_abs_path,
deciding by path SHAPE (POSIX, drive, UNC) rather than by host, so the
tests run and fail everywhere rather than only on Windows.

Linux behaviour is unchanged, deliberately: the backslash-to-slash rewrite
fires only for a Windows-shaped input, because a backslash is a legal
filename character on Unix and rewriting it would point /home/v/AC\DC at
a directory that does not exist. There is a test for exactly that.

Three of the seven sites were not in the plan's list and were found by its
step 8 grep: local_ephemeral.rs, local_playlist_qt.rs, playback_qt.rs.
Two starts_with('/') hits stay and are not local-path tests:
qbz-library/src/mount_info.rs is cfg(linux) mount-point arithmetic, and
qbz-theme's is parsing a COSMIC desktop config that Windows never reads.

cc
2026-08-27 03:22:32 -06:00
vicrodh 3e8a1cf942 build(windows): GUI subsystem so no console opens beside the app
windows_subsystem was declared nowhere, so the app carried a console
window on Windows. The file logger is unaffected; only the inherited
stdio console goes.

The offscreen smoke gate has not run against this yet. If smoke.log comes
back empty the fix is AttachConsole(ATTACH_PARENT_PROCESS) behind
cfg(windows), not reverting this; there is a note at the attribute saying
so.

cc
2026-08-26 23:07:25 -06:00
vicrodh 8a08dcb69e fix(qt): Windows arm for the gl renderer pref; pin the Basic controls style
The gl/gles/femtovg pref forced QSG_RHI_BACKEND=opengl on every non-macOS
host, dragging Windows off its healthy d3d11 default onto desktop GL. That
is a downgrade, not the GPU tier the pref means, so Windows takes the same
remap macOS already had.

And with no explicit style Qt loads Windows on Windows and Fusion on
Linux, never Basic, so the popups without an explicit background inherit
native chrome. Pinned before QGuiApplication, since it must run before the
first QtQuick.Controls import, and windeployqt then ships one style.

cc
2026-08-26 23:07:25 -06:00
vicrodh 42bc4ba1ec fix(windows): do not panic in souvlaki without an HWND; open folders via open::that
souvlaki's Windows backend does config.hwnd.expect() at
platform/windows/mod.rs:57, so the None we passed was a panic inside a
tokio task on the first session, not the Err the match was written for.
The comment on that field claimed init would merely fail; it was read from
the comment, not the mechanism. No HWND is wired yet, so spawn() bows out
on Windows and the body moves to spawn_native, which is compiled out
there. Phase A ships without media keys and says so.

The offline-folder opener spawned xdg-open on every non-macOS host,
Windows included, where it does not exist. Route it through the open crate
like the other eleven sites in this crate; Linux and macOS reach the same
two binaries as before.

cc
2026-08-26 23:07:11 -06:00
vicrodh f06ffc7141 fix(qbzd): gate the instance lock per OS
lock.rs imported std::os::unix and called libc::flock unconditionally, so
a workspace test run could not compile on Windows.

The Windows arm locks ONE byte at offset 1 GiB rather than the whole file.
Byte-range locks are mandatory there, not advisory like flock: measured on
this box, a whole-file lock from offset 0 makes the losing instance's
read_to_string fail with ERROR_LOCK_VIOLATION, so AlreadyRunning would
always carry None - the pid is the only reason that variant exists. With
the lock byte past any content the pid still reads back, the same handle
conflict is still detected, and the lock still releases when the File
drops. Reserving a region past EOF is what SQLite's Windows VFS does.

Only ERROR_LOCK_VIOLATION means contention; a filesystem that does not
implement byte-range locks answers ERROR_INVALID_FUNCTION and must surface
as Io, not as a daemon that is not running. The unix arm keeps its
existing any-failure-means-busy behaviour unchanged.

cc
2026-08-26 23:07:02 -06:00
vicrodh 57f900bec4 fix(local-catalog): Windows arms for free-space preflight and bootstrap lock
The not(unix) arm returned Err and both preflight() and prepare()
propagate it, so the catalog never bootstrapped on Windows and the Local
Library died at preflight.

GetDiskFreeSpaceExW on the nearest existing ancestor, since the catalog
root may not exist on first run; LockFileEx with FAIL_IMMEDIATELY, mapping
ERROR_LOCK_VIOLATION to BootstrapBusy like the flock arm and any other
error to Io. Nothing reads this lock file's contents, so the whole-file
range is safe here.

cc
2026-08-26 23:06:52 -06:00
vicrodh b94e0e6cdb fix(secrets): select the keyring backend per target and refuse the mock
qbz-credentials still asked for the Linux features on every target with
default_features on. keyring 3 has no default backend: without the
per-platform feature it exports the in-memory mock, whose writes succeed
and whose contents die with the process, so the offline-cache master key
was regenerated every launch and every wrapped blob failed AES-GCM on the
next start, with the logs reporting a working keyring. It survived only
because Cargo unified features with qbz-secrets, which is the fragility
the per-target block exists to remove.

Also refuse a non-disk-backed backend at runtime and take the KDF path.
Measured in keyring-3.6.3, not assumed: windows.rs, macos.rs and
secret_service.rs all inherit the trait default UntilDelete
(credential.rs:171); mock.rs:228 overrides it to EntryOnly. Testing for
ProcessOnly, as first drafted, would never have fired.

cc
2026-08-26 23:06:41 -06:00
vicrodh 18a3d01152 build(qt): pass the MSVC conformance flags Qt 6.9 requires
Neither cc-rs nor cxx-qt-build passes them, and without both nothing that
includes a Qt header compiles on Windows.

/Zc:__cplusplus: MSVC reports __cplusplus as 199711L whatever /std: says,
and qcompilerdetection.h:1317 rejects that value outright on every
translation unit, ours and moc's alike.

/permissive-: measured on Qt 6.9.3, the headers do not parse in MSVC's
default mode - qtmochelpers.h:262 C2065 'result', qcomparehelpers.h:1348
C2968 recursive alias, and C2737 on every moc staticMetaObject.

Applied to both cc builders: this crate's own, which compiles the nine RHI
items, and cxx-qt's. Patching only the latter changed nothing, because the
failure came from the former. Gated on the target env, so the Linux and
macOS builds cannot see either flag.

cc
2026-08-26 23:06:31 -06:00
vicrodh 6beb1e695e build(qt): slash-normalise qrc aliases and find qsb.exe
qt-build-utils writes the collected path verbatim as the qrc alias, and
read_dir joins with a backslash on Windows, so none of the 1469 aliases
resolved: 1106 icons, 9 fonts and 21 shaders would each fail with
"Cannot open". Normalise only when the build host is Windows, since a
backslash is a legal filename character on Unix.

Also probe qsb.exe and QT_ROOT_DIR/bin, because Path::is_file never
appends .exe, and fix the SpectrumBand hand-bake comment, whose command
lacked --hlsl 50 and the GLES variants that build.rs actually passes.

cc
2026-08-26 23:06:20 -06:00
vicrodh d9ed19eb64 refactor(mixtape): move provider resolution to source registry
cx
2026-08-26 21:38:58 -06:00
vicrodh 910bee49a5 refactor(mixtape): integrate optional source resolution (#694)
cx
2026-08-26 21:31:52 -06:00
vicrodh b6c69509df build(deps): unify lofty at 0.25.1
cx
2026-08-26 21:31:47 -06:00
vicrodh c039f0d0ee build(deps): integrate lofty 0.24 update (#679)
cx
2026-08-26 21:29:02 -06:00
vicrodh b2d3656eb4 docs(contributors): credit adopted external fixes
cx
2026-08-26 21:28:56 -06:00
vicrodh b60ed2c268 fix(secrets): integrate real desktop keyring backends (#697)
Preserve Afonso’s restart regression test while selecting native stores only on Linux, macOS and Windows. Unsupported targets take the persisted KDF path instead of keyring’s successful in-memory mock; the stale workflow change is deliberately excluded.

cx
2026-08-26 20:59:27 -06:00
vicrodh 388a3591e2 fix(qobuz): integrate atomic bundle cache replacement (#707)
Preserve Afonso’s same-directory temp-file replacement on top of the configurable cache root from #708. Cover the complete explicit-root round trip and document the exact process-crash and concurrent-writer guarantees.

cx
2026-08-26 20:50:33 -06:00
vicrodh 7bd5cb1ec6 scripts: aarch64 build scripts for the Qt binary
build-aarch64-linux.sh builds -p qbz-qt natively with the distro's Qt
(gated at >= 6.8, the tree's floor; Debian 13 / Ubuntu 25.04 / Fedora
41 qualify), installs rustup when absent, forces one rustc at a time on
<= 4 GB boxes, and runs the same offscreen smoke as CI. Its CROSS mode
is retired honestly: cxx-qt runs the target Qt's qmake during the
build, which cross-rs's Ubuntu 20.04 images cannot do. The qbzd script
and Cross.toml keep cross-compiling the daemon, with the Qt-free dep
set.

cc
2026-08-26 19:11:01 -06:00
vicrodh b292e84abb chore(deps): integrate serde_json 1.0.151 (#650)
cx
2026-08-26 17:45:51 -06:00
vicrodh 0a934ae4a0 fix(offline-cache): integrate relocatable CMAF bundles (#696)
cx
2026-08-26 17:44:20 -06:00
vicrodh 4d8779e17f fix(secrets): integrate mobile KDF fallback (#695)
cx
2026-08-26 17:43:55 -06:00
vicrodh 9aeee886db feat(qobuz): integrate configurable bundle cache directory (#708)
cx
2026-08-26 17:42:23 -06:00
vicrodh d555b8fde4 feat(qt): add album quick view and queue focus controls
cx
2026-08-26 16:29:16 -06:00
vicrodh aa66c58ea4 fix(playlists): restore cover editing
cx
2026-08-26 16:29:04 -06:00
vicrodh 4630c40222 feat(queue): make history occurrences reorderable
cx
2026-08-26 12:31:48 -06:00
vicrodh 8d1fb5593d refactor(ui): rename music link action
cx
2026-08-26 12:31:35 -06:00
vicrodh edcb12b8a1 feat(qt): close migration parity gaps
cx
2026-08-26 11:11:50 -06:00
vicrodh 2bfc2b244c fix(auth): isolate guest and account state
cx
2026-08-26 11:11:27 -06:00
vicrodh 69ed612077 refactor(frontend): retire Slint application
cx
2026-08-26 11:10:18 -06:00
vicrodh fb6c38cbfd fix(qbz-qt): preserve collection builder viewport
cx
2026-08-26 02:29:30 -06:00
vicrodh fc7fe4f094 fix(qbz-qt): align collection controls with theme
cx
2026-08-26 02:28:52 -06:00
vicrodh 1b57f47c5a fix(qbz-qt): unify top result artwork
cx
2026-08-26 02:22:59 -06:00
vicrodh 272d85fcd6 fix(qbz-qt): make listen list reordering tangible
cx
2026-08-26 02:12:49 -06:00
vicrodh fdc77b0c93 style(qbz-qt): improve search quality legibility
cx
2026-08-26 01:50:20 -06:00
vicrodh 40339e564d fix(qbz-qt): preserve media server album artwork
cx
2026-08-26 01:37:09 -06:00
vicrodh d45e7d9430 feat(qbz-qt): enrich search curtain results
cx
2026-08-26 00:56:24 -06:00
vicrodh cdc5eb99e7 feat(qbz-qt): add atmosphere to local album headers
cx
2026-08-26 00:11:00 -06:00