"Wallpaper" now behaves like a window that sees straight through to the desktop: it always paints the part of the wallpaper that lies under the window, wherever the window is moved, with a stronger blur so nothing in the picture competes with the text. X11, macOS and Windows already told Qt where the window is. Wayland does not, so on KDE Plasma a tracker reads the window's geometry from org_kde_plasma_window_management on its own client connection and thread (wayland-client + the plasma protocol crate, pure Rust backend). It follows this process's windows only, drops every other window's object after its initial state, and republishes only when the geometry list changes; the field picks the window by size and ignores updates while another background is showing. Where the protocol is not offered the crop stays centred and one line is logged. KWin hands that protocol only to a binary whose desktop entry names it by an absolute Exec and lists it in X-KDE-Wayland-Interfaces, so the Linux desktop entries now carry both (the deb/rpm /usr/bin/qbz symlink resolves to the same binary). The AppImage step restores the bare Exec name that linuxdeploy resolves inside the AppDir, and the Nix package rewrites Exec to its store path. "Wallpaper, blurred" is Blurred art with the wallpaper in the cover's place, so it now drifts while the transport plays and holds still when it does not. cc
137 lines
5.7 KiB
Nix
137 lines
5.7 KiB
Nix
{
|
|
description = "QBZ — Native hi-fi Qobuz desktop player for Linux";
|
|
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
|
flake-utils.url = "github:numtide/flake-utils";
|
|
};
|
|
|
|
outputs = { self, nixpkgs, flake-utils }:
|
|
let
|
|
# ──────────────────────────────────────────────
|
|
# VERSION BUMP: bump `qbzVersion` and the per-arch tarball hashes AFTER a
|
|
# tag publishes its release assets (hashes are computed from the published
|
|
# asset at its final URL — see below).
|
|
#
|
|
# This flake installs the prebuilt Qt binary tarball — the SAME bare-binary
|
|
# asset AUR-bin / Gentoo / Flathub repack — instead of compiling the Rust
|
|
# + Qt workspace. That matches the project's binary-repack packaging
|
|
# doctrine and sidesteps the cxx-qt / qt-build-utils source build entirely
|
|
# (github #744: `Could not find qmltyperegistrar`, which needs Qt host
|
|
# tools from several outputs on PATH at build time).
|
|
# ──────────────────────────────────────────────
|
|
qbzVersion = "2.1.1";
|
|
|
|
# Bare-binary release tarballs, per arch. Layout inside each:
|
|
# qbz_<ver>_<arch>/{qbz, qbzd, LICENSE, licenses/, qbz.desktop, icons/}
|
|
# Hashes: `nix-prefetch-url <url>` then `nix hash convert --to sri`.
|
|
assets = {
|
|
"x86_64-linux" = {
|
|
name = "qbz_${qbzVersion}_amd64.tar.gz";
|
|
hash = "sha256-A8/eHVTTleSlPGgHBW2Qn9CWb95clgf5tifEXwKYvLg=";
|
|
};
|
|
"aarch64-linux" = {
|
|
name = "qbz_${qbzVersion}_aarch64.tar.gz";
|
|
hash = "sha256-LbC9KPQOqZ2sDWNoErQiK+jlEr5cNlsgf1Qu3cpFU4w=";
|
|
};
|
|
};
|
|
in
|
|
flake-utils.lib.eachSystem (builtins.attrNames assets) (system:
|
|
let
|
|
pkgs = import nixpkgs { inherit system; };
|
|
asset = assets.${system};
|
|
|
|
# Opened by name at runtime rather than linked; wrapQtAppsHook already
|
|
# covers Qt's own plugin/QML closure.
|
|
runtimeLibs = with pkgs; [ libjack2 ];
|
|
runtimeBins = with pkgs; [ pipewire pulseaudio xdg-utils ];
|
|
in
|
|
{
|
|
packages.default = pkgs.stdenv.mkDerivation {
|
|
pname = "qbz";
|
|
version = qbzVersion;
|
|
|
|
src = pkgs.fetchurl {
|
|
url = "https://github.com/vicrodh/qbz/releases/download/v${qbzVersion}/${asset.name}";
|
|
inherit (asset) hash;
|
|
};
|
|
|
|
# autoPatchelfHook rewrites the prebuilt binary's interpreter + rpath
|
|
# against the nixpkgs closure; wrapQtAppsHook sets the Qt plugin / QML
|
|
# import paths the binary needs at run time.
|
|
nativeBuildInputs = with pkgs; [
|
|
autoPatchelfHook
|
|
qt6.wrapQtAppsHook
|
|
];
|
|
|
|
# qt6-base/declarative/svg/wayland mirror the AUR `qbz-bin` depends;
|
|
# the rest satisfy the bare binary's DT_NEEDED (ALSA, xkbcommon,
|
|
# wayland, zlib, libstdc++) plus the dlopen'd JACK backend.
|
|
buildInputs = with pkgs; [
|
|
alsa-lib
|
|
qt6.qtbase
|
|
qt6.qtdeclarative
|
|
qt6.qtsvg
|
|
qt6.qtwayland
|
|
libxkbcommon
|
|
wayland
|
|
zlib
|
|
stdenv.cc.cc.lib
|
|
] ++ runtimeLibs;
|
|
|
|
# Only the desktop client — `qbzd` ships as its own package elsewhere,
|
|
# matching the source flake's previous scope.
|
|
installPhase = ''
|
|
runHook preInstall
|
|
|
|
install -Dm755 qbz "$out/bin/qbz"
|
|
install -Dm644 qbz.desktop \
|
|
"$out/share/applications/com.blitzfc.qbz.desktop"
|
|
# KWin matches the Exec path against /proc/<pid>/exe before it
|
|
# offers org_kde_plasma_window_management (Wallpaper background).
|
|
substituteInPlace "$out/share/applications/com.blitzfc.qbz.desktop" \
|
|
--replace-warn "Exec=/usr/bin/qbz" "Exec=$out/bin/qbz"
|
|
if [ -d icons ]; then cp -r icons "$out/share/icons"; fi
|
|
install -Dm644 LICENSE "$out/share/licenses/qbz/LICENSE"
|
|
if [ -d licenses ]; then
|
|
cp -r licenses "$out/share/licenses/qbz/third-party"
|
|
fi
|
|
|
|
runHook postInstall
|
|
'';
|
|
|
|
# Fold the runtime helpers/libraries QBZ opens by name into the SAME
|
|
# wrap wrapQtAppsHook performs (no double wrapper).
|
|
preFixup = ''
|
|
qtWrapperArgs+=(--prefix PATH : ${pkgs.lib.makeBinPath runtimeBins})
|
|
qtWrapperArgs+=(--prefix LD_LIBRARY_PATH : ${pkgs.lib.makeLibraryPath runtimeLibs})
|
|
'';
|
|
|
|
meta = with pkgs.lib; {
|
|
description = "Native, full-featured hi-fi Qobuz desktop player for Linux";
|
|
homepage = "https://qbz.lol";
|
|
downloadPage = "https://github.com/vicrodh/qbz/releases";
|
|
license = licenses.mit;
|
|
mainProgram = "qbz";
|
|
platforms = [ "x86_64-linux" "aarch64-linux" ];
|
|
sourceProvenance = [ sourceTypes.binaryNativeCode ];
|
|
};
|
|
};
|
|
|
|
apps.default = {
|
|
type = "app";
|
|
program = "${self.packages.${system}.default}/bin/qbz";
|
|
};
|
|
|
|
# Running a locally-compiled debug binary (crates/target/debug/qbz)
|
|
# needs the dlopen'd JACK backend on LD_LIBRARY_PATH, same as the
|
|
# wrapped package. Rust itself comes from the contributor's rustup.
|
|
devShells.default = pkgs.mkShell {
|
|
packages = with pkgs; [ rust-analyzer rustfmt clippy ];
|
|
shellHook = ''
|
|
export LD_LIBRARY_PATH="${pkgs.lib.makeLibraryPath runtimeLibs}''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
|
'';
|
|
};
|
|
});
|
|
}
|