MIDI Over Network Daemon - RTP-MIDI implementation with client and server
nmidi is a Rust-based implementation of the RTP-MIDI (AppleMIDI) protocol that enables MIDI communication over IP networks. It consists of two main components:
- nmidi-core: Core library implementing AppleMIDI session management, RTP-MIDI packet encoding/decoding, network sockets, and mDNS discovery
- nmidi-server: Network MIDI server that exposes local MIDI ports over the network
- nmidi-client: Network MIDI client that connects to remote MIDI services
This implementation follows the specifications in:
- RFC 6295: RTP Payload Format for MIDI
- Apple MIDI Network Driver Protocol
- RFC 6762/6763: DNS-SD over mDNS for service discovery
- AppleMIDI protocol support (session handshake, synchronization)
- RTP-MIDI packet encoding/decoding
- mDNS-based service discovery (
_apple-midi._udp) - UDP-based transport (control and data channels)
- Automatic MIDI port detection with continuous monitoring
- Multi-port advertising: Each MIDI port gets its own mDNS entry (Apple MIDI compatible)
- Compatible with macOS Audio MIDI Setup
- Cross-platform (Linux, macOS, Windows with ALSA/CoreMIDI/WinMM)
On Linux (Debian/Ubuntu):
sudo apt-get install libasound2-devOn macOS:
# CoreMIDI is included with Xcodecargo build --releaseStart a server to expose local MIDI ports:
./target/release/nmidi-server --name "My MIDI Server"Options:
-n, --name <NAME>: Device name to advertise (default: "nmidi-server")-b, --bind <ADDR>: Bind address (default: "0.0.0.0")--monitor-interval <SECONDS>: Port monitoring interval in seconds (default: 5)-l, --log-level <LEVEL>: Log level (trace, debug, info, warn, error)
The server will:
- Detect available MIDI input and output ports
- Monitor for port changes in the background
- Advertise each MIDI port via separate mDNS entry with service type
_apple-midi._udp - Automatically allocate UDP port pairs for each MIDI port (OS-assigned)
- Listen for incoming connections on all advertised ports
- Handle AppleMIDI session handshakes and MIDI data transport
- Dynamically add/remove services as MIDI ports are connected/disconnected
Multi-Port Advertising: Following Apple MIDI's approach, each physical MIDI port (input or output) is advertised as a separate mDNS service. This ensures maximum compatibility with Apple Audio MIDI Setup and other RTP-MIDI implementations. Each service includes TXT records with port metadata (name, type, index). Services are automatically cleaned up when ports are disconnected.
The client uses subcommands for better user experience.
Discover services on the network:
Options:
-H, --host <HOST>: Remote host to connect to (required for connect)-p, --port <PORT>: Remote control port (default: 5004)-n, --name <NAME>: Device name (defaults to system hostname)-b, --bind <ADDR>: Local bind address (default: "0.0.0.0:0")-l, --log-level <LEVEL>: Log level
The implementation includes:
-
Session Management:
IN(Invitation): Initiate connectionOK(Invitation Accepted): Accept connectionBY(End): Terminate sessionCK(Synchronization): Clock sync for timestamp alignment
-
Packet Structure:
- 2-byte signature (0xFFFF)
- 4-byte command
- Version, token, SSRC fields
- Device name (null-terminated string)
- RTP Header: Standard RTP v2 header with MIDI payload type
- MIDI Command Section: Timestamped MIDI events with delta times
- Variable-Length Encoding: For delta times and command lengths
Uses DNS-SD over mDNS:
- Service type:
_apple-midi._udp.local. - One mDNS entry per MIDI port for Apple MIDI compatibility
- TXT records:
name=<port_name>,ver=2,type=<input|output>,index=<port_index> - Automatically discoverable by macOS Audio MIDI Setup
Run the protocol tests:
cargo test-
Start the server on one machine:
./target/release/nmidi-server --name "TestServer" -
From another machine (or terminal), browse for services:
./target/release/nmidi-client discover
-
Connect to the server:
./target/release/nmidi-client connect --host <server-ip>
-
On macOS, open "Audio MIDI Setup" → "MIDI Studio" → "Network" to see the advertised service
MIT