Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Midi Router Client

Create routes from anywhere to anywhere

Midi Router Client is an advanced, cross-platform tool designed to route and manipulate MIDI signals in real time. It allows users to create virtual MIDI ports, map MIDI events (e.g., CC to pitch wheel), monitor inputs, and build custom controls like program change dropdowns—all with minimal latency

Homepage: https://sourceforge.net/projects/midi-router-client/

Github and support: https://github.com/shemeshg/MidiRouterClient

Installation Guide

Windows

Install via winget:

winget install Shemeshg.MidiRouterClient

Also see Windows Service (manual installation)

macOS

Install via Homebrew:

brew remove --cask midi-router-client
brew install --cask shemeshg/homebrew-tap/midi-router-client
codesign --force --deep --sign - /Applications/midi-router-client.app/
xattr -c /Applications/midi-router-client.app/

Note: macOS requires manual code signing and removal of extended attributes to ensure proper execution.

Linux

Prebuilt .zip and .deb packages are available, targeting the oldest supported Ubuntu LTS at the time of release.

⚠️ Additional Notes

  • Distributed binaries are not code-signed.

Windows Service (manual installation)

A standalone ZIP package is also provided:

midi-router-client-cli-<version>-win64.zip

This package contains:

  • A standard Windows service executable
  • A CLI executable (same binary) for Linux/macOS‑style command‑line usage

Because this ZIP is not installed via winget, Windows users must manually upgrade the service for each new version:

  1. Download the new ZIP
  2. Extract it
  3. Test the executable (important for unsigned binaries)
  4. Update the Windows service to point to the new version

Below are the correct commands.


Updating the Windows Service Manually

Replace <path> with the full path to the extracted folder.

1. Test the executable (important for unsigned binaries)

Before registering it as a service, ensure Windows allows the executable to run:

midi-router-client-cli.exe --headless

If Windows prompts for authorization, approve it.
Once it runs successfully, continue with the service update.


2. Stop the existing service

sc stop MidiRouterCli

3. Delete the existing service

sc delete MidiRouterCli

4. Re‑create the service with the new version

⚠️ Important:
binPath= must be followed by a space before the quoted path, or Windows will reject the command.

sc create MidiRouterCli binPath= "D:\midi-router-client-cli-2.21.0-win64\bin\midi-router-client-cli.exe"

5. Start the service

sc start MidiRouterCli

Notes

  • The service name is MidiRouterCli
  • The executable must remain in the same location after creation
  • If you move or delete the folder, the service will fail to start
  • Upgrading requires repeating the stop/delete/create/start sequence
  • Running the executable once manually ensures Windows trusts the unsigned binary before it runs as a service

MIDI Configuration Overview

This document describes how configuration, presets, routing, and user‑control dropdowns work within the application. It also explains how configuration is stored and how users can manage it through the interface.

Connected Inputs and Outputs

The configuration includes a list of all currently active MIDI ports.
These ports may be physical or virtual (where supported).

Presets

Presets store settings for both connected and disconnected ports. A preset may include:

  • Routing definitions
  • User control mappings (sliders, dropdowns, etc.)

Presets allow you to quickly restore a complete setup without manually reconfiguring each port.

Dropdowns allow users to select values using friendly labels.
A label may also contain embedded MIDI commands, which override the default user‑control behavior.

How Dropdowns Work

  • Dropdown items are generated from the User Control definition.
  • A label may optionally include one or more embedded MIDI instructions.
  • When embedded commands are detected, the normal User Control action is skipped.
    Instead, the embedded MIDI messages are sent immediately.

Virtual Ports

Virtual MIDI ports can be defined for internal routing.
⚠️ Note: Virtual ports are currently not supported on Windows.

Persisting Configuration

Configuration is stored in a json file.
Because the schema may change between versions, it is recommended to back up your configuration regularly.

Automatic Load/Save

The Login tab allows you to load the configuration when the application starts, and save it when the application closes or when changes are applied (with throttling).

Accessing the Configuration File

Clicking the link in the Login tab opens the server folder where the JSON configuration is stored.
You can copy this file for backup.

Additional Options

The menu provides:

  • About information
  • Options to download, upload, and apply the current configuration
  • Accessibility (font size)
  • UI preferences, monitor in external dialog.

cli options available for linux and macos only

Since the application does not automatically re‑apply its configuration when MIDI devices disconnect or reconnect, it can be useful to trigger a re‑apply through the CLI — both for local and remote servers. A successful apply operation returns exit code 0.

Usage: ./midi-router-client [options]

Options:
  -h, --help  Displays help on commandline options.
  --help-all  Displays help, including generic Qt options.
  --headless  Run in headless mode on the specified port by the gui.
               --config-file  <path>    Full path to config file.
               --server-port  <path>    serevr port.
  --apply     Apply a preset (local or remote).
               --address <address>      Remote address (ip:port).
               --preset-name <preset>   Preset name (regex) to apply, use "" to
              list presets

 example:
  ./midi-router-client  --apply --address 127.0.0.1:2222 --preset-name "neutron"

Screenshots

Settings

Login Tab

Supported Dropdown Embedded Commands

A dropdown label may include any of the following tokens.
They can appear anywhere in the label, in any order, and the system will automatically detect and schedule them.

MIDI Control Commands

TokenMeaning
CC-x-ySend Control Change x with value y
PC-xSend Program Change x
NRPN-x-ySend NRPN parameter x with value y

Note Commands

TokenMeaning
NOTE-ON-x-yPlay note x with velocity y
NOTE-OFF-x-yStop note x with velocity y

Notes are passed internally as a QStringList, so even a single note is handled consistently with multi‑note APIs.

Timing Commands

TokenMeaning
WAIT-xDelay the next command(s) by x milliseconds

WAIT does not block the UI thread.
Instead, commands are scheduled preserving order.

Multiple WAITs accumulate:

WAIT-100 WAIT-200  → total delay = 300 ms

Commands scheduled at the same delay fire in the order they appear.


Example

Selecting Program 3 in Program Bank 5:

Item default send zero for whatever is defined in user control
Item that sends program change | CC-0-5  CC-32-0  PC-3

Commands after | are processed internally but hidden from the dropdown label to keep it readable.

This sends:

  • CC 0 → 5 (Bank Select MSB)
  • CC 32 → 0 (Bank Select LSB)
  • PC 3 (Program Change)

Example with Notes and Timing

NOTE-ON-60-100 WAIT-500 NOTE-OFF-60-50

This will:

  1. Play note 60 at velocity 100
  2. Wait 500 ms
  3. Stop note 60 at velocity 50

Presets

Presets are containers for user-defined input configurations. They can be activated via mouse click or MIDI event, offering flexible and dynamic control.

Each preset holds its own distinct settings across all available input channels.

Usage Notes

While multiple presets can be active at once, it’s generally recommended to use only one at a time—especially when applying advanced input configurations such as 14-bit resolution or clock routing.

Using a single preset helps maintain clarity and avoids potential conflicts between overlapping input settings.

MIDI Preset Activation Modes

when the assigned MIDI event is received

  • select — Activates the selected preset and disables all others.
  • toggle — Enables or disables the current preset.
  • on — Enables the preset.
  • off — Disables the preset.

Screenshots

Presets

Preset

Input Ports

This tab lets you set up and manage your input ports.
Only ports that are currently connected will be shown.

Port Settings

Here’s what you can adjust:

  • Ignore Message Types: Choose which types of MIDI messages to ignore.
  • MIDI Clock Settings: Control how MIDI clock signals are handled, including advanced options like converting SPP (Song Position Pointer) to time signatures.
  • 14-bit CC Translation: Enables more accurate conversion of 14-bit MIDI messages—for example, turning them into pitch wheel data.

Only the active and selected preset determines the applied port settings.

Monitoring

Monitoring lets you keep an eye on incoming MIDI messages. It also makes tricky stuff—like 14-bit values or NRPNs—way easier to read by turning them into something more understandable.

Routing Options

You can set up routing in two ways:

  • EasyConfig: A simple, beginner-friendly tool that helps you create routing setups without needing to dive into technical details.
  • Routes: A more advanced option for users who want full control over routing configurations.

EasyConfig automatically builds the Routes setup for you, so you get the best of both worlds!


Screenshots

In ports

EasyConfig Overview

EasyConfig makes MIDI routing simple and approachable—no need to dive into complex low-level setup.

The interface is organized into two main tabs: Routes and Split, each designed to help you configure your MIDI setup quickly and efficiently.

EasyConfig Routes

Destination Setup

You can route MIDI data to either:

  • A local output name, or
  • A network destination using the format: <address>:<port>/<destinationName>

To make remote setup easier, there’s a Query button that checks if the remote port is available and confirms connectivity.
All network communication uses WebSocket over TCP, ensuring reliable data transfer.

Keyboard Split

The Split tab lets you define a split point on your keyboard—this divides it into separate zones. This is especially useful for setting up layered instruments or assigning different sounds to different parts of the keyboard.

Once zones are created, you can assign them as sources for note on/off events (when a key is pressed or released)


Screenshots

Split

EasyConfig

Route

A Route is a container for multiple chains, enabling modular and sequential processing of MIDI data.

Learning to Create Routes

If you’re trying to understand how routes are built, the easiest way is to start with an EasyConfig. Once you’ve created one, inspect how it’s automatically translated into a full route. This reverse-engineering method offers a hands-on, intuitive way to grasp the structure and logic of route creation—without needing to dive into low-level details right away.


Chains

A chain defines a linear path composed of a sequence of filters. Each filter performs a specific transformation or analysis on the MIDI stream, allowing for flexible and customizable data manipulation as it flows through the chain.


Filter Types

TO_MIDI_DESTINATION

Routes MIDI events to a specific local MIDI destination.

TO_CONSOLE

Logs MIDI events to the console (either server or client). This filter is also used for inter-server communication, such as sending logged MIDI messages to a client or triggering preset changes via MIDI.

TO_NETWORK

Sends all MIDI events to a remote destination.

SCHEDULE_TO

Holds MIDI events and schedules them for future delivery based on deferredType and deferredTo parameters. Requires MIDI clock events to function properly.

FILTER_AND_TRANSFORM

Allows both filtering and transforming MIDI event data. Transformation notation includes:

  • [[fromStart, fromEnd, toStart, toEnd]] — Maps a range from fromStart to fromEnd onto toStart to toEnd.
  • [[fromStart, fromEnd, toStart]] — Short form where toEnd = toStart + (fromEnd - fromStart).
  • [[value1, value2]] — Maps value1 to value2.
  • [[value]] — Equivalent to [[value, value]], a single value mapping.

SWITCH_DATA1_DATA2

Swap data1 and data2, or swap NRPN control and NRPN data when using NRPN. This can be useful, for example, when routing a Note On key value to CC data.

📚 Reference

Filter Type 0: TO_MIDI_DESTINATION

Parameters:

  • filterType: 0
  • midiInputName: Name of the MIDI input port

Filter Type 1: TO_CONSOLE

Parameters:

  • filterType: 1
  • logTo: Logging destination
    • 0 (CLIENT): Client console
    • 1 (SERVER): Server console
  • userdata: Optional user-defined JSON data

Filter Type 2: TO_NETWORK

Parameters:

  • filterType: 2
  • midiInputName: MIDI input port name
  • serverName: Target server name
  • serverPort: Target server port

Filter Type 3: SCHEDULE_TO

Parameters:

  • filterType: 3
  • deferredType: Scheduling mode
    • 0: IN_SPP (relative to Song Position Pointer)
    • 1: IN_BAR (relative to current bar)
    • 2: AT_SPP (specific SPP)
    • 3: AT_BAR (specific bar)
    • 4: QUANTIZE_SPP (nearest SPP)
    • 5: QUANTIZE_BAR (nearest bar)
  • deferredTo: Number of units to defer

Filter Type 4: FILTER_AND_TRANSFORM

Parameters:

  • conditionAction: Event deletion logic
    • 0: DO_NOT_DELETE
    • 1: DELETE_IF_NOT_MET_CONDITION
    • 2: DELETE_IF_MET_CONDITION
  • filterChannel: MIDI channel filter
  • filterData1: Data1 byte filter/transform
  • filterData2: Data2 byte filter/transform
  • filterEvents: MIDI event types to filter (e.g., [8] for Note On)
  • filterType: 4
  • name: Filter name

Filter Type 5: SWITCH_DATA1_DATA2

User Controls

Each preset can include interactive controls such as sliders, optionally paired with dropdown menus.

User controls can be programmed to trigger MIDI messages to any port when the Midi Router Client receives program changes

Only the controls associated with the currently selected preset are displayed.

These controls send MIDI events to a predefined local port. The following MIDI event types are supported:

  • Control Change (CC)
  • Program Change
  • NRPN (Non-Registered Parameter Number)

The is64Mode flag interprets the value 64 as the center or zero point, commonly used for bipolar ranges.

Dropdowns can also be used to store and select predefined preset names.


Screenshorts

controls

control

Reference

Event Types

The value used at the json mapped to midi event id

[
  { "value": 0, "text": "[] - -" },
  { "value": 1, "text": "[8, 9] - Note on/off" },
  { "value": 2, "text": "[9] - Note off" },
  { "value": 3, "text": "[8] - Note on" },
  { "value": 4, "text": "[10] - Key Aftertouch" },
  { "value": 5, "text": "[11] - Control Change" },
  { "value": 7, "text": "[100] - NRPN" },
  { "value": 8, "text": "[12] - Program Change" },
  { "value": 9, "text": "[13] - Channel Aftertouch" },
  { "value": 10, "text": "[14] - Pitch Bend" }
]

Preset configuration example

Users aren’t expected to manually edit or create json files—this example is provided solely to help you understand the configuration structure.

As the configuration grows, it may become increasingly difficult to grasp its overall purpose. It’s recommended to maintain a separate README file outside the app to document and explain your configuration.

Routing a Control Change (CC) event to NRPN, using channel 6 for both, and mapping a value range from 0–127 to 0–255.

{
  "midiRoutePresets": [
    {
      "midiRouteInputs": [
        {
          "midiInputName": "0_Launch Control XL",
          "easyConfig": {
            "easyConfigRoutes": [
              {
                "fromCcOrNrpnEnd": 127,
                "fromCcOrNrpnStart": 0,
                "fromChannel": 6,
                "fromData1": -1,
                "fromSelectedMidiEventTypeId": 5,
                "splitRangeId": -1,
                "toCcOrNrpnEnd": 255,
                "toCcOrNrpnStart": 0,
                "toChannel": 6,
                "toData1": 8,
                "toDestinationName": "localhost:12345/0_Scarlett 2i4 USB",
                "toSelectedMidiEventTypeId": 7,
                "transpose": 0,
                "uuid": "d3bc0cb8-0de6-43ec-94c5-91b4a6ed7c6d"
              }
            ],
            "keyboardSplits": [],
            "zoneNames": []
          }
        }
      ]
    }
  ]
}

List of Midi CC commands

Some of these commands may be reserved, although certain devices might not reserve them at all and instead use them for different functions. The following list represents a common convention, but individual devices are not strictly required to adhere to it.

bankselectcoarse: 0,
modulationwheelcoarse: 1,
breathcontrollercoarse: 2,
footcontrollercoarse: 4,
portamentotimecoarse: 5,
dataentrycoarse: 6,
volumecoarse: 7,
balancecoarse: 8,
pancoarse: 10,
expressioncoarse: 11,
effectcontrol1coarse: 12,
effectcontrol2coarse: 13,
generalpurposeslider1: 16,
generalpurposeslider2: 17,
generalpurposeslider3: 18,
generalpurposeslider4: 19,
bankselectfine: 32,
modulationwheelfine: 33,
breathcontrollerfine: 34,
footcontrollerfine: 36,
portamentotimefine: 37,
dataentryfine: 38,
volumefine: 39,
balancefine: 40,
panfine: 42,
expressionfine: 43,
effectcontrol1fine: 44,
effectcontrol2fine: 45,
holdpedal: 64,
portamento: 65,
sustenutopedal: 66,
softpedal: 67,
legatopedal: 68,
hold2pedal: 69,
soundvariation: 70,
resonance: 71,
soundreleasetime: 72,
soundattacktime: 73,
brightness: 74,
soundcontrol6: 75,
soundcontrol7: 76,
soundcontrol8: 77,
soundcontrol9: 78,
soundcontrol10: 79,
generalpurposebutton1: 80,
generalpurposebutton2: 81,
generalpurposebutton3: 82,
generalpurposebutton4: 83,
reverblevel: 91,
tremololevel: 92,
choruslevel: 93,
celestelevel: 94,
phaserlevel: 95,
databuttonincrement: 96,
databuttondecrement: 97,
nonregisteredparametercoarse: 98,
nonregisteredparameterfine: 99,
registeredparametercoarse: 100,
registeredparameterfine: 101

Runtime control of the server via Qt WebChannel

This capability is no more used by the GUI of the application. Instead, configuration is handled exclusively through submitted JSON files.

https://github.com/shemeshg/qwebchannelTypeScriptExample/blob/master/src/main.ts

SBOM

https://github.com/shemeshg/MidiRouterClient/blob/main/SBOM.md

LICENSE

https://github.com/shemeshg/MidiRouterClient/blob/main/LICENSE