Skip to content

In-box Preview 10

Pre-release
Pre-release

Choose a tag to compare

@Psychlist1972 Psychlist1972 released this 04 Oct 05:19
· 67 commits to main since this release
3f695f2

In-box Preview 10

This is now open to all customers who would like to try out the features and functionality.

Highlights and instructions

Key items

  • MIDI 1.0 Loopbacks, RTP-MIDI 1.0, Network MIDI 2.0, Bluetooth LE MIDI 1.0 transports
  • Apps including keyboard, Windows MIDI Glass, Windows MIDI Patchbay, and much more. Details here
  • General MIDI Synth is a MIDI 2.0 synthesizer now

Packages and Installation Instructions

If you are running any of the older rc4 or similar SDK Runtime and Tools, or any of the older preview transports, fully uninstall them from Settings > Apps > Installed Apps before installing anything here.

Install the Tools package to have access to all the in-box tools required to configure endpoints, customize, route MIDI endpoints, create controller surfaces, and much more. Everyone will want this package. The tools are documented on the tools page.

Install the Transports package to have access to preview versions of

  • General MIDI Synth
  • Basic MIDI 1.0 Loopback Transport
  • RTP-MIDI Transport
  • Network MIDI 2.0 Transport
  • Bluetooth LE MIDI Transport

You can turn the individual transports on or off on the Transports page of MIDI Troubleshooting and Repair, which is in the Tools package.

If you installed the separate Preview 9 transport installers, you don't need to remove them first. The Transports package removes them when it installs. Uninstalling them first won't cause any harm. The uninstall instructions above are to cover everyone, regardless of what they have installed. When in doubt, uninstall the old stuff.

MIDI Glass App (Using the Acrylic backdrop on my PC)

image

MIDI Patchbay App (Using the Mica backdrop with a custom blue tint on my PC)

image

All the apps let you set the background style (Solid Color, Acrylic, Mica) and your desired color.


Details for Developers and Technical Customers

Developer permitted use

We want to ensure customers have the best experience going forward. Because of this, we want to ensure that these app-local binaries are not normally present on customer systems which have the binaries in System32.

Distributing these API binaries is a choice you make. Although we will try to keep compatibility, Microsoft makes no guarantee that the in-box API binaries or service transports will be compatible with this Preview release. If that is not acceptable, please wait to distribute your app until the transports and API ship in Windows.

Developer Go-live agreement

This is the first Windows MIDI Services API release with a "go live" license for Windows.Devices.Midi2.dll, .winmd, and .pri.

This is still a preview, and we want to ensure that customers have a great experience going forward, so if you do go live with this, you need to agree to the following terms. These replace in whole the previous preview distribution terms.

By distributing the API binaries with my app, I (the developer of the app) agree:

Agreement updated 2026-10-05 due to tests run

Why this change: In all language projections we tested, unlike most DLLs, a local WinRT DLL is the fallback not the first pick by Windows. So once the API goes into Windows, your locally distributed copy will no longer be called.

That means that you as a developer need to stay up to date with any breaking changes up through when we indicate that the API surface area and metadata is locked.

Once Windows includes Windows.Devices.Midi2, your app uses the Windows copy, even if you still ship your own. Your copy is only used on PCs where Windows doesn't have it.

Given that, and the impact it will have on your customers, the new agreement is as follows:

  1. I understand that the API is not yet locked, and breaking changes in metadata may cause my app not to work when the API is in-box in Windows. I will be prepared to compile against the latest .winmd file from Microsoft available before the rollout.
  2. I have a mechanism to update the app to remove the API binaries once they are in-box in Windows, and to keep up to date with any additional previews.
  3. I will make all possible efforts to keep up with any additional preview releases, and update my app to include those, ensuring customers have the latest fixes and features at least up through the point where we announce that the API surface area / metadata is locked
  4. I will let my customers know that I am using preview Windows MIDI Services APIs, until the point when the preview API is removed from my product.
  5. I will not ship the Windows.Devices.Midi2 API to versions of Windows below Windows 11 25h2 (Windows 11 24h2 is unsupported, and will not get the required fixes, so we recommend customers move to a supported version of Windows 11, or switch to Legacy API Mode)
  6. I will file bugs on GitHub for any issues I encounter, and make an effort to assist in the debugging of the reported problems.
  7. When the 1.0 version of the Windows MIDI Services WinRT API is in Windows, and I have a new release of the app built against it, I will make an effort to contact my customers to inform them of the new version and encourage them to update to it, if that process is not automatic.

Failed WinRT component activation is typically projected as an exception in your applications, so keeping up to date with the latest updates is important. Microsoft will endeavor to lock the API well before the expected release date so this isn't a last-minute surprise, but there's always the possibility that the .winmd has to differ in some way in the in-box version.

Previous agreement:

  1. I have a mechanism to update the app to remove the API binaries once they are in-box in Windows, and to keep up to date with any additional previews.
  2. I will make a reasonable effort to keep up with any additional preview releases, and update my app to include those, ensuring customers have the latest fixes and features.
  3. I will let my customers know that I am using preview Windows MIDI Services APIs.
  4. I will update my app to remove the out-of-band API and release a version compiled against the actual in-box Windows.Devices.Midi2 API within 90 days of the API implementation shipping in Windows 11 25h2 and later. Earlier is better.
  5. I will not ship the Windows.Devices.Midi2 API to versions of Windows below Windows 11 25h2 (Windows 11 24h2 is unsupported, and will not get the required fixes, so we recommend customers move to a supported version of Windows 11, or switch to Legacy API Mode)
  6. I will file bugs on GitHub for any issues I encounter, and make an effort to assist in the debugging of the reported problems.
  7. When the Windows MIDI Services API is in Windows, and I have a new release of the app built against it, I will make an effort to contact my customers to inform them of the new version and encourage them to update to it, if that process is not automatic.

Note: The .pri file contains resources and must be installed with the dll. In the distribution acquired here, the resources are en-US only. The version that ships in Windows will be translated.

What this doesn't cover

If you develop a reusable MIDI library for other apps, contact Pete Brown directly. In many cases, once another developer takes a dependency on your library, they don't come back for updates. Therefore, it's much harder to ensure that all customers are covered in that scenario, so the ability to go-live will be made on a case-by-case basis, with a strong lean towards not allowing redistribution in this scenario.

Do not redistribute any of the installers, tools, or transports. The only redistributable files covered here are Windows.Devices.Midi2.dll and Windows.Devices.Midi2.pri and the related .winmd and C# projection files, and only if you adhere to the above terms. We're not trying to hold you back here, but we want to prevent customer dissatisfaction with your apps and with Windows.

Remainder

This set of release notes only covers the delta from Preview 9. Please refer to Preview 9 and earlier for everything before that.

A few items below may already be on your PC if you installed the September 21 refresh of Preview 9. They weren't listed in its update notes, so they're included here. Items that were listed in that update aren't repeated.

Installers

Each platform now has two installers, Tools and Transports. In Preview 9, each transport had an installer of its own.

  • Windows MIDI Services Tools (0.99.88-preview.10) has every app, the MIDI Console, the PowerShell module, the command line tools such as mididiag, and the Windows MIDI Services API files the apps use. Network MIDI Setup and Bluetooth MIDI Setup moved here from their transport installers, and MIDI Glass is new.
  • Windows MIDI Services Transports (1.0.35-preview.8) has all five preview transports: Network MIDI 2.0, RTP-MIDI, Basic Loopback, the General MIDI Synth and Bluetooth MIDI. It replaces the separate Network MIDI 2.0, Bluetooth MIDI, Basic Loopback and General MIDI Synth installers from Preview 9. It removes them when it installs, so you don't have to, and they leave the Installed apps list too.
  • Every app now installs into one folder, Program Files\Windows MIDI Services\Tools, instead of a folder each. The Start menu shortcuts are in the Windows MIDI (Preview) folder.
  • Double-click a .midilayout file to open it in MIDI Glass, or a .midipatch file to add it to MIDI Patchbay. The first time, Windows asks which app to use.

API Changes

NuGet package version for this release is 0.99.88-preview.10. The prerelease label changed from devpreview to preview.

Most of this round came from two places: MIDI Association member feedback on the Capability Inquiry API in Preview 9, and new features in MIDI Glass, MIDI Monitor and the MIDI Console that needed things the sequencing API didn't have. The two loopback namespaces also gained feedback protection, there's a new namespace for the new RTP-MIDI transport, and the loopback, network and Bluetooth transports can now tell you what they've saved. Network MIDI 2.0 and RTP-MIDI also gained a sending speed limit, and a way to keep a host on one network adapter.

The Capability Inquiry, Sequencing and Files namespaces aren't locked yet. Their contracts stay at version 1 and new members were added to existing types in place, so rebuild against this package rather than mixing it with Preview 9 binaries. One existing method signature changed. It's called out below. The loopback, Network MIDI 2.0 and Bluetooth namespaces got additions in place the same way. No signature that was already there changed, but a few behaviors did, and they're listed below. The new RTP-MIDI namespace isn't locked either.

Capability Inquiry

Property Exchange subscriptions

New on both sides. An application can ask a device to tell it when a resource changes instead of asking over and over, and a virtual device can offer the same thing to others.

Asking:

  • MidiCapabilityInquirySession.SubscribeAsync(destinationMuid, resource, resourceId), which returns a MidiPropertySubscription
  • MidiCapabilityInquirySession.UnsubscribeAsync(subscription) and GetSubscriptions()
  • MidiCapabilityInquirySession.PropertySubscriptionUpdated, raised with MidiPropertySubscriptionUpdatedEventArgs when a device sends an update or ends a subscription. The reply the specification requires is sent for you before the event is raised.
  • MidiPropertySubscription: Status, ResourceStatus, ResponderMuid, Resource, ResourceId, SubscribeId and IsActive
  • MidiPropertySubscriptionUpdatedEventArgs: Subscription, Command (full, partial, notify or end), IsSubscriptionEnded and Update

Only subscribe to a resource whose resource list entry says CanSubscribe. A refused subscription comes back with a Status of NegativeAcknowledgment and the device's own code in ResourceStatus. Anything still subscribed when the session closes is ended for you.

Answering:

  • MidiCapabilityInquiryDeviceResponder.SetResourceSubscribable(resource, canSubscribe) and IsResourceSubscribable(resource). Every resource starts out not subscribable, because accepting a subscription is a promise to send updates.
  • MidiCapabilityInquiryDeviceResponder.NotifyResourceChanged(resource, resourceId) sends the resource to everyone subscribed to it and returns how many were told. Call it after you change the resource, not before.
  • The resource list the responder builds now says canSubscribe for those resources, and a subscriber whose MUID is invalidated is dropped.

Declaring what a session supports

MidiCapabilityInquirySession.SupportedCategories and ReceivableMaximumSystemExclusiveSize are new, and you can set them. They used to be fixed inside DiscoverAsync. The defaults are what it sent before (property exchange plus profile configuration, and the smallest size the specification allows), so nothing changes unless you set them. This lets an app that only asks questions, like MIDI Keyboard, say that it answers none.

Endpoint Inquiry

New support for the MIDI-CI Endpoint Inquiry, which asks for information about the UMP endpoint a function block belongs to. The only thing it can ask for so far is the product instance ID.

  • MidiCapabilityInquiryMessageBuilder.BuildEndpointInquiry and BuildEndpointReply
  • MidiCapabilityInquiryMessage.HasEndpointFields, EndpointStatus and EndpointInformation
  • MidiCapabilityInquiryDeviceResponder answers it for you, with the product instance ID the virtual device declares in endpoint discovery, so the two always match. The specification allows only printable ASCII characters there, up to 42 of them. If your ID doesn't fit, the request comes to you through MessageReceived instead.

Devices that use MIDI-CI 1.1

  • The session ignored the Discovery Reply from any device that declares MIDI-CI 1.1, so those devices never showed up, and there was no error. A 1.1 reply is shorter because two fields were added in 1.2. Fixed. We found this testing against a shipping third-party software instrument, which is now the first non-Microsoft device this API has read a patch list from.
  • The session now writes each message in the MIDI-CI version the device declared in its own Discovery. Several messages grew in 1.2, and a 1.1 device reads a fixed length. A broadcast Discovery still goes out in the current version, because it isn't addressed to anyone in particular.
  • Responders now answer in the version the request arrived in.
  • Breaking change: MidiCapabilityInquiryMessageBuilder.BuildPropertyExchangeCapabilitiesInquiry and BuildPropertyExchangeCapabilitiesReply have a new last parameter, messageVersion. Pass the version the other device declared. Code that calls either one has to be updated.

Other Capability Inquiry fixes

  • Property Exchange Capabilities messages never parsed. MidiCapabilityInquiryMessage marked them invalid, so the session and MidiCapabilityInquiryDeviceResponder both dropped them. Fixed. The builder also no longer builds these two messages in the chunked layout, which they don't have.
  • The session now asks each responder for its Property Exchange capabilities before its first property request, once per responder. It carries on either way, so a device that doesn't answer still works. RequestPropertyExchangeCapabilitiesAsync is still there if you want to ask again.
  • When a device sends Invalidate MUID, the session now removes it from the responder list and ends its subscriptions. Before, a device that was switched off stayed in the list for good.

Still not there

  • The session records how many requests a device will take at once, but doesn't enforce that limit. If your app sends several requests at the same time, keeping under it is up to you.
  • BuildDiscoveryReply and the profile message builders always write the current MIDI-CI version.
  • The Preview 9 "What is not there yet" list hasn't changed: no in-box endpoint answers a profile inquiry, and the six newer Property Exchange resource specifications don't have strong types.

Sequencing and MIDI Files

Build a sequence in code

Windows.Devices.Midi2.Utilities.Sequencing.MidiSequenceBuilder is new. Until now, the only way to get a MidiSequence was to read an SMF MIDI 1.0 file. What comes out is the same MidiSequence a file produces, so the player, the position maps and a piano roll all work with it unchanged.

  • TicksPerQuarterNote and TimingMode
  • AddTrack(name), which returns the track index the other methods take
  • AddTempoChange(tick, beatsPerMinute) and AddTimeSignature(tick, numerator, denominator)
  • AddNote(tick, durationTicks, trackIndex, channel, noteNumber, velocity), which writes both halves of the note, so a built sequence can't leave a note hanging
  • AddSystemExclusive(trackIndex, tick, data), including the leading F0 and trailing F7
  • AddMessages(trackIndex, tick, words), which stores Universal MIDI Packet words exactly as given, except for the group, which is set to the group the sequence plays on. This is the only way to put a message in a sequence that MIDI 1.0 can't express.
  • GetSequence() and Clear(). You can call GetSequence() again after adding more. Each call makes a new sequence and leaves the builder alone.

Bad input is dropped rather than thrown.

Timing in real time

New enum MidiSequenceTimingMode, with Musical and Absolute, and a new MidiSequence.TimingMode property. In Absolute, a tick is one microsecond and tempo doesn't apply. That's what you want when a gap has to be a real gap, such as a system exclusive dump whose packets a device needs spaced out in time rather than in beats. A file always reads back as Musical. Ticks are 32 bits, so an absolute sequence tops out at about 71 minutes.

Per-track routing now works

In Preview 9, MidiSequencePlayer.SetTrackRouting applied only IsMuted. It accepted Connection, Group and ChannelOverride and then never used them, even though the documentation said tracks could go to different endpoints. All four are honored now.

  • Tracks can play to different endpoints at the same time and stay together, because they share one clock.
  • You can change routing during playback.
  • Panic goes to every destination, and seeking re-sends each channel's state to each destination.
  • Passing null for a track's routing sends it back to the player's own connection and unmutes it.

Write Standard MIDI Files

Windows.Devices.Midi2.Utilities.Files.MidiStandardFileWriter is new, the mirror of the reader. MIDI Monitor and the MIDI Console use it to save monitor captures as .mid files.

  • WriteAsync(stream, sequence) and WriteToFileAsync(file, sequence), each with an overload that takes options
  • MidiFileWriteOptions: WriteSingleTrack (format 0), UseRunningStatus, AbsoluteTimingTicksPerQuarterNote and MaximumFileBytes
  • MidiFileWriteResult: Succeeded, Status, TrackCount, ByteCount and SkippedEventCount
  • MidiFileWriteStatus: Success, NothingToWrite, TooLarge, AccessDenied, WriteError and OutOfMemory

Notes:

  • Read a file, write it and read it again, and you get the same sequence: the same events at the same ticks, the same tempo and time signature maps, and the same text. You won't get the same bytes, because the reader repairs a missing tempo and converts older text to UTF-8 on the way in. Writing that result again does give identical bytes.
  • A format 2 file is written back as format 1.
  • A Standard MIDI File holds MIDI 1.0. MIDI 2.0 messages are translated where MIDI 1.0 has an equivalent. Per-note controllers, per-note pitch bend, 8-bit system exclusive, flex data and stream messages have none, so they're left out and counted in SkippedEventCount. A MIDI 2.0 note on whose velocity would scale down to 0 is written at 1, so it doesn't turn into a note off.
  • A sequence in Absolute timing is laid out at 120 beats per minute, using AbsoluteTimingTicksPerQuarterNote.

Enumeration

  • MidiLegacyPortDeviceInformation.GetAdditionalPropertiesList() now includes three more keys, so Properties shows the duplicate device number, base name and identity the service used when it named the port. They're there to help troubleshoot names and aren't typed properties. See the duplicate device naming fix under Transports.
  • Fixed: after the MIDI 1.0 ports were renumbered, for example when another device was unplugged, MidiLegacyPortDeviceWatcher reported the Number of each input port as one higher than it really was.
  • Fixed: MidiEndpointDeviceInformation.GetGroupTerminalBlocks() on an endpoint from a MidiEndpointDeviceWatcher listed each block again every time the endpoint was updated.

Loopbacks

Windows.Devices.Midi2.Transports.Loopback and Windows.Devices.Midi2.Transports.BasicLoopback have new members for feedback protection, which is described under Transports. Each member below exists in both namespaces. The basic loopback types have Basic in their names, such as MidiBasicLoopbackManager.

  • MidiLoopbackManager.IsFeedbackProtectionAvailable. Check it before using the rest, and check each kind of loopback on its own, because a PC can have one without the other. When it's false, entries report Off.
  • New enum MidiLoopbackFeedbackProtection, with Mute and Off. Mute is the default.
  • MidiLoopbackCreationConfig.FeedbackProtection sets it for a new loopback.
  • MidiLoopbackManager.SetFeedbackProtection(associationId, feedbackProtection) changes it for an existing loopback. The change takes effect right away, but it isn't saved to the configuration. To save it, use MidiLoopbackUpdateConfig, described under Saved configuration.
  • MidiLoopbackEntry.FeedbackProtection, IsMutedForFeedback and FeedbackDetectedTime report the setting, and whether and when the loopback muted itself. Any change to the muted state clears the last two.
  • New error code FeedbackProtectionNotAvailable (0x41), which SetFeedbackProtection returns when IsFeedbackProtectionAvailable is false.
  • MidiBasicLoopbackErrorCode also gained InvalidAssociationId, UniqueIdTooLong and InvalidUniqueId. The service already returned these codes, but the enum had no names for them.

Network MIDI 2.0

Windows.Devices.Midi2.Transports.Network gained a sending speed limit, a choice of network adapter for hosts, and a way to find out why a client isn't connected. What the transport does with them is described under Transports.

Sending speed

  • New enum MidiNetworkSendSpeedLimit: Unlimited, which is the default, Midi1WireSpeed, which is the speed of a MIDI 1.0 DIN cable, and Midi1WireSpeedTimes2 through Midi1WireSpeedTimes32, for 2, 4, 8, 16 and 32 times that.
  • SendSpeedLimit and ReduceSendSpeedAutomatically are new on MidiNetworkHostCreationConfig, MidiNetworkHostUpdateConfig, MidiNetworkClientConnectConfig and MidiNetworkClientUpdateConfig. MidiNetworkConfiguredHost, MidiNetworkConfiguredClient, MidiNetworkHostConnection, MidiNetworkSavedHost and MidiNetworkSavedClient report them.
  • CurrentSendSpeedLimit on MidiNetworkConfiguredClient and MidiNetworkHostConnection is the speed a connection is sending at right now. It's lower than SendSpeedLimit while ReduceSendSpeedAutomatically has slowed the connection down.
  • A host can give one device a speed of its own. New MidiNetworkRemoteClientSettings names the device by RemoteClientName and RemoteClientProductInstanceId, and holds its SendSpeedLimit and ReduceSendSpeedAutomatically. Put the host's whole list in a new MidiNetworkHostRemoteClientSettingsConfig, then send it with SendUpdate and save it with SaveUpdate. The list replaces the one the host has, so start from MidiNetworkConfiguredHost.RemoteClientSettings. A host keeps settings for up to 256 devices.
  • MidiNetworkSavedHost.RemoteClientSettings is the saved list, and MidiNetworkHostConnection.UsesRemoteClientSettings says whether a connection is using a device's own speed.
  • A new speed applies right away, including to connections that are already up, and doesn't disconnect anything.

Network adapters

  • NetworkAdapterId, NetworkAdapterName and AllowNetworkAdapterFallback are new on MidiNetworkHostCreationConfig, MidiNetworkHostUpdateConfig, MidiNetworkConfiguredHost and MidiNetworkSavedHost. The id is the GUID Windows gives the adapter, the same value as Windows.Networking.Connectivity.NetworkAdapter.NetworkAdapterId. An empty GUID, the default, runs the host on every adapter.
  • MidiNetworkConfiguredHost.IsNetworkAdapterMissing and UsedNetworkAdapterFallback tell you when a host isn't running where it was asked to.
  • New error code NetworkAdapterNotAvailable in MidiNetworkHostCreationErrorCode and MidiNetworkHostUpdateErrorCode, for a host whose adapter is missing and that isn't allowed to use the others. The host is still created, and it starts by itself when the adapter is back.
  • Changing NetworkAdapterId with MidiNetworkHostUpdateConfig restarts the host, which ends its connections.

Why a client isn't connected

  • New MidiNetworkConfiguredClient.LastErrorCode says why the client's last invitation didn't open a session.
  • MidiNetworkClientConnectErrorCode gained HostBusy, InvitationRefused, AuthenticationRequired and InvitationEndedByHost. You'll find these, along with NoReplyToInvitation and InvitationNotApproved, in LastErrorCode.

Changes in behavior

  • A direct client, one set up with a host name or IP address, now goes back to Pending when it can't reach its host, and is tried again after DirectConnectionScanIntervalMilliseconds, which is 20 seconds by default. A host name is looked up again each time. Before, the client was marked Unavailable and wasn't tried again until an app asked. Unavailable is still in the enum, but the service doesn't report it any more.
  • A client whose host turns the connection down, or asks for authentication, is marked Failed. It isn't tried again until you call ConnectNetworkClientAsync again. A client whose host says it's busy is tried again 10 to 30 seconds later.
  • MidiNetworkHostUpdateConfig changes only the properties you set. Before, it always sent both CreateMidi1Ports and FallbackMidi1PortCount, so changing one of them set the other back to its default.
  • The default for MidiNetworkTransportSettings.MaxRetransmitBufferCommandPackets is now 250, up from 50. Each connection keeps no more than 256 KB of them.
  • Fixed: MidiNetworkClientConnectResponse.ClientId was always empty, so it couldn't be used to disconnect the client later.

RTP-MIDI

Windows.Devices.Midi2.Transports.Rtp is new. It's the API for the new RTP-MIDI transport described under Transports, and it's in the NuGet package with everything else, under its own contract, MidiTransportsRtpApiContract. It follows the Network MIDI 2.0 namespace closely, so if you've written code for one, the other will look familiar.

  • MidiRtpTransportManager is where everything starts. All its members are static.
  • Hosts, which other devices connect to: CreateRtpHostAsync, RemoveRtpHostAsync, StopRtpHostAsync and StartRtpHostAsync, with MidiRtpHostCreationConfig and MidiRtpHostRemovalConfig. CreateRtpHostAsync doesn't return until the host has started. To change a host, set HostId on a MidiRtpHostCreationConfig to the host's id, and pass it to CreateRtpHostAsync. The host restarts with the new settings and keeps its allow and deny decisions.
  • Clients, which connect to another device: ConnectRtpClientAsync, ReconnectRtpClientAsync and DisconnectRtpClientAsync, with MidiRtpClientConnectConfig, MidiRtpClientMatchCriteria and MidiRtpClientDisconnectConfig. A client finds its device by the name it advertises, or by its address and port. ConnectRtpClientAsync returns as soon as the service has the entry, and connecting happens in the background.
  • Approval, for a host that asks before letting a device in: GetPendingRemoteClients, ApproveOrDenyRemoteClientConnectRequestAsync, DisconnectRemoteClientAsync and ForgetRemoteClientAsync, each with its own config and response type. Save a host's decisions with MidiRtpHostKnownClientsConfig, which holds MidiRtpKnownRemoteClient entries.
  • Status: GetConfiguredHosts, GetConfiguredClients and GetAdvertisedHosts, which return MidiRtpConfiguredHost, MidiRtpConfiguredClient and MidiRtpAdvertisedHost. Hosts and clients both report their connections as MidiRtpConnection, with latency, packet and message counts, and how many lost packets were repaired.
  • Sending speed and network adapters work the same way as in Network MIDI 2.0, above. New enum MidiRtpSendSpeedLimit has the same values as MidiNetworkSendSpeedLimit. SendSpeedLimit is on MidiRtpHostCreationConfig, MidiRtpClientConnectConfig, MidiRtpConfiguredHost, MidiRtpConfiguredClient, MidiRtpConnection, MidiRtpSavedHost and MidiRtpSavedClient, and CurrentSendSpeedLimit is on the configured host, the configured client and the connection. Changing only the speed doesn't restart a host or drop a client's connection. There's no ReduceSendSpeedAutomatically, because an RTP-MIDI device repairs lost data from the recovery journal and never asks for it again.
  • New MidiRtpRemoteClientSettings and MidiRtpHostRemoteClientSettingsConfig give one device on a host a speed of its own. An RTP-MIDI device gives only its name when it connects, so RemoteClientName is all the host knows it by. RemoteClientSettings on MidiRtpConfiguredHost and MidiRtpSavedHost lists them, and MidiRtpConnection.UsesRemoteClientSettings says whether a connection uses one.
  • NetworkAdapterId, NetworkAdapterName and AllowNetworkAdapterFallback are on MidiRtpHostCreationConfig, MidiRtpConfiguredHost and MidiRtpSavedHost. IsNetworkAdapterMissing and UsedNetworkAdapterFallback are on MidiRtpConfiguredHost, and MidiRtpHostCreationErrorCode has a new NetworkAdapterNotAvailable.
  • Every Async method returns a response with Success, ErrorCode and ErrorMessage, and none of them throw. Each has its own error code enum.
  • MidiRtpConnection.RemoteHostName is the other device's DNS host name, such as Studio-Mac.local, from its RTP-MIDI advertisement. It's empty when the device doesn't advertise, or when two advertised devices list the same address. A device that offers both RTP-MIDI and Network MIDI 2.0 uses the same host name for both, so compare this with MidiNetworkAdvertisedHost.HostName, ignoring case, to find out whether a device you're connected to over RTP-MIDI also has Network MIDI 2.0. When it does, Network MIDI 2.0 is the better choice.

Like the Network MIDI 2.0 API, these methods change the running service only. To keep a host, a client, a host's decisions or its devices' own speeds after a restart, also save the same configuration object with MidiServiceTransportPluginConfigManager.SaveUpdate.

Saved configuration

An app could already save settings to the service's configuration file, but it couldn't read them back. The only way to see what the service would set up at its next start was to read the file yourself, which isn't supported. Now the loopback, Network MIDI 2.0, RTP-MIDI and Bluetooth transports tell you through the API, and these calls work even when the service isn't running. MIDI Loopback Setup, Network MIDI Setup and Bluetooth MIDI Setup use them, so none of the three opens the configuration file itself any more.

"Saved" is what's in the configuration file, which the service sets up when it starts. "Configured" and "active", as in GetConfiguredHosts and GetActiveLoopbackEntries, are what's running now.

  • MidiLoopbackManager.GetSavedLoopbackEntries() returns MidiLoopbackSavedEntry items, with AssociationId, EndpointDefinitionA, EndpointDefinitionB, IsMuted and FeedbackProtection. MidiBasicLoopbackManager.GetSavedLoopbackEntries() returns MidiBasicLoopbackSavedEntry items, which have one EndpointDefinition.
  • MidiNetworkTransportManager.GetSavedHosts() and GetSavedClients() return MidiNetworkSavedHost and MidiNetworkSavedClient items, with the settings each was saved with. A saved host includes its KnownRemoteClients and RemoteClientSettings.
  • MidiRtpTransportManager.GetSavedHosts() and GetSavedClients() do the same for RTP-MIDI, with MidiRtpSavedHost and MidiRtpSavedClient.
  • MidiBluetoothTransportManager.GetSavedDevices() returns MidiBluetoothSavedDevice items, with BluetoothDeviceId, Comment, IsEnabled and OfflineRetentionSeconds. A device that's saved but turned off has IsEnabled set to false.

To change a loopback that already exists:

  • New MidiLoopbackUpdateConfig and MidiBasicLoopbackUpdateConfig. Set only what you want to change: names, descriptions, pictures, muting or feedback protection. Anything you don't set stays as it is.
  • MidiLoopbackManager.UpdateLoopback(config) and MidiBasicLoopbackManager.UpdateLoopback(config) change the running loopback. Save the same config with SaveUpdate to keep the change after a restart.

When you save:

  • New MidiServiceConfigSaveResult.ErrorEntryNotSaved (101). SaveUpdate returns it when you save a change to something that isn't saved itself, such as a loopback created without saving it, or a device's own sending speed on a host that isn't saved. Save the entry first.
  • Saving a MidiNetworkClientDisconnectConfig with SaveUpdate now removes that client from the configuration file, so the service doesn't connect it at its next start. Before, SaveUpdate refused it, so there was no way to remove a saved client through the API. Disconnecting and forgetting are still two steps. To do both, call DisconnectNetworkClientAsync and then SaveUpdate with the same object.

Bluetooth MIDI

  • MidiBluetoothTransportManager.GetSavedDevices() is new. See Saved configuration above.
  • GetAvailableDevices() keeps listing a paired device, and a device the service is trying to connect, while it isn't advertising, for example when it's switched off. Before, both dropped out of the list.
  • MidiBluetoothConnectionState.Connected now means the endpoint is ready to open. Before, a device could report Connected for a moment before its endpoint existed, with an empty EndpointDeviceId. A device that's next in line to connect reports Connecting.
  • A Bluetooth device id with colons or dashes, or in lowercase, such as a1:b2:c3:d4:e5:f6, now works everywhere: GetDevice, connecting, disconnecting and offline retention. Before, the service accepted those forms without matching them to a device, so a disconnect could report success and do nothing.
  • Sending or saving a MidiBluetoothOfflineRetentionConfig for a device no longer connects it, or saves it as a device to connect.

SysEx transfers

When the buffer between your app and the service is full, MidiSystemExclusiveSender now waits and tries again instead of failing the transfer. That happens when the destination takes data more slowly than you send it, like a network connection with a sending speed limit. A message that still can't be sent after 30 seconds fails the transfer.

Still open from Preview 9

The three items under "Still open from this round" in the Preview 9 notes are unchanged.

Samples

New, in both C++/WinRT and C#:

  • capability-inquiry-program-list reads the General MIDI Synth's channel list and program lists a page at a time, groups the programs by category, and uses an entry to choose the sound on a channel.
  • midi-file-player reads a Standard MIDI File, shows what's in it, and plays it on the General MIDI Synth, setting the synth's volume while it plays.
  • midi-file-writer saves a sequence as a Standard MIDI File, shows which messages MIDI 1.0 can't hold, and reads the file back.
  • sequence-builder builds two sequences in memory, one in musical time and one in real time, and plays them on the General MIDI Synth.

All sample projects reference the new NuGet package version.

Transports

Transport package version for this release is 1.0.35-preview.8. All five preview transports are now in one Transports package. See Installers above.

RTP-MIDI (new)

A new transport, in preview. RTP-MIDI is the network MIDI 1.0 protocol from IETF RFC 6295, along with Apple's protocol for setting up connections. It's built into macOS and iOS, and many MIDI interfaces and apps use it too. Now Windows can exchange MIDI with them over your network, without any other software.

  • It's in the Transports package. Set it up in Network MIDI Setup, which has RTP-MIDI pages next to its Network MIDI 2.0 pages.
  • This PC can be a host that other devices connect to, a client that connects to other devices, or both at once. A host can be advertised on the local network, so a Mac or an iPad lists it without being told the address. A client finds a device by the name it advertises, or by its address and port.
  • Each connection gets its own endpoint, with MIDI 1.0 ports for apps that use the older Windows MIDI APIs. The endpoint is there while the connection is up. When the same device connects again, its endpoint gets the same id, so a name or setting you gave it stays put.
  • Nothing listens until a host is set up. A new install has no hosts and no clients.
  • A host can let anyone connect, or ask first. RTP-MIDI knows a device only by the name it sends, and it has no authentication, so asking first keeps out devices you didn't expect, but it doesn't secure the host.
  • A client connects again by itself when its device comes back, including a device at a fixed address, unless you turn that off.
  • RTP-MIDI never sends a lost packet again. Each packet carries a recovery journal instead, which repairs the damage when a packet goes missing. A note that can't be repaired is ended, so it doesn't hang.
  • Incoming messages are timestamped with when the other device sent them, on this PC's clock, not with when the packet happened to arrive.
  • A host or client can limit how fast this PC sends, for a device that loses data when a lot of it arrives at once, and a host can give one device a speed of its own. A host can also be kept on one network adapter. Both work as they do for Network MIDI 2.0, described below, except that RTP-MIDI can't slow down by itself. A device repairs lost data from the recovery journal, so it never tells this PC that it's falling behind.

We've tested it with macOS in both directions, and with third-party hardware and software.

Not there yet:

  • MIDI Notifications doesn't tell you when an RTP-MIDI device is waiting for you to let it connect. Network MIDI Setup shows it, and so does midi rtp pending.
  • The MIDI Console only reports on RTP-MIDI, and the PowerShell module can connect to devices but can't create a host. Use Network MIDI Setup or the API for that.
  • For a host to take connections, midisrv.exe has to be allowed through Windows Firewall, the same as for Network MIDI 2.0.
  • An endpoint exists only while its connection is up, so an app that lists endpoints only when it starts won't see a connection made later.

See WinRT API support for RTP-MIDI endpoints.

General MIDI Synth

Crash fix

Sending the synth a GM or GS reset, a program change, or a few other messages before it had made any sound could crash the MIDI service, which stops MIDI for every app on the PC. Fixed.

The same fix makes the synth's channel state right from the moment it loads, not just once audio starts:

  • Channel 10 is the drum channel straight away, so a MIDI-CI client asking before anything has played gets the right answer. Before, channel 10 reported Piano 1 like every other channel.
  • A program change sent before the first note is no longer lost when the audio device opens.
  • Changing a synth setting such as the render mode, bank select mode or effects no longer resets every channel's sound in the middle of a song.

Property Exchange

The synth is still the easiest Property Exchange device to test against without hardware, and it's now a much more complete one. Much of this came from MIDI Association member feedback.

  • Channel list entries now carry links to the program list for that channel.
  • The nine drum kits are published for the first time, in their own program list. The melodic list has resource id melodic and the kits have drums. The drum channel links to the kit list, and the link follows the drum channel if it moves.
  • Program list entries now carry category, using the General MIDI 1 instrument group names, such as Piano, Chromatic Percussion and Organ, exactly as the GM specification lists them. Drum kits are Drum Kit.
  • The resource list now says requireResId and canSubscribe where they apply, and no longer lists itself.
  • The channel list can be subscribed to, so a client hears about a program change on any channel, no matter who sent it.
  • A request for a resource id the synth doesn't have now gets a 404 instead of no answer.
  • Every program list reply carries totalCount, whether it's a page or not. An offset past the end returns an empty list, which is how a client paging forward knows it's done.
  • A MIDI-CI inquiry the synth doesn't support now gets a NAK instead of silence, which saves the sender a timeout on every one.
  • The synth now handles a MUID collision, and picks a new MUID after its own is invalidated instead of going quiet for good.
  • Replies are in the MIDI-CI version the request arrived in.
  • It answers the MIDI-CI Endpoint Inquiry with its product instance ID, GM1, the same one it gives in endpoint discovery (#1249).
  • Several smaller fixes from checking the Property Exchange specifications requirement by requirement, including the header order in subscription messages and how non-ASCII characters are escaped in JSON.

The synth still doesn't answer profile inquiries.

Loopback feedback protection

Both kinds of loopback now protect themselves from feedback. A feedback loop happens when MIDI that comes out of a loopback finds its way back into the same loopback, usually because an app has MIDI thru turned on. The same messages then go around and around as fast as the PC can move them. You get stuck notes, a DAW that stops responding and a busy PC, and until now you had to track it down yourself.

When a loopback finds a loop, it mutes itself, just as if you had muted it by hand. That stops the loop right away, and every app keeps its ports. Unmute the loopback once the loop is fixed.

  • Protection is on for every loopback, including the ones you already have. Each loopback can be set to mute itself, which is the default, or to do nothing. Do nothing means no checking at all.
  • Busy MIDI alone never mutes a loopback. When the traffic looks like it's going around in a circle, the loopback holds its messages for a fraction of a second. A real loop goes quiet during the pause, while an app that's really sending keeps sending. It checks twice before it mutes anything, and the check loses nothing: whatever it held is delivered, in order, right afterward.
  • An app that answers every message it gets by sending another one straight back, as fast as it can, is a loop on purpose, and it will be muted. Set the loopback it uses to do nothing.
  • Each time a loopback mutes itself, it writes a warning to the MIDI trace log with its association id and how fast messages were arriving, and for a MIDI 2.0 loopback, which direction the loop was going.
  • The basic loopback transport in this release's transport package has it. The MIDI 2.0 loopback transport ships in Windows, so protection for MIDI 2.0 loopbacks arrives with a Windows update, and only on a PC that also has loopback muting turned on.

See Why a loopback mutes itself for how to find a loop.

Bluetooth MIDI

  • A device you switch on now connects right away, even while the transport is retrying saved devices that are switched off. Before, each retry of a switched-off paired device could take more than 20 seconds, and new connections waited behind them. A device that keeps failing is now retried less often, from every 10 seconds up to every 60.
  • The transport now knows which devices are paired. In Preview 9 it treated every device as unpaired, so a paired device that was switched off dropped out of the list, and a device that paired while it was connected could stop sending messages until you connected it again.
  • For some devices, the usual way Windows asks for the MIDI service fails, even though the device answers. They could only connect once they were paired, and the transport wrongly told you they needed pairing. The transport now asks a second way when the first fails, so they can connect without pairing.
  • Connection errors say more, such as the Windows error number, the Bluetooth error, and whether the device has been heard from recently. All of the transport's messages can now be translated.
  • Fixed a case where an endpoint that was closed and opened again quickly could stop receiving messages.

Network MIDI 2.0

  • Sending speed. Some devices lose data when a lot of it arrives at once, like a hardware synth taking a long SysEx dump, or a network to DIN bridge. A host or a client can now send no faster than MIDI 1.0 wire speed, which is the speed of a DIN cable, or 2, 4, 8, 16 or 32 times that. A host can also give one device a speed of its own, and uses it every time that device connects. A single note or knob turn is never held back. Only a burst of data is spaced out, and nothing is dropped. With Slow down when a device misses data turned on, Windows sends more slowly each time a device asks for data again, and speeds back up once it stops asking. The default is still no limit. See Sending speed.
  • Network adapters. A host can be kept on one network adapter, like the wired network at a show. It advertises itself only there, and only answers devices that reach it through that adapter. If the adapter goes away, the host either runs on every adapter until it's back, or waits for it, whichever you chose. A USB network adapter plugged into a different USB port is still recognized. See Network adapters.
  • A host created on this PC now shows up more reliably on other devices on the network, such as a Mac, right after it's created.
  • An app that opens an endpoint the moment it appears now gets it. Before, opening it in roughly the first second could fail.
  • A device that sends MIDI the instant this PC accepts its connection is no longer disconnected for it, and a device that sends its invitation twice no longer ends a connection that was already working.
  • An endpoint that's closed and opened again quickly now opens, and keeps receiving messages.
  • Hosts and clients use a much larger network receive buffer, so a burst of messages, such as SysEx from several devices at once, isn't dropped before the transport can read it.
  • Changing a host's settings, such as its endpoint name or whether it makes MIDI 1.0 ports, now applies to the next device that connects. Before, new connections kept the old settings until the service restarted.
  • A host now answers from the address the device contacted. On a PC with more than one address on a network, which is common with IPv6, the answer could come from a different address, and the device ignored it, so it couldn't connect. A device that contacts this PC at a new address, for example after an IPv6 address changed, now gets its answers from that address.
  • When a device asks for data again, the answer now goes out right away, ahead of anything else waiting to be sent. Before, it waited until a large transfer, like a SysEx dump, had finished, and by then the data was often gone (#1249). Each connection also keeps more of what it sent, 250 packets by default instead of 50, and a burst of repeated requests for data that's gone gets one error back, not one for each request.
  • Fixed: a message could wait up to two seconds before it was sent, when it arrived just as the connection finished sending the ones before it.
  • A device you connected to by host name or IP address now keeps being tried while it doesn't answer, with 20 seconds between tries by default. Its host name is looked up again each time, so a device whose address changed is still found. Before, it was tried once and then left alone until you connected again. A device that turns the connection down, or asks for a password, which Windows doesn't support yet, isn't tried again until you ask. A device that says it's busy is tried again 10 to 30 seconds later. Network MIDI Setup and the MIDI Console say why a device isn't connected.
  • Finding devices works better on a PC with more than one network adapter. Each adapter is searched on its own, a device's link-local IPv6 address now includes the adapter it was found on, so it can be used, and a device that drops one of its addresses keeps the others.

Other transports

  • Basic Loopback: endpoints now say they use the MIDI 1.0 protocol. Before, that property was empty, so an app that checks it couldn't tell which protocol to send.
  • Bluetooth MIDI, Network MIDI 2.0 and RTP-MIDI now report the version and author from their file properties, like the other transports, so the version midi enumerate transports shows always matches the file that's installed.
  • Basic Loopback, Bluetooth MIDI, General MIDI Synth, Network MIDI 2.0 and RTP-MIDI: each transport grouped all of its endpoints together as if they were parts of one device, and Windows could show that device under the name of one of them, such as one of your Bluetooth MIDI devices. Each endpoint now belongs to the PC itself, the same as the loopback and app-to-app endpoints already in Windows. Endpoints you already have move over by themselves.

In-box service and transports

These parts ship in Windows. The fixes below reach customers with the November Windows release, not through the preview packages.

  • Duplicate device names (#1224, #1205). When you have more than one of the same model, the second and later units get a number in their names, such as 2- UM-ONE. Two things were wrong. The number went up every time a unit was unplugged and plugged back in, so 2- UM-ONE became 3- UM-ONE and then 4- UM-ONE. And two units of the same model on different drivers or transports never saw each other, so both got the same name. The service now hands out these numbers across every transport. A unit that comes back gets its old number back, as long as nothing else took it while it was gone, and a new unit takes the lowest number no connected device is using.
  • MIDI 1.0 port names. When Windows names ports in the new style, it now keeps the name a device or its driver gives a port, generic words and all. Before, it threw away names like In, Out or Port, and names that only added a word like MIDI IN to the device's name. On a device whose driver names each port, like Acme DR-1, Acme DR-1 CTRL and Acme DR-1 MIDI IN, that could leave two inputs with the same name, and then every input got a group number added to its name. See How Windows MIDI Services generates MIDI 1.0 port names.
  • KS Aggregate: fixed a race when the transport shuts down that could crash the MIDI service.
  • Three older servicing gates were retired, which makes their fixes permanent. No change in behavior.

Applications

Tools package version for this release is 0.99.88-preview.10.

MIDI Glass Preview

A brand new app. Windows MIDI Glass is a control surface you design yourself: knobs, faders, pads, keys and more, laid out however you like, sending MIDI to any endpoint and group. It's designed with touch screens like Surface Pro in mind, and works with a mouse and keyboard too.

This app is very much a preview, but there's a lot here to try.

  • A library of your layouts, kept in Documents\MIDI Layouts. Each card is a picture of the real layout. Search, sort, favorites and recent. You can also double-click a .midilayout file to run it.
  • A new layout can start from a template: Mixer, DJ deck, Drum pads, Transport, Mackie Control, a horizontal or vertical toolbar, a floating palette, or Blank.
  • Controls include buttons, toggles, pads, switches, knobs, faders, wheels, ribbons, a DJ turntable, XY pads, joysticks, a mono keyboard, note pads and hex pads for playing chords, meters, lamps, readouts, a stopwatch, a beat clock, an LFO and a small step sequencer, plus text, pictures, lines, group frames and page tabs.
  • A control can send notes, control changes, program changes, pitch bend, channel pressure, RPN and NRPN, per-note controllers, system exclusive from a .syx file or typed as hex, raw UMP messages, a sequence of steps, or a jump to another page. A per-note controller can be any of the registered ones, picked by name, or one your instrument assigns. You can set a note's velocity, for both note on and note off, and give a MIDI 2.0 note an attribute. Controls can spring back when you let go, and show their value in your device's own units.
  • Each device a layout sends to has a protocol. With MIDI 2.0, values are percentages at full resolution. With MIDI 1.0, you type the 0 to 127 numbers from the device's manual. Mackie Control turns the layout into a control surface for your DAW: controls pick functions such as Play or Fader 1, and the lights and motor faders follow the DAW.
  • Learn fills in what a control sends when you move a control on your hardware, for one control or a whole bank at once.
  • Pickup sets what a fader, XY pad, joystick or ribbon that follows your DAW does when you touch it far from its value: jump to your finger, wait until your finger catches up, or move by as far as your finger moves.
  • LFO and Steps controls can follow the tempo of MIDI clock from another device, such as your DAW. They follow its speed, not its start and stop.
  • The mono keyboard can show each key's note name. MIDI Glass names notes the same way as the rest of Windows MIDI Services: note 60, middle C, is C3.
  • An editor with a palette, an outline, an inspector, snapping and guides, undo and redo, and auto-save. Group controls so they move as one, lock a control so it can't be picked or moved, nudge with the arrow keys, and line controls up with align, spread and gap labels. Press Ctrl + Enter to try the layout in place, with a message monitor underneath.
  • Twenty-five built-in themes, and a theme editor for making your own. Labels can use any font installed on the PC.
  • Full screen with a small corner button, several layouts open at once, and Panic.
  • A layout can run as a floating toolbar or palette, with no title bar, a see-through background, and always on top of your other apps.
  • Layout settings for pages and devices, so a layout can move to another PC and find its devices again by exact device, name or USB model. A page can be a band, which stays on screen on top of every other page, for things like a transport row or your page tabs.
  • Pictures and video in image controls and group frames, a background picture or video for the whole layout, and a way to package a layout to share it or back it up.
  • Ask an AI assistant, next to Open a file in the library, shows a starting prompt to paste into the AI assistant you use. It links to MIDI Glass layout files, a guide for AI agents and lists your MIDI devices and themes, so the layout the assistant makes can find your devices. MIDI Glass doesn't send anything itself, and you can turn the button off under Appearance and settings.

Not there yet: the per-layout virtual device, and remembering which display a layout runs on. For Mackie Control, MIDI Glass doesn't speak HUI, doesn't answer the handshake some DAWs use to find a surface, and doesn't show the DAW's meters, V-Pot rings or display text. We'd especially like feedback from anyone with a touch screen.

To get started, see Windows MIDI Glass.

MIDI Patchbay

  • Group rows show the name the device gives each group, from its function blocks, or from its group terminal blocks when no function block names it. Endpoint boxes widen to fit their longest name, and pointing at a shortened group name shows the whole name in a tooltip.
  • The endpoint's description shows under its manufacturer.
  • Zoom goes from 10% to 400%, with Fit to screen in the zoom menu, and you can drag the overview to move around the canvas.
  • New transforms: channel mapping, program mapping with General MIDI names, and bank select mapping. Along with the existing ones, they do everything the old Windows MIDI Mapper did.
  • Velocity can be shown and typed as 0 to 127 or as a percentage, and can be set to one fixed value for every note.
  • Transposing and note mapping now move a MIDI 2.0 note's exact pitch along with its note number, or you can choose to leave those notes alone.
  • New Control change values transforms change a controller's value on its way out: invert it, set the ends of its range coming in and going out, and pick a curve. Aftertouch can be shaped the same way.
  • Patch files are now .midipatch instead of .midipatch.json, and Patchbay renames your existing patches the first time it starts. Double-click a patch file, or use Import patch, to add one from another folder. A patch added that way doesn't route until you turn it on.
  • A bar at the top says when the patch you're looking at isn't routing, with a button to start it. Start automatically, in the patch's header, sets whether a patch starts with Patchbay, and a second bar tells you when a saved patch won't.
  • Sending speed, on each connection, slows down what Patchbay sends to a device that loses data when a lot of it arrives at once, from MIDI 1.0 wire speed up to 32 times that. It's the last step, after the filters and transforms. A single note or knob turn is never held back. Patchbay holds what's waiting, instead of slowing down the app or device that sent it, and Activity shows how much is waiting. See Sending speed.
  • Wait for send complete, in a patch's ... menu, makes Patchbay wait until a device's driver has taken each message before it sends the next one. Apps that use the older WinMM API wait like that on their own, but the waiting stops at a loopback, so this puts it back between the loopback and the device.
  • Ask an AI assistant, under Import patch, shows a starting prompt to paste into the AI assistant you use. It links to MIDI Patchbay patch files, a guide for AI agents and lists your MIDI devices, so the patch the assistant makes can find them. Patchbay doesn't send anything itself, and you can turn the button off in the appearance and settings flyout.
  • Labels are shorter and use the same words as the other apps, such as Source, Destination and Start with Windows.

MIDI Keyboard

  • Latch keeps notes sounding after you let go. It's the only way to build a chord with a mouse, and it works with the arpeggiator.
  • The program picker can show programs in one list or by category, and remembers your choice. The choice is hidden for a device that doesn't publish categories.
  • It now finds a device that starts after the keyboard does, such as a DAW or a software instrument. It notices when a MIDI-CI device announces itself, and Keep looking for the device's programs (on by default) asks again every few seconds until something answers.
  • It answers MIDI-CI Discovery as itself, so a device or DAW that asks who's there can see it, and it keeps one identity the whole time it's connected instead of drawing a new one for each query.
  • It asks for the resource list first, follows the link from each channel to the right program list, and subscribes to the channel list when the device offers it, so it hears about changes without asking again.
  • Notes are mapped to the physical keys, so the playing shape is the same on QWERTY, QWERTZ and AZERTY keyboards. The letters drawn on the keys follow your Windows keyboard layout, and a setting lets you pick a different installed layout for them. When a text box or list has the keystrokes, the keys dim and a reminder appears. Press Esc to play again.
  • The device, group and channel are now on the toolbar, in that order, with the connection status at the end of the row. They used to be in the settings panel. The group list shows the names the device gives its groups.
  • The virtual device choice, which was turned off in Preview 9, is gone. It may come back in a later release.
  • Black keys and White keys tabs under Appearance let you pick your own key colors. The letters on the keys switch between dark and light by themselves, so they stay easy to read, and the lines between the keys stay a little darker or lighter than the keys.

MIDI Clock

  • Divider, swing and offset. Run a clock at half speed, double speed, dotted, triplets or any other ratio, and every one is exact. Add swing from 50% to 75% on eighths or sixteenths without changing the tempo, and shift one clock up to half a second earlier or later than the others.
  • MIDI Time Code. A clock can now send timecode instead of a beat clock, at 24, 25, 29.97 drop frame or 30 frames per second, from any start time, with a full timecode message when it starts and stops.
  • Fixed: selecting Start, Stop or the check box on a clock's tile also opened the clock's editor.

MIDI Monitor

  • Save to File now offers four kinds of file: text for reading, comma separated values for a script or a spreadsheet, a Standard MIDI File for a sequencer, and binary UMP words for a hex editor (#1249). The comma separated column names are always in English, so a script works on any machine.
  • Copy as binary data, in the right-click menu, copies the same bytes the binary file holds, as hex text you can paste into a hex editor.

MIDI Loopback Setup

  • The create and edit dialogs have a new choice, If MIDI feeds back into this loopback: Mute the loopback (recommended) or Do nothing.
  • A loopback that muted itself says so in its row, with the date and time, and a Feedback detected message at the top of the page says what to look for. Unmute it once the loop is fixed.
  • These only appear when the loopback transport on the PC supports feedback protection. Each kind of loopback is checked on its own.
  • It now reads and saves everything through the Windows MIDI Services API. The order you drag your loopbacks into is kept for each Windows user instead of in the MIDI configuration file, so an order you set in Preview 9 doesn't carry over. Drag them into place once more if you need to.

Network MIDI Setup

  • Renamed from Network MIDI 2.0 Setup, because it now sets up RTP-MIDI as well. When the RTP-MIDI transport is installed, the app has an RTP-MIDI heading with its own Network devices and This PC pages. They work like the Network MIDI 2.0 pages: connect to RTP-MIDI devices on your network, create a host that Apple devices and other RTP-MIDI software can connect to, and allow or block devices that ask to connect. Each connection shows how many packets were lost and repaired.
  • When a device offers both RTP-MIDI and Network MIDI 2.0, the RTP-MIDI page says so and asks before it connects, because Network MIDI 2.0 is the better choice, and connecting both ways gives you two sets of endpoints for the same device.
  • Sending speed. Every host, and every device you connect to, shows its sending speed with a Change link, and you can pick a speed when you connect or create a host. Under a host, each connected device shows the speed it gets, and Change gives that device a speed of its own, which Windows remembers. Devices with their own sending speed lists them, even when they aren't connected. For Network MIDI 2.0, Slow down when a device misses data lets Windows pick a slower speed by itself, and a connection that has slowed down says so. See Choosing a sending speed.
  • Network adapter, under Advanced when you create a host, keeps the host on one network. To change it later, open Details on the host. A host whose adapter is missing shows a warning with a Choose adapter button. Network MIDI 2.0 and RTP-MIDI hosts both have this. See Choosing a network adapter.
  • A device that isn't connected now says why, such as The device did not answer. Windows will keep trying. And Try again now works for a device you connected to by address.
  • A host's address now lists both its IPv4 and IPv6 addresses. Each device you connected to is listed under the name you gave it, or the name it advertises, instead of the name this PC announces to it.
  • It now reads and saves everything through the Windows MIDI Services API. If a change can't be saved, the app says so, and the change lasts until the MIDI service restarts.

Bluetooth MIDI Setup

  • A device you've asked to connect stays in the list while it's switched off, and says Windows is waiting for it.
  • It gets your saved devices from the Windows MIDI Services API instead of reading the MIDI configuration file.

Notifications

  • A new notification tells you when a loopback mutes itself because of feedback. Its button opens MIDI Loopback Setup on the page with that loopback, and the notification goes away once the loopback is unmuted.
  • Another new notification tells you when a Network MIDI 2.0 or RTP-MIDI host on this PC can't start, because the network adapter it's kept on is missing. Its button opens Network MIDI Setup on your hosts, and the notification goes away once the adapter is back or you choose another one.

MIDI Settings

  • MIDI Clock and MIDI Glass are on the toolbar.
  • Global MIDI Settings and Notifications stay pinned at the right end of the toolbar. Tools that don't fit move into a ... menu, and you can turn off Show button labels for a compact row of icons.
  • The Notifications dialog has two new switches, Loopbacks muted because of feedback and Network hosts missing their network adapter. Both are on unless you turn them off.

MIDI Console

  • endpoint monitor can capture to comma separated values or a Standard MIDI File with --capture-format ump|csv|smf. The default is still ump.
  • endpoint send-beat-clock gained --clock-ratio, --swing, --swing-subdivision and --offset.
  • New endpoint send-time-code (also send-mtc, time-code and mtc) sends MIDI Time Code, with --frame-rate, --begin-at, --group, --full-frame and --offset.
  • New midi rtp commands report on RTP-MIDI: list-hosts, list-clients, browse, pending and status. They don't change anything.
  • network list-hosts and rtp list-hosts show each host's sending speed and network adapter, and list the devices that have a speed of their own. network list-clients and rtp list-clients show each client's sending speed, and a Network MIDI 2.0 client that isn't connected says why.
  • An endpoint id given before the command, as in midi endpoint <id> request function-blocks, now works for every command. Before, some commands never got it, and a command that takes a list, such as notes or groups, could take the id as one more item.
  • midi enumerate transports shows just the table unless you add --verbose. Before, it printed each transport's details as well.

MIDI Troubleshooting and Repair

  • A time travel trace can't be detached from the MIDI service once it's attached, so the service runs slowly until Windows or the service is restarted. The capture option now says so up front, and the app reminds you after the capture.
  • The Transports page, renamed from Enabled transports, can now turn each transport on or off. If you only use USB devices, for example, you can turn off Bluetooth and the network transports, so the MIDI service stops looking for those devices and stops opening network ports. It needs administrator rights, and the page offers to restart the MIDI service so the change takes effect. Each transport shows whether it's enabled and whether it's loaded.
  • On the Diagnostics page, the mididiag report appears as it's written, instead of all at once at the end. Save as zip saves it small enough to attach to a GitHub issue. View report opens it in a window of its own, with the findings first, errors in red, and each section opening and closing on its own. It also opens a report somebody sent you, even inside the zip it came in.
  • If the MIDI service stops answering while mididiag runs, the page offers to save a memory dump of the service, which shows the developers where it's stuck. Save it before you restart the PC.
  • Fixed: the app lost the last part of every report it ran, so copied and saved reports were cut short.

mididiag

  • The report has a new layout that both a person and a script can read, at less than half the size. It starts with your PC and Windows, and ends with findings: things the report noticed that are worth a look, each written as a plain sentence. MIDI Diagnostics Report has the rules for reading it with a script, and C++ files you can copy to read it in your own tool.
  • It covers much more: the versions of the MIDI parts of Windows, the API mode, times in the last 30 days when the MIDI service stopped unexpectedly, USB and MIDI devices with a problem, the firewall rules network MIDI needs, Bluetooth MIDI, Network MIDI 2.0, RTP-MIDI and loopback details, saved names and pictures that no longer match any device, and how long it takes to open a MIDI connection.
  • It reads everything it can from Windows before it asks the MIDI service anything. If the service stops answering, the report stops after a short wait, says where it got to, and still lists its findings.
  • It leaves out your user name and most of each IP address.
  • The ports apps see through the older WinRT MIDI 1.0 API are left out unless you add --include-winrt-midi1.
  • For each endpoint, the report now shows whether it's muted, and details of the device behind it: USB vendor and product IDs and serial number, and the driver's service name, .inf file and version.
  • A new section lists every app connected to the MIDI service and the endpoints it has open.
  • The Network MIDI 2.0 and RTP-MIDI sections show each host's network adapter setting and whether the adapter is missing, the sending speed of hosts, clients and connections, and the last connection error of each Network MIDI 2.0 client.
  • It shows the UseLegacyMidi value when it's set, and the report now starts with the current date and time.
  • Diagnostic loopback and ping endpoints are left out of the endpoint list.
  • Fixed: developer mode read as enabled when the registry value was missing.

PowerShell module

Seventeen new cmdlets, for 49 in all.

  • Get-MidiChannelList and Get-MidiProgramList read a device's channels and programs through MIDI Capability Inquiry.
  • Get-MidiRtpAdvertisedHost, Get-MidiRtpConfiguredHost, Get-MidiRtpConfiguredClient, Connect-MidiRtpHost and Disconnect-MidiRtpHost do for RTP-MIDI what the Network MIDI 2.0 cmdlets do.
  • Set-MidiNetworkRemoteClientSendSpeed and Remove-MidiNetworkRemoteClientSendSpeed give one device on a Network MIDI 2.0 host a sending speed of its own, or put it back on the host's speed. Set-MidiRtpRemoteClientSendSpeed and Remove-MidiRtpRemoteClientSendSpeed do the same for RTP-MIDI.
  • Connect-MidiNetworkHost gained -SendSpeedLimit and -ReduceSendSpeedAutomatically, and Connect-MidiRtpHost gained -SendSpeedLimit. The ClientId that Connect-MidiNetworkHost returns is now filled in, so you can pass it to Disconnect-MidiNetworkHost.
  • Get-MidiSynthSoundSet, Get-MidiSynthInstrument and Set-MidiSynthDrumChannel for the General MIDI Synth.
  • Suspend-MidiFilePlayback and Resume-MidiFilePlayback pause and resume a file, and Start-MidiFilePlayback -StartAtSeconds starts partway through.
  • Receive-MidiMessage records what an endpoint receives and saves it as a Standard MIDI File.
  • Send-MidiSystemExclusive and Receive-MidiSystemExclusive can take -EndpointDeviceId instead of a connection you opened yourself.
  • Every message the module shows can now be translated.

All apps

  • The PREVIEW badge is drawn smoothly at fractional display scaling, and several app icons were refreshed.
  • MIDI Glass and MIDI Patchbay list your devices sooner after they start, and no longer rebuild the list over and over afterward. It makes the most difference on a PC that has had many MIDI devices connected over time. While MIDI Glass is still looking, it says so instead of saying there are no devices.
  • MIDI File Player, MIDI Scratch Pad and MIDI SysEx Tool have no other changes in this release.

Documentation

  • New knowledge base article: How the built-in General MIDI synthesizer works. What it plays, how to turn it on and off and set it up, and full MIDI 2.0 and MIDI-CI implementation charts.
  • New knowledge base article: Why a loopback mutes itself. What a feedback loop is, how to find one, and when to turn protection off. The MIDI Loopback Setup page and both loopback transport articles link to it.
  • New knowledge base articles for AI assistants: MIDI Glass layout files, a guide for AI agents and MIDI Patchbay patch files, a guide for AI agents. Each one says what to ask, gives the whole file format with a working example, and has a script that checks the finished file. A new llms.txt points AI assistants to them, and to How MIDI Glass themes work.
  • How Network MIDI 2.0 works in Windows has new sections on sending speed and network adapters, and the Network MIDI Setup page explains how to choose both.
  • New WinRT API reference pages for MidiLoopbackFeedbackProtection and MidiBasicLoopbackFeedbackProtection. The loopback and basic loopback manager, entry, creation config and error code pages cover the new members.
  • New WinRT API reference pages for MidiPropertySubscription, MidiPropertySubscriptionUpdatedEventArgs, MidiSequenceBuilder, MidiSequenceTimingMode, MidiStandardFileWriter, MidiFileWriteOptions, MidiFileWriteResult and MidiFileWriteStatus.
  • New WinRT API reference for RTP-MIDI: an overview of the Windows.Devices.Midi2.Transports.Rtp namespace, with hosts, clients, approval, how clients reconnect and what's saved, plus a page for each of its 39 types. The API contracts page lists the new contract.
  • New WinRT API reference pages for the saved configuration types: MidiLoopbackSavedEntry, MidiLoopbackUpdateConfig, MidiBasicLoopbackSavedEntry, MidiBasicLoopbackUpdateConfig, MidiNetworkSavedHost, MidiNetworkSavedClient, MidiRtpSavedHost, MidiRtpSavedClient and MidiBluetoothSavedDevice. The manager pages and MidiServiceConfigSaveResult cover the new members.
  • New WinRT API reference pages for MidiNetworkSendSpeedLimit, MidiNetworkRemoteClientSettings and MidiNetworkHostRemoteClientSettingsConfig, and the RTP-MIDI pages that match them. The host, client and connection pages for both transports cover sending speed and network adapters, and the Network MIDI 2.0 overview has a new table of what the service does when a client can't connect.
  • New tools page for Windows MIDI Glass, and three knowledge base articles for it: How MIDI Glass themes work, How to control your DAW with Mackie Control in MIDI Glass and How to make a floating toolbar or palette in MIDI Glass.
  • Updated reference pages for MidiCapabilityInquirySession, MidiCapabilityInquiryDeviceResponder, MidiCapabilityInquiryMessage, MidiCapabilityInquiryMessageBuilder, MidiSequence and MidiSystemExclusiveSender, and the Utilities.Sequencing and Utilities.Files namespace pages.
  • The pages the Preview 9 notes listed as not yet written are now published: WinRT API support for the General MIDI synthesizer, and tools pages for MIDI File Player, MIDI Keyboard and MIDI Clock.
  • Tools pages updated for the new features in MIDI Clock, MIDI Monitor, MIDI Keyboard, MIDI Patchbay, MIDI Loopback Setup, MIDI Settings, Network MIDI Setup, MIDI Troubleshooting and Repair, the MIDI Console and the PowerShell module. The console page covers send-time-code, --capture-format, the new send-beat-clock options and midi rtp, and the PowerShell page covers every cmdlet, including the synth and file playback ones that weren't documented before. The Bluetooth MIDI Setup, Loopback Setup and Network MIDI Setup pages now explain that you don't need to keep the app running.
  • Every app's tools page now opens with a Quick start: a picture of the app with numbered callouts, and a line about each one.
  • The MIDI Diagnostics Report page was rewritten for the new report: what's in it, what it leaves out for your privacy, its exit codes, and how to read it with a script.
  • The MIDI Patchbay page has a tip for putting a loopback in a device's place, so apps that find a device by its name keep working while you filter what they receive.
  • The overview page lists Bluetooth MIDI, Network MIDI 2.0, RTP-MIDI and the General MIDI Synth as transports in preview. It used to call Bluetooth MIDI and Network MIDI 2.0 future plans.
  • The knowledge base and tools pages were rewritten in plainer language, about 30 pages in all. How to change the API mode and How to switch between MIDI class drivers now start with the MIDI Troubleshooting and Repair app and keep the manual steps second.
  • The feature table in Application Backwards Compatibility is up to date: the in-box GS synth, Bluetooth MIDI 1.0 and Network MIDI 2.0 are listed as in preview, and 32-bit desktop apps are listed as supported by WinRT MIDI 1.0.
  • Fixed two tables that didn't display, and two links to Enumeration reference pages that led nowhere.
  • Tools pages now get an automatic "On this page" list. Links in articles are blue and underlined, with a visible outline for keyboard users.

Not yet written: a knowledge base article for the RTP-MIDI transport, and samples for subscriptions and RTP-MIDI.