Name: arctis-sound-manager Version: 1.4.10 Release: 1%{?dist} Summary: Linux GUI for SteelSeries Arctis headsets # Fedora ships slightly older versions of ruamel-yaml and pyudev — suppress the # auto-generated versioned requirements from the wheel metadata and rely on the # explicit Requires: lines below instead. %global __requires_exclude python3[0-9.]*dist\\((ruamel-yaml|pyudev)\\) # python3-dbus-next entered the Fedora repos in F40. On F40+ depend on the # system package; on older Fedora (or non-Fedora rebuilds) bundle the wheel. # Bundling on F40+ collides with python3-dbus-next's files (issue #73). %if 0%{?fedora} && 0%{?fedora} < 40 %global bundle_dbus_next 1 %else %global bundle_dbus_next 0 %endif License: GPL-3.0-or-later URL: https://github.com/loteran/Arctis-Sound-Manager Source0: %{url}/archive/refs/tags/v%{version}.tar.gz Source1: arctis_sound_manager-%{version}-py3-none-any.whl %if %{bundle_dbus_next} Source2: dbus_next-0.2.3-py3-none-any.whl %endif BuildArch: noarch BuildRequires: python3-devel BuildRequires: python3-installer BuildRequires: python3-ruamel-yaml BuildRequires: systemd-rpm-macros BuildRequires: desktop-file-utils BuildRequires: libappstream-glib Requires: python3-babel Requires: python3-pyside6 Requires: python3-pillow Requires: python3-pulsectl Requires: python3-pyudev Requires: python3-pyusb Requires: python3-ruamel-yaml Requires: pipewire Requires: pipewire-pulseaudio Requires: wireplumber Requires: libusb1 Requires: pulseaudio-libs # The `pactl` CLI (used at GUI startup and for EQ/Sonar routing) ships in # pulseaudio-utils, NOT in pipewire-pulseaudio or pulseaudio-libs. Without it # a clean install crashes on launch with FileNotFoundError: 'pactl' (#117). Requires: pulseaudio-utils # Used by asm-setup to download the HRIR file (~/.local/share/pipewire/ # hrir_hesuvi/EAC_Default.wav) on first run. asm-setup tries curl first, # then wget — but if both are missing the HRIR never lands and Spatial # Audio stays silent forever. curl is in the Fedora minimal install set # but minimal containers / Server netinstall may strip it. Requires: curl # Fedora ships the Steve Harris SWH LADSPA pack as `ladspa-swh-plugins` # (the upstream name `swh-plugins` is the Debian/Arch package name and # does not exist in Fedora repos). Required by HeSuVi 7.1 virtual # surround (`plate_1423` reverb plugin) — Spatial Audio is silent # without it (issue #23). # # Promoted from Recommends: to Requires: so DNF auto-pulls the package # on upgrade for users who installed earlier ASM versions before this # spec carried the dependency. `Recommends:` is only re-evaluated at # initial install, so existing users would otherwise stay broken until # they ran `dnf reinstall arctis-sound-manager` manually. Requires: ladspa-swh-plugins # ── Clips (opt-in) ─────────────────────────────────────────────────────── # Unlike the LADSPA packs above, none of this is needed to run ASM: Clips is # off by default and its packages are installed from the toggle that turns it # on (Settings → Clips, which runs these same commands through pkexec). A # mixer-and-EQ install should not drag in a screen recorder's encoders, so # these are weak dependencies — dnf installs them by default, and anyone who # does not want them can --setopt=install_weak_deps=False and still have a # working ASM. # python3-gobject — the Gst/Gio bindings the capture is written against # pipewire-gstreamer — pipewiresrc, the portal's screen stream # gstreamer1-plugins-base — appsrc, audioconvert/audioresample, opusenc # gstreamer1-plugins-good — pulsesrc (channel audio), matroskamux (the .mkv) # gstreamer1-plugins-ugly-free — x264enc, the software encoder fallback # ffmpeg-free — poster frames, track levels, export Recommends: python3-gobject Recommends: pipewire-gstreamer Recommends: gstreamer1-plugins-base Recommends: gstreamer1-plugins-good Recommends: gstreamer1-plugins-ugly-free Recommends: ffmpeg-free # Hardware H.264 encoders are a performance choice on top of that — the # capture probes for them and falls back to x264enc. Suggests: gstreamer1-plugins-bad-free %if ! %{bundle_dbus_next} Requires: python3-dbus-next %endif # rnnoise LADSPA plugin for ClearCast mic noise suppression. # noise-suppression-for-voice is NOT in the official Fedora repos — it lives in # the lkiesow/noise-suppression-for-voice COPR. The repo file is written and the # plugin is installed in the background by the %post scriptlet (issue #41). %description Arctis Sound Manager is a Linux application for configuring SteelSeries Arctis headsets. It provides a 4-channel audio mixer (Game / Chat / Media / HDMI), a full Sonar parametric EQ system with 297+ presets, virtual 7.1 surround sound, ANC/Transparent mode control, and device management via PipeWire. %prep %autosetup -n Arctis-Sound-Manager-%{version} %build # Wheel is pre-built in SRPM via .copr/Makefile %install python3 -m installer --destdir=%{buildroot} %{SOURCE1} %if %{bundle_dbus_next} # Bundle dbus-next (older Fedora repos lack python3-dbus-next) python3 -m installer --destdir=%{buildroot} %{SOURCE2} %endif # udev rules — generated from device YAMLs at build time (single source of truth) install -Dm644 /dev/null %{buildroot}%{_udevrulesdir}/91-steelseries-arctis.rules python3 scripts/generate_udev_rules.py src/arctis_sound_manager/devices/ \ > %{buildroot}%{_udevrulesdir}/91-steelseries-arctis.rules # Systemd user services (single source of truth in systemd/, not heredocs) install -Dm644 systemd/arctis-manager.service %{buildroot}%{_userunitdir}/arctis-manager.service install -Dm644 systemd/arctis-video-router.service %{buildroot}%{_userunitdir}/arctis-video-router.service install -Dm644 systemd/arctis-stream-guard.service %{buildroot}%{_userunitdir}/arctis-stream-guard.service install -Dm644 systemd/app-ArctisManager.service %{buildroot}%{_userunitdir}/app-ArctisManager.service # dinit service templates install -Dm644 dinit/arctis-manager %{buildroot}%{_datadir}/%{name}/dinit/arctis-manager install -Dm644 dinit/arctis-video-router %{buildroot}%{_datadir}/%{name}/dinit/arctis-video-router install -Dm644 dinit/arctis-stream-guard %{buildroot}%{_datadir}/%{name}/dinit/arctis-stream-guard install -Dm644 dinit/arctis-gui %{buildroot}%{_datadir}/%{name}/dinit/arctis-gui install -Dm644 dinit/pipewire-filter-chain %{buildroot}%{_datadir}/%{name}/dinit/pipewire-filter-chain install -Dm755 scripts/asm-diag-dinit.py %{buildroot}%{_bindir}/asm-diag-dinit # Post-upgrade helper (packaging machinery, not a user-facing command) install -Dm755 scripts/restart-user-services.sh %{buildroot}%{_prefix}/lib/%{name}/restart-user-services.sh # AppStream catalog entry — ties the component to a package name, without which # GNOME Software and Discover cannot show it (the metainfo alone is not enough). install -d %{buildroot}%{_datadir}/swcatalog/xml python3 scripts/generate_appstream_catalog.py \ --output %{buildroot}%{_datadir}/swcatalog/xml/%{name}.xml.gz chmod 644 %{buildroot}%{_datadir}/swcatalog/xml/%{name}.xml.gz # Desktop entry install -Dm644 src/arctis_sound_manager/desktop/ArctisManager.desktop \ %{buildroot}%{_datadir}/applications/ArctisManager.desktop desktop-file-validate %{buildroot}%{_datadir}/applications/ArctisManager.desktop # Icon install -Dm644 src/arctis_sound_manager/gui/images/steelseries_logo.svg \ %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/arctis-manager.svg # AppStream metainfo (releases injected from CHANGELOG.md — never hardcode) python3 scripts/generate_metainfo_releases.py --in-place install -Dm644 src/arctis_sound_manager/desktop/com.github.loteran.arctis-sound-manager.metainfo.xml \ %{buildroot}%{_metainfodir}/com.github.loteran.arctis-sound-manager.metainfo.xml appstream-util validate-relax --nonet \ %{buildroot}%{_metainfodir}/com.github.loteran.arctis-sound-manager.metainfo.xml # PipeWire configs install -Dm644 scripts/pipewire/10-arctis-virtual-sinks.conf \ %{buildroot}%{_datadir}/%{name}/pipewire/10-arctis-virtual-sinks.conf install -Dm644 scripts/pipewire/sink-virtual-surround-7.1-hesuvi.conf \ %{buildroot}%{_datadir}/%{name}/pipewire/sink-virtual-surround-7.1-hesuvi.conf # filter-chain.service (bundled for distros that don't ship one) install -Dm644 scripts/filter-chain.service \ %{buildroot}%{_datadir}/%{name}/filter-chain.service # Device configs install -d %{buildroot}%{_datadir}/%{name}/devices install -Dm644 src/arctis_sound_manager/devices/*.yaml \ -t %{buildroot}%{_datadir}/%{name}/devices/ # First-run autostart (triggers asm-setup on first graphical login) install -Dm644 debian/asm-first-run.desktop \ %{buildroot}/etc/xdg/autostart/asm-first-run.desktop %post %systemd_user_post arctis-manager.service arctis-video-router.service arctis-stream-guard.service app-ArctisManager.service udevadm control --reload-rules || : # Scoped to SteelSeries (idVendor=1038), the way the Distrobox installers # have always done it. Re-adding every USB device on the machine disturbs # hardware that has nothing to do with ASM, and — because this runs while # asm-daemon still holds the headset's interface with the kernel driver # detached — it makes the running daemon lose the device (errno 19) and # lets hid-generic claim interface 4 back. The headset then reads as absent # until it is physically replugged, after every single upgrade. udevadm trigger --action=add --subsystem-match=usb --attr-match=idVendor=1038 || : # On upgrade ($1 >= 2), restart the user services: dnf replaced the files, but # the running asm-daemon still holds the previous version in memory. if [ "$1" -ge 2 ]; then [ -x %{_prefix}/lib/%{name}/restart-user-services.sh ] && \ %{_prefix}/lib/%{name}/restart-user-services.sh || : fi # ── ClearCast / rnnoise COPR (Fedora/Nobara) ───────────────────────────────── # noise-suppression-for-voice lives in the lkiesow/noise-suppression-for-voice # COPR, not in the official Fedora repos. Write the .repo file directly (no # dnf lock contention) then schedule the plugin install in the background so # the current transaction is not blocked (issue #41). _ASM_RNNOISE_REPO="/etc/yum.repos.d/_asm-noise-suppression-for-voice.repo" if [ ! -f "$_ASM_RNNOISE_REPO" ]; then cat > "$_ASM_RNNOISE_REPO" << 'REPOEOF' [copr:copr.fedoraproject.org:lkiesow:noise-suppression-for-voice] name=Copr repo for noise-suppression-for-voice owned by lkiesow (added by arctis-sound-manager) baseurl=https://download.copr.fedorainfracloud.org/results/lkiesow/noise-suppression-for-voice/fedora-$releasever-$basearch/ type=rpm-md skip_if_unavailable=True gpgcheck=1 gpgkey=https://download.copr.fedorainfracloud.org/results/lkiesow/noise-suppression-for-voice/pubkey.gpg repo_gpgcheck=0 enabled=1 enabled_metadata=1 REPOEOF systemd-run --no-block --unit=asm-rnnoise-install \ /bin/bash -c "dnf install -y ladspa-realtime-noise-suppression-plugin 2>/dev/null" \ 2>/dev/null || : fi # Run asm-setup immediately if the installing user has an active D-Bus session. # Falls back to /etc/xdg/autostart/asm-first-run.desktop on next login otherwise. REAL_USER="${SUDO_USER:-}" if [ -n "$REAL_USER" ]; then REAL_UID=$(id -u "$REAL_USER") XDG_RUNTIME_DIR="/run/user/$REAL_UID" DBUS_SOCKET="$XDG_RUNTIME_DIR/bus" if [ -S "$DBUS_SOCKET" ]; then echo " Running asm-setup for ${REAL_USER}..." su -l "$REAL_USER" -c \ "XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS=unix:path=$DBUS_SOCKET asm-setup" \ || echo " [!] asm-setup failed — run manually: asm-setup" else echo " No active session found — asm-setup will run on next login." fi fi %preun # Remove the rnnoise COPR repo file only on real uninstall (not upgrade). if [ $1 -eq 0 ]; then rm -f /etc/yum.repos.d/_asm-noise-suppression-for-voice.repo || : fi %systemd_user_preun arctis-manager.service arctis-video-router.service arctis-stream-guard.service app-ArctisManager.service %postun %systemd_user_postun arctis-manager.service arctis-video-router.service arctis-stream-guard.service app-ArctisManager.service # Clean up user-level PipeWire configs on real removal (not upgrade). # RPM passes the post-transaction package count as $1 — 0 means uninstall, # >=1 means an upgrade is in progress and we must keep configs in place. # Without this block the "ghost" Arctis virtual sinks keep being loaded # by PipeWire on every login because asm-setup deployed them to # ~/.config/pipewire/ and the package can't reach into $HOME (issue #24). # Audio profiles in ~/.config/arctis_manager/profiles/ are PRESERVED. if [ "$1" = "0" ]; then REAL_USER="${SUDO_USER:-}" if [ -n "$REAL_USER" ]; then REAL_UID=$(id -u "$REAL_USER" 2>/dev/null || echo "") if [ -n "$REAL_UID" ]; then XDG_RUNTIME_DIR="/run/user/$REAL_UID" DBUS_SOCKET="$XDG_RUNTIME_DIR/bus" echo "==> Cleaning up user-level configs for ${REAL_USER} (audio profiles preserved)..." su -l "$REAL_USER" -c " XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS=unix:path=$DBUS_SOCKET export XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS for unit in arctis-manager.service arctis-video-router.service arctis-stream-guard.service app-ArctisManager.service arctis-gui.service filter-chain.service; do systemctl --user disable --now \"\$unit\" >/dev/null 2>&1 || true done rm -f \"\$HOME/.config/pipewire/pipewire.conf.d/10-arctis-virtual-sinks.conf\" rm -f \"\$HOME/.config/pipewire/filter-chain.conf.d/sink-virtual-surround-7.1-hesuvi.conf\" rm -f \"\$HOME/.config/pipewire/filter-chain.conf.d\"/sonar-*.conf rm -f \"\$HOME/.config/systemd/user/arctis-manager.service\" rm -f \"\$HOME/.config/systemd/user/arctis-video-router.service\" rm -f \"\$HOME/.config/systemd/user/arctis-stream-guard.service\" rm -f \"\$HOME/.config/systemd/user/app-ArctisManager.service\" rm -f \"\$HOME/.config/systemd/user/arctis-gui.service\" rm -f \"\$HOME/.local/share/applications/ArctisManager.desktop\" rm -f \"\$HOME/.local/share/applications/ArctisManagerSystray.desktop\" update-desktop-database \"\$HOME/.local/share/applications\" >/dev/null 2>&1 || true if [ -S \"\$DBUS_SOCKET\" ]; then systemctl --user daemon-reload >/dev/null 2>&1 || true systemctl --user restart pipewire pipewire-pulse >/dev/null 2>&1 || true fi " 2>/dev/null || true fi else echo "==> arctis-sound-manager removed." echo " To finish cleaning up ghost virtual sinks (run as your normal user):" echo " curl -fsSL https://raw.githubusercontent.com/loteran/Arctis-Sound-Manager/main/scripts/uninstall.sh | bash -s -- --purge --yes" fi fi %files %license LICENSE %doc README.md CHANGELOG.md %{python3_sitelib}/arctis_sound_manager/ %{python3_sitelib}/arctis_sound_manager-*.dist-info/ %if %{bundle_dbus_next} %{python3_sitelib}/dbus_next/ %{python3_sitelib}/dbus_next-*.dist-info/ %endif %{_bindir}/asm-daemon %{_bindir}/asm-gui %{_bindir}/asm-cli %{_bindir}/asm-router %{_bindir}/asm-stream-guard %{_bindir}/asm-clipd %{_bindir}/asm-setup %{_udevrulesdir}/91-steelseries-arctis.rules %{_userunitdir}/arctis-manager.service %{_userunitdir}/arctis-video-router.service %{_userunitdir}/arctis-stream-guard.service %{_userunitdir}/app-ArctisManager.service %{_datadir}/%{name}/dinit/ %{_bindir}/asm-diag-dinit %{_prefix}/lib/%{name}/restart-user-services.sh %{_datadir}/swcatalog/xml/%{name}.xml.gz %{_datadir}/applications/ArctisManager.desktop %{_datadir}/icons/hicolor/scalable/apps/arctis-manager.svg %{_metainfodir}/com.github.loteran.arctis-sound-manager.metainfo.xml %{_datadir}/%{name}/ /etc/xdg/autostart/asm-first-run.desktop %changelog * Tue Apr 22 2026 loteran - 1.0.64-1 - Fix: install update button now always shown in home banner (not only for pipx installs) * Tue Apr 22 2026 loteran - 1.0.63-1 - Add: product_id to telemetry payload — enables per-variant hardware tracking - Add: scripts/update_readme_stats.py — auto-updates README devices/distros tables from telemetry - Add: cloudflare/migrate_v2.sql — D1 migration for product_id column * Mon Apr 21 2026 loteran - 1.0.62-1 - Fix: ASM claims default sink on start (pactl) and restores previous default on exit — EasyEffects coexists cleanly - Revert: priority.session back to neutral (1000/unset) — explicit metadata selection is the correct mechanism * Mon Apr 21 2026 loteran - 1.0.61-1 - Fix: raise priority.session to 2000 on all ASM virtual sinks so ASM always wins over EasyEffects in WirePlumber routing * Mon Apr 21 2026 loteran - 1.0.60-1 - Refactor: udev rules generated at build time from device YAMLs — no more hardcoded rules that drift out of sync - Add: asm-cli udev dump-rules subcommand (stdout output for packaging) - Add: python3-ruamel-yaml to BuildRequires * Mon Apr 21 2026 loteran - 1.0.59-1 - Fix: udev rules missing PID 1294 for Arctis Pro Wireless — caused Errno 13 Access denied on Fedora/Nobara - Fix: remove ENV{DEVTYPE}=="usb_device" from all udev rules — fails silently on some kernels - Fix: sync udev rules with all device yamls (add Nova 7 Gen1/Gen2, Arctis 1/7X/7P, Arctis Pro 2019, Nova 3P/3X, Nova 7P Gen2) * Thu Apr 16 2026 loteran - 1.0.43-1 - Fix: udev rules file installed with 0600 perms (pkexec cp) — dialog reappeared at every login - Fix: arctis-gui.service missing from package — systray never started at login despite "launch on startup" * Wed Apr 15 2026 loteran - 1.0.40-1 - Fix udev: remove GROUP="plugdev" from generated rules (breaks on Fedora) - Fix report dialog: clipboard copy and GitHub issue link (URL too long) - Fix RPM: filter auto-generated python dist version requires - Feat: in-app update detects install method and shows correct package manager command * Mon Apr 14 2026 loteran - 1.0.38-1 - Rename preset files: remove tm/r symbols that broke bsdtar packaging - Fix AUR: use uv pip install --prefix instead of uv pip download * Sun Apr 12 2026 loteran - 1.0.36-1 - Fix cross-distro USB permissions: udev rules use plugdev group and drop DEVTYPE check * Sun Apr 12 2026 loteran - 1.0.35-1 - Fix udev rules: one rule per PID instead of multi-value ATTRS{idProduct} (not supported by all udev versions) * Sat Apr 12 2026 loteran - 1.0.34-1 - Bundle dbus-next and pulsectl (not in Fedora/Ubuntu/Debian/Arch repos) - Add wireplumber to Requires - Auto-run asm-setup in %%post when user session is active (SUDO_USER + D-Bus socket) - Install XDG autostart fallback (/etc/xdg/autostart/asm-first-run.desktop) - asm-setup: write .setup_done flag to skip autostart on subsequent logins * Sat Apr 12 2026 loteran - 1.0.33-1 - Bundle dbus-next (not in Fedora repos) - Add wireplumber to Requires - Auto-run asm-setup in %%post if user session is active - Install XDG autostart fallback for asm-setup * Fri Apr 11 2026 loteran - 1.0.31-1 - Bundle 334 Sonar presets in package (312 Game, 8 Chat, 14 Mic) - asm-setup: full automation (desktop, udev, services, PipeWire) - Settings: Launch at startup toggle via systemd - Fix: hardcoded device YAML and NVMe path * Thu Apr 10 2026 loteran - 1.0.27-1 - Fix: silent Game channel persists after Sonar mode switch (issue #14) — duplicate HeSuVi node (install.sh places static config in pipewire.conf.d, Sonar generates dynamic in filter-chain.conf.d; both registering the same node name caused the game sink to connect to nothing) * Thu Apr 10 2026 loteran - 1.0.26-1 - Fix: silent Game channel on first Sonar mode switch (issue #14) * Thu Apr 10 2026 loteran - 1.0.25-1 - Fix: install.sh PATH regression — export PATH=~/.local/bin always set so asm-cli/asm-daemon found on reinstall (issue #3) - CI: automate AUR and COPR builds on release * Fri Apr 04 2026 loteran - 1.0.13-1 - Fix: DeviceConfiguration.device_init and .status always initialized (no more AttributeError) - Fix: SELECT widget IndexError/KeyError when options not loaded - Fix: device_state thread safety via threading.Lock - Fix: PipeWire node.target omitted when empty (invalid SPA JSON) * Fri Apr 04 2026 loteran - 1.0.12-1 - Fix: LADSPA mic processing (noise gate, RNNoise, compressor) silently broken — missing = in PipeWire control syntax - Fix: get_physical_source() retries 15x on PulseAudio error - Fix: D-Bus polling loop survives transient connection errors * Tue Apr 01 2026 loteran - 1.0.7-1 - Add one-click auto-update from GUI * Tue Apr 01 2026 loteran - 1.0.6-1 - Add Debian/Ubuntu packaging (.deb + Launchpad PPA) * Mon Mar 30 2026 loteran - 1.0.5-1 - Fix desktop entry for Fedora desktop-file-validate - Add remote icon and AppStream metainfo for package manager GUIs - Widen uv_build version range - Add COPR packaging for Fedora * Sun Mar 29 2026 loteran - 1.0.4-1 - External output EQ, volume control, stream routing - Update notifications and clean exit - ANC/Transparent mode restore on device init * Sun Mar 29 2026 loteran - 1.0.0-1 - Initial release