NOW LOADING

WinRT API Support for Network MIDI 2.0 Endpoints


Namespace for creating and managing Network MIDI 2.0 (UDP) hosts and clients
Windows.Devices.Midi2.Transports.Network

Types for creating, removing, and monitoring Network MIDI 2.0 hosts and client connections at runtime, and for discovering Network MIDI 2.0 hosts advertised on the local network.

Everything here is reached through the static MidiNetworkTransportManager class.

Definitions

Network MIDI 2.0 calls the two ends of a session the host and the client. The names say which end waits for a connection and which end starts it, not which end sends MIDI messages. Once a session is set up, data goes both ways.

  • Host: Windows MIDI Services listens on a UDP port and accepts sessions from remote clients. Usually there’s one per PC. It can be advertised over mDNS so other devices can find it.
  • Client: Windows MIDI Services connects to a remote host. That’s either one found over mDNS, or one you reach directly by its host name or IP address, and port.

A single PC can be both at the same time.

Prerequisites

  • The Network MIDI 2.0 transport is installed and enabled in the service
  • midisrv.exe is allowed through Windows Firewall and any other firewall in use
  • For discovery, mDNS is running on the PC and allowed on the network. Windows MIDI Services uses the mDNS support built into Windows, not Bonjour
  • Direct connections by address and port don’t need mDNS, and they aren’t limited to the local subnet, as long as your network and firewalls allow them

Typical flows

Creating a host so other devices can connect to this PC

  1. Fill in a MidiNetworkHostCreationConfig
  2. await MidiNetworkTransportManager.CreateNetworkHostAsync(config)
  3. Check Success on the returned MidiNetworkHostCreationResponse

CreateNetworkHostAsync doesn’t return until the host is running. So a successful result means the host is up and, if you asked for it, advertising.

Connecting to a remote host

  1. Discover hosts with a MidiNetworkAdvertisedHostWatcher, or address one directly
  2. Fill in a MidiNetworkClientConnectConfig with a MidiNetworkClientMatchCriteria
  3. await MidiNetworkTransportManager.ConnectNetworkClientAsync(config)

Approving remote clients

A host set to require approval answers an unknown remote device with “pending,” instead of accepting it. Call GetPendingRemoteClients() to find them, and decide on each one with ApproveOrDenyRemoteClientConnectRequestAsync. The service doesn’t send a notification, so check every few seconds.

Changing a host or a connection that’s already running

  1. Fill in a MidiNetworkHostUpdateConfig or a MidiNetworkClientUpdateConfig, identifying the entry by its HostId or ClientId
  2. await MidiNetworkTransportManager.UpdateNetworkHostAsync(config) or UpdateNetworkClientAsync(config)
  3. Check Success on the returned MidiNetworkHostUpdateResponse or MidiNetworkClientUpdateResponse

Neither one stops the host or disconnects the client. A setting that can change on a running session, such as FallbackMidi1PortCount, takes effect right away. A setting that’s decided when an endpoint is built, such as CreateMidi1Ports, is saved for the next connection. Success means the service accepted the settings, not that each one changed something you can see.

Giving one device on a host a sending speed of its own

A host sends to every connected device at the host’s speed. When one device needs a different speed, like a hardware synth that loses data during a long SysEx dump, give it a speed of its own:

  1. Read the list the running host holds from MidiNetworkConfiguredHost.RemoteClientSettings
  2. Fill in a MidiNetworkHostRemoteClientSettingsConfig with that list, with the device added or changed
  3. Pass it to MidiServiceTransportPluginConfigManager.SendUpdate, and then to SaveUpdate to keep it

The device is recognized by its name and product instance id, so it gets the same speed every time it connects. A device that’s already connected changes speed right away.

Choosing and naming the MIDI 1.0 ports a connection gets

A device that describes itself with function blocks gets MIDI 1.0 ports for its own groups. For one that doesn’t, such as another Windows PC, fill FallbackMidi1PortGroups with MidiNetworkMidi1PortGroup objects, one for each group that should have ports, with the name MIDI 1.0 apps should show. A client entry, a host, and one device on a host each have the list. Check for the fallbackMidi1PortGroups capability first, because an older transport only reads FallbackMidi1PortCount.

Reconnection behavior

Once a client is set up, the service manages the connection for you. What it does when a remote host goes away depends on how the client was set up, because each way gives the service different information to work with.

Situation Discovered (mDNS) client Direct client (host name or IP address)
Host not present at startup Connects when the host advertises Tried again after the retry interval
Host goes away and returns Reconnects when it advertises again Tried again right away, then after each retry interval
Never answered Retried whenever it advertises Tried again after the retry interval
Asked for permission, and nobody answered in time Retried whenever it advertises Tried again after the retry interval
Said it’s busy Tried again after 10 to 30 seconds Tried again after 10 to 30 seconds
Turned the connection down, or asked for authentication Marked Failed Marked Failed

Nothing announces that a direct host is back, so the service tries it again after the retry interval. That’s DirectConnectionScanIntervalMilliseconds in MidiNetworkTransportSettings, and it’s 20 seconds by default. Each try is up to five invitations over about 10 seconds, and a host name is looked up again every time, so the service finds a host whose address has changed. A host that’s gone for good keeps being tried until you disconnect the client. To try one right away, call ConnectNetworkClientAsync again with the same ClientId. For an entry that already exists, this means “it’s reachable now, try again.”

A busy host is the exception, because it did answer. A Windows host says it’s busy while it still holds this PC’s previous session, which it lets go after about 10 seconds without an answer. So this is what a reconnect runs into when a connection drops, for example because either PC’s network address changed. A host turns a connection down when its owner refuses it, or when it wants authentication, which isn’t built yet. Asking again won’t change that, so the service waits for you to call ConnectNetworkClientAsync again.

A host with more than one address. A host can have an IPv4 address and several IPv6 addresses, whether it’s discovered or reached by host name. The service tries them in the order Windows uses for every name it looks up, which usually puts IPv6 first, and leaves out any address this PC has no route to. When a try gets no answer, the next try goes to the next address right away, instead of after the retry interval. Once a session opens, that address is tried first from then on. A client given an IP address only ever uses that address. An administrator can make the whole PC prefer IPv4 over IPv6.

Use MidiNetworkConfiguredClient.EntryState to show this in your app, and LastErrorCode to say why an entry isn’t connected. See MidiNetworkClientEntryState and MidiNetworkClientConnectErrorCode.

Persistence

Hosts and clients created with this API are temporary, and go away when the service restarts. To keep one, also pass the same configuration object to MidiServiceTransportPluginConfigManager.SaveUpdate. MIDI Settings and Network MIDI Setup do this for you.

To keep a host’s allow and deny decisions after a restart, save a MidiNetworkHostKnownClientsConfig the same way. The service reads those lists when it starts, but it never saves them itself.

To see what’s saved, call GetSavedHosts and GetSavedClients. They read the configuration file, so they work even when the service isn’t running. MidiNetworkTransportManager lists which configuration object to save for each change, including removing a saved host or client.

Current limitations

  • Authentication isn’t built yet. A host set up to require it is rejected when it’s configured, instead of quietly accepting connections that aren’t authenticated. See issue 733
  • mDNS discovery only works on the local subnet. Direct connections don’t have that limit
  • mDNS discovery can take a while to find everything. midimdnsinfo.exe in the MIDI tools helps you check what’s visible on the network
  • A connection’s endpoint exists only while the connection is up. Unlike RTP-MIDI and Bluetooth MIDI, there’s no setting to keep it while the device is away. Windows runs endpoint discovery and protocol negotiation only for a new endpoint, and keeping one would need a big exception to that

Types in this namespace

Click or tap the type name to view more details.

Type Description
MidiNetworkAdvertisedHost A Network MIDI 2.0 host discovered on the network over mDNS
MidiNetworkAdvertisedHostAddedEventArgs Event args for a Network MIDI 2.0 host appearing on the network
MidiNetworkAdvertisedHostChangedProperties Which properties of an advertised network host changed
MidiNetworkAdvertisedHostRemovedEventArgs Event args for a Network MIDI 2.0 host disappearing from the network
MidiNetworkAdvertisedHostUpdatedEventArgs Event args for a change to an advertised Network MIDI 2.0 host
MidiNetworkAdvertisedHostWatcher Watches the network for Network MIDI 2.0 hosts appearing and disappearing
MidiNetworkAuthenticationType Authentication required by a Network MIDI 2.0 host
MidiNetworkClientConnectConfig Config sent to the service to connect to a remote Network MIDI 2.0 host
MidiNetworkClientConnectErrorCode Error codes returned when connecting to a remote Network MIDI 2.0 host
MidiNetworkClientConnectResponse Result of a request to connect to a remote Network MIDI 2.0 host
MidiNetworkClientDisconnectConfig Disconnects a Network MIDI 2.0 client, or forgets a saved one
MidiNetworkClientDisconnectErrorCode Error codes returned when disconnecting a Network MIDI 2.0 client
MidiNetworkClientDisconnectResponse Result of a request to disconnect a Network MIDI 2.0 client
MidiNetworkClientEntryState Where a configured Network MIDI 2.0 client entry is in its life
MidiNetworkClientMatchCriteria Describes how to locate the remote host a client should connect to
MidiNetworkClientUpdateConfig Config sent to the service to change settings on an existing Network MIDI 2.0 client connection
MidiNetworkClientUpdateErrorCode Error codes returned when changing settings on a Network MIDI 2.0 client connection
MidiNetworkClientUpdateResponse Result of a request to change settings on a Network MIDI 2.0 client connection
MidiNetworkConfiguredClient Information about a Network MIDI 2.0 client connection configured in the service
MidiNetworkConfiguredHost Information about a Network MIDI 2.0 host configured in the service
MidiNetworkHostConnection Information about one remote client connected to a host on this PC
MidiNetworkHostCreationConfig Config sent to the service to create a Network MIDI 2.0 host
MidiNetworkHostCreationErrorCode Error codes returned when creating a Network MIDI 2.0 host
MidiNetworkHostCreationResponse Result of a request to create a Network MIDI 2.0 host
MidiNetworkHostKnownClientsConfig The allow and deny decisions saved for a Network MIDI 2.0 host
MidiNetworkHostRemoteClientSettingsConfig The remote clients of a Network MIDI 2.0 host that have a sending speed of their own
MidiNetworkHostRemovalConfig Config sent to the service to remove a Network MIDI 2.0 host
MidiNetworkHostRemovalErrorCode Error codes returned when removing a Network MIDI 2.0 host
MidiNetworkHostRemovalResponse Result of a request to remove a Network MIDI 2.0 host
MidiNetworkHostUpdateConfig Config sent to the service to change settings on an existing Network MIDI 2.0 host
MidiNetworkHostUpdateErrorCode Error codes returned when starting or stopping a Network MIDI 2.0 host
MidiNetworkHostUpdateResponse Result of a request to start or stop a Network MIDI 2.0 host
MidiNetworkKnownRemoteClient A remote client a Network MIDI 2.0 host has already been told to allow or deny
MidiNetworkMidi1PortGroup A group on a Network MIDI 2.0 connection that gets MIDI 1.0 ports when the device doesn't describe itself, and what those ports are called
MidiNetworkPendingRemoteClient A remote client waiting for a user decision before it may connect
MidiNetworkRemoteClientApprovalConfig Config sent to the service to approve or deny a waiting remote client
MidiNetworkRemoteClientApprovalErrorCode Error codes returned when approving or denying a remote Network MIDI 2.0 client
MidiNetworkRemoteClientApprovalResponse Result of approving or denying a waiting remote client
MidiNetworkRemoteClientDisconnectConfig Config sent to end one remote client's active session with a host on this PC
MidiNetworkRemoteClientDisconnectErrorCode Error codes for disconnecting a remote client from a host on this PC
MidiNetworkRemoteClientDisconnectResponse Result of disconnecting one remote client from a host on this PC
MidiNetworkRemoteClientForgetConfig Config sent to drop a remembered allow or deny decision for a remote client
MidiNetworkRemoteClientForgetErrorCode Error codes for dropping a remembered decision for a remote client
MidiNetworkRemoteClientForgetResponse Result of dropping a remembered decision for one remote client
MidiNetworkRemoteClientPolicy How a host handles unknown remote client connection requests
MidiNetworkRemoteClientSettings The sending speed and MIDI 1.0 ports a Network MIDI 2.0 host uses for one remote client instead of its own
MidiNetworkSavedClient A Network MIDI 2.0 client saved in the configuration file
MidiNetworkSavedHost A Network MIDI 2.0 host saved in the configuration file
MidiNetworkSendSpeedLimit How fast a Network MIDI 2.0 host or client sends, as a multiple of MIDI 1.0 wire speed
MidiNetworkTransportManager The primary class used to create, remove, and monitor Network MIDI 2.0 hosts and client connections
MidiNetworkTransportSettings The settings which apply to the Network MIDI 2.0 transport as a whole, rather than to any one host or client

Didn't find what you were looking for?

Windows MIDI Services is an open source project with all source available on GitHub. We have a great community on Discord as well. Between GitHub and Discord, you should find the information you are looking for.