No description
  • Java 98.2%
  • Nix 1.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Kata c16560009a
Some checks failed
Java CI with Maven / build (push) Has been cancelled
Merge pull request #11 from nohn/fix/restore-mute-state-on-app-start
fix: restore mute LED state on app start
2026-11-09 03:54:53 +02:00
.github/workflows Update maven.yml 2025-04-29 18:09:00 +03:00
.idea Intial commit 2025-04-29 01:32:18 +03:00
doc add documentation for the Midi CC IDs for the different controls 2026-10-15 06:37:12 +02:00
src/main fix: restore mute LED state on app start 2026-11-06 15:55:28 +01:00
.envrc Added flake.nix and .envrc for nix-direnv support 2026-01-30 17:34:38 +02:00
.gitignore Added flake.nix and .envrc for nix-direnv support 2026-01-30 17:34:38 +02:00
dependency-reduced-pom.xml bump version 2026-10-16 08:04:05 +03:00
flake.lock Added flake.nix and .envrc for nix-direnv support 2026-01-30 17:34:38 +02:00
flake.nix Added flake.nix and .envrc for nix-direnv support 2026-01-30 17:34:38 +02:00
LICENSE Create LICENSE 2025-04-29 17:18:16 +03:00
pom.xml bump version 2026-10-16 08:04:05 +03:00
README.md doc clarification 2026-10-15 07:29:16 +02:00

Midi pw-mixer

A Midi mixer software to target Pipewire on linux and Korg nanoKONTROL2

Maven build

Alternative repos:
https://github.com/Katacc/Midi-pw-mixer
https://codeberg.org/Katacc/Midi-pw-mixer

Getting started

Prequisites

  • Java 21 JDK or JRE
  • Pipewire
  • pw-dump
  • wpctl
  • User configuration file
  • Korg nanoKONTROL2

Installation

You can either grab the repo and compile the software with maven using

$ mvn package
$ cd target
$ java -jar midi-mixer-<VERSION>.jar # Run the program
$ java -jar midi-mixer-<VERSION>.jar & disown # To send the program to background

Or just grab the latest build from release, I will include a bash script for easier launching of the application, then just put them into your PATH and autostart on login if you want to

Usage

This software relies on the user configuration file. Please create a folder and a file in your /home/user/.config/ The folder and configuration files should be /home/user/.config/midi-mixer/config.ini

The config allows you to map applications to faders (rectangles), knobs (circles) and buttons (squares):

Schematic view of the MIDI Control Change IDs

Green controls are freely assignable and not preassigned. Transport and cycle controls (buttons 41 [play-pause], 42 [stop], 43 [previous], 44 [next] and 46 [cycle]) are also freely assignable, but are preassigned to their standard functions when not specified in configuration.

Here is a configuration file example:

[fader 5]
application = spotify

[fader 6]
application = Zen

[fader 7]
application = Last Epoch.exe:Warframe.x64.exe
[button 55]
application = Last Epoch.exe:Warframe.x64.exe
action = mute

[knob 16]
application = Firefox

# assign default behaviour of #43 and #44 (prev/next) to #58 and #59, change #43 and #44 to offset -/+ 15
[button 58]
action = previous

[button 59]
action = next

[button 43]
action = position
offset = -15

[button 44]
action = position
offset = +15

Follow the same syntax to add the rest of the faders, knobs and applications to map to the faders or knobs.

The faders IDs are from left to right 0 - 7 and the knob IDs are 16 - 23. To map spotify to the leftmost fader you would type

[fader 0]
application = spotify

To map Firefox to the leftmost knob you would type

[knob 16]
application = Firefox

To map Firefox mute/unmute to the leftmost "M" button you would type

[button 48]
application = Firefox
action = mute

To map seeking forward/backward to buttons, you can configure position actions with an offset:

[button 51]
action = position
offset = +5

[button 52]
action = position
offset = -5

Supported button actions include:

  • mute: Toggles mute for the mapped application(s) or node(s). LED state syncs to the mute state of the respective sink/source. You may need to set your nanoKONTROL2 mode setting to "External" in the original nanoKONTROL2 software.
  • position: Seeks playback position by an arbitrary offset (e.g., +5 or -5) via playerctl.
  • play-pause: Toggles media play/pause via playerctl (default for button 41).
  • stop: Stops media playback via playerctl (default for button 42).
  • previous: Jumps to the previous track via playerctl (default for button 43).
  • next: Jumps to the next track via playerctl (default for button 44).
  • cycle: Reloads the configuration file (default for button 46).

You can map any pipewire node to any fader, knob or button, i.e. not only applications, but also for example output and devices:

[fader 6]
application = alsa_output.usb-Beyerdynamic_FOX_5.00-00.analog-stereo

[fader 22]
application = alsa_input.usb-Beyerdynamic_FOX_5.00-00.mono-fallback.3

[knob 54]
application = alsa_output.usb-Beyerdynamic_FOX_5.00-00.analog-stereo

You can force reconfiguration with cycle button from midiKONTROL2. This is required if you open up a application after starting midi-mixer

(This way we avoid any time based configuration parsing that would lead to constant CPU usage for the time calculations)

Logging and Debugging

You can set the log level using the -l (--log-level) parameter. Valid values are TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF. Defaults to INFO. DEBUG dumps raw MIDI messages received and Pipewire commands sent.

$ java -jar midi-mixer-<VERSION>.jar -l DEBUG # Run the program with DEBUG log level
$ java -jar midi-mixer-<VERSION>.jar -l OFF   # Run the program without logging

The -d (--debug) parameter is deprecated and is equivalent to -l DEBUG.

Changing cooldown time for Pipewire ID refreshes

If a Pipewire node is not found (because for example it was not active while pw-mixer was started), the program will try to refresh the Pipewire ID every 10000ms.

That cooldown time can be changed through the -c parameter:'

$ java -jar midi-mixer-<VERSION>.jar -c 1000 # Change the cooldown to 1000ms

Future and additions

This project was meant to target my specific setup, but if enough interest rises, I might add support for other configurations. If you want a feature added, be sure to make an issue or pull request with the added feature, or make a fork for yourself :)