- The window never had a title, so taskbars and window lists showed it as untitled on every Linux desktop; it is now titled "Midi Harbor". The header draws its own title, which is why it went unnoticed. - On X11 the window's class comes from argv[0], because the pinned libcosmic replaces its X11 window attributes with its Wayland ones. The desktop entry's StartupWMClass is now midi-harbor, the class a package install gets, so X11 taskbars match the window to its entry and icon; Wayland still pairs by the application ID. |
||
|---|---|---|
| .cargo | ||
| .claude/skills | ||
| .specify | ||
| crates | ||
| docs | ||
| fuzz | ||
| packaging | ||
| proto/midiharbor/v1 | ||
| scripts | ||
| specs | ||
| src | ||
| tests | ||
| .gitignore | ||
| .goreleaser.yaml | ||
| AGENTS.md | ||
| build.rs | ||
| Cargo.lock | ||
| Cargo.toml | ||
| clippy.toml | ||
| Icon.svg | ||
| LICENSE.txt | ||
| Makefile | ||
| README.md | ||
| rust-toolchain.toml | ||
| rustfmt.toml | ||
| VERSION | ||
midi-harbor
Midi Harbor manages MIDI connections on macOS, Linux and Windows: virtual ports other applications can use, attached MIDI hardware, RTP-MIDI network sessions to other computers, and Bluetooth LE MIDI devices. A daemon owns every connection and repairs it on its own. A network session that drops is reconnected, hardware that is unplugged and plugged back in picks up where it left off, and notes sounding when a link went away are released rather than left ringing.
The command line and the graphical interface are both clients of the daemon, so closing either changes nothing.
Install
Download a package or archive from the releases, or build this project. midi-harbor-headless
leaves out the graphical interface, for machines without a display.
sudo apt install ./midi-harbor_<version>_<arch>.deb # Debian and Ubuntu
sudo dnf install ./midi-harbor-<version>-1.<arch>.rpm # Fedora and RHEL
The release builds need glibc 2.35 or newer, so RHEL 9 and its rebuilds must build from source.
The Windows executable is not signed, so it warns the first time it runs; Installation says how to let it run.
On Windows, virtual ports need Windows MIDI Services. Windows 11 includes it from its late-2026 update; before that, install Microsoft's Windows MIDI Services SDK Runtime and Tools.
Building
Building needs Rust 1.96 or newer. On Linux it also needs the ALSA, D-Bus and Avahi development files and libclang, and for the graphical interface the xkbcommon and Wayland development files.
On Debian and Ubuntu:
sudo apt install build-essential pkg-config libasound2-dev libdbus-1-dev \
libavahi-client-dev libclang-dev
sudo apt install libxkbcommon-dev libwayland-dev # for the graphical interface
On Fedora and RHEL (enable CodeReady Builder first on RHEL and its rebuilds):
sudo dnf install gcc pkgconf-pkg-config alsa-lib-devel dbus-devel avahi-devel clang-devel
sudo dnf install libxkbcommon-devel wayland-devel # for the graphical interface
Then:
cargo build --release # with the graphical interface
cargo build --release --no-default-features # without it
Windows builds are cross-compiled with mingw-w64:
rustup target add x86_64-pc-windows-gnu
cargo build --release --target x86_64-pc-windows-gnu
Release packages for every platform are built with GoReleaser in Docker, through make snapshot
and make release.
Running as a service
The daemon registers itself with launchd, a systemd user unit, or Task Scheduler, and runs at every login:
midi-harbor service install --start
midi-harbor service status
Running from the command line
To try things out, or to see more of what the daemon is doing, run it in the foreground:
midi-harbor daemon -vv
Config
The setup lives in one YAML file per user, which the daemon writes as things change.
midi-harbor config path prints where it is. It can be written by hand; only names and kinds
are required:
endpoints:
- name: Sequencer Bus
kind: virtual_port
- name: Studio
kind: network_port
routes:
- from: Sequencer Bus
to: Studio
Run midi-harbor config reload after editing it while the daemon runs.
Usage
Every command has help:
midi-harbor --help
Run with no command, midi-harbor opens the graphical interface.
A basic setup that sends a local virtual port to another computer:
midi-harbor port create "Sequencer Bus"
midi-harbor network create "Studio"
midi-harbor network discover
midi-harbor network connect "Studio" "Stage Mac"
midi-harbor route create "Sequencer Bus" "Studio"
MIDI played into "Sequencer Bus" now reaches "Stage Mac", and keeps reaching it across sleep, network changes, and either machine restarting.
Testing
make test # unit tests
make test-integration # the daemon, CLI and protocols over real files and sockets
make test-live # tests needing real MIDI, a Bluetooth radio or a session peer