Name: patchance Version: 1.3.0 Release: 1%{?dist} Summary: A JACK patch-bay GUI for GNU/Linux License: GPL-2.0-or-later URL: https://github.com/Houston4444/Patchance Source0: %{url}/releases/download/v%{version}/Patchance-%{version}-source.tar.gz Source1: GPL-2 BuildArch: noarch %global __brp_python_bytecompile %{nil} BuildRequires: python3-devel BuildRequires: python3-QtPy BuildRequires: make BuildRequires: gcc BuildRequires: python3-pyqt6 BuildRequires: qt6-linguist BuildRequires: pkgconfig(Qt6Core) BuildRequires: pkgconfig(Qt6Gui) BuildRequires: pkgconfig(Qt6Widgets) BuildRequires: pkgconfig(Qt6UiTools) BuildRequires: help2man Requires: python3 Requires: python3-QtPy Requires: python-jack-client %description Patchance is a JACK patch bay GUI for GNU/Linux systems. It provides an easy-to-use interface for connecting audio, MIDI and CV ports and includes embedded themes and the HoustonPatchbay sub-module. %prep %autosetup -C %build # Pre-generate Qt resource and UI files when available. # Detect rcc/pyrcc/pyside tools and produce a Python resource module # or a binary `.rcc` plus a small loader. RC_CMD="" RC_CMD_TYPE="" if command -v pyrcc6 >/dev/null 2>&1; then RC_CMD_TYPE="pyrcc6" RC_CMD="pyrcc6 -o" elif python3 -c "import PyQt6.pyrcc_main" >/dev/null 2>&1; then RC_CMD_TYPE="pyqt6" RC_CMD="python3 -m PyQt6.pyrcc_main -o" elif command -v pyside6-rcc >/dev/null 2>&1; then RC_CMD_TYPE="pyside6" RC_CMD="pyside6-rcc -o" elif python3 -c "import PySide6.scripts.rcc" >/dev/null 2>&1; then RC_CMD_TYPE="pyside6mod" RC_CMD="python3 -m PySide6.scripts.rcc -o" elif command -v rcc >/dev/null 2>&1; then RC_CMD_TYPE="rcc" RC_CMD="rcc -binary -o" fi # resources in top-level `resources/` and in HoustonPatchbay if [ -n "$RC_CMD" ] && [ -f resources/resources.qrc ]; then if [ "$RC_CMD_TYPE" = "rcc" ]; then $RC_CMD src/resources.rcc resources/resources.qrc || true cat > src/resources_rc.py <<'PYR' from PyQt6.QtCore import QResource import os try: QResource.registerResource(os.path.join(os.path.dirname(__file__), 'resources.rcc')) except Exception: pass PYR else $RC_CMD src/resources_rc.py resources/resources.qrc || true fi chmod 644 src/resources_rc.py || true [ -f src/resources.rcc ] && chmod 644 src/resources.rcc || true fi if [ -n "$RC_CMD" ] && [ -f HoustonPatchbay/resources/resources.qrc ]; then mkdir -p HoustonPatchbay/source/patchbay || true if [ "$RC_CMD_TYPE" = "rcc" ]; then $RC_CMD HoustonPatchbay/source/patchbay/resources.rcc HoustonPatchbay/resources/resources.qrc || true cat > HoustonPatchbay/source/patchbay/resources_rc.py <<'PYR' from PyQt6.QtCore import QResource import os try: QResource.registerResource(os.path.join(os.path.dirname(__file__), 'resources.rcc')) except Exception: pass PYR else $RC_CMD HoustonPatchbay/source/patchbay/resources_rc.py HoustonPatchbay/resources/resources.qrc || true fi chmod 644 HoustonPatchbay/source/patchbay/resources_rc.py || true [ -f HoustonPatchbay/source/patchbay/resources.rcc ] && chmod 644 HoustonPatchbay/source/patchbay/resources.rcc || true fi # The install-time steps that modify the installed tree are performed # during the main install section so generated loader files exist before we # try to reference them. # Now run the normal build %{__make} QT_VERSION=6 %install rm -rf %{buildroot} %{__make} install DESTDIR=%{buildroot} PREFIX=%{_prefix} QT_VERSION=6 # If only a binary `.rcc` was produced, create a small runtime loader so # `from .. import resources_rc` works at runtime. if [ -f %{buildroot}%{_datadir}/patchance/src/resources.rcc ] && [ ! -f %{buildroot}%{_datadir}/patchance/src/resources_rc.py ]; then cat > %{buildroot}%{_datadir}/patchance/src/resources_rc.py <<'PYR' from PyQt6.QtCore import QResource import os try: QResource.registerResource(os.path.join(os.path.dirname(__file__), 'resources.rcc')) except Exception: pass PYR chmod 644 %{buildroot}%{_datadir}/patchance/src/resources_rc.py || true fi if [ -f %{buildroot}%{_datadir}/patchance/HoustonPatchbay/source/patchbay/resources.rcc ] && [ ! -f %{buildroot}%{_datadir}/patchance/HoustonPatchbay/source/patchbay/resources_rc.py ]; then cat > %{buildroot}%{_datadir}/patchance/HoustonPatchbay/source/patchbay/resources_rc.py <<'PYR' from PyQt6.QtCore import QResource import os try: QResource.registerResource(os.path.join(os.path.dirname(__file__), 'resources.rcc')) except Exception: pass PYR chmod 644 %{buildroot}%{_datadir}/patchance/HoustonPatchbay/source/patchbay/resources_rc.py || true fi # Remove any zero-length files left by failed resource compilation find %{buildroot} -type f -size 0 -exec rm -f {} + || : # Ensure `resources_rc` is available early to avoid import-time errors # in UI modules that expect it during package import. if [ -f %{buildroot}%{_datadir}/patchance/HoustonPatchbay/source/patchbay/__init__.py ]; then # Ensure a safe `resources_rc` symbol is present on the package so # UI modules which do `from .. import resources_rc` won't raise during # package import. If an actual `resources_rc` module exists it will be # imported; otherwise we create a simple placeholder object exposing a # `registerResource` no-op to satisfy callers. grep -q "def _patchance_resources_loader" %{buildroot}%{_datadir}/patchance/HoustonPatchbay/source/patchbay/__init__.py >/dev/null 2>&1 || \ sed -i '1s;^;import types\ntry:\n from . import resources_rc\nexcept Exception:\n _patchance_resources_loader = types.SimpleNamespace(registerResource=lambda *a, **k: None)\n resources_rc = _patchance_resources_loader\n\n;' %{buildroot}%{_datadir}/patchance/HoustonPatchbay/source/patchbay/__init__.py || true fi # Make scripts executable (fix shebangs) for f in $(grep -Il '^#!' -R %{buildroot} 2>/dev/null || true); do chmod 755 "$f" || true done # Install license file (prefer Source1 when present) mkdir -p %{buildroot}/usr/share/licenses/%{name} if [ -f %{SOURCE1} ]; then cp -p %{SOURCE1} %{buildroot}/usr/share/licenses/%{name}/COPYING || true elif [ -f GPL-2 ]; then cp -p GPL-2 %{buildroot}/usr/share/licenses/%{name}/COPYING || true elif [ -f COPYING ]; then cp -p COPYING %{buildroot}/usr/share/licenses/%{name}/COPYING || true fi # Remove compiled Python bytecode and __pycache__ directories to avoid # rpmlint warnings about packaged bytecode. find %{buildroot} -name '__pycache__' -type d -exec rm -rf {} + || : find %{buildroot} -name '*.pyc' -type f -delete || : # Remove remaining precompiled bytecode. brp python bytecompile is disabled # to avoid rpmbuild regenerating .pyc files with mismatched mtimes. find %{buildroot}%{_datadir}/patchance -name '__pycache__' -type d -exec rm -rf {} + || : find %{buildroot}%{_datadir}/patchance -name '*.pyc' -type f -delete || : # Remove hidden .directory files from installed manuals/themes find %{buildroot}%{_datadir}/patchance -name '.directory' -type f -delete || : # Remove duplicate icon copies installed into manual/source rm -f %{buildroot}%{_datadir}/patchance/HoustonPatchbay/manual/en/images/patchance.svg || : rm -f %{buildroot}%{_datadir}/patchance/HoustonPatchbay/manual/fr/images/patchance.svg || : # If `xdg.py` is duplicated (one in `src/` and one in the HoustonPatchbay tree), # keep the HoustonPatchbay copy and make the `src/xdg.py` entry a relative symlink # to that copy so the package contains only a single file content-wise. if [ -f %{buildroot}%{_datadir}/patchance/src/xdg.py ] && [ -f %{buildroot}%{_datadir}/patchance/HoustonPatchbay/source/patchbay/patchcanvas/xdg.py ]; then rm -f %{buildroot}%{_datadir}/patchance/src/xdg.py || true ln -s ../HoustonPatchbay/source/patchbay/patchcanvas/xdg.py %{buildroot}%{_datadir}/patchance/src/xdg.py || true fi mkdir -p %{buildroot}%{_mandir}/man1 # Create a temporary helper that sets PYTHONPATH and runs the installed # script. Run help2man on that helper to generate the manpage. if [ -f %{buildroot}%{_bindir}/patchance ]; then mkdir -p %{buildroot}%{_libexecdir} || true cat > %{buildroot}%{_libexecdir}/patchance-help <<'SH' #!/bin/sh # helper used only during packaging to let help2man run with the # buildroot-installed modules available via PYTHONPATH PYPATH="%{_datadir}/patchance/src" export PYTHONPATH="${PYPATH}:$PYTHONPATH" exec "%{buildroot}%{_bindir}/patchance" "$@" SH chmod 0755 %{buildroot}%{_libexecdir}/patchance-help || true # Run help2man against the transient helper. BuildRequires includes # `help2man`; fail the build if help2man cannot generate the manpage. /bin/bash -i -c "/usr/bin/help2man --no-discard-stderr --output=%{buildroot}%{_mandir}/man1/patchance.1 %{buildroot}%{_libexecdir}/patchance-help" rm -f %{buildroot}%{_libexecdir}/patchance-help || true fi %check # no upstream test suite true %files %{_prefix}/share/licenses/%{name}/COPYING %doc readme.md INSTALL.md CHANGELOG %{_bindir}/patchance %{_datadir}/patchance %exclude %{_datadir}/patchance/src/*.c %{_datadir}/applications/patchance.desktop # install all hicolor icons and scalable svg %{_datadir}/icons/hicolor/*/apps/patchance.png %{_datadir}/icons/hicolor/scalable/apps/patchance.svg %{_mandir}/man1/patchance.1* # Exclude compiled Python bytecode from the package to prevent # rpmlint `python-bytecode-inconsistent-mtime` errors. %exclude %{_datadir}/patchance/src/__pycache__ %exclude %{_datadir}/patchance/src/__pycache__/* %package devel Summary: Development files for Patchance Group: Development/Tools Requires: %{name} = %{version}-%{release} %description -n %{name}-devel C source files and other development artifacts for building extensions or for developers working on Patchance. %files -n %{name}-devel %{_datadir}/patchance/src/*.c %changelog * Wed Jan 21 2026 Erich Eickmeyer - 1.3.0-1 - Initial RPM for Fedora