Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
e7571aa
Add Wave XLR MK.2 (0fd9:00a6) as a supported device
NyleGarcia Aug 29, 2026
c008fe2
Match the MK.2's card name when resolving mic and headphone nodes
NyleGarcia Aug 29, 2026
ea58869
Route the Personal Mix to a resolvable output instead of only the Wav…
NyleGarcia Aug 29, 2026
e9d6a26
Fix subprocess teardown: merge duplicate do_shutdown, reap dead loopb…
NyleGarcia Aug 29, 2026
3bbd28a
Add a mix definition store, seeded with the three built-ins
NyleGarcia Aug 29, 2026
ee12e58
Drive mixer, setup and app from the mix store
NyleGarcia Aug 29, 2026
8cf68c5
Give every mix its own output device
NyleGarcia Aug 29, 2026
c69a9a9
Show Wave XLR gain in dB instead of a raw hex word
NyleGarcia Aug 29, 2026
ca72edb
Read ALSA control ranges from the driver instead of hardcoding them
NyleGarcia Aug 29, 2026
0515ec4
Create, rename and delete mixes from the mix column header
NyleGarcia Aug 29, 2026
3a41ede
Add hardware capture devices as matrix sources
NyleGarcia Aug 29, 2026
ce9d5a8
Share one stream matcher, and show a source whose app is not running
NyleGarcia Aug 29, 2026
c0c9478
Bind an application that is not running, and edit an existing source
NyleGarcia Aug 29, 2026
32db834
Keep a mix playing when the window is closed
NyleGarcia Aug 29, 2026
167ee77
Put the sliders in their cards and collapse the device sidebar
NyleGarcia Aug 29, 2026
c93ddab
Say when a mix carries nothing, and stop offering plumbing as applica…
NyleGarcia Aug 29, 2026
f913c41
Move an application's audio into its source, instead of copying it
NyleGarcia Aug 29, 2026
43df0e3
Seed System, Game, Music, Browser and Voice sources on first run
NyleGarcia Aug 29, 2026
a0f71d0
Manage application matches as a list, not a comma-separated string
NyleGarcia Aug 29, 2026
82f420f
Reorder sources, make System the catch-all, and size the window to it…
NyleGarcia Aug 29, 2026
42c4a08
Drag to reorder, wire the source sliders, and fix the row layout
NyleGarcia Aug 29, 2026
140a5cd
Make the source row slider actually attenuate
NyleGarcia Aug 29, 2026
f0857fe
Microphone icons on capture rows, and mark a muted row
NyleGarcia Aug 29, 2026
b4c1ee0
Mark muted mix cells, start them muted, and keep 0% and mute in step
NyleGarcia Aug 29, 2026
81ca6a5
Add a unit test suite, CI, and document the routing model
NyleGarcia Aug 29, 2026
a19525f
Publish each mix as a capture source, and keep it linked
NyleGarcia Aug 29, 2026
6a826a5
Keep an intake sink from becoming the system default
NyleGarcia Aug 29, 2026
26914c2
Cover sink creation and the default-sink rescue
NyleGarcia Aug 29, 2026
6cb44ba
Identify every node OpenWave creates
NyleGarcia Aug 29, 2026
bdf8aac
Add 48V phantom power control
NyleGarcia Aug 29, 2026
d247873
Match an ALSA card to its USB device, not to a name
NyleGarcia Aug 29, 2026
99884ff
Give every Elgato input its own row, named after the device
NyleGarcia Aug 29, 2026
7a20a05
Group sources so only one in a group is live at a time
NyleGarcia Aug 29, 2026
a4af63d
Pair the built-in row's microphone and headphones to one device
NyleGarcia Aug 29, 2026
544bec1
Show which group a source is in on its row
NyleGarcia Aug 30, 2026
0bd60e6
Group by dragging, switch with one press, and move the add buttons up
NyleGarcia Aug 30, 2026
24ca513
Retire the special microphone row
NyleGarcia Aug 30, 2026
24e7a21
Make the switch button an action, not a state readout
NyleGarcia Aug 30, 2026
58d4aa5
Let the swap button hand the group over from either row
NyleGarcia Aug 30, 2026
dc6362b
Pin plumbing loopbacks to unity gain
NyleGarcia Aug 30, 2026
50344e1
Expose source level, mute and a state snapshot on the session bus
NyleGarcia Aug 30, 2026
6d63abe
Document phantom power, groups and the remote-control surface
NyleGarcia Aug 30, 2026
cc71dd1
Add a screenshot of the matrix
NyleGarcia Aug 30, 2026
f017b99
Cover running with no Elgato device attached
NyleGarcia Aug 30, 2026
1ecf51a
Expose per-cell sends on the session bus
NyleGarcia Aug 30, 2026
749812a
Put OpenWave in the app drawer, and make starting at login a switch
NyleGarcia Aug 30, 2026
302ee8f
Reopen a capture device that enumerated but never started
NyleGarcia Aug 30, 2026
cc3cfb0
Only hide into a tray that exists
NyleGarcia Aug 30, 2026
c0298a3
Remember mix master levels across a reboot
NyleGarcia Aug 30, 2026
e3988fd
Survive an install prefix and an icon theme that are not the default
NyleGarcia Aug 30, 2026
078f9d8
Say whether the microphone is live, in an icon of our own
NyleGarcia Aug 30, 2026
2bc4718
Keep a mix master from reverting: two ways the saved value lost
NyleGarcia Aug 30, 2026
7758ad5
Stop the test suite from wiping the user's mixing matrix
NyleGarcia Aug 30, 2026
ad31c17
Title picker rows with the app's real name, not the bridge's
NyleGarcia Aug 30, 2026
7ad8722
Let the hardware track a slider drag instead of hearing about it after
NyleGarcia Aug 30, 2026
7ca9980
Stop the picker offering an app some row already matches
NyleGarcia Aug 30, 2026
5c90ca1
Discover the ALSA controls by name instead of trusting numids 4/5/6
NyleGarcia Aug 30, 2026
0438a03
Reconnect to a Wave that appears after launch
NyleGarcia Aug 30, 2026
b9a338b
Credit CryoByte33/openwave where its work was taken
NyleGarcia Aug 30, 2026
74d6aef
Let the app be called OpenWave, and say what it is
NyleGarcia Aug 30, 2026
ba3596c
Put a seam between the mixer's decisions and the machine's audio
NyleGarcia Aug 30, 2026
e1a4df4
Merge the PipeWire adapter seam
NyleGarcia Aug 30, 2026
2844b3f
Cut versioned releases with installable objects from a tag
NyleGarcia Aug 30, 2026
88b74db
Green the suite on a runner that has no PyGObject
NyleGarcia Aug 30, 2026
3d8c1bf
Do not let a hidden window overwrite the remembered geometry
NyleGarcia Aug 30, 2026
ce02a62
Build the Arch package from this fork's releases, via the Makefile
NyleGarcia Aug 30, 2026
1ae5d0d
Document the project the way openxlr documents its
NyleGarcia Aug 30, 2026
10fc462
Plan the enhancement sprint the comparison exposed
NyleGarcia Aug 30, 2026
3b84b02
Derive the udev rules and their check from the device profiles
NyleGarcia Aug 30, 2026
e6bd39d
Give the generated desktop entry the packaged one's identity
NyleGarcia Aug 30, 2026
77163eb
Let one tag push own the whole release, AUR included
NyleGarcia Aug 30, 2026
b27f67e
Hold every Wave on the bus, and survive one being yanked
NyleGarcia Aug 30, 2026
916bed5
Bundle everything a bug report needs into one file
NyleGarcia Aug 30, 2026
f9500ed
Let a named scene recall every level as one gesture
NyleGarcia Aug 30, 2026
7f1671d
Wire the window for many devices, scenes, meters and one shared mute
NyleGarcia Aug 30, 2026
104eb4c
Offer an experimental Flatpak for the panel and the matrix
NyleGarcia Aug 30, 2026
42cdd7b
Respawn a device's cell loopbacks when its node comes back
NyleGarcia Aug 30, 2026
def9584
Explain installing on Bazzite and the other Atomic images
NyleGarcia Aug 30, 2026
92f930f
Point the metainfo screenshot at main, which now has it
NyleGarcia Aug 30, 2026
a9e93ee
Ship an rpm with every release
NyleGarcia Aug 30, 2026
2a5dcd3
Keep rpm's Version legal on dry-run builds
NyleGarcia Aug 30, 2026
fb7efe6
Make the Flatpak real: it builds, boots, and knows it is sandboxed
NyleGarcia Aug 30, 2026
2b98220
Plan the DSP chain around what is proven, park NVIDIA behind questions
NyleGarcia Aug 30, 2026
d07007e
Grow the DSP plan to the full chain the matrix deserves
NyleGarcia Aug 30, 2026
2f9bcec
Give every microphone row a DSP chain built from builtins
NyleGarcia Aug 31, 2026
a7be7d2
Add a gate and a compressor to the microphone chain
NyleGarcia Aug 31, 2026
32c939a
Speak the LADSPA plugins' real port names, verified against the library
NyleGarcia Aug 31, 2026
3ed4066
Rebuild a cell's loopback when its capture source changes
NyleGarcia Aug 31, 2026
7c7b426
Let the session manager own the links a real Source can carry
NyleGarcia Aug 31, 2026
2b76dd0
Calibrate the gate and compressor by listening, not guessing
NyleGarcia Aug 31, 2026
e81d3ad
Calibrate the tone controls too: low cut, high shelf, mono
NyleGarcia Aug 31, 2026
fe5de3c
Line the source rows up, and give FX a face every theme can draw
NyleGarcia Aug 31, 2026
bc79509
Meter for the eyes that are actually looking
NyleGarcia Aug 31, 2026
2a85078
Turn the remote surface from poll-only into push, and widen it
NyleGarcia Aug 31, 2026
cfd6804
Let the Wave drive, and watch for the faults the keepalive can't see
NyleGarcia Sep 1, 2026
3237103
Ignore the comparison notes — local scratch now
NyleGarcia Sep 1, 2026
8412791
Let the device's mute button and its row tell one story
NyleGarcia Sep 2, 2026
2236f14
Teach the watchdogs patience, and make them say what they measured
NyleGarcia Sep 2, 2026
1fdc2bd
Cut 1.2.0
NyleGarcia Sep 2, 2026
24940b4
Keep the main loop free, and let a calibration be stopped
NyleGarcia Sep 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 0 additions & 120 deletions .github/workflows/build.yml

This file was deleted.

220 changes: 220 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
name: Release

# Tag-driven semver, adapted from the Stream Deck plugin's release flow.
# That repo computes versions with semantic-release from Angular commit
# messages; this one writes prose commit subjects, which semantic-release
# reads as "never release". So the version is the tag -- push v1.2.3 and
# this builds the release objects -- and everything downstream of the
# version (gate on the suite, build artifacts, publish a Release, point the
# PKGBUILD at it and publish to AUR) is as automatic as the plugin's.
#
# git tag v1.2.3 && git push <remote> v1.2.3
#
# This workflow is the only one that creates Releases and tags carry no other
# automation, so one tag push can never produce two Releases. The AUR job
# no-ops quietly when the AUR_SSH_PRIVATE_KEY secret is absent (forks).

on:
push:
tags: ["v[0-9]+.[0-9]+.[0-9]+*"]
# Buildable on demand so the artifact steps can be exercised without
# spending a version number; a dispatch run uploads workflow artifacts
# but publishes no Release.
workflow_dispatch:

permissions:
contents: read

jobs:
test:
name: Gate on the suite
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install libusb
run: sudo apt-get update -qq && sudo apt-get install -y -qq libusb-1.0-0
- name: Run unit tests
run: python -m unittest discover -s tests -t . -v
- name: Byte-compile every module
run: python -m compileall -q wavexlr tests

build:
name: Build release objects
needs: [test]
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4

- name: Resolve version
id: version
run: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT"
else
echo "version=0.0.0-dev.${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
fi

- name: Source tarball
run: |
V="${{ steps.version.outputs.version }}"
git archive --format=tar.gz --prefix="openwave-${V}/" \
-o "openwave-${V}.tar.gz" HEAD

# A .deb built on the runner installs into the runner distribution's
# own site-packages path (the Makefile asks the interpreter), which is
# the right path for the systems that will install the .deb. Depends
# mirrors install.sh's apt list; python3-xlib is Recommends, matching
# its strictly-optional status.
- name: Debian package
run: |
V="${{ steps.version.outputs.version }}"
PKG="openwave_${V}_all"
# SITEPKG pinned: the Makefile asks the interpreter, and Ubuntu's
# system python answers /usr/local/... first -- the right path for
# a live install on that machine, the wrong one inside a package.
make install DESTDIR="$PWD/$PKG" PREFIX=/usr \
SITEPKG=/usr/lib/python3/dist-packages
mkdir -p "$PKG/DEBIAN"
cat > "$PKG/DEBIAN/control" <<EOF
Package: openwave
Version: ${V}
Section: sound
Priority: optional
Architecture: all
Depends: python3 (>= 3.10), python3-gi, gir1.2-gtk-4.0, gir1.2-adw-1, libadwaita-1-0, libusb-1.0-0, pipewire
Recommends: python3-xlib
Maintainer: OpenWave contributors
Homepage: https://github.com/rikkichy/openwave
Description: The audio mixing matrix for Linux
Per-app mixes with per-mix outputs, plus native control of Elgato
Wave hardware - the Wave XLR interface (original and MK.2/XLR
Dock) and the Wave:3 microphone.
EOF
dpkg-deb --build --root-owner-group "$PKG"

# noarch rpm from the spec: module under /usr/share/openwave with
# PYTHONPATH launchers, so one rpm serves every Fedora python.
- name: RPM package
run: |
V="${{ steps.version.outputs.version }}"
RV="${V//-/\~}" # rpm Version forbids '-'; ~ is its pre-release
sudo apt-get install -y -qq rpm
mkdir -p rpmbuild/{SOURCES,SPECS}
cp "openwave-${V}.tar.gz" rpmbuild/SOURCES/
sed -e "s/@VERSION@/${RV}/" -e "s/@SRCVER@/${V}/" \
packaging/rpm/openwave.spec > rpmbuild/SPECS/openwave.spec
rpmbuild --define "_topdir $PWD/rpmbuild" \
--define "dist %{nil}" -bb rpmbuild/SPECS/openwave.spec
cp rpmbuild/RPMS/noarch/openwave-*.rpm .

- name: Checksums
run: sha256sum openwave-*.tar.gz openwave_*.deb openwave-*.rpm > sha256sums.txt

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: release-objects
path: |
openwave-*.tar.gz
openwave_*.deb
openwave-*.rpm
sha256sums.txt

publish:
name: Publish Release
needs: [build]
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
with:
name: release-objects
- name: Create Release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "${GITHUB_REF#refs/tags/}" \
--repo "${GITHUB_REPOSITORY}" \
--title "OpenWave ${GITHUB_REF#refs/tags/v}" \
--generate-notes \
openwave-*.tar.gz openwave_*.deb sha256sums.txt

aur:
name: Publish to AUR
needs: [publish]
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
container: archlinux:base-devel
timeout-minutes: 10
permissions:
contents: write
steps:
- name: Install tools
run: pacman -Syu --noconfirm git openssh

- uses: actions/checkout@v4
with:
ref: ${{ github.event.repository.default_branch }}

- uses: actions/download-artifact@v4
with:
name: release-objects

# The artifact tarball IS the file the Release serves, so its checksum
# is the one the PKGBUILD must pin. The old manual flow bumped pkgver
# without touching sha256sums, which could only ever be stale: the
# tarball it points at does not exist until this workflow publishes it.
- name: Point the PKGBUILD at this release
run: |
V="${GITHUB_REF#refs/tags/v}"
SUM=$(sha256sum "openwave-${V}.tar.gz" | cut -d' ' -f1)
sed -i "s/^pkgver=.*/pkgver=${V}/" PKGBUILD
sed -i "s/^pkgrel=.*/pkgrel=1/" PKGBUILD
sed -i "s/^sha256sums=.*/sha256sums=('${SUM}')/" PKGBUILD

- name: Commit the PKGBUILD back
run: |
git config --global --add safe.directory "$PWD"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add PKGBUILD
git diff --cached --quiet || git commit -m "Point the PKGBUILD at v${GITHUB_REF#refs/tags/v}"
git push

- name: Push to AUR
env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
AUR_USERNAME: ${{ secrets.AUR_USERNAME }}
AUR_EMAIL: ${{ secrets.AUR_EMAIL }}
run: |
if [ -z "$AUR_SSH_PRIVATE_KEY" ]; then
echo "AUR_SSH_PRIVATE_KEY not set; skipping AUR publish."
exit 0
fi
V="${GITHUB_REF#refs/tags/v}"
mkdir -p ~/.ssh
echo "$AUR_SSH_PRIVATE_KEY" > ~/.ssh/aur
chmod 600 ~/.ssh/aur
ssh-keyscan -t ed25519,rsa aur.archlinux.org > ~/.ssh/known_hosts 2>&1 || true
export GIT_SSH_COMMAND="ssh -i ~/.ssh/aur -o StrictHostKeyChecking=accept-new"
git config --global user.name "$AUR_USERNAME"
git config --global user.email "$AUR_EMAIL"
git config --global --add safe.directory '*'

git clone ssh://aur@aur.archlinux.org/openwave.git aur-repo
cp PKGBUILD aur-repo/PKGBUILD
useradd -m builder
chown -R builder:builder aur-repo
cd aur-repo
su builder -c "makepkg --printsrcinfo" > .SRCINFO
git add PKGBUILD .SRCINFO
git commit -m "Update to v${V}"
git push
41 changes: 41 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Tests

on:
push:
branches: ["**"]
pull_request:
workflow_dispatch:

jobs:
unit:
name: Unit tests
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# 3.10 is the floor the README states; the newest catches deprecations
# early. Nothing between them is interesting enough to pay for.
python: ["3.10", "3.13"]

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}

# wavexlr/device.py loads libusb through ctypes at import time, so the
# runner needs the shared library even though no device is present. It
# is the only system dependency the suite has.
- name: Install libusb
run: sudo apt-get update -qq && sudo apt-get install -y -qq libusb-1.0-0

# No Python dependencies on purpose. The suite covers the backend modules,
# which import neither GTK nor libusb, so it runs on a bare runner with
# no audio server, no PipeWire and no hardware. Anything needing those
# belongs in a manual check, not here.
- name: Run unit tests
run: python -m unittest discover -s tests -t . -v

- name: Byte-compile every module
run: python -m compileall -q wavexlr tests
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ __pycache__/
*.pyc
*.pyo
.vscode/
docs/comparison.md
Loading