diff --git a/build/staging/version/BundleInfo.wxi b/build/staging/version/BundleInfo.wxi
index 8b223f2c..f49b5b23 100644
--- a/build/staging/version/BundleInfo.wxi
+++ b/build/staging/version/BundleInfo.wxi
@@ -1,4 +1,4 @@
-
+
diff --git a/docs/_site/assets/js/search-data.json b/docs/_site/assets/js/search-data.json
index 3c1984f9..481c47a9 100644
--- a/docs/_site/assets/js/search-data.json
+++ b/docs/_site/assets/js/search-data.json
@@ -1,1481 +1,1614 @@
{"0": {
"doc": "IMidiEndpointMessageProcessingPlugin",
"title": "IMidiEndpointMessageProcessingPlugin",
- "content": "(In progress) . ",
+ "content": "This interface is implemented by any type which can be an endpoint processing plugin in the client API. These plugins are used to process or manipulate messages coming from an endpoint. Microsoft provides several plugins in the API, including the MidiVirtualEndpointDevice, the MidiChannelEndpointListener, and the MidiGroupEndpointListener. All of these types implement the IMidiEndpointMessageProcessingPlugin interface and operate in the same way. The main part of message processing is the ProcessIncomingMessage callback. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/IMidiEndpointMessageProcessingPlugin.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/IMidiEndpointMessageProcessingPlugin.html"
},"1": {
+ "doc": "IMidiEndpointMessageProcessingPlugin",
+ "title": "Properties",
+ "content": "| Property | Description | . | Id | Generated GUID for this plugin instance. This is needed if you want to remove the plugin from the endpoint connection | . | Name | Optional application-supplied name for this plugin instance. | . | Tag | Optional application-supplied arbitrary data to associate with this plugin instance | . | IsEnabled | True if the plugin is enabled and should participate in message processing | . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/IMidiEndpointMessageProcessingPlugin.html#properties",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/IMidiEndpointMessageProcessingPlugin.html#properties"
+ },"2": {
+ "doc": "IMidiEndpointMessageProcessingPlugin",
+ "title": "Functions",
+ "content": "| Function | Description | . | Initialize(endpointConnection) | Called by the endpoint connection. Perform any setup code which requires the endpoint connection pointer here. | . | OnEndpointConnectionOpened() | Callback when the endpoint connection is opened. If the plugin is added after the endpoint connection has already been opened, this is called immediately. | . | ProcessIncomingMessage(args, skipFurtherListeners, skipMainMessageReceivedEvent) | Callback for processing an incoming message. If the code sets skipFurtherListeners to true, any plugins after this one will not be called. If the code sets skipMainMessageReceivedEvent to true, the endpoint’s MessageReceived event will not be called for this message. Note: this callback is synchronous, so code in this should execute quickly and return immediately when complete. | . | Cleanup() | Called when the endpoint is tearing down | . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/IMidiEndpointMessageProcessingPlugin.html#functions",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/IMidiEndpointMessageProcessingPlugin.html#functions"
+ },"3": {
"doc": "IMidiEndpointMessageProcessingPlugin",
"title": "IDL",
"content": "IMidiEndpointMessageProcessingPlugin IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/IMidiEndpointMessageProcessingPlugin.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/IMidiEndpointMessageProcessingPlugin.html#idl"
- },"2": {
+ },"4": {
"doc": "IMidiUniversalPacket",
"title": "IMidiUniversalPacket",
- "content": "This interface is implemented by the rich MidiMessageXX runtime class types. It may also be used as the interface for message-specific classes you create yourself. | Property | Description | . | Timestamp | 64 bit timestamp set by the receiving transport in the case of incoming messages, or by the sender in the case of outgoing messages | . | MessageType | A MidiMessageType enumeration value which represents the 4 bit MIDI Message type 0x0 - 0xF as defined by the MIDI UMP standard. | . | PacketType | A MidiPacketType enumeration value which can be cast to an int to get the number of 32-bit words in the message packet | . | Function | Description | . | PeekFirstWord() | Provides access to the first word of data, even if the message type and size is not yet known by the API user | . IMidiUniversalPacket IDL . ",
+ "content": "This interface is implemented by the rich MidiMessageXX runtime class types. It may also be used as the interface for message-specific classes you create yourself. | Property | Description | . | Timestamp | 64 bit timestamp set by the receiving transport in the case of incoming messages, or by the sender in the case of outgoing messages | . | MessageType | A MidiMessageType enumeration value which represents the 4 bit MIDI Message type 0x0 - 0xF as defined by the MIDI UMP standard. | . | PacketType | A MidiPacketType enumeration value which can be cast to an int to get the number of 32-bit words in the message packet | . | Function | Description | . | PeekFirstWord() | Provides access to the first word of data, even if the message type and size is not yet known by the API user | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/IMidiUniversalPacket.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/IMidiUniversalPacket.html"
- },"3": {
+ },"5": {
+ "doc": "IMidiUniversalPacket",
+ "title": "IDL",
+ "content": "IMidiUniversalPacket IDL . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/messages/IMidiUniversalPacket.html#idl",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/messages/IMidiUniversalPacket.html#idl"
+ },"6": {
"doc": "MidiChannel",
"title": "MidiChannel",
"content": "The MidiChannel class is used to provide formatting and data validation for MIDI 1.0 and MIDI 2.0 channels. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiChannel.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiChannel.html"
- },"4": {
+ },"7": {
"doc": "MidiChannel",
"title": "Properties",
"content": "| Property | Description | . | Index | The data value, or channel Index (0-15) | . | NumberForDisplay | The number that should be displayed in any UI. (1-16) | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiChannel.html#properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiChannel.html#properties"
- },"5": {
+ },"8": {
"doc": "MidiChannel",
"title": "Static Properties",
"content": "| Static Property | Description | . | LabelShort | Returns the localized abbreviation. For example, “Ch” in English. | . | LabelFull | Returns the localized full name. For example, “Channel” in English. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiChannel.html#static-properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiChannel.html#static-properties"
- },"6": {
+ },"9": {
"doc": "MidiChannel",
"title": "Functions",
"content": "| Function | Description | . | MidiChannel() | Constructs an empty MidiChannel | . | MidiChannel(index) | Constructs a MidiChannel with the specified index | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiChannel.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiChannel.html#functions"
- },"7": {
+ },"10": {
"doc": "MidiChannel",
"title": "Static Functions",
"content": "| Static Function | Description | . | IsValidChannelIndex(index) | Verifies that the provided index is valid (between 0 and 15) | . MidiChannel IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiChannel.html#static-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiChannel.html#static-functions"
- },"8": {
+ },"11": {
"doc": "MidiChannelEndpointListener",
"title": "MidiChannelEndpointListener",
- "content": "(In progress) . ",
+ "content": "This class acts as a filter. Incoming messages with the specified group and channel will be provided through the MessageReceived event. Other messages will be ignored. In addition to the properties and methods in IMidiEndpointMessageProcessingPlugin, and the MessageReceived event from IMidiMessageReceivedEventSource the class provides the following: . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiChannelEndpointListener.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiChannelEndpointListener.html"
- },"9": {
+ },"12": {
+ "doc": "MidiChannelEndpointListener",
+ "title": "Properties",
+ "content": "| Property | Description | . | IncludeGroup | The MidiGroup that this listener will listen to. | . | IncludeChannels | The channels that this listener will listen to on the group. | . | PreventCallingFurtherListeners | True if this plugin should prevent further listeners from processing a message that is in-scope for this processor. | . | PreventFiringMainMessageReceivedEvent | True if this plugin should prevent the endpoint’s MessageReceived event from firing if the message was in-scope for this plugin. | . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiChannelEndpointListener.html#properties",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiChannelEndpointListener.html#properties"
+ },"13": {
+ "doc": "MidiChannelEndpointListener",
+ "title": "Functions",
+ "content": "| Property | Description | . | MidiChannelEndpointListener() | Construct a new instance of this type | . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiChannelEndpointListener.html#functions",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiChannelEndpointListener.html#functions"
+ },"14": {
"doc": "MidiChannelEndpointListener",
"title": "IDL",
"content": "MidiChannelEndpointListener IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiChannelEndpointListener.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiChannelEndpointListener.html#idl"
- },"10": {
+ },"15": {
"doc": "MidiClock",
"title": "MidiClock",
"content": "The MidiClock is what is used for all timestamps in Windows MIDI Services. Although it is internally backed by QueryPerformanceCounter, we recommend using the MidiClock type directly instead of calling QPC yourself. Also note that QueryPerformanceCounter technically returns a signed 64 bit integer, but the timestamp values used in Windows MIDI Services are unsigned 64 bit integers. Typically, this is of no practical concern as the tick resolution is currently 100ns and takes tens of thousands of years to wrap around even with a 64 bit signed integer. Note: The MIDI Clock is unrelated to wall clock time. It is an ever-increasing value of period 1/TimestampFrequency seconds that starts over when the PC is rebooted. To convert to wall clock time, you need to get the MidiClock.Now value at a known time, and then use that as a baseline until the next time you reboot the PC. You can learn more about high-resolution timestamps in Windows at https://aka.ms/miditimestamp. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/clock/MidiClock.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/clock/MidiClock.html"
- },"11": {
+ },"16": {
"doc": "MidiClock",
"title": "Static Properties",
"content": "| Static Property | Description | . | Now | Returns the current timestamp | . | TimestampFrequency | Returns the number of timestamp ticks per second. This is calculated the first time it is called, and then cached for future calls. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/clock/MidiClock.html#static-properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/clock/MidiClock.html#static-properties"
- },"12": {
+ },"17": {
"doc": "MidiClock",
"title": "Static Functions",
"content": "The static functions are for convenience in calculating offsets to a timestamp, and for converting between units. | Static Function | Description | . | ConvertTimestampToMicroseconds(timestampValue) | Converts the provided timestamp to microseconds | . | ConvertTimestampToMilliseconds(timestampValue) | Converts the provided timestamp to milliseconds | . | ConvertTimestampToSeconds(timestampValue) | Converts the provided timestamp to seconds | . | OffsetTimestampByTicks(timestampValue, offsetTicks) | Offsets a given timestamp by the provided (signed) number of ticks | . | OffsetTimestampByMicroseconds(timestampValue, offsetMicroseconds) | Offsets a given timestamp by the provided (signed) number of microseconds | . | OffsetTimestampByMilliseconds(timestampValue, offsetMilliseconds) | Offsets a given timestamp by the provided (signed) number of milliseconds | . | OffsetTimestampBySeconds(timestampValue, offsetSeconds) | Offsets a given timestamp by the provided (signed) number of seconds | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/clock/MidiClock.html#static-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/clock/MidiClock.html#static-functions"
- },"13": {
+ },"18": {
"doc": "MidiClock",
"title": "IDL",
"content": "MidiClock IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/clock/MidiClock.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/clock/MidiClock.html#idl"
- },"14": {
+ },"19": {
"doc": "MidiEndpointConnection",
"title": "MidiEndpointConnection",
"content": "The MidiEndpointConnection type represents a single connection to a single endpoint managed by Windows MIDI Services. It is created using the functions of the MidiSession, and is tied to the lifetime of that session. Connections allocate resources including send/receive buffers, and processing threads. For that reason, a session should generally not open more than one connection to a single endpoint. If you need to partition out messages more easily (by group or channel, for example) the MessageProcessingPlugins collection will help you do that. To ensure an application is able to wire up processing plugins and event handlers before the connection is active, the connection returned by the MidiSession is not yet open. Once the connection is acquired, the application should assign event handlers, and optionally assign any message processing plugins. Once complete, the application calls the Open() function to connect to the service, create the queues, and begin sending and receiving messages. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html"
- },"15": {
+ },"20": {
"doc": "MidiEndpointConnection",
"title": "Properties",
"content": "| Property | Description | . | ConnectionId | The generated GUID which uniquely identifes this connection instance. This is what is provided to the MidiSession when disconnecting an endpoint | . | EndpointDeviceId | The system-wide identifier for the device connection. This is returned through enumeration calls. | . | Tag | You may use this Tag property to hold any additional information you wish to have associated with the connection. | . | IsOpen | True if this connection is currently open. When first created, the connection is not open until the consuming code calls the Open method | . | Settings | Settings used to create this connection. | . | MessageProcessingPlugins | Collection of all message processing plugins which will optionally handle incoming messages. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html#properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html#properties"
- },"16": {
+ },"21": {
"doc": "MidiEndpointConnection",
"title": "Static Member Functions",
"content": "| Static Function | Description | . | GetDeviceSelector() | Returns the device selector used for enumerating endpoint devices compatible with this API. | . | SendMessageSucceeded(sendResult) | Helper function to decipher the return result of a message sending function to tell if it succeeded. | . | SendMessageFailed(sendResult) | Helper function to decipher the return result of a message sending function to tell if it failed. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html#static-member-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html#static-member-functions"
- },"17": {
+ },"22": {
"doc": "MidiEndpointConnection",
"title": "Functions",
"content": "| Function | Description | . | Open() | Open the connection and start receiving messages. Wire up the message event handler before calling this method. | . | SendMessagePacket(message) | Send an IMidiUniversalPacket-implementing type such as MidiMessage64 or a strongly-typed message class. | . | SendMessageStruct(timestamp, message, wordCount) | Send a fixed-sized MidiMessageStruct containing wordCount valid words. Additional words are ignored. | . | SendMessageWordArray(timestamp, words, startIndex, wordCount) | Note: Some projections will send the entire array as a copy, so this may not be the most effecient way to send messages from your language. | . | SendMessageWords(timestamp, word0) | Send a single 32-bit Universal MIDI Packet as 32-bit words. This is often the most efficient way to send this type of message | . | SendMessageWords(timestamp, word0, word1) | Send a single 64-bit Universal MIDI Packet as 32-bit words. This is often the most efficient way to send this type of message | . | SendMessageWords(timestamp, word0, word1, word2) | Send a single 96-bit Universal MIDI Packet as 32-bit words. This is often the most efficient way to send this type of message | . | SendMessageWords(timestamp, word0, word1, word2, word3) | Send a single 128-bit Universal MIDI Packet as 32-bit words. This is often the most efficient way to send this type of message | . | SendMessageBuffer(timestamp, buffer, byteOffset, byteLength) | Send a single Universal MIDI Packet as bytes from a buffer. The number of bytes sent must match the size read from the first 4 bits of the data starting at the specified offset, and must be laid out correctly with the first byte corresponding to the MSB of the first word of the UMP (the word which contains hte message type). If you want to manage a chunk of buffer memory, the IMemoryBuffer type is the acceptable WinRT approach, and is as close as you get to sending a pointer into a buffer. | . | AddEndpointProcessingPlugin(plugin) | Add an endpoint processing plugin to this connection | . | RemoveEndpointProcessingPlugin(id) | Remove an endpoint processing plugin | . Tip: In all the functions which accept a timestamp to schedule the message, you can send a timestamp of 0 (zero) to bypass the scheduler and send the message immediately. Otherwise, the provided timestamp is treated as an absolute time for when the message should be sent from the service. Note that the service-based scheduler (currently based on a std::priority_queue) gets less efficient when there are thousands of messages in it, so it’s recommended that you not schedule too many messages at a time or too far out into the future. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html#functions"
- },"18": {
+ },"23": {
"doc": "MidiEndpointConnection",
"title": "Events",
"content": "| Event | Description | . | MessageReceived(source, args) | From IMidiMessageReceivedEventSource. This is the event for receiving MIDI Messages, one at a time. | . When processing the MessageReceived event, do so quickly. This event is synchronous. If you need to do long-running processing of incoming messages, add them to your own incoming queue structure and have them processed by another application thread. Note: Wire up event handlers and add message processing plugins prior to calling Open(). ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html#events",
"relUrl": "/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html#events"
- },"19": {
+ },"24": {
"doc": "MidiEndpointConnection",
"title": "IDL",
"content": "MidiEndpointConnection IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html#idl"
- },"20": {
+ },"25": {
"doc": "MidiEndpointConnection",
"title": "Sample",
"content": "Here’s an excerpt from the full “API client basics” sample. It shows sending and receiving messages using the two built-in loopback endpoints. For more information on the loopback endpoints, see diagnostics endpoints. using (var session = MidiSession.CreateSession(\"API Sample Session\")) { // get the endpoint Ids. Normally, you'd use enumeration functions to get this // for non-diagnostics endpoints. var endpointAId = MidiEndpointDeviceInformation.DiagnosticsLoopbackAEndpointId; var endpointBId = MidiEndpointDeviceInformation.DiagnosticsLoopbackBEndpointId; Console.WriteLine(\"Connecting to Sender UMP Endpoint: \" + endpointAId); Console.WriteLine(\"Connecting to Receiver UMP Endpoint: \" + endpointBId); var sendEndpoint = session.CreateEndpointConnection(endpointAId); var receiveEndpoint = session.CreateEndpointConnection(endpointBId); void MessageReceivedHandler(object sender, MidiMessageReceivedEventArgs args) { var ump = args.GetMessagePacket(); Console.WriteLine(); Console.WriteLine(\"Received UMP\"); Console.WriteLine(\"- Current Timestamp: \" + MidiClock.Now); Console.WriteLine(\"- UMP Timestamp: \" + ump.Timestamp); Console.WriteLine(\"- UMP Msg Type: \" + ump.MessageType); Console.WriteLine(\"- UMP Packet Type: \" + ump.PacketType); Console.WriteLine(\"- Message: \" + MidiMessageUtility.GetMessageFriendlyNameFromFirstWord(args.PeekFirstWord())); if (ump is MidiMessage32) { var ump32 = ump as MidiMessage32; if (ump32 != null) Console.WriteLine(\"- Word 0: 0x{0:X}\", ump32.Word0); } }; // wire up the event handler before opening the endpoint receiveEndpoint.MessageReceived += MessageReceivedHandler; Console.WriteLine(\"Opening endpoint connection\"); receiveEndpoint.Open(); sendEndpoint.Open(); Console.WriteLine(\"Creating MIDI 1.0 Channel Voice 32-bit UMP...\"); var ump32 = MidiMessageBuilder.BuildMidi1ChannelVoiceMessage( MidiClock.Now, // use current timestamp 5, // group 5 Midi1ChannelVoiceMessageStatus.NoteOn, // 9 3, // channel 3 120, // note 120 - hex 0x78 100); // velocity 100 hex 0x64 sendEndpoint.SendMessagePacket((IMidiUniversalPacket)ump32); // could also use the SendWords methods, etc. Console.WriteLine(\" ** Wait for the message to arrive, and then press enter to cleanup. ** \"); Console.ReadLine(); // you should unregister the event handler as well receiveEndpoint.MessageReceived -= MessageReceivedHandler; // not strictly necessary if the session is going out of scope or is in a using block session.DisconnectEndpointConnection(sendEndpoint.ConnectionId); session.DisconnectEndpointConnection(receiveEndpoint.ConnectionId); } . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html#sample",
"relUrl": "/developer-docs/Windows.Devices.Midi2/connections/MidiEndpointConnection.html#sample"
- },"21": {
+ },"26": {
"doc": "MidiEndpointDeviceInformation",
"title": "MidiEndpointDeviceInformation",
"content": "This class is a specialized equivalent of the DeviceInformation WinRT class. It handles requesting all of the additional properties necessary for MIDI devices, and also goes a step further to retrieve parent device information so that applications can display the endpoints and parent devices in context. We’ve heard from developers that we did not provide sufficient information about devices in the past, so we created this class and the associated properties to remedy that. We also heard that Async calls were a non-starter for most DAW applications, so everything in this class is synchronous. Note: the MidiEndpointDeviceWatcher is a better way to retrieve devices because you can then keep the watcher open in a background thread, and be notified of property changes, device add/remove, etc. When displaying endpoint devices to users, you’ll typically want to stick to the defaults: IncludeClientUmpNative | IncludeClientByteStreamNative. You do not want to show the Diagnostic Ping ever, and you typically will not want to show the system-wide Diagnostic Loopback singletons. Finally, you don’t want to show the Virtual Device Responder endpoints because those should be reserved only for the “device” application in app-to-app MIDI. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html"
- },"22": {
+ },"27": {
"doc": "MidiEndpointDeviceInformation",
"title": "In-protocol discovered information",
"content": "When a device is first enumerated by the MIDI Service, if it is a UMP-native device, we will attempt endpoint discover and protocol negotiation. During that, we request all endpoint information and all function block information. The received data is then cached in the device properties so that applications do not need to perform this process themselves. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#in-protocol-discovered-information",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#in-protocol-discovered-information"
- },"23": {
+ },"28": {
"doc": "MidiEndpointDeviceInformation",
"title": "Properties",
"content": "| Property | Source | Description | . | Id | Windows | The endpoint device interface id | . | ContainerId | Windows | The device container | . | DeviceInstanceId | Windows | The device instance id without the interface information | . | Name | Various | This is the name which should be displayed in any application. It calculates the correct name based on the hierarchy of possible names, including a user-specified name. Always respect the user’s choice here. | . | TransportSuppliedName | Transports | The name provided by the driver or the endpoint transport. | . | EndpointSuppliedName | MIDI 2.0 | The name provided by MIDI 2.0 endpoint information. This is discovered in-protocol. | . | UserSuppliedName | Configuration | The name provided by the user. | . | ProductInstanceId | MIDI 2.0 | Property of the same name discovered by MIDI 2.0 in-protocol endpoint information. | . | SpecificationVersionMajor | MIDI 2.0 | Discovered UMP version | . | SpecificationVersionMinor | MIDI 2.0 | Discovered UMP version | . | SupportsMidi10Protocol | MIDI 2.0 | Discovered protocol support | . | SupportsMidi20Protocol | MIDI 2.0 | Discovered protocol support | . | `ConfiguredToReceiveJRTimestamps | MIDI 2.0 | Note that JR timestamps are handled entirely in the service and are not sent back down to the client. | . | `ConfiguredToSendJRTimestamps | MIDI 2.0 | Note that JR timestamps are handled entirely in the service and are not sent back down to the client. | . | DeviceIdentitySystemExclusiveId | MIDI 2.0 | Device Identity information | . | DeviceIdentityDeviceFamilyLsb | MIDI 2.0 | Device Identity information | . | DeviceIdentityDeviceFamilyMsb | MIDI 2.0 | Device Identity information | . | DeviceIdentityDeviceFamilyModelNumberLsb | MIDI 2.0 | Device Identity information | . | DeviceIdentityDeviceFamilyModelNumberMsb | MIDI 2.0 | Device Identity information | . | DeviceIdentitySoftwareRevisionLevel | MIDI 2.0 | Device Identity information | . | TransportId | Windows | The Id of the transport abstraction that manages this endpoint | . | TransportMnemonic | Windows | A short abbreviation for the transport. This can be used as a transport identifier. | . | TransportSuppliedSerialNumber | Windows | iSerialNumber, when available in USB, and other ids from other transports. | . | ManufacturerName | Windows | The name of the manufacturer of the device, if available | . | SupportsMultiClient | Windows | True if this endpoint supports multi-client use | . | NativeDataFormat | Windows | Because the driver and service handle data format translation, it’s not immediately obvious if the device is natively UMP or natively Byte Stream. This property provides that information | . | GroupTerminalBlocks | Windows | A collection of Group Terminal Blocks. These are used only in USB. For MIDI 2.0 devices, Function Blocks are preferred. | . | HasStaticFunctionBlocks | MIDI 2.0 | True if the function blocks are static. That is, the groups never change. | . | FunctionBlockCount | MIDI 2.0 | The number of function blocks the endpoint has declared. Function blocks always start at index zero and go to FunctionBlockCount-1 | . | EndpointPurpose | Windows | The purpose of the endpoint. This is used primarily for filtering. | . | Description | Configuration | An endpoint description which is typically provided by the user | . | LargeImagePath | Configuration | The path to a png or jpg image that represents this endpoint. Typically user-supplied. | . | SmallImagePath | Configuration | The path to a png or jpg image that represents this endpoint. Typically user-supplied. | . | RequiresNoteOffTranslation | Configuration | True if the endpoint requires internal translation of Note On with zero velocity (in the case of MIDI 1.0) to a Note Off message. Typically user-supplied. | . | RecommendedCCAutomationIntervalMS | Configuration | Number of milliseconds between automation value changes. This is usually only for old and slow MIDI 1.0 devices that are prone to data flooding. User-supplied. | . | Properties | Windows | A collection of all the raw properties. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#properties"
- },"24": {
+ },"29": {
"doc": "MidiEndpointDeviceInformation",
"title": "Static Properties",
"content": "| Static Property | Description | . | DiagnosticsLoopbackAEndpointId | Endpoint Id for the diagnostic loopback used for development and support purposes. | . | DiagnosticsLoopbackBEndpointId | Endpoint Id for the diagnostic loopback used for development and support purposes. | . | EndpointInterfaceClass | The class GUID which appears at the end of the Endpoint Ids | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#static-properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#static-properties"
- },"25": {
+ },"30": {
"doc": "MidiEndpointDeviceInformation",
"title": "Functions",
"content": "| Function | Description | . | GetParentDeviceInformation() | Finds and then retrieves the parent DeviceInformation type with appropriate properties. | . | GetContainerInformation() | Gets the device container information and returns its DeviceInformation with appropriate properties | . | UpdateFromDeviceInformation(deviceInformation) | For use by any watcher which must update this object | . | UpdateFromDeviceInformationUpdate(deviceInformationUpdate) | For use by any watcher which must update this object | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#functions"
- },"26": {
+ },"31": {
"doc": "MidiEndpointDeviceInformation",
"title": "Static Functions",
"content": "| Static Function | Description | . | CreateFromId(id) | Creates a new MidiEndpointDeviceInformation object from the specified id | . | FindAll() | Searches for all endpoint devices and returns a list in the default sort order | . | FindAll(sortOrder) | Searches for all endpoint devices and returns a list in the specified sort order | . | FindAll(sortOrder, endpointFilter) | Searches for all endpoint devices which match the filter, and returns a list in the specified sort order. | . | DeviceMatchesFilter(deviceInformation, endpointFilter) | A helper function to compare a device against the filter. | . | GetAdditionalPropertiesList() | This returns the list of properties which must be requested during enumeration. Typically not needed for applications, as the watcher calls this function | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#static-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#static-functions"
- },"27": {
+ },"32": {
"doc": "MidiEndpointDeviceInformation",
"title": "IDL",
"content": "MidiEndpointDeviceInformation IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#idl"
- },"28": {
+ },"33": {
"doc": "MidiEndpointDeviceInformation",
"title": "Sample",
"content": "What follows is an excerpt of the larger C++/WinRT enumeration sample. #include \"pch.h\" #include <iostream> using namespace winrt::Windows::Devices::Midi2; // API int main() { winrt::init_apartment(); bool includeDiagnosticsEndpoints = true; // enumerate all endpoints. A normal application should enumerate only // IncludeClientByteStreamNative | IncludeClientUmpNative auto endpoints = MidiEndpointDeviceInformation::FindAll( MidiEndpointDeviceInformationSortOrder::Name, MidiEndpointDeviceInformationFilter::IncludeClientByteStreamNative | MidiEndpointDeviceInformationFilter::IncludeClientUmpNative | MidiEndpointDeviceInformationFilter::IncludeDiagnosticLoopback | MidiEndpointDeviceInformationFilter::IncludeVirtualDeviceResponder ); std::cout << endpoints.Size() << \" endpoints returned\" << std::endl << std::endl; for (auto const& endpoint : endpoints) { std::cout << \"Identification\" << std::endl; std::cout << \"- Name: \" << winrt::to_string(endpoint.Name()) << std::endl; std::cout << \"- Id: \" << winrt::to_string(endpoint.Id()) << std::endl; std::cout << std::endl << \"Endpoint Metadata\" << std::endl; std::cout << \"- Product Instance Id: \" << winrt::to_string(endpoint.ProductInstanceId()) << std::endl; std::cout << \"- Endpoint-supplied Name: \" << winrt::to_string(endpoint.EndpointSuppliedName()) << std::endl; std::cout << std::endl << \"User-supplied Metadata\" << std::endl; std::cout << \"- User-supplied Name: \" << winrt::to_string(endpoint.UserSuppliedName()) << std::endl; std::cout << \"- Description: \" << winrt::to_string(endpoint.Description()) << std::endl; std::cout << \"- Small Image Path: \" << winrt::to_string(endpoint.SmallImagePath()) << std::endl; std::cout << \"- Large Image Path: \" << winrt::to_string(endpoint.LargeImagePath()) << std::endl; // ... } } . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#sample",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformation.html#sample"
- },"29": {
+ },"34": {
"doc": "MidiEndpointDeviceInformationUpdateEventArgs",
"title": "MidiEndpointDeviceInformationUpdateEventArgs",
"content": "Represents a notification that endpoint properties have been updated . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformationUpdateEventArgs.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformationUpdateEventArgs.html"
- },"30": {
+ },"35": {
"doc": "MidiEndpointDeviceInformationUpdateEventArgs",
"title": "Functions",
- "content": "| Property | Description | ————— | ———– | Id | Id of the endpoint which has been updated | UpdatedName | True if the name properties have been updated | UpdatedEndpointInformation | True if the in-protocol endpoint information has been updated | UpdatedDeviceIdentity | True if the in-protocol device identity information has been updated | UpdatedStreamConfiguration | True if protocol negotiation changed configuration of the endpoint | UpdatedFunctionBlocks | True if any function blocks have been updated | UpdatedUserMetadata | True if any user-supplied metadata fields have been updated | UpdatedAdditionalCapabilities | True if the additional capabilities have been updated | DeviceInformationUpdate | The source Windows.Devices.Enumeration.DeviceInformationUpdate` object. | . If none of the UpdatedXX properties are true, then other properties have been updated. ",
+ "content": "| Property | Description | . | Id | Id of the endpoint which has been updated | . | UpdatedName | True if the name properties have been updated | . | UpdatedEndpointInformation | True if the in-protocol endpoint information has been updated | . | UpdatedDeviceIdentity | True if the in-protocol device identity information has been updated | . | UpdatedStreamConfiguration | True if protocol negotiation changed configuration of the endpoint | . | UpdatedFunctionBlocks | True if any function blocks have been updated | . | UpdatedUserMetadata | True if any user-supplied metadata fields have been updated | . | UpdatedAdditionalCapabilities | True if the additional capabilities have been updated | . | DeviceInformationUpdate | The source Windows.Devices.Enumeration.DeviceInformationUpdate object. | . If none of the UpdatedXX properties are true, then other properties have been updated. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformationUpdateEventArgs.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformationUpdateEventArgs.html#functions"
- },"31": {
+ },"36": {
"doc": "MidiEndpointDeviceInformationUpdateEventArgs",
"title": "IDL",
"content": "MidiEndpointDeviceInformationUpdateEventArgs IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformationUpdateEventArgs.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceInformationUpdateEventArgs.html#idl"
- },"32": {
+ },"37": {
"doc": "MidiEndpointDeviceWatcher",
"title": "MidiEndpointDeviceWatcher",
"content": "WinRT provides a Windows.Devices.Enumeration namespace with a DeviceWatcher class. That class is generic to any type of device, and so requires additional work to use with MIDI devices. Because of that, we’ve wrapped that functionality in the MidiEndpointDeviceWatcher class and the related MidiEndpointDeviceInformation class. This is the class applications should use when they want to find devices, and also be notified when devices are added or removed, or when properties like function blocks or device names change. Create a MidiEndpointDeviceWatcher on a background thread, and use the internal list of Endpoints as your source of record for device properties. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceWatcher.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceWatcher.html"
- },"33": {
+ },"38": {
"doc": "MidiEndpointDeviceWatcher",
"title": "Properties",
"content": "| Function | Description | . | Status | The current status. See the Windows.Devices.Enumeration.DeviceWatcherStatus enumeration | . | EnumeratedEndpointDevices | The list of enumerated devices. Provided here for convenience so applications do not need to keep their own list of MIDI devices. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceWatcher.html#properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceWatcher.html#properties"
- },"34": {
+ },"39": {
"doc": "MidiEndpointDeviceWatcher",
"title": "Functions",
"content": "| Function | Description | . | Start() | Begin device enumeration. Wire up event handlers before calling this function. | . | Stop() | Stop device enumeration. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceWatcher.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceWatcher.html#functions"
- },"35": {
+ },"40": {
"doc": "MidiEndpointDeviceWatcher",
"title": "Static Functions",
"content": "| Static Function | Description | . | CreateWatcher(endpointFilter) | Create a watcher which will enumerate devices based on the provided filter | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceWatcher.html#static-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceWatcher.html#static-functions"
- },"36": {
+ },"41": {
"doc": "MidiEndpointDeviceWatcher",
"title": "Events",
"content": "| Event | Description | . | Added(source, deviceInformation) | A new endpoint has been added. | . | Removed(source, deviceInformationUpdate) | An endpoint has been removed. | . | Updated(source endpointDeviceInformationUpdate) | Properties of an endpoint have been updated. This is much more common than it was with the older MIDI 1.0 APIs due to both in-protocol endpoint information, and user configuration. | . | EnumerationCompleted(source) | Raised when the initial device enumeration has been completed. Devices may still be added or removed after this event, but use this to decide when you have enough information to display an initial list. | . | Stopped(source) | Enumeration has been stopped. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceWatcher.html#events",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceWatcher.html#events"
- },"37": {
+ },"42": {
"doc": "MidiEndpointDeviceWatcher",
"title": "IDL",
"content": "MidiEndpointDeviceWatcher IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceWatcher.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/MidiEndpointDeviceWatcher.html#idl"
- },"38": {
+ },"43": {
"doc": "MidiFunctionBlock",
"title": "MidiFunctionBlock",
"content": "The original MIDI 2.0 USB specification includes the concept of a Group Terminal Block. After ratification of that specification, it was found that Group Terminal Blocks were insufficient for two main reasons: . | Group Terminal Blocks are USB-specific, and so are not available on other transports like Network or Virtual. | Group Terminal Blocks are static, defined in USB descriptors, and so cannot change during runtime. | . Group Terminal Blocks are still available, but function blocks are the preferred approach for defining capapbilities of a device. When both are available, you should use the function block information. A function block represents a function of a MIDI 2.0 device. A function block may span one or more groups, and if not a static function block, those group numbers may change during operation. For example, a Tone Generator function of a device may need 64 channels to represent its multi-timbral nature. One way it can accomplish this is to declare a function block which spans 4 groups, each of which has 16 channels of data (16x4 = 64). Function blocks also represent the valid groups for communication with an endpoint. If an endpoint declares 4 function blocks, which together cover only group indexes 0-5, and all of those blocks are marked active, only those groups should be available to users of an application. This helps cut down on clutter caused by always displaying 16 groups. Function blocks have names which should be displayed to the user along with the group numbers. In the end, the actual addressible entity is the endpoint stream with the group number in the Universal MIDI Packet. But the function block provides context for that group number. Per the specification, function blocks can span more than one group, and can overlap with each other so that different functions can be available on the same group. Function blocks are used in the Windwos MIDI Services API in three ways: . | A property of a MidiEndpointDeviceInformation object, representing function blocks discovered through endpoint discovery. These function blocks are read-only. | The return value of the AsEquivalentFunctionBlock method of the GroupTerminalBlock class. This is a convenience function. These function blocks are read-only | Provided by the application as part of the device definition for a virtual device in app-to-app MIDI. These function blocks are editable before adding them to the device definition. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/metadata/MidiFunctionBlock.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/metadata/MidiFunctionBlock.html"
- },"39": {
+ },"44": {
"doc": "MidiFunctionBlock",
"title": "Properties",
"content": "Most properties are 1:1 with the MIDI 2.0 UMP specification section on function blocks. We assemble the name for you and map values to enumerations when possible. | Property | Description | . | IsReadOnly | True if this function block should be treated as read-only. If you attempt to assign a value to a property in a read-only function block, the assignment will silently fail. | . | Number | The index of the block 0-31. We use “number” here to be consistent with the specification | . | Name | The assembled name of the function block | . | IsActive | True if this block is active | . | Direction | The direction of the block from the block’s point of view. | . | UIHint | A hint which tells you how this block should be treated in a user interface. This should be considered a “soft filter” for display, not a mechanism to keep blocks completely hidden from a user. | . | Midi10Connection | How to treat this block if it is a MIDI 1.0 connection | . | FirstGroupIndex | Zero-based index of the first group spanned by this block. | . | GroupCount | The number of groups spanned. | . | MidiCIMessageVersionFormat | MIDI CI version format value | . | MaxSystemExclusive8Streams | The maximum number of System Exclusive 8 streams allowed. Please refer to the UMP specification for how to treat this value. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/metadata/MidiFunctionBlock.html#properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/metadata/MidiFunctionBlock.html#properties"
- },"40": {
+ },"45": {
"doc": "MidiFunctionBlock",
"title": "Functions",
"content": "| Function | Description | . | MidiFunctionBlock() | Construct an empty function block | . | IncludesGroup(group) | Helper function which returns true if this function exists on the supplied group | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/metadata/MidiFunctionBlock.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/metadata/MidiFunctionBlock.html#functions"
- },"41": {
+ },"46": {
"doc": "MidiFunctionBlock",
"title": "IDL",
"content": "MidiFunctionBlock IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/metadata/MidiFunctionBlock.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/metadata/MidiFunctionBlock.html#idl"
- },"42": {
+ },"47": {
"doc": "MidiGroup",
"title": "MidiGroup",
"content": "The MidiGroup class is used to provide formatting and data validation for UMP (Universal MIDI Packet) groups. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiGroup.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiGroup.html"
- },"43": {
+ },"48": {
"doc": "MidiGroup",
"title": "Properties",
"content": "| Property | Description | . | Index | The data value, or group Index (0-15) | . | NumberForDisplay | The number that should be displayed in any UI. (1-16) | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiGroup.html#properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiGroup.html#properties"
- },"44": {
+ },"49": {
"doc": "MidiGroup",
"title": "Static Properties",
"content": "| Static Property | Description | . | LabelShort | Returns the localized abbreviation. For example, “Gr” in English. | . | LabelFull | Returns the localized full name. For example, “Group” in English. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiGroup.html#static-properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiGroup.html#static-properties"
- },"45": {
+ },"50": {
"doc": "MidiGroup",
"title": "Functions",
"content": "| Function | Description | . | MidiGroup() | Constructs an empty MidiGroup | . | MidiGroup(index) | Constructs a MidiGroup with the specified index | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiGroup.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiGroup.html#functions"
- },"46": {
+ },"51": {
"doc": "MidiGroup",
"title": "Static Functions",
"content": "| Static Function | Description | . | IsValidGroupIndex(index) | Verifies that the provided index is valid (between 0 and 15) | . MidiGroup IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiGroup.html#static-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiGroup.html#static-functions"
- },"47": {
+ },"52": {
"doc": "MidiGroupEndpointListener",
"title": "MidiGroupEndpointListener",
- "content": "(In progress) . ",
+ "content": "This class acts as a filter. Incoming messages with the specified group will be provided through the MessageReceived event. Other messages will be ignored. For a MIDI 1.0 device, where the ports (virtual MIDI cables) have been mapped to UMP groups, this class can provide the equivalent of a MIDI 1.0 port to an application, ignoring all other inputs and operating only on the included groups. In addition to the properties and methods in IMidiEndpointMessageProcessingPlugin, and the MessageReceived event from IMidiMessageReceivedEventSource the class provides the following: . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiGroupEndpointListener.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiGroupEndpointListener.html"
- },"48": {
+ },"53": {
+ "doc": "MidiGroupEndpointListener",
+ "title": "Properties",
+ "content": "| Property | Description | . | IncludeGroups | The list of MidiGroup numbers that this listener will listen to. | . | PreventCallingFurtherListeners | True if this plugin should prevent further listeners from processing a message that is in-scope for this processor. | . | PreventFiringMainMessageReceivedEvent | True if this plugin should prevent the endpoint’s MessageReceived event from firing if the message was in-scope for this plugin. | . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiGroupEndpointListener.html#properties",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiGroupEndpointListener.html#properties"
+ },"54": {
+ "doc": "MidiGroupEndpointListener",
+ "title": "Functions",
+ "content": "| Property | Description | . | MidiGroupEndpointListener() | Construct a new instance of this type | . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiGroupEndpointListener.html#functions",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiGroupEndpointListener.html#functions"
+ },"55": {
"doc": "MidiGroupEndpointListener",
"title": "IDL",
"content": "MidiGroupEndpointListener IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiGroupEndpointListener.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiGroupEndpointListener.html#idl"
- },"49": {
+ },"56": {
"doc": "MidiGroupTerminalBlock",
"title": "MidiGroupTerminalBlock",
"content": "A Group Terminal Block is a USB-only feature used to describe the groups on a device. When available, Function Blocks are the preferred mechanism for finding active groups, names, and more, meaning that the Group Terminal Block can typically be ignored in those cases. For more context, please see the documentation for the MidiFunctionBlock type. Note: In Windows MIDI Services, we translate MIDI 1.0 device “ports” into individual Group Terminal Blocks. Each virtual cable number in the stream, which used to become a separate input or output port, now maps to a group number. For example, a 5 port MIDI 1.0 device will now show up as a single endpoint with 5 Group Terminal Blocks each spanning a single group. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/metadata/MidiGroupTerminalBlock.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/metadata/MidiGroupTerminalBlock.html"
- },"50": {
+ },"57": {
"doc": "MidiGroupTerminalBlock",
"title": "Properties",
"content": "| Property | Description | . | Number | Block number | . | Name | Name provided by USB. In the case of MIDI 1.0 devices, when available, this is the iJack string | . | Direction | Direction of the block, from the block’s point of view | . | Protocol | Information about the protocol in use. Note that the Jitter Reduction values here should be ignored. Jitter reduction timestamp handling is negotiated through protocol negotiation, and is entirely handled by the service | . | FirstGroupIndex | The index of the first group spanned by this block | . | GroupCount | The number of groups spanned | . | MaxDeviceInputBandwidthIn4KBitsPerSecondUnits | Please see the USB MIDI 2.0 specification for the actual value for this field. | . | MaxDeviceOutputBandwidthIn4KBitsPerSecondUnits | Please see the USB MIDI 2.0 specification for the actual value for this field. | . | CalculatedMaxDeviceInputBandwidthBitsPerSecond | Bits-per-second calculated value for the MaxDeviceInputBandwidthIn4KBitsPerSecondUnits property | . | CalculatedMaxDeviceOutputBandwidthBitsPerSecond | Bits-per-second calculated value for the MaxDeviceOutputBandwidthIn4KBitsPerSecondUnits property | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/metadata/MidiGroupTerminalBlock.html#properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/metadata/MidiGroupTerminalBlock.html#properties"
- },"51": {
+ },"58": {
"doc": "MidiGroupTerminalBlock",
"title": "Functions",
"content": "| Function | Description | . | IncludesGroup(group) | Helper function which returns true if this function exists on the supplied group | . | AsEquivalentFunctionBlock() | Helper function which returns a MidiFunctionBlock that is approximately equivalent to this MidiGroupTerminalBlock. This is to enable applications to be able to deal with only a single type of block when showing the metadata | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/metadata/MidiGroupTerminalBlock.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/metadata/MidiGroupTerminalBlock.html#functions"
- },"52": {
+ },"59": {
"doc": "MidiGroupTerminalBlock",
"title": "IDL",
"content": "MidiGroupTerminalBlock IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/metadata/MidiGroupTerminalBlock.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/metadata/MidiGroupTerminalBlock.html#idl"
- },"53": {
+ },"60": {
"doc": "MidiMessage128",
"title": "MidiMessage128",
- "content": "MidiMessage128 is used for some data messages as well as important “Type F” stream metadata messages. Includes all functions and properties in IMidiUniversalPacket, as well as: . | Property | Description | . | Word0 | First 32-bit MIDI word | . | Word1 | Second 32-bit MIDI word | . | Word2 | Third 32-bit MIDI word | . | Word3 | Fourth 32-bit MIDI word | . | Function | Description | . | MidiMessage128() | Default constructor | . | MidiMessage128(timestamp, word0, word1, word2, word3) | Construct a new message with a timestamp and all 32 bit MIDI words | . MidiMessage128 IDL . ",
+ "content": "MidiMessage128 is used for some data messages as well as important “Type F” stream metadata messages. Includes all functions and properties in IMidiUniversalPacket, as well as: . | Property | Description | . | Word0 | First 32-bit MIDI word | . | Word1 | Second 32-bit MIDI word | . | Word2 | Third 32-bit MIDI word | . | Word3 | Fourth 32-bit MIDI word | . | Function | Description | . | MidiMessage128() | Default constructor | . | MidiMessage128(timestamp, word0, word1, word2, word3) | Construct a new message with a timestamp and all 32 bit MIDI words | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessage128.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessage128.html"
- },"54": {
+ },"61": {
+ "doc": "MidiMessage128",
+ "title": "IDL",
+ "content": "MidiMessage128 IDL . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessage128.html#idl",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessage128.html#idl"
+ },"62": {
"doc": "MidiMessage32",
"title": "MidiMessage32",
- "content": "MidiMessage32 is used for short messages such as utility messages and MIDI 1.0 messages in UMP format. Includes all functions and properties in IMidiUniversalPacket, as well as: . | Property | Description | . | Word0 | First 32-bit MIDI word | . | Function | Description | . | MidiMessage32() | Default constructor | . | MidiMessage32(timestamp, word0) | Construct a new message with a timestamp and 32 bit MIDI word | . MidiMessage32 IDL . ",
+ "content": "MidiMessage32 is used for short messages such as utility messages and MIDI 1.0 messages in UMP format. Includes all functions and properties in IMidiUniversalPacket, as well as: . | Property | Description | . | Word0 | First 32-bit MIDI word | . | Function | Description | . | MidiMessage32() | Default constructor | . | MidiMessage32(timestamp, word0) | Construct a new message with a timestamp and 32 bit MIDI word | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessage32.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessage32.html"
- },"55": {
+ },"63": {
+ "doc": "MidiMessage32",
+ "title": "IDL",
+ "content": "MidiMessage32 IDL . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessage32.html#idl",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessage32.html#idl"
+ },"64": {
"doc": "MidiMessage64",
"title": "MidiMessage64",
- "content": "MidiMessage64 is used for some data messages and for MIDI 2.0 Channel Voice messages. Includes all functions and properties in IMidiUniversalPacket, as well as: . | Property | Description | . | Word0 | First 32-bit MIDI word | . | Word1 | Second 32-bit MIDI word | . | Function | Description | . | MidiMessage64() | Default constructor | . | MidiMessage64(timestamp, word0, word1) | Construct a new message with a timestamp and all 32 bit MIDI words | . MidiMessage64 IDL . ",
+ "content": "MidiMessage64 is used for some data messages and for MIDI 2.0 Channel Voice messages. Includes all functions and properties in IMidiUniversalPacket, as well as: . | Property | Description | . | Word0 | First 32-bit MIDI word | . | Word1 | Second 32-bit MIDI word | . | Function | Description | . | MidiMessage64() | Default constructor | . | MidiMessage64(timestamp, word0, word1) | Construct a new message with a timestamp and all 32 bit MIDI words | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessage64.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessage64.html"
- },"56": {
+ },"65": {
+ "doc": "MidiMessage64",
+ "title": "IDL",
+ "content": "MidiMessage64 IDL . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessage64.html#idl",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessage64.html#idl"
+ },"66": {
"doc": "MidiMessage96",
"title": "MidiMessage96",
- "content": "MidiMessage96 is currently unused in the MIDI 2.0 UMP specification. Includes all functions and properties in IMidiUniversalPacket, as well as: . | Property | Description | . | Word0 | First 32-bit MIDI word | . | Word1 | Second 32-bit MIDI word | . | Word2 | Third 32-bit MIDI word | . | Function | Description | . | MidiMessage96() | Default constructor | . | MidiMessage96(timestamp, word0, word1, word2) | Construct a new message with a timestamp and all 32 bit MIDI words | . MidiMessage96 IDL . ",
+ "content": "MidiMessage96 is currently unused in the MIDI 2.0 UMP specification. Includes all functions and properties in IMidiUniversalPacket, as well as: . | Property | Description | . | Word0 | First 32-bit MIDI word | . | Word1 | Second 32-bit MIDI word | . | Word2 | Third 32-bit MIDI word | . | Function | Description | . | MidiMessage96() | Default constructor | . | MidiMessage96(timestamp, word0, word1, word2) | Construct a new message with a timestamp and all 32 bit MIDI words | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessage96.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessage96.html"
- },"57": {
+ },"67": {
+ "doc": "MidiMessage96",
+ "title": "IDL",
+ "content": "MidiMessage96 IDL . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessage96.html#idl",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessage96.html#idl"
+ },"68": {
"doc": "MidiMessageBuilder",
"title": "MidiMessageBuilder",
"content": "(In progress) . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageBuilder.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageBuilder.html"
- },"58": {
+ },"69": {
"doc": "MidiMessageBuilder",
"title": "Functions",
"content": "| Function | Description | . | | | . | | | . | | | . | | | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageBuilder.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageBuilder.html#functions"
- },"59": {
+ },"70": {
"doc": "MidiMessageBuilder",
"title": "IDL",
"content": "MidiMessageBuilder IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageBuilder.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageBuilder.html#idl"
- },"60": {
+ },"71": {
"doc": "MidiMessageConverter",
"title": "MidiMessageConverter",
"content": "(In progress) . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageConverter.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageConverter.html"
- },"61": {
+ },"72": {
"doc": "MidiMessageConverter",
"title": "Functions",
"content": "| Function | Description | . | | | . | | | . | | | . | | | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageConverter.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageConverter.html#functions"
- },"62": {
+ },"73": {
"doc": "MidiMessageConverter",
"title": "IDL",
"content": "MidiMessageConverter IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageConverter.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageConverter.html#idl"
- },"63": {
+ },"74": {
"doc": "MidiMessageReceivedEventArgs",
"title": "MidiMessageReceivedEventArgs",
"content": "This is the main class to use when receving MIDI data from a message source such as a connection or a message processing plugin. Note: Do not keep a copy of the MidiMessageReceivedEventArgs class, as the data it points to is guaranteed to exist for only the duration of the event handler call for which this instance was an argument. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/connections/MidiMessageReceivedEventArgs.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/connections/MidiMessageReceivedEventArgs.html"
- },"64": {
+ },"75": {
"doc": "MidiMessageReceivedEventArgs",
"title": "Properties",
"content": "| Property | Description | . | Timestamp | The 64-bit MIDI Clock timestamp set by the service when this message was received | . | PacketType | Type of Universal MIDI Packet. This value can be cast to get the number of valid words in the data. You can use this value to determine which of the FillMessageXX methods would be appropriate to call. For example, if the value is MidiPacketType.UniversalMidiPacket64 you would call FillMessage64 | . | MessageType | The type of Universal MIDI Packet Message. This comes from the first 4 bits of the data. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/connections/MidiMessageReceivedEventArgs.html#properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/connections/MidiMessageReceivedEventArgs.html#properties"
- },"65": {
+ },"76": {
"doc": "MidiMessageReceivedEventArgs",
"title": "Functions",
"content": "| Function | Description | . | PeekFirstWord() | Returns the first word of the message data without removing it. | . | GetMessagePacket() | Returns an IMidiUniversalPacket runtime class representing the data. This requires an allocation. | . | FillWords(word0, word1, word2, word3) | Puts the data in the supplied words and returns the number of valid words to read. If the return value is 2, for example, then only word0 and word1 contain valid data. | . | FillMessageStruct(message) | Fills the provided lightweight structure with the message data. Returns the number of valid words in the updated struct. | . | FillMessage32(message) | Adds the data to the provided MidiMessage32 runtimeclass. The reference behavior is projection-dependent. Returns true if the provided type matches the expected packet type and the data has been written. | . | FillMessage64(message) | Adds the data to the provided MidiMessage64 runtimeclass. The reference behavior is projection-dependent. Returns true if the provided type matches the expected packet type and the data has been written. | . | FillMessage96(message) | Adds the data to the provided MidiMessage96 runtimeclass. The reference behavior is projection-dependent. Returns true if the provided type matches the expected packet type and the data has been written. | . | FillMessage128(message) | Adds the data to the provided MidiMessage128 runtimeclass. The reference behavior is projection-dependent. Returns true if the provided type matches the expected packet type and the data has been written. | . | FillWordArray(words, startIndex) | Writes the data starting at the zero-based startIndex. Some projections pass a copy of all the data, so this may not always be an efficient approach. Returns the number of words written. | . | FillByteArray(bytes, startIndex) | Writes the data starting at the zero-based startIndex. Some projections pass a copy of all the data, so this may not always be an efficient approach. Returns the number of bytes written. | . | FillBuffer(buffer, byteOffset) | Writes the data to the buffer starting at byteOffset. Returns the number of bytes written. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/connections/MidiMessageReceivedEventArgs.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/connections/MidiMessageReceivedEventArgs.html#functions"
- },"66": {
+ },"77": {
"doc": "MidiMessageReceivedEventArgs",
"title": "IDL",
"content": "MidiMessageReceivedEventArgs IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/connections/MidiMessageReceivedEventArgs.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/connections/MidiMessageReceivedEventArgs.html#idl"
- },"67": {
+ },"78": {
"doc": "MidiMessageStruct",
"title": "MidiMessageStruct",
- "content": "MidiMessageStruct is provided for cases where the API consumer wants to have a fixed value type they can use to send and receive messages. In the case of receiving messages, a function which fills the struct will typically return a count of valid words. The MidiMessageStruct struct type is simpler than the other runtime class types and may therefore perform better in some projections and for some uses. Note that this type does not include the timestamp field. | Field | Description | . | Word0 | First 32-bit MIDI word | . | Word1 | Second 32-bit MIDI word | . | Word2 | Third 32-bit MIDI word | . | Word3 | Fourth 32-bit MIDI word | . MidiMessageStruct IDL . ",
+ "content": "MidiMessageStruct is provided for cases where the API consumer wants to have a fixed value type they can use to send and receive messages. In the case of receiving messages, a function which fills the struct will typically return a count of valid words. The MidiMessageStruct struct type is simpler than the other runtime class types and may therefore perform better in some projections and for some uses. Note that this type does not include the timestamp field. | Field | Description | . | Word0 | First 32-bit MIDI word | . | Word1 | Second 32-bit MIDI word | . | Word2 | Third 32-bit MIDI word | . | Word3 | Fourth 32-bit MIDI word | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessageStruct.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessageStruct.html"
- },"68": {
+ },"79": {
+ "doc": "MidiMessageStruct",
+ "title": "IDL",
+ "content": "MidiMessageStruct IDL . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessageStruct.html#idl",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessageStruct.html#idl"
+ },"80": {
"doc": "MidiMessageTranslator",
"title": "MidiMessageTranslator",
"content": "(In progress) . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageTranslator.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageTranslator.html"
- },"69": {
+ },"81": {
"doc": "MidiMessageTranslator",
"title": "Functions",
"content": "| Function | Description | . | | | . | | | . | | | . | | | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageTranslator.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageTranslator.html#functions"
- },"70": {
+ },"82": {
"doc": "MidiMessageTranslator",
"title": "IDL",
"content": "MidiMessageTranslator IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageTranslator.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageTranslator.html#idl"
- },"71": {
+ },"83": {
"doc": "MidiMessageTypeEndpointListener",
"title": "MidiMessageTypeEndpointListener",
- "content": "(In progress) . ",
+ "content": "This class acts as a filter. Incoming messages with the specified message type will be provided through the MessageReceived event. Other messages will be ignored. In this way, the listener can be set up to, for example, only pay attention to MIDI 2.0 Channel Voice messages, leaving stream messages and System Exclusive by the wayside. In addition to the properties and methods in IMidiEndpointMessageProcessingPlugin, and the MessageReceived event from IMidiMessageReceivedEventSource the class provides the following: . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiMessageTypeEndpointListener.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiMessageTypeEndpointListener.html"
- },"72": {
+ },"84": {
+ "doc": "MidiMessageTypeEndpointListener",
+ "title": "Properties",
+ "content": "| Property | Description | . | IncludeMessageTypes | The list of MidiMessageType values that this listener will listen to. | . | PreventCallingFurtherListeners | True if this plugin should prevent further listeners from processing a message that is in-scope for this processor. | . | PreventFiringMainMessageReceivedEvent | True if this plugin should prevent the endpoint’s MessageReceived event from firing if the message was in-scope for this plugin. | . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiMessageTypeEndpointListener.html#properties",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiMessageTypeEndpointListener.html#properties"
+ },"85": {
+ "doc": "MidiMessageTypeEndpointListener",
+ "title": "Functions",
+ "content": "| Property | Description | . | MidiGroupEndpointListener() | Construct a new instance of this type | . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiMessageTypeEndpointListener.html#functions",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiMessageTypeEndpointListener.html#functions"
+ },"86": {
"doc": "MidiMessageTypeEndpointListener",
"title": "IDL",
"content": "MidiMessageTypeEndpointListener IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiMessageTypeEndpointListener.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiMessageTypeEndpointListener.html#idl"
- },"73": {
+ },"87": {
"doc": "MidiMessageType",
"title": "MidiMessageType Enumeration",
- "content": "The values correspond directly to the “mt” field in the MIDI UMP packet and may be cast as such if trimmed to 4 bits and shifted into place. | Property | Value | Description | . | UtilityMessage32 | 0x0 | 32-bit utility message | . | SystemCommon32 | 0x1 | 32-bit system common message | . | Midi1ChannelVoice32 | 0x2 | 32-bit MIDI 1.0 channel voice message | . | DataMessage64 | 0x3 | 64-bit data message (including MIDI 1.0 System Exclusive) | . | Midi2ChannelVoice64 | 0x4 | 64-bit MIDI 2.0 channel voice message | . | DataMessage128 | 0x5 | 128-bit Data Message | . | FutureReserved632 | 0x6 | Reserved for future use by the MIDI standards bodies | . | FutureReserved732 | 0x7 | Reserved for future use by the MIDI standards bodies | . | FutureReserved864 | 0x8 | Reserved for future use by the MIDI standards bodies | . | FutureReserved964 | 0x9 | Reserved for future use by the MIDI standards bodies | . | FutureReservedA64 | 0xA | Reserved for future use by the MIDI standards bodies | . | FutureReservedB96 | 0xB | Reserved for future use by the MIDI standards bodies | . | FutureReservedC96 | 0xC | Reserved for future use by the MIDI standards bodies | . | FlexData128 | 0xD | 128-bit Flex Data message including song file data messages | . | FutureReservedE128 | 0xE | Reserved for future use by the MIDI standards bodies | . | Stream128 | 0xF | 128-bit stream message, including endpoint discovery and function block messages | . MidiMessageType IDL . ",
+ "content": "The values correspond directly to the “mt” field in the MIDI UMP packet and may be cast as such if trimmed to 4 bits and shifted into place. | Property | Value | Description | . | UtilityMessage32 | 0x0 | 32-bit utility message | . | SystemCommon32 | 0x1 | 32-bit system common message | . | Midi1ChannelVoice32 | 0x2 | 32-bit MIDI 1.0 channel voice message | . | DataMessage64 | 0x3 | 64-bit data message (including MIDI 1.0 System Exclusive) | . | Midi2ChannelVoice64 | 0x4 | 64-bit MIDI 2.0 channel voice message | . | DataMessage128 | 0x5 | 128-bit Data Message | . | FutureReserved632 | 0x6 | Reserved for future use by the MIDI standards bodies | . | FutureReserved732 | 0x7 | Reserved for future use by the MIDI standards bodies | . | FutureReserved864 | 0x8 | Reserved for future use by the MIDI standards bodies | . | FutureReserved964 | 0x9 | Reserved for future use by the MIDI standards bodies | . | FutureReservedA64 | 0xA | Reserved for future use by the MIDI standards bodies | . | FutureReservedB96 | 0xB | Reserved for future use by the MIDI standards bodies | . | FutureReservedC96 | 0xC | Reserved for future use by the MIDI standards bodies | . | FlexData128 | 0xD | 128-bit Flex Data message including song file data messages | . | FutureReservedE128 | 0xE | Reserved for future use by the MIDI standards bodies | . | Stream128 | 0xF | 128-bit stream message, including endpoint discovery and function block messages | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessageTypeEnum.html#midimessagetype-enumeration",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessageTypeEnum.html#midimessagetype-enumeration"
- },"74": {
+ },"88": {
+ "doc": "MidiMessageType",
+ "title": "IDL",
+ "content": "MidiMessageType IDL . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessageTypeEnum.html#idl",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessageTypeEnum.html#idl"
+ },"89": {
"doc": "MidiMessageType",
"title": "MidiMessageType",
"content": " ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiMessageTypeEnum.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiMessageTypeEnum.html"
- },"75": {
+ },"90": {
"doc": "MidiMessageUtility",
"title": "MidiMessageUtility",
"content": "This class contains a number of static helper functions for reading information from Universal MIDI Packets, and also manipulating that information. In most cases, the calling application needs to do some validation before calling functions which return specific fields. If, for example, the application asks for the Flex Data Status, but doesn’t provide a valid Flex Data message, the function will happily return whatever other data is in the position of that field. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html"
- },"76": {
+ },"91": {
"doc": "MidiMessageUtility",
"title": "Validation Functions",
"content": "| Function | Description | . | ValidateMessage32MessageType(word0) | Validate that the message type field in the word is for a 32-bit UMP | . | ValidateMessage64MessageType(word0) | Validate that the message type field in the word is for a 64-bit UMP | . | ValidateMessage96MessageType(word0) | Validate that the message type field in the word is for a 96-bit UMP | . | ValidateMessage128MessageType(word0) | Validate that the message type field in the word is for a 128-bit UMP | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html#validation-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html#validation-functions"
- },"77": {
+ },"92": {
"doc": "MidiMessageUtility",
"title": "Informational Functions",
"content": "| Function | Description | . | MessageTypeHasGroupField(messageType) | Returns true if the message type is known to be one which contains a group field. Valid only for message types known at the type the API was written. | . | MessageTypeHasChannelField(messageType) | Returns true if the message type is known to be one which contains a channel field. Valid only for message types known at the type the API was written. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html#informational-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html#informational-functions"
- },"78": {
+ },"93": {
"doc": "MidiMessageUtility",
"title": "Field Access Functions",
"content": "| Function | Description | . | GetMessageTypeFromMessageFirstWord(word0) | Returns the MidiMessageType for the message | . | GetPacketTypeFromMessageFirstWord(word0) | Returns the MidiPacketType for the message | . | GetGroupFromMessageFirstWord(word0) | Returns the MidiGroup for the message. First check to see if the message type has a group field. | . | GetChannelFromMessageFirstWord(word0) | Returns the MidiChannel for the message. First check to see if the message type has a channel field. | . | GetStatusFromUtilityMessage(word0) | Returns the status byte | . | GetStatusFromMidi1ChannelVoiceMessage(word0) | When provided a MIDI 1.0 channel voice message, returns the Midi1ChannelVoiceMessageStatus for the message. | . | GetStatusFromMidi2ChannelVoiceMessageFirstWord(word0) | When provided a MIDI 2.0 channel voice message, returns the Midi2ChannelVoiceMessageStatus for the message. | . | GetStatusBankFromFlexDataMessageFirstWord(word0) | Returns the status bank byte | . | GetStatusFromFlexDataMessageFirstWord(word0) | Returns the status byte | . | GetStatusFromSystemCommonMessage(word0) | Returns the status byte | . | GetStatusFromDataMessage64FirstWord(word0) | Returns the status byte | . | GetNumberOfBytesFromDataMessage64FirstWord(word0) | Returns the byte count field | . | GetStatusFromDataMessage128FirstWord(word0) | Returns the status byte | . | GetNumberOfBytesFromDataMessage128FirstWord(word0) | Returns the byte count field | . | GetFormFromStreamMessageFirstWord(word0) | Returns the form nibble as a byte | . | GetStatusFromStreamMessageFirstWord(word0) | Returns the status byte | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html#field-access-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html#field-access-functions"
- },"79": {
+ },"94": {
"doc": "MidiMessageUtility",
"title": "Field Manipulation Functions",
"content": "| Function | Description | . | ReplaceGroupInMessageFirstWord(word0, newGroup) | Replaces the group field in word0 and returns the resulting MIDI word | . | ReplaceChannelInMessageFirstWord(word0, newChannel) | Replaces the channel field in word0 and returns the resulting MIDI word | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html#field-manipulation-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html#field-manipulation-functions"
- },"80": {
+ },"95": {
"doc": "MidiMessageUtility",
"title": "Additional Functions",
"content": "| Function | Description | . | GetMessageFriendlyNameFromFirstWord(UInt32 word0) | Returns the localized “Friendly Name” string for a message. For example, this is what is displayed in the console output when you are monitoring an endpoint in verbose mode. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html#additional-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html#additional-functions"
- },"81": {
+ },"96": {
"doc": "MidiMessageUtility",
"title": "IDL",
"content": "MidiMessageUtility IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiMessageUtility.html#idl"
- },"82": {
+ },"97": {
"doc": "MidiPacketType",
"title": "MidiPacketType Enumeration",
- "content": "The values correspond to the number of 32-bit MIDI words in the packet. | Property | Value | Description | . | UnknownOrInvalid | 0 | An invalid zero-length Universal MIDI Packet | . | UniversalMidiPacket32 | 1 | 32-bit (1 word) Universal MIDI Packet | . | UniversalMidiPacket64 | 2 | 64-bit (2 words) Universal MIDI Packet | . | UniversalMidiPacket96 | 3 | 96-bit (3 words) Universal MIDI Packet | . | UniversalMidiPacket128 | 4 | 128-bit (4 words) Universal MIDI Packet | . MidiPacketType IDL . ",
+ "content": "The values correspond to the number of 32-bit MIDI words in the packet. | Property | Value | Description | . | UnknownOrInvalid | 0 | An invalid zero-length Universal MIDI Packet | . | UniversalMidiPacket32 | 1 | 32-bit (1 word) Universal MIDI Packet | . | UniversalMidiPacket64 | 2 | 64-bit (2 words) Universal MIDI Packet | . | UniversalMidiPacket96 | 3 | 96-bit (3 words) Universal MIDI Packet | . | UniversalMidiPacket128 | 4 | 128-bit (4 words) Universal MIDI Packet | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiPacketTypeEnum.html#midipackettype-enumeration",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiPacketTypeEnum.html#midipackettype-enumeration"
- },"83": {
+ },"98": {
+ "doc": "MidiPacketType",
+ "title": "IDL",
+ "content": "MidiPacketType IDL . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiPacketTypeEnum.html#idl",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiPacketTypeEnum.html#idl"
+ },"99": {
"doc": "MidiPacketType",
"title": "MidiPacketType",
"content": " ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/MidiPacketTypeEnum.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/MidiPacketTypeEnum.html"
- },"84": {
+ },"100": {
"doc": "MidiService",
"title": "MidiService",
"content": "The MidiService class contains a number of static functions which enable working with the service outside of a specific session. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiService.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiService.html"
- },"85": {
+ },"101": {
"doc": "MidiService",
"title": "Static Functions",
"content": "| Static Function | Description | . | PingService(pingCount) | Send one or more ping messages to the ping endpoint and report on the status and time. Return if the responses are not received in a calculated timeout period. | . | PingService(pingCount, timeoutMilliseconds) | Send one or more ping messages to the ping endpoint and report on the status and time. Return if responses are not received in the specified timeout period. | . | GetInstalledTransportPlugins() | Returns a list of MidiServiceTransportPluginInformation representing all service transport plugins (also called Abstractions) | . | GetInstalledMessageProcessingPlugins() | Returns a list of MidiServiceMessageProcessingPluginInformation objects representing all service message processing plugins (also called Transforms) | . | GetActiveSessions() | Returns a list of MidiSessionInformation detailing all active Windows MIDI Services sessions on this PC. | . | UpdateRuntimeConfiguration(configurationUpdate) | Used by client-side SDK components for some transports and other plugins, and by the MIDI Settings app. The format of the data is dependent upon the target specified in the data. Use with caution. For more information, see the config JSON documentation | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiService.html#static-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiService.html#static-functions"
- },"86": {
+ },"102": {
"doc": "MidiService",
"title": "A note on the ping process",
"content": "Pinging the Windows service uses the same mechanism as sending any UMP message. The actual message sent is a prioprietary message. (At the time this was created, there was no standard MIDI 2.0 UMP ping message). The message itself is sent to the diagnostics endpoint in the service, which is implemented like any other transport. Therefore, the speed of the pings here and the success of the ping process is a reasonable indicator of service, cross-process queue, and client API health. The diagnostic ping endpoint does not understand any other type of message, and should not be used by applications other than through the ping functions here. The ping does not tell you if a specific transport or device is in a bad state. For example, if a specific USB MIDI device has crashed, this ping message will still work because it is not sent out over USB. Here’s an example of ping responses through the MIDI console app . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiService.html#a-note-on-the-ping-process",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiService.html#a-note-on-the-ping-process"
- },"87": {
+ },"103": {
"doc": "MidiService",
"title": "A note on updating runtime configuration",
"content": "In order to foster an open plugin ecosystem, we need a way to get settings and configuration for those plugins up to them in the Windows service. The way we’ve chosen to do that is JSON, because that same JSON, when not transient in nature, can also be saved into the permanent configuration file for the active MIDI setup. The runtime configuration update should only be used by code which understands exactly what will be done with the data, and can handle the response which is returned. It is not a general API endpoint, but is designed for components which will extend Windows MIDI Services. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiService.html#a-note-on-updating-runtime-configuration",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiService.html#a-note-on-updating-runtime-configuration"
- },"88": {
+ },"104": {
"doc": "MidiService",
"title": "IDL",
"content": "MidiService IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiService.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiService.html#idl"
- },"89": {
+ },"105": {
"doc": "MidiServiceMessageProcessingPluginInformation",
"title": "MidiServiceMessageProcessingPluginInformation",
- "content": " ",
+ "content": "(section in progress) . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiServiceMessageProcessingPluginInformation.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiServiceMessageProcessingPluginInformation.html"
- },"90": {
+ },"106": {
+ "doc": "MidiServiceMessageProcessingPluginInformation",
+ "title": "IDL",
+ "content": "MidiSessionMidiServiceMessageProcessingPluginInformationInformation IDL . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiServiceMessageProcessingPluginInformation.html#idl",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiServiceMessageProcessingPluginInformation.html#idl"
+ },"107": {
"doc": "MidiServicePingResponse",
"title": "MidiServicePingResponse",
"content": "This class represents a single ping message response. This is used to assess health and performance of the Windows service. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiServicePingResponse.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiServicePingResponse.html"
- },"91": {
+ },"108": {
"doc": "MidiServicePingResponse",
"title": "Static Functions",
"content": "| Property | Description | . | SourceId | Id used to track this ping source connection instance, in the case of multiple applications using the same ping endpoint | . | Index | Index of the ping | . | ClientSendMidiTimestamp | The time the client sent the ping message | . | ServiceReportedMidiTimestamp | The time the service reported receiving the ping message | . | ClientReceiveMidiTimestamp | The time the client received the ping response | . | ClientDeltaTimestamp | The delta between the client sending the message and receiving the response | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiServicePingResponse.html#static-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiServicePingResponse.html#static-functions"
- },"92": {
+ },"109": {
"doc": "MidiServicePingResponse",
"title": "IDL",
"content": "MidiServicePingResponse IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiServicePingResponse.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiServicePingResponse.html#idl"
- },"93": {
+ },"110": {
"doc": "MidiServicePingResponseSummary",
"title": "MidiServicePingResponseSummary",
"content": "This class represents a summary of the ping attempts against the Windows service. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiServicePingResponseSummary.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiServicePingResponseSummary.html"
- },"94": {
+ },"111": {
"doc": "MidiServicePingResponseSummary",
"title": "Static Functions",
"content": "| Property | Description | . | Success | True if the ping was a success | . | FailureReason | In case of a failure, this includes information about why the failure happened. | . | TotalPingRoundTripMidiClock | The total MIDI Clock time for all ping messages to be sent and received | . | AveragePingRoundTripMidiClock | Calculated average round trip time for ping messages | . | Responses | A list of all the responses for the ping messages | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiServicePingResponseSummary.html#static-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiServicePingResponseSummary.html#static-functions"
- },"95": {
+ },"112": {
"doc": "MidiServicePingResponseSummary",
"title": "IDL",
"content": "MidiServicePingResponseSummary IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiServicePingResponseSummary.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiServicePingResponseSummary.html#idl"
- },"96": {
+ },"113": {
"doc": "MidiServiceTransportPluginInformation",
"title": "MidiServiceTransportPluginInformation",
- "content": " ",
+ "content": "(section in progress) . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiServiceTransportPluginInformation.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiServiceTransportPluginInformation.html"
- },"97": {
+ },"114": {
+ "doc": "MidiServiceTransportPluginInformation",
+ "title": "IDL",
+ "content": "MidiServiceTransportPluginInformation IDL . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiServiceTransportPluginInformation.html#idl",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiServiceTransportPluginInformation.html#idl"
+ },"115": {
"doc": "MidiSession",
"title": "MidiSession",
"content": "Before you can connect to an endpoint, you must start a new MIDI session. An application may have any number of sessions open. For example, the application may open one session per open project, or one session per tab in the case of a browser. The lifetime of endpoint connections opened through a session are controlled through the session. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/session/MidiSession.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/session/MidiSession.html"
- },"98": {
+ },"116": {
"doc": "MidiSession",
"title": "Properties",
"content": "| Property | Description | . | Id | Generated Id for the session | . | Name | Name for this session. To change the name after creating the session, use the UpdateName() function. This will update the service | . | Settings | The settings used to create this session | . | IsOpen | True if this session is open and ready to use | . | Connections | Map of all endpoint connections created through this session. Disconnecting an endpoint using DisconnectEndpointConnection will remove the connection from this map. The map key is the generated connection GUID that identifies an instance of an endpoint connection | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/session/MidiSession.html#properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/session/MidiSession.html#properties"
- },"99": {
+ },"117": {
"doc": "MidiSession",
"title": "Static Member Functions",
"content": "The two static functions are factory-pattern methods for creating a new session. | Static Function | Description | . | CreateSession(sessionName) | Create and return a new session with the specified name | . | CreateSession(sessionName, settings) | Create and return a new session with the specified name and settings | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/session/MidiSession.html#static-member-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/session/MidiSession.html#static-member-functions"
- },"100": {
+ },"118": {
"doc": "MidiSession",
"title": "Functions",
"content": "| Function | Description | . | CreateEndpointConnection(endpointDeviceId) | Create a new connection to the specified endpoint device Id | . | CreateEndpointConnection(endpointDeviceId, options) | Create a new connection to the specified endpoint device Id, using the provided connection options | . | CreateEndpointConnection(endpointDeviceId, options, settings) | Create a new connection to the specified endpoint device Id, using the provided connection options and the endpoint-specific settings | . | CreateVirtualDeviceAndConnection(deviceDefinition) | Create the device-side of an app-to-app virtual endpoint. The calling application will perform as a MIDI device, responding to discovery and other MIDI 2.0 protocol messages. | . | DisconnectEndpointConnection(endpointConnectionId) | Cleanly disconnect an endpoint connection and remove it from the connection map | . | UpdateName(newName) | Update the name of this session locally and in the MIDI Service | . Note: If you manually close a MidiEndpointConnection using IClosable (or IDisposable), it will not be removed from the MidiSession’s collection of endpoints. Instead, use the DisconnectEndpointConnection method of the session to keep both in sync. For that reason, we do not recommend that you wrap the CreateEndpointConnection calls in a using statement. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/session/MidiSession.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/session/MidiSession.html#functions"
- },"101": {
+ },"119": {
"doc": "MidiSession",
"title": "IDL",
"content": "MidiSession IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/session/MidiSession.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/session/MidiSession.html#idl"
- },"102": {
+ },"120": {
"doc": "MidiSession",
"title": "Sample",
"content": "using (var session = MidiSession.CreateSession(\"API Sample Session\")) { ... } . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/session/MidiSession.html#sample",
"relUrl": "/developer-docs/Windows.Devices.Midi2/session/MidiSession.html#sample"
- },"103": {
+ },"121": {
"doc": "MidiSessionConnectionInformation",
"title": "MidiSessionConnectionInformation",
- "content": "This class represents an open connection in a Windows MIDI Services session. ",
+ "content": "This class represents an open connection in a Windows MIDI Services session. This is an informational class only for reporting system-wide connection usage. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiSessionConnectionInformation.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiSessionConnectionInformation.html"
- },"104": {
+ },"122": {
"doc": "MidiSessionConnectionInformation",
"title": "Static Functions",
"content": "| Property | Description | . | EndpointDeviceId | The endpoint device id for the connection | . | InstanceCount | The number of instances of this connection which are open in the parent session | . | EarliestConnectionTime | The date and time the first instance of the connection was opened | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiSessionConnectionInformation.html#static-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiSessionConnectionInformation.html#static-functions"
- },"105": {
+ },"123": {
"doc": "MidiSessionConnectionInformation",
"title": "IDL",
"content": "MidiSessionConnectionInformation IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiSessionConnectionInformation.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiSessionConnectionInformation.html#idl"
- },"106": {
+ },"124": {
"doc": "MidiSessionInformation",
"title": "MidiSessionInformation",
"content": "This class represents an open Windows MIDI Services session. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiSessionInformation.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiSessionInformation.html"
- },"107": {
+ },"125": {
"doc": "MidiSessionInformation",
"title": "Static Functions",
"content": "| Property | Description | . | SessionId | The generated internal GUID for the session | . | ProcessId | The process id for the session | . | ProcessName | The process name for the session, captured when the session was created | . | SessionName | The name of the session provided through the API | . | StartTime | The date and time the session was created | . | Connections | A list of MidiSessionConnectionInformation objects detailing the connections currently open for this session | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiSessionInformation.html#static-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiSessionInformation.html#static-functions"
- },"108": {
+ },"126": {
+ "doc": "MidiSessionInformation",
+ "title": "Example",
+ "content": "The Windows MIDI Services Console app uses the MidiSessionInformation MidiSessionConnectionInformation and the MidiService class to display active sessions. In this case, you can see three open sessions. The process name and process id are on the left. The session name is in the text on the right, after the word “Session”, and the start time is the date and time in green. Finally, the list of connections for each session is underneath the session information. ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiSessionInformation.html#example",
+
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiSessionInformation.html#example"
+ },"127": {
"doc": "MidiSessionInformation",
"title": "IDL",
"content": "MidiSessionInformation IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/MidiSessionInformation.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/MidiSessionInformation.html#idl"
- },"109": {
+ },"128": {
"doc": "MidiSessionSettings",
"title": "MidiSessionSettings",
"content": "MidiSessionSettings are currently unused. We are evaluating keeping this in the API. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/session/MidiSessionSettings.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/session/MidiSessionSettings.html"
- },"110": {
+ },"129": {
"doc": "MidiSessionSettings",
"title": "IDL",
"content": "MidiSessionSettings IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/session/MidiSessionSettings.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/session/MidiSessionSettings.html#idl"
- },"111": {
+ },"130": {
"doc": "MidiStreamConfigurationRequestReceivedEventArgs",
"title": "MidiStreamConfigurationRequestReceivedEventArgs",
"content": "(in development) . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/virtual-device/MidiStreamConfigurationRequestReceivedEventArgs.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/virtual-device/MidiStreamConfigurationRequestReceivedEventArgs.html"
- },"112": {
+ },"131": {
"doc": "MidiStreamConfigurationRequestReceivedEventArgs",
"title": "IDL",
"content": "MidiStreamConfigurationRequestReceivedEventArgs IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/virtual-device/MidiStreamConfigurationRequestReceivedEventArgs.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/virtual-device/MidiStreamConfigurationRequestReceivedEventArgs.html#idl"
- },"113": {
+ },"132": {
"doc": "MidiStreamMessageBuilder",
"title": "MidiStreamMessageBuilder",
"content": "(In progress) . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiStreamMessageBuilder.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiStreamMessageBuilder.html"
- },"114": {
+ },"133": {
"doc": "MidiStreamMessageBuilder",
"title": "Functions",
"content": "| Function | Description | . | | | . | | | . | | | . | | | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiStreamMessageBuilder.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiStreamMessageBuilder.html#functions"
- },"115": {
+ },"134": {
"doc": "MidiStreamMessageBuilder",
"title": "IDL",
"content": "MidiStreamMessageBuilder IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/MidiStreamMessageBuilder.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/MidiStreamMessageBuilder.html#idl"
- },"116": {
+ },"135": {
"doc": "MidiUniqueId",
"title": "MidiUniqueId",
"content": "The MidiUniqueId class is used to provide formatting and data validation for MIDI-CI MUID types used in Function Blocks and MIDI CI transactions. In the specification, Byte1 is the LSB and Byte4 is the MSB. We follow that convention here. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiUniqueId.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiUniqueId.html"
- },"117": {
+ },"136": {
"doc": "MidiUniqueId",
"title": "Properties",
"content": "| Property | Description | . | Byte1 | The data value for byte 1 of the MUID | . | Byte2 | The data value for byte 2 of the MUID | . | Byte3 | The data value for byte 3 of the MUID | . | Byte4 | The data value for byte 4 of the MUID | . | As28BitInteger | The data value converted to a 28 bit integer | . | IsBroadcast | True if this is the broadcast MUID value | . | IsReserved | True if this is the reserved MUID value | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiUniqueId.html#properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiUniqueId.html#properties"
- },"118": {
+ },"137": {
"doc": "MidiUniqueId",
"title": "Static Properties",
"content": "| Static Property | Description | . | LabelShort | Returns the localized abbreviation. | . | LabelFull | Returns the localized full name. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiUniqueId.html#static-properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiUniqueId.html#static-properties"
- },"119": {
+ },"138": {
"doc": "MidiUniqueId",
"title": "Functions",
"content": "| Function | Description | . | MidiUniqueId() | Constructs an empty MidiUniqueId | . | MidiUniqueId(integer28bit) | Constructs the MidiUniqueId from the given 28 bit integer | . | MidiUniqueId(byte1, byte2, byte3, byte4) | Constructs a MidiUniqueId with the specified bytes | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiUniqueId.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiUniqueId.html#functions"
- },"120": {
+ },"139": {
"doc": "MidiUniqueId",
"title": "Static Functions",
"content": "| Function | Description | . | CreateBroadcast() | Constructs a broadcast MidiUniqueId | . | CreateRandom() | Constructs a random MidiUniqueId | . MidiUniqueId IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/MidiUniqueId.html#static-functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/MidiUniqueId.html#static-functions"
- },"121": {
+ },"140": {
"doc": "MidiVirtualEndpointDevice",
"title": "MidiVirtualEndpointDevice",
"content": "The MidiVirtualEndpointDeviceDefinition class specifies, in an easy to use format, the responses for discovery and protocol negotiation, as well as the properties to use when constructing the device endpoint. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDevice.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDevice.html"
- },"122": {
+ },"141": {
"doc": "MidiVirtualEndpointDevice",
"title": "Properties",
"content": "| Property | Description | . | DeviceDefinition | The MidiVirtualEndpointDeviceDefinition used to create this device. This should be treated as read-only data. | . | FunctionBlocks | Current list of function blocks for this device. | . | SuppressHandledMessages | True if the protocol messages handled by this class should be filtered out of the incoming message stream | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDevice.html#properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDevice.html#properties"
- },"123": {
+ },"142": {
"doc": "MidiVirtualEndpointDevice",
"title": "Functions",
"content": "| Function | Description | . | UpdateFunctionBlock | Update the properties of a single function block. The number of actual function blocks cannot change after creation (per the UMP specification) but blocks may be marked as active or inactive. Changes here will result in the MIDI 2.0 function block notification messages being sent out. | . | UpdateEndpointName | Update the endpoint name, and send out the appropriate endpoint name notification messages. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDevice.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDevice.html#functions"
- },"124": {
+ },"143": {
"doc": "MidiVirtualEndpointDevice",
"title": "Events",
"content": "| Event | Description | . | StreamConfigurationRequestReceived(device, args) | Raised when this device receives a Stream Configuration Request UMP message. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDevice.html#events",
"relUrl": "/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDevice.html#events"
- },"125": {
+ },"144": {
"doc": "MidiVirtualEndpointDevice",
"title": "IDL",
"content": "MidiVirtualEndpointDevice IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDevice.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDevice.html#idl"
- },"126": {
+ },"145": {
"doc": "MidiVirtualEndpointDeviceDefinition",
"title": "MidiVirtualEndpointDeviceDefinition",
"content": "The MidiVirtualEndpointDeviceDefinition class specifies, in an easy to use format, the responses for discovery and protocol negotiation, as well as the properties to use when constructing the device endpoint. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDeviceDefinition.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDeviceDefinition.html"
- },"127": {
+ },"146": {
"doc": "MidiVirtualEndpointDeviceDefinition",
"title": "Properties",
"content": "| Property | Description | . | EndpointName | Name of the endpoint used for both the device enumeration and for responding to the endpoint name request UMP message | . | EndpointProductInstanceId | The unique identifier for this device. This value is used when creating the device Id, and is also used as the response for endpoint discovery when the id is requested. In general, this value should be kept to less than 32 characters and not include any special characters or symbols | . | SupportsMidi1ProtocolMessages | For endpoint discovery. True if this endpoint supports MIDI 1.0 protocol messages over UMP | . | SupportsMidi2ProtocolMessages | For endpoint discovery. True if this endpoint supports MIDI 2.0 protocol messages over UMP | . | SupportsReceivingJRTimestamps | For endpoint discovery. True if this endpoint supports recieving JR timestamps (typically, you’ll want to set this to false) | . | SupportsSendingJRTimestamps | For endpoint discovery. True if this endpoint supports sending JR timestamps (typically, you’ll want to set this to false) | . | DeviceManufacturerSystemExclusiveId | MIDI 2.0 UMP Device Identity value | . | DeviceFamilyLsb | MIDI 2.0 UMP Device Identity value | . | DeviceFamilyMsb | MIDI 2.0 UMP Device Identity value | . | DeviceFamilyModelLsb | MIDI 2.0 UMP Device Identity value | . | DeviceFamilyModelMsb | MIDI 2.0 UMP Device Identity value | . | SoftwareRevisionLevel | MIDI 2.0 UMP Device Identity value | . | AreFunctionBlocksStatic | True if the function blocks will not change in any way | . | FunctionBlocks | list of function blocks for this device | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDeviceDefinition.html#properties",
"relUrl": "/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDeviceDefinition.html#properties"
- },"128": {
+ },"147": {
"doc": "MidiVirtualEndpointDeviceDefinition",
"title": "Functions",
"content": "| Function | Description | . | MidiVirtualEndpointDeviceDefinition() | Construct a new device definition | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDeviceDefinition.html#functions",
"relUrl": "/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDeviceDefinition.html#functions"
- },"129": {
+ },"148": {
"doc": "MidiVirtualEndpointDeviceDefinition",
"title": "IDL",
"content": "MidiVirtualEndpointDeviceDefinition IDL . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDeviceDefinition.html#idl",
"relUrl": "/developer-docs/Windows.Devices.Midi2/virtual-device/MidiVirtualEndpointDeviceDefinition.html#idl"
- },"130": {
+ },"149": {
"doc": "Service",
"title": "Service",
"content": "The MidiService class is a utility class which provides access to health and status information related to the MidiSrv Service. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/service/README.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/service/README.html"
- },"131": {
+ },"150": {
"doc": "Session",
"title": "Session",
"content": "Interaction with a MIDI Endpoint always starts with creating a session. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/session/README.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/session/README.html"
- },"132": {
+ },"151": {
"doc": "Connections",
- "title": "Connection APIs",
- "content": " ",
- "url": "/docs/developer-docs/Windows.Devices.Midi2/connections/README.html#connection-apis",
+ "title": "Connecting to a MIDI Endpoint",
+ "content": "In Windows MIDI Services, once you have opened a session, you will typically open one or more connections to device endpoints. The session class contains methods which return an initialized, but not open, connection to the specified endpoint. The remainder of your interaction for sending and receiving data is with the MidiEndpointConnection class. All endpoints in Windows MIDI Services send and receive messages using the Universal MIDI Packet format. Any required translation (for MIDI 1.0 devices, for example) is handled in the service and/or in the USB driver. Workflow . | Open a session | Using an endpoint id discovered through enumeration or another mechanism, create an endpoint connection | Wire up to the connection any event handlers or message processors | Open the connection | Send and receive messages | Using the session, disconnect the connection when you are done with it. | . ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/connections/README.html#connecting-to-a-midi-endpoint",
- "relUrl": "/developer-docs/Windows.Devices.Midi2/connections/README.html#connection-apis"
- },"133": {
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/connections/README.html#connecting-to-a-midi-endpoint"
+ },"152": {
"doc": "Connections",
"title": "Connections",
"content": " ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/connections/README.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/connections/README.html"
- },"134": {
+ },"153": {
"doc": "Client Plugins",
"title": "Client-side Processing Plugins",
"content": "Connections allocate service resources (time and memory), so we recommend applications maintain only a single connection to an endpoint within any session. But because the new endpoint stream-focused approach aggregates what used to be considered ports, we provide processing plugins to parcel out the incoming messages based on criteria set by the application. In this way, an application can have the logical equivalent of several input ports, without the associated resource usage. MIDI 1.0 had the concept of ports. Each port was just a single cable/jack from a MIDI stream exposed by the device. The API and driver were responsible for merging all of the different cables into the single stream for outgoing data, or pulling them apart for incoming data. In MIDI 2.0, what used to be a Port is now morally equivalent to a Group address in the message data. Instead of speaking to N different enumerated entities for a device, the application speaks to a single bidirectional UMP endpoint which aggregates all of this information, much like the driver did behind the scenes in MIDI 1.0. We recognize that there are cases when the old model of MIDI Ports is more convenient for passing around in a DAW or similar app, particularly for incoming data. To help, there are plugins which implement IMidiEndpointMessageProcessingPlugin. The API includes a few stock plugins, but developers are free to provide their own. Listener instances are 1:1 with endpoint connections. We don’t support using the same listener on multiple endpoints. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/README.html#client-side-processing-plugins",
"relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/README.html#client-side-processing-plugins"
- },"135": {
+ },"154": {
"doc": "Client Plugins",
"title": "Client Plugins",
"content": " ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/README.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/processing-plugins/README.html"
- },"136": {
+ },"155": {
"doc": "Endpoint Enumeration",
- "title": "Enumeration APIs",
- "content": " ",
- "url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/README.html#enumeration-apis",
+ "title": "Enumerating Endpoints",
+ "content": "Windows MIDI Services provides detailed information about each MIDI endpoint on the system. In addition to ids and names, you can also get user metadata, function blocks, group terminal blocks, in-protocol properties, the parent device and container, and much more. There are two ways to enumerate endpoint devices. | Static enumeration using the MidiEndpointDeviceInformation class. This is a snapshot in time and is not updated when in-protocol information is updated, or the user has specified new properties like the name. This approach is really only useful in the simplest of scenarios, as it does not handle device connects and disconnects after the initial enumeration. | Dynamic enumeration using the MidiEndpointDeviceWatcher. When you set up a watcher on a background thread, you will be notified when any new endpoints are connected to the system, or any existing endpoints are disconnected. You will also be alerted when properties change on an enumerated device. For example, when new function block information is sent in-protocol, the properties are updated and an event is raised. For these reasons, the device watcher approach is the approach any non-trival application should use to list and track MIDI endpoints. | . Note that you can enumerate endpoint devices using the stock Windows.Devices.Enumeration.DeviceInformation and Windows.Devices.Enumeration.DeviceWatcher classes. However, those classes do not automatically request the extended property set needed for MIDI, do not translate the binary properties like the group terminal blocks and function blocks, and also do not automatically resolve the relationship with the parent device. ",
+ "url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/README.html#enumerating-endpoints",
- "relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/README.html#enumeration-apis"
- },"137": {
+ "relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/README.html#enumerating-endpoints"
+ },"156": {
"doc": "Endpoint Enumeration",
"title": "Endpoint Enumeration",
"content": " ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/enumeration/README.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/enumeration/README.html"
- },"138": {
+ },"157": {
"doc": "Simple Types",
"title": "Simple Types",
"content": "There are several simple or basic types used in Windows MIDI Services. These types provide formatting and validation to help ensure applications display data in similar ways. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/simple-types/README.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/simple-types/README.html"
- },"139": {
+ },"158": {
"doc": "Metadata",
"title": "Metadata",
"content": "The Windows Service intercepts (but does not remove from the stream) Endpoint metadata notifications. For example, we’ll intercept Endpoint Name notifications and use those to provide a new endpoint-supplied name for the device. These are cached in the SWD properties for the Endpoint Device. In addition to the endpoint data, we also capture and store block data. The block data should be used by applications to identify which groups are active and how to display them to the user. For example, you may want to display a function block name including group numbers like “Sequencer (Groups 1, 2, 3)” in a way similar to how you treated ports in the past. Function Blocks and Group Terminal Blocks are important types of MIDI 2.0 metadata which describe an endpoint and so have their own discrete types. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/metadata/README.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/metadata/README.html"
- },"140": {
+ },"159": {
"doc": "Messages",
"title": "Messages",
- "content": "Windows MIDI Services messages are all sent and received in Universal MIDI Packet (UMP) format. a UMP is made up of 1-4 32 bit MIDI words, sized in 32 bit, 64 bit, 96 bit, and 128 bit packets. The first four bits of the packet are the message type, and from that, you can identify the type and size of message which follows. ",
+ "content": "Windows MIDI Services messages are all sent and received in Universal MIDI Packet (UMP) format, even if the device is a bytestream MIDI 1.0 device (we do the translation for you). a UMP is made up of 1-4 32 bit MIDI words, sized in 32 bit, 64 bit, 96 bit, and 128 bit packets. The first four bits of the packet are the message type, and from that, you can identify the type and size of message which follows. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/README.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/README.html"
- },"141": {
+ },"160": {
"doc": "Messages",
"title": "Words",
"content": "Several functions operate on one or more 32 bit MIDI words directly. This is efficient for transmission, but may not be convenient for storage or processing. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/README.html#words",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/README.html#words"
- },"142": {
+ },"161": {
"doc": "Messages",
"title": "Rich Types",
"content": "The rich UMP types are full runtime classes, and so have more overhead than the fixed types or raw words. However, they offer conveniences not offered by the other types, including storage of the timestamp, message and packet type enumerations, and interface-based polymorphism. If your send/receive speed is not super critical, these are often the easiest solution. If you are familiar with the Windows.Devices.Midi message types, these are the conceptual equivalent in UMP. For the most part, we do not provide strongly-typed discrete message types (like specific MIDI 2.0 Channel Voice messages or similar) in the API as that is a moving target, and many applications also include their own message creation and processing functions using their own libraries or any of the libraries included on https://midi2.dev. If there’s demand for strongly-typed messages, we may provide them in the future. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/README.html#rich-types",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/README.html#rich-types"
- },"143": {
+ },"162": {
"doc": "Messages",
"title": "Fixed-Size Struct type",
"content": "In addition to the richer types and raw words, the MidiMessageStruct type offers a fixed 128 bit message which can be used to send or receive any type of MIDI UMP. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/messages/README.html#fixed-size-struct-type",
"relUrl": "/developer-docs/Windows.Devices.Midi2/messages/README.html#fixed-size-struct-type"
- },"144": {
+ },"163": {
"doc": "Message Utilities",
"title": "Message Utilities",
- "content": " ",
+ "content": "There are many open source and internal libraries that can be used for creating and parsing message data. For a functional MIDI API, however, we did have to create a number of these ourselves, and so surface them in the API so that you may take advantage of them in your own code. For other open source MIDI libraries, visit the official site midi2.dev, run by members of the MIDI Association. The Windows MIDI Services service and API code uses some of this open source internally. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/message-utilities/README.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/message-utilities/README.html"
- },"145": {
+ },"164": {
"doc": "Virtual Devices",
"title": "Virtual Devices",
"content": "Fully-featured app-to-app MIDI in a MIDI 2.0 world involves connections to a virtual device which must participate in the full MIDI 2.0 protocol, from discovery through protocol negotiation. To support this scenario, the way app-to-app MIDI works in Windows MIDI Services is for an application to define a device and then using the MidiSession, construct that device’s endpoint. Once the device endpoint is opened, Windows MIDI Services will then construct a second application-visible multi-client endpoint which applications will use to talk to the device app. During that conversation, the service will also handle discovery and protocol negotiation with the virtual device just like it would any physical device. In addition to the service component, it is implemented in the client API as a type of Client-SIde Processing Plugin . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/virtual-device/README.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/virtual-device/README.html"
- },"146": {
+ },"165": {
"doc": "Windows.Devices.Midi2 API",
"title": "Windows.Devices.Midi2",
"content": "The Windows.Devices.Midi2 types are documented in these pages. Typical API workflow: . | Create a new session, with an appropriate name. The name will be visible to users and so should be meaningful. Each application may open more than one session at a time (for example, different songs in a DAW, or different tabs in a browser). A single session manages the lifetime of the connections opened through it. | Connect to an endpoint. Typically, you’ll get the endpoint’s id through the enumeration functions. | Wire up a MidiMessageReceived event handler. This is how you will receive incoming messages from the endpoint. Messages are received individually, with one event per message. | Optionally, add any processing plugins. If you want to filter messages or provide multiple “views” into a stream, you can add the appropriate client message processing plugins. | Open the connection. Once the connection is open, you may send and receive messages. | . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/README.html#windowsdevicesmidi2",
"relUrl": "/developer-docs/Windows.Devices.Midi2/README.html#windowsdevicesmidi2"
- },"147": {
+ },"166": {
"doc": "Windows.Devices.Midi2 API",
"title": "Endpoint Enumeration",
"content": "Enumeration is how you discover endpoints and get notified of endpoints when they are added, updated, or removed. For the best user experience, keep a MidiEndpointDeviceWatcher running in a background thread so you can monitor device removal, and property updates (name, function blocks, etc.) . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/README.html#endpoint-enumeration",
"relUrl": "/developer-docs/Windows.Devices.Midi2/README.html#endpoint-enumeration"
- },"148": {
+ },"167": {
"doc": "Windows.Devices.Midi2 API",
"title": "Session",
"content": "Interaction with a MIDI Endpoint always starts with creating a session. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/README.html#session",
"relUrl": "/developer-docs/Windows.Devices.Midi2/README.html#session"
- },"149": {
+ },"168": {
"doc": "Windows.Devices.Midi2 API",
"title": "Connections",
"content": "Once you have a session, you will create one or more connections to send and receive messages. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/README.html#connections",
"relUrl": "/developer-docs/Windows.Devices.Midi2/README.html#connections"
- },"150": {
+ },"169": {
"doc": "Windows.Devices.Midi2 API",
"title": "Clock",
"content": "The MIDI clock is used for creating timestamps for use in sending MIDI messages. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/README.html#clock",
"relUrl": "/developer-docs/Windows.Devices.Midi2/README.html#clock"
- },"151": {
+ },"170": {
"doc": "Windows.Devices.Midi2 API",
"title": "Messages",
"content": "MIDI Messages are discrete packets of data of a known length. In the MIDI 2.0 specification, they are known as Universal MIDI Packets. In Windows MIDI Services, even MIDI 1.0 bytestream messages are presented in their equivalent Universal MIDI Packet format. The API includes several classes not only for the messages, but also to help construct and parse them. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/README.html#messages",
"relUrl": "/developer-docs/Windows.Devices.Midi2/README.html#messages"
- },"152": {
+ },"171": {
"doc": "Windows.Devices.Midi2 API",
"title": "Metadata",
"content": "Function Blocks and Group Terminal Blocks are important types of MIDI 2.0 metadata which describe an endpoint. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/README.html#metadata",
"relUrl": "/developer-docs/Windows.Devices.Midi2/README.html#metadata"
- },"153": {
+ },"172": {
"doc": "Windows.Devices.Midi2 API",
"title": "Client-Side Processing Plugins",
"content": "Connections allocate service resources (time and memory), so we recommend applications maintain only a single connection to an endpoint within any session. But because the new endpoint stream-focused approach aggregates what used to be considered ports, we provide processing plugins to parcel out the incoming messages based on criteria set by the application. In this way, an application can have the logical equivalent of several input ports, without the associated resource usage. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/README.html#client-side-processing-plugins",
"relUrl": "/developer-docs/Windows.Devices.Midi2/README.html#client-side-processing-plugins"
- },"154": {
+ },"173": {
"doc": "Windows.Devices.Midi2 API",
"title": "Virtual Devices",
"content": "A virtual device is the mechanism through which app-to-app MIDI works through the API. One application acts as the MIDI Endpoint Device, and other applications connect to it. In addition to the service component, it is implemented in the client API as a type of Client-SIde Processing Plugin . ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/README.html#virtual-devices",
"relUrl": "/developer-docs/Windows.Devices.Midi2/README.html#virtual-devices"
- },"155": {
+ },"174": {
"doc": "Windows.Devices.Midi2 API",
"title": "Simple Types",
"content": "There are several simple or basic types used in Windows MIDI Services. These types provide formatting and validation to help ensure applications display data in similar ways. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/README.html#simple-types",
"relUrl": "/developer-docs/Windows.Devices.Midi2/README.html#simple-types"
- },"156": {
+ },"175": {
"doc": "Windows.Devices.Midi2 API",
"title": "Service",
"content": "The MidiService class is a utility class which provides access to health and status information related to the MidiSrv Service. ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/README.html#service",
"relUrl": "/developer-docs/Windows.Devices.Midi2/README.html#service"
- },"157": {
+ },"176": {
"doc": "Windows.Devices.Midi2 API",
"title": "Windows.Devices.Midi2 API",
"content": " ",
"url": "/docs/developer-docs/Windows.Devices.Midi2/README.html",
"relUrl": "/developer-docs/Windows.Devices.Midi2/README.html"
- },"158": {
+ },"177": {
"doc": "Best Practices",
"title": "Best Practices and Performance Optimizations",
"content": "Here’s a list of best practices and performance optimizations for MIDI API-consuming applications. ",
"url": "/docs/developer-docs/best-practices.html#best-practices-and-performance-optimizations",
"relUrl": "/developer-docs/best-practices.html#best-practices-and-performance-optimizations"
- },"159": {
+ },"178": {
"doc": "Best Practices",
"title": "Fast transmission of messages",
"content": "For maximum compatibility across languages, and for safety, WinRT doesn’t allow pointers to be exposed by any properties or as parameters or return types for any function. In addition, the by-value and by-reference semantics for parameters are not always under the control of the API developer. For those reasons, and to maximize ease of use across a number of languages and use-cases, we have multiple ways to send and receive messages. You will want to do your own performance testing from your application and scenarios, but in general, the send/receives with the least overhead are those which send/receive individual 32 bit words, a single 128 bit structure, or the IMemoryBuffer. The word and struct methods do pass copies of data, but the amount of data, for most time critical messages, is still 64 bits or less (MIDI 1.0 channel voice messages are 32 bits, MIDI 2.0 channel voice messages are 64 bits). The IMemoryBuffer approach is a more advanced way to transfer data to and from the API. This wraps a buffer of data which you can reuse between calls, including send/receive, as long as you manage and avoid any potential overlaps. Internally, the COM types used to access this ensures that only pointers are passed into the API. There’s a bit more ceremony to using this approach, so we recommend investing time there only if it better fits your app’s programming model. In addition, because IMemoryBuffer deals with bytes and not 32 bit words, you need to ensure you are correctly copying the data in, following the endianness rules for our internal MIDI 2.0 data representation. The most flexible, but least performant approach, is to use the IMidiMessage interface and the methods which return strongly typed messages. These do involve additional type allocations either on the part of the caller or in the API code. Data copies . In the underlying implementation, copying of data is unavoidable in places. Here are the main places where it happens. When sending messages . | The individual WinRT projection for your language may enforce a copy or translation of the data going into the API. This varies. Arrays, in particular, vary here. | The API copies the data (typically a memcpy), regardless of how it is provided, into the cross-process queue for that client endpoint connection. This is shared cross-process memory on Windows. It’s also a circular queue, so we can’t hold onto pointers for long, which is why 4 below operates how it does. | On the service side, the pointers into the buffer are provided to the client connection and the plugins in that chain. No copying here. | There will be copies of the data created if there are any processing plugins which must significantly manipulate the data (each plugin decides how it deals with the data), or if you schedule the message to be sent in the future (see 2 above). | Finally, the messages may be copied when being supplied to the transport. In the case of USB, we make a call into a kernel driver, so have another cross process queue for that which requires we copy data into it to supply it to the driver. In the case of networking, we have to copy the data into the network buffers and transmit. In app-to-app / virtual MIDI, and also the built-in loopback endpoints, we typically just send the same message pointers through the entire process and do not copy any data in the transport. | . This code is all quite efficient, and the amount of data in a single message is small, so these happen quite quickly. Nevertheless, we’re always looking at places where we can further optimize, but still retain the flexibility provided by having a Windows Service which processes the messages. When receiving messages, the process is almost exactly the opposite of sending. There’s no in-bound message scheduling, but there may be data transformations that plugins perform. In addition, endpoints with multiple clients connected do require fanning out those messages into multiple queues, resulting in multiple copies across the different cross-process inbound client connection queues. That is a small price to pay for full multi-client MIDI support. ",
"url": "/docs/developer-docs/best-practices.html#fast-transmission-of-messages",
"relUrl": "/developer-docs/best-practices.html#fast-transmission-of-messages"
- },"160": {
+ },"179": {
"doc": "Best Practices",
"title": "Displaying connections to your app users",
"content": "Most apps need to display device and endpoint connection information to their users. Here are some details related to that. Use the MidiEndpointDeviceWatcher to respond to device changes . MIDI devices come and go based on connecting/disconnecting USB cables, or new network endpoints coming online. In addition, properties like Function Blocks and Endpoint Name are subject to change at any time. Use the MidiEndpointDeviceWatcher class on a background thread to monitor these endpoints, and receive notifications when anything changes. This is a much more robust approach vs simply enumerating a snapshot of devices up-front. There’s no API or service reason to require a customer to reboot or reload a MIDI DAW or other application to see newly added endpoints. Don’t include diagnostics endpoints for most apps . Unless the app is a utility / testing app, we recommend you do not display the UMP Loopback Endpoints to the user. These are for diagnostics and testing only. By default, they are excluded during enumeration. Enable drill-down into Groups (functions) . A single function block may exist on multiple groups, and multiple groups may overlap function blocks. That is the nature of the MIDI 2.0 specification. In most cases, you’ll find that a function is associated with one or more groups and those groups do not span other function blocks. We recommend that, when displaying a connection to the user, you connect them to the UMP Endpoint, but then enable some sort of drill-down to show the function block names and their associated groups. SynthCompany Foo Synth 5 - Synthesizer (Groups 1, 2, 3) - Sequencer (Groups 4, 5) - MIDI DIN Out (Group 6) . Or similar based on the conventions of your application. Note that a flat list, like what many apps used for MIDI 1.0 ports, is not as reasonable in a MIDI 2.0 world. Use the Function Block UI Hint to help you decide how to show functions . The UI Hint property of a Function Block was created to give the UI an indication of the intended direction of communication, as a user would see it, for a function block. This shouldn’t necessarily block functions from showing up in a list that contains, for example, input devices, but it may be that you want to prioritize the ones with an appropriate UI hint, and have a “see all” option or similar to display the rest. ",
"url": "/docs/developer-docs/best-practices.html#displaying-connections-to-your-app-users",
"relUrl": "/developer-docs/best-practices.html#displaying-connections-to-your-app-users"
- },"161": {
+ },"180": {
"doc": "Best Practices",
"title": "Prefer not mixing legacy APIs and Windows MIDI Services in the same session",
"content": "There’s nothing technically preventing you from using winmm or WinRT MIDI 1.0 in the same application, at the same time as the new API, but there’s also no need to beyond transitioning code. The new API will do everything the old does, plus a lot more. The older APIs don’t have access to a lot of the metadata you’ll need for devices, and in the case of MIDI 2.0 endpoints, will require additional message translation in the service. Of course, offering a choice between Windows MIDI Services and an older API in your application is perfectly acceptable, based on your use cases, and which versions of the operating systems you need to support. ",
"url": "/docs/developer-docs/best-practices.html#prefer-not-mixing-legacy-apis-and-windows-midi-services-in-the-same-session",
"relUrl": "/developer-docs/best-practices.html#prefer-not-mixing-legacy-apis-and-windows-midi-services-in-the-same-session"
- },"162": {
+ },"181": {
"doc": "Best Practices",
"title": "Best Practices",
"content": " ",
"url": "/docs/developer-docs/best-practices.html",
"relUrl": "/developer-docs/best-practices.html"
- },"163": {
+ },"182": {
"doc": "Config JSON",
"title": "JSON Config File",
"content": "It’s best to use the Settings application and the transport / processing plugins for Settings to manipulate the file. However, if you edit it by hand, here are some notes. ",
"url": "/docs/config-json.html#json-config-file",
"relUrl": "/config-json.html#json-config-file"
- },"164": {
+ },"183": {
"doc": "Config JSON",
"title": "The File location is Restricted",
"content": "The JSON configuration files are all stored in %allusersprofile%\\Microsoft\\MIDI which typically resolves to C:\\ProgramData\\Microsoft\\MIDI. For security reasons, we don’t allow the file to be stored in any other location. However, you can have as many files in that folder as you want, and switch between them as needed. The default config file is typically named Default.midiconfig.json. The actual name is stored in the registry under HKLM\\SOFTWARE\\Microsoft\\Windows MIDI Services in the CurrentConfig value. This value must not contain any non-filename path characters (no backslashes, colons, etc.). ",
"url": "/docs/config-json.html#the-file-location-is-restricted",
"relUrl": "/config-json.html#the-file-location-is-restricted"
- },"165": {
+ },"184": {
"doc": "Config JSON",
"title": "JSON is Case-Sensitive",
- "content": "JSON is typically case-sensitive for all keys. The Windows.Data.Json parser used by Windows MIDI Services is case-sensitive with no option to ignore case. That includes GUID values. For example, the following two values are not equivalent JSON keys: . \"{26FA740D-469C-4D33-BEB1-3885DE7D6DF1}\": { \"_comment\": \"KS MIDI (USB etc.)\" }, . and . \"{26fa740d-469c-4d33-beb1-3885de7d6df1}\": { \"_comment\": \"KS MIDI (USB etc.)\" }, . ",
+ "content": "JSON is typically case-sensitive for all keys. The Windows.Data.Json parser used by Windows MIDI Services is case-sensitive with no option to ignore case. That includes GUID values. For example, the following two values are not equivalent JSON keys: . \"{26FA740D-469C-4D33-BEB1-3885DE7D6DF1}\": { \"_comment\": \"KS MIDI (USB etc.)\" } . and . \"{26fa740d-469c-4d33-beb1-3885de7d6df1}\": { \"_comment\": \"KS MIDI (USB etc.)\" } . ",
"url": "/docs/config-json.html#json-is-case-sensitive",
"relUrl": "/config-json.html#json-is-case-sensitive"
- },"166": {
+ },"185": {
"doc": "Config JSON",
"title": "Schema",
- "content": "The JSON config file is such that each transport owns its own schema within the bucket associated with its class ID (GUID). We do not impose a schema on the transports or other plugins. Therefore there is no formal JSON Schema for this file. Here’s an example of a bare-bones file, with sections for three different transports. { \"header\": { \"_comment\": \"NOTE: All json keys are case-sensitive, including GUIDs.\", \"product\" : \"Windows MIDI Services\", \"fileVersion\": 1.0 }, \"endpointTransportPluginSettings\": { \"{26FA740D-469C-4D33-BEB1-3885DE7D6DF1}\": { \"_comment\": \"KS MIDI (USB etc.)\" }, \"{C95DCD1F-CDE3-4C2D-913C-528CB8A4CBE6}\": { \"_comment\": \"Network MIDI\" }, \"{8FEAAD91-70E1-4A19-997A-377720A719C1}\": { \"_comment\": \"Virtual MIDI\" } }, \"endpointProcessingPluginSettings\": { } } . Endpoint Properties . The basics of this are identical for each transport. We’ll use KS (USB) as an example . \"{26FA740D-469C-4D33-BEB1-3885DE7D6DF1}\": { \"_comment\": \"KS MIDI (USB etc.)\" \"SWD: \\\\\\\\?\\\\SWD#MIDISRV#MIDIU_KS_BIDI_6799286025327820155_OUTPIN.0_INPIN.2#{e7cce071-3c03-423f-88d3-f1045d02552b}\": { \"userSuppliedName\" : \"Pete's Kontrol S61\", \"userSuppliedDescription\" : \"This is my most favorite MIDI 2.0 controller in the whole world!\" } ... }, . Of those, the identification method SWD is the most important. This controls how we identify a matching device. In cases where the manufacturer doesn’t supply a unique iSerialNumber in USB, unplugging your device from one USB port and plugging it into another can result in a new Id. Similarly, if you have two or more of the same device, and they do not have unique serial numbers, it can be impossible for Windows to distinguish between them. Valid values for the identification method prefix . | SWD: : (The colon and trailing space are required). Use the full Windows Endpoint Device Interface Id. For example \\\\\\\\?\\\\SWD#MIDISRV#MIDIU_KS_BIDI_16024944077548273316_OUTPIN.0_INPIN.2#{e7cce071-3c03-423f-88d3-f1045d02552b}. (Note how the backslashes have to be escaped with additional backslashes.) If the device has an iSerialNumber or you never move it between USB ports, this tends to work fine. | (other methods to be added here when we implement them) | . Valid properties you can set across all supported endpoints . | Property | Type | Description | . | userSuppliedName | Quoted Text | The name you want to use for the endpoint. This will override the name displayed in correctly-coded applications, but won’t necessarily change what you see in Device Manager. These names should be relatively short so they display fully in all/most applications, but meaningful to you. | . | userSuppliedDescription | Quoted Text | A text description and/or notes about the endpoint. Applications may or may not use this data | . | forceSingleClientOnly | Boolean true/false (no quotes) | Most endpoints are multi-client (more than one application can use them simultaneously) by default. This setting is for forcing an endpoint to be single-client only (a value of true). It’s unusual to need this, but a typical use may be to disable multi-client for a device which has a custom driver which doesn’t gracefully handle multiple client applications at the same time. | . ",
+ "content": "The JSON config file is such that each transport owns its own schema within the bucket associated with its class ID (GUID). We do not impose a schema on the transports or other plugins. Therefore there is no formal JSON Schema for this file. Here’s an example of a bare-bones file, with sections for three different transports. { \"header\": { \"_comment\": \"NOTE: All json keys are case-sensitive, including GUIDs.\", \"product\" : \"Windows MIDI Services\", \"fileVersion\": 1.0 }, \"endpointTransportPluginSettings\": { \"{26FA740D-469C-4D33-BEB1-3885DE7D6DF1}\": { \"_comment\": \"KS MIDI (USB etc.)\" }, \"{C95DCD1F-CDE3-4C2D-913C-528CB8A4CBE6}\": { \"_comment\": \"Network MIDI\" }, \"{8FEAAD91-70E1-4A19-997A-377720A719C1}\": { \"_comment\": \"Virtual MIDI\" } }, \"endpointProcessingPluginSettings\": { } } . Endpoint Properties . The basics of this are identical for each transport. We’ll use KS (USB) as an example . \"{26FA740D-469C-4D33-BEB1-3885DE7D6DF1}\": { \"_comment\": \"KS MIDI (USB etc.)\" \"SWD: \\\\\\\\?\\\\SWD#MIDISRV#MIDIU_KS_BIDI_6799286025327820155_OUTPIN.0_INPIN.2#{e7cce071-3c03-423f-88d3-f1045d02552b}\": { \"userSuppliedName\" : \"Pete's Kontrol S61\", \"userSuppliedDescription\" : \"This is my most favorite MIDI 2.0 controller in the whole world!\" } }, . Of those, the identification method SWD is the most important. This controls how we identify a matching device. In cases where the manufacturer doesn’t supply a unique iSerialNumber in USB, unplugging your device from one USB port and plugging it into another can result in a new Id. Similarly, if you have two or more of the same device, and they do not have unique serial numbers, it can be impossible for Windows to distinguish between them. Valid values for the identification method prefix . | SWD: : (The colon and trailing space are required). Use the full Windows Endpoint Device Interface Id. For example \\\\\\\\?\\\\SWD#MIDISRV#MIDIU_KS_BIDI_16024944077548273316_OUTPIN.0_INPIN.2#{e7cce071-3c03-423f-88d3-f1045d02552b}. (Note how the backslashes have to be escaped with additional backslashes.) If the device has an iSerialNumber or you never move it between USB ports, this tends to work fine. | (other methods to be added here when we implement them) | . Valid properties you can set across all supported endpoints . | Property | Type | Description | . | userSuppliedName | Quoted Text | The name you want to use for the endpoint. This will override the name displayed in correctly-coded applications, but won’t necessarily change what you see in Device Manager. These names should be relatively short so they display fully in all/most applications, but meaningful to you. | . | userSuppliedDescription | Quoted Text | A text description and/or notes about the endpoint. Applications may or may not use this data | . | forceSingleClientOnly | Boolean true/false (no quotes) | Most endpoints are multi-client (more than one application can use them simultaneously) by default. This setting is for forcing an endpoint to be single-client only (a value of true). It’s unusual to need this, but a typical use may be to disable multi-client for a device which has a custom driver which doesn’t gracefully handle multiple client applications at the same time. | . ",
"url": "/docs/config-json.html#schema",
"relUrl": "/config-json.html#schema"
- },"167": {
+ },"186": {
"doc": "Config JSON",
"title": "Plugin-specific settings",
- "content": "This is not an exhaustive list, because the transport and processing plugins may be created by anyone. Virtual MIDI . Virtual MIDI includes three different sections inside its transport bucket. \"{8FEAAD91-70E1-4A19-997A-377720A719C1}\": { \"_comment\": \"Virtual MIDI\", \"add\": { }, \"update\": { }, \"remove\": { } } . For the persistent configuration file, typically “add” is all that is specified, as it doesn’t make sense to update or remove endpoints or routing on service start. NOTE: This document is not yet complete. We’ll add more details as the schemas are finalized . KS (USB etc) MIDI . TODO: Show how to update endpoint names and provide other properties here . ",
+ "content": "This is not an exhaustive list, because the transport and processing plugins may be created by anyone. Virtual MIDI . TODO: Provide examples for this . For the persistent configuration file, typically “add” is all that is specified, as it doesn’t make sense to update or remove endpoints or routing on service start. NOTE: This document is not yet complete. We’ll add more details as the schemas are finalized . KS (USB etc) MIDI . TODO: Show how to update endpoint names and provide other properties here . ",
"url": "/docs/config-json.html#plugin-specific-settings",
"relUrl": "/config-json.html#plugin-specific-settings"
- },"168": {
+ },"187": {
"doc": "Config JSON",
"title": "Config JSON",
"content": " ",
"url": "/docs/config-json.html",
"relUrl": "/config-json.html"
- },"169": {
+ },"188": {
"doc": "Consuming the MIDI API",
"title": "Consuming the Windows MIDI Services API",
"content": "The Windows MIDI Services API is built using C++/WinRT. WinRT, a requirement for modern APIs on Windows, enables desktop applications, regardless of language, to be able to use APIs, SDKs, etc. that we create. The older tools, C++/CX, are arguably simpler to implement in, but because they include proprietary extensions to C++, we decided to go with standards-based C++/WinRT instead. ",
"url": "/docs/developer-docs/consuming-midi-api.html#consuming-the-windows-midi-services-api",
"relUrl": "/developer-docs/consuming-midi-api.html#consuming-the-windows-midi-services-api"
- },"170": {
+ },"189": {
"doc": "Consuming the MIDI API",
"title": "Prerequisites",
"content": "To use the API, your application language and tools must be able to work with WinRT metadata and libraries, or the generated projection header file. | Visual Studio 2022+ if you are using Visual Studio | Windows SDK 10.0.20348 (Install with Visual Studio) | Windows 10 22H2, or preferably, the latest version of Windows 11. Our development machines are all running Windows 11. | C++ 17 (C++ 20 may work, C++ 14 will not) | The NuGet package(s) from the release | . Note that there are somewhat hacky ways to get traditional C to work with the COM interfaces, but it is a ton of work for you, and is not a scenario we support. If you find yourself in that situation, I recommend factoring out the MIDI code into its own lib and encapsulating all the C++ calls in there. NOTE: In the period of time before Windows MIDI Services ships in Windows, you will also need to run the latest Windows 11 Insider Canary build of Windows in order to be able to use the USB MIDI 2.0 driver. Click here to learn more and join the Windows Insider Program. CPU Architecture: The public GitHub releases currently support Intel/AMD x64 only. Our internal builds and in-box release support x64 as well as Arm64. There is no planned support for Arm(32) or x86. We only support 64 bit applications. ",
"url": "/docs/developer-docs/consuming-midi-api.html#prerequisites",
"relUrl": "/developer-docs/consuming-midi-api.html#prerequisites"
- },"171": {
+ },"190": {
"doc": "Consuming the MIDI API",
"title": "Consuming from C++ with Visual Studio",
"content": "Add the C++/WinRT Nuget package to your C++ project in Visual Studio. This installs the required tools and build process. See the C++/WinRT FAQ link below for using LLVM/Clang. Note that the Windows MIDI Services team does not provide any support for LLVM/Clang, but we will take PRs as required if we need to change something reasonable to ensure you are successful with those tools, within what C++/WinRT can support. In your project, set your target and minimum SDK versions to 10.0.20348.0 . Download the NuGet package for the Core SDK . | Until this is published on NuGet.org, you’ll need to set up a local package repository. This is easy to do inside the NuGet Package Manager in Visual Studio. You simply point to a folder. The structure I use in the local clone of the repo is a subfolder of the release folder for all NuGet packages. Specifically D:\\peteb\\Documents\\GitHub\\microsoft\\midi\\build\\release\\NuGet\\ | . If needed, modify the project file as required (info in the C++/WinRT docs, and you can also look at the sample application code). If you are not using Visual Studio as your toolchain for your project, you may want to pull out the MIDI code into a library in your project which does. It’s not strictly required, but it’s much easier to use C++/WinRT. (If you do not want to do this, you’ll need to manually set up the cppwinrt tools as part of your build process to generate the required Windows.Devices.Midi2.h projection header. After that, you can develop using your normal flow.). Read through this page, specifically the “If the API is implemented in a Windows Runtime component”. After that, you reference the types as you would anything else in C++. Only the toolchain is an extra step. What it produces is standard C++. We’re considering what we can do here to possibly eliminate even that step in the future, but it’s required for now. When in doubt, REbuild your project. C++/WinRT does a lot of code generation for the projections. | C++ Windows MIDI Services Example Code | Introduction to C++/WinRT | C++/WinRT on GitHub | C++/WinRT FAQ | C++/WinRT Troubleshooting | . ",
"url": "/docs/developer-docs/consuming-midi-api.html#consuming-from-c-with-visual-studio",
"relUrl": "/developer-docs/consuming-midi-api.html#consuming-from-c-with-visual-studio"
- },"172": {
+ },"191": {
"doc": "Consuming the MIDI API",
"title": "Consuming from C# Desktop App",
"content": "Your project will currently need to target .NET 7 or above. We prefer .NET 8. Releases will eventually be in the official NuGet.org package source. For now, you can create a local package source and place the NuGet package in there. Then add it to your package sources in the NuGet Package Manager in Visual Studio. The package contains the .NET (C#) projection for .NET 7 and .NET 8. You will still need to install the C#/WinRT NuGet package in your project because we use other Windows SDK types from Windows.Foundation and more. Note that other .NET languages (like Visual Basic) may work, but have not been tested. | C# Windows MIDI Services Example Code | C#/WinRT on GitHub | . ",
"url": "/docs/developer-docs/consuming-midi-api.html#consuming-from-c-desktop-app",
"relUrl": "/developer-docs/consuming-midi-api.html#consuming-from-c-desktop-app"
- },"173": {
+ },"192": {
"doc": "Consuming the MIDI API",
"title": "Consuming from C# UWP",
"content": "Support for this is not yet in place. We are evaluating the need for UWP support. Our top priority is desktop application support. ",
"url": "/docs/developer-docs/consuming-midi-api.html#consuming-from-c-uwp",
"relUrl": "/developer-docs/consuming-midi-api.html#consuming-from-c-uwp"
- },"174": {
+ },"193": {
"doc": "Consuming the MIDI API",
"title": "Consuming from Rust / RS WinRT",
"content": "We will provide more information in the future. However, you will follow a similar approach to C++ using windows-rs instead of C++/WinRT. Note that the Rust WinRT tools are newer and are still in active development. Supporting non-Windows SDK winmd files is or will be supported, but is not intuitive at the moment. There is no existing crate for Windows MIDI Services right now. | Getting Started with windows-rs | Rust for Windows and the windows crate | Set up your Rust Development Environment | Rust Windows MIDI Services Example Code | windows-rs on GitHub | . ",
"url": "/docs/developer-docs/consuming-midi-api.html#consuming-from-rust--rs-winrt",
"relUrl": "/developer-docs/consuming-midi-api.html#consuming-from-rust--rs-winrt"
- },"175": {
+ },"194": {
"doc": "Consuming the MIDI API",
"title": "Consuming from C++ without Visual Studio (using cmake or other tools)",
"content": "The C++/WinRT tool cppwinrt.exe will generate a standard C++ 17 header file Windows.Devices.Midi2.h which you can pull in and include in your project. The header file projections for WinRT types outside of Windows::Devices::Midi2 are included with the Windows SDK. When we ship Windows MIDI Services in-box in Windows, this API will be projected in the same way as all the others in the Windows SDK. First, install the Windows SDK. You can get the SDK from the Windows Dev Center . The SDK install includes the cppwinrt.exe tool. For the 10.0.22621.0 version of the SDK, it is found here on my PC: C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.22621.0\\x64 and C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.22621.0\\arm64 . Pick the version appropriate for your development PC architecture. Normally, all SDK header files, on my PC with the 10.0.22621.0 version of the SDK installed, are located here C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.22621.0\\cppwinrt\\winrt . Generating the Projection Headers . The tool produces the header files from from the .winmd file. This file can be found with the developer release of Windows MIDI Services either as a separate download in the release, or by opening the NuGet package (it’s just a zip file) and pulling it from there. The .winmd file is just metadata about the implementation dll. C:\\demos\\cppwinrt>dir Volume in drive C has no label. Volume Serial Number is 0AEC-1038 Directory of C:\\demos\\cppwinrt 11/09/2023 02:21 PM <DIR> . 11/09/2023 02:20 PM <DIR> .. 11/06/2023 08:48 PM 55,808 Windows.Devices.Midi2.winmd 1 File(s) 55,808 bytes 2 Dir(s) 32,987,725,824 bytes free C:\\demos\\cppwinrt> C:\\demos\\cppwinrt>set cppwinrt=\"C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.22621.0\\x64\\cppwinrt.exe\" C:\\demos\\cppwinrt>%cppwinrt% -input Windows.Devices.Midi2.winmd -reference 10.0.20348.0+ -output .\\projection C:\\demos\\cppwinrt>dir /s Volume in drive C has no label. Volume Serial Number is 0AEC-1038 Directory of C:\\demos\\cppwinrt 11/09/2023 02:26 PM <DIR> . 11/09/2023 02:20 PM <DIR> .. 11/09/2023 02:26 PM <DIR> projection 11/06/2023 08:48 PM 55,808 Windows.Devices.Midi2.winmd 1 File(s) 55,808 bytes Directory of C:\\demos\\cppwinrt\\projection 11/09/2023 02:26 PM <DIR> . 11/09/2023 02:26 PM <DIR> .. 11/09/2023 02:26 PM <DIR> winrt 0 File(s) 0 bytes Directory of C:\\demos\\cppwinrt\\projection\\winrt 11/09/2023 02:26 PM <DIR> . 11/09/2023 02:26 PM <DIR> .. 11/09/2023 02:26 PM <DIR> impl 11/09/2023 02:26 PM 349,214 Windows.Devices.Midi2.h 1 File(s) 349,214 bytes Directory of C:\\demos\\cppwinrt\\projection\\winrt\\impl 11/09/2023 02:26 PM <DIR> . 11/09/2023 02:26 PM <DIR> .. 11/09/2023 02:26 PM 155,054 Windows.Devices.Midi2.0.h 11/09/2023 02:26 PM 22,170 Windows.Devices.Midi2.1.h 11/09/2023 02:26 PM 26,886 Windows.Devices.Midi2.2.h 3 File(s) 204,110 bytes Total Files Listed: 5 File(s) 609,132 bytes 11 Dir(s) 32,988,221,440 bytes free C:\\demos\\cppwinrt> . The minimum SDK to build against is 10.0.20348.0, to support Windows 10. If you get a “Mismatched C++/WinRT headers” message, you can change the version in the command line to be the version of the SDK you downloaded. Typically, that is not necessary as long as you use the version of cppwinrt.exe from the same SDK root location where you reference the SDK headers from. Using the Projection . Once you have the header file referenced, you can use the same sample code used in the C++/WinRT examples. Note that the generated projection header takes care of referencing dependencies from the generated files and from the SDK. You will need to ensure that referenced tree of files is part of your build process by having the correct include path for the generated files and the SDK headers. NOTE: don’t use my example below. That is subject to change. Use what is actually generated. // WARNING: Please don't edit this file. It was generated by C++/WinRT v2.0.220110.5 #pragma once #ifndef WINRT_Windows_Devices_Midi2_H #define WINRT_Windows_Devices_Midi2_H #include \"winrt/base.h\" static_assert(winrt::check_version(CPPWINRT_VERSION, \"2.0.220110.5\"), \"Mismatched C++/WinRT headers.\"); #define CPPWINRT_VERSION \"2.0.220110.5\" #include \"winrt/Windows.Devices.h\" #include \"winrt/impl/Windows.Data.Json.2.h\" #include \"winrt/impl/Windows.Devices.Enumeration.2.h\" #include \"winrt/impl/Windows.Devices.Midi.2.h\" #include \"winrt/impl/Windows.Foundation.2.h\" #include \"winrt/impl/Windows.Foundation.Collections.2.h\" #include \"winrt/impl/Windows.Devices.Midi2.2.h\" ... Note: As of the time of this writing, the generated projections are compatible with C++/17. [They are not compatible with C++/20]https://github.com/microsoft/cppwinrt/issues/1322(). This issue is out of the control of the MIDI project. GCC Support . We haven’t tried it ourselves, but C++/WinRT does appear to be compatible with GCC. See this pull request from 2022. ",
"url": "/docs/developer-docs/consuming-midi-api.html#consuming-from-c-without-visual-studio-using-cmake-or-other-tools",
"relUrl": "/developer-docs/consuming-midi-api.html#consuming-from-c-without-visual-studio-using-cmake-or-other-tools"
- },"176": {
+ },"195": {
"doc": "Consuming the MIDI API",
"title": "Consuming from NodeJS / Electron",
"content": "We are investigating projection support for node.js / Electron. We have a prelimary version working. In that version, the code to enumerate endpoints and then send messages in a loop looks like this: . function createWindow () { const mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__dirname, 'preload.js') } }) mainWindow.loadFile('index.html') // Enumerate endpoints const endpoints = midi2.MidiEndpointDeviceInformation.findAll( midi2.MidiEndpointDeviceInformationSortOrder.name, midi2.MidiEndpointDeviceInformationFilter.includeDiagnosticLoopback + midi2.MidiEndpointDeviceInformationFilter.includeClientUmpNative + midi2.MidiEndpointDeviceInformationFilter.includeClientByteStreamNative); console.log(endpoints); for (var i = 0; i < endpoints.size; i++) { var endpoint = endpoints.getAt(i); console.log(endpoint.id); console.log(endpoint.deviceInstanceId); console.log(endpoint.name); console.log(endpoint.description); console.log(endpoint.transportMnemonic); console.log(\"------------------------------------------------\"); console.log(\"\"); } const loopbackAId = midi2.MidiEndpointDeviceInformation.diagnosticsLoopbackAEndpointId; const loopbackBId = midi2.MidiEndpointDeviceInformation.diagnosticsLoopbackBEndpointId; // create a new session var session = midi2.MidiSession.createSession(\"Electron Test Session\"); // connect to loopback A var sendConnection = session.createEndpointConnection(loopbackAId); // connection needs to be opened before it is used sendConnection.open(); // send messages out to that endpoint for (var j = 0; j < 1000; j++) { sendConnection.sendMessageWords(midi2.MidiClock.now, 0x48675309, 0xDEADBEEF); } session.close(); } . You can see it’s very similar to the code for other languages like C# and C++. Here’s what the output looked like in the initial test. I also had a midi.exe console running and all 1000 messages were received. C:\\demos\\node-midi\\electron-midi>npm start > electron-midi@1.0.0 start > electron . Windows::Foundation::Collections:IVectorView { __winRtInstance__: true } \\\\?\\SWD#MIDISRV#MIDIU_DIAG_LOOPBACK_A#{e7cce071-3c03-423f-88d3-f1045d02552b} SWD\\MIDISRV\\MIDIU_DIAG_LOOPBACK_A Diagnostics Loopback A Diagnostics loopback endpoint. For testing purposes. DIAG ------------------------------------------------ \\\\?\\SWD#MIDISRV#MIDIU_DIAG_LOOPBACK_B#{e7cce071-3c03-423f-88d3-f1045d02552b} SWD\\MIDISRV\\MIDIU_DIAG_LOOPBACK_B Diagnostics Loopback B Diagnostics loopback endpoint. For testing purposes. DIAG ------------------------------------------------ \\\\?\\SWD#MIDISRV#MIDIU_KS_BIDI_14488056966904779946_OUTPIN.0_INPIN.1#{e7cce071-3c03-423f-88d3-f1045d02552b} SWD\\MIDISRV\\MIDIU_KS_BIDI_14488056966904779946_OUTPIN.0_INPIN.1 UM-ONE KS ------------------------------------------------ C:\\demos\\node-midi\\electron-midi> . ",
"url": "/docs/developer-docs/consuming-midi-api.html#consuming-from-nodejs--electron",
"relUrl": "/developer-docs/consuming-midi-api.html#consuming-from-nodejs--electron"
- },"177": {
+ },"196": {
"doc": "Consuming the MIDI API",
"title": "Flutter / Dart",
"content": "Once the API is in-box on Windows, it will be possible for the projections to be generated by the Flutter/Dart teams, like they do with the Windows SDK today. ",
"url": "/docs/developer-docs/consuming-midi-api.html#flutter--dart",
"relUrl": "/developer-docs/consuming-midi-api.html#flutter--dart"
- },"178": {
+ },"197": {
"doc": "Consuming the MIDI API",
"title": "Webview2 Hosted / PWA",
"content": "We are investigating. ",
"url": "/docs/developer-docs/consuming-midi-api.html#webview2-hosted--pwa",
"relUrl": "/developer-docs/consuming-midi-api.html#webview2-hosted--pwa"
- },"179": {
+ },"198": {
"doc": "Consuming the MIDI API",
"title": "Python",
"content": "Once the API is in the Windows SDK, tools like PyWinRT can be used to create projections. ",
"url": "/docs/developer-docs/consuming-midi-api.html#python",
"relUrl": "/developer-docs/consuming-midi-api.html#python"
- },"180": {
+ },"199": {
"doc": "Consuming the MIDI API",
"title": "Consuming the MIDI API",
"content": " ",
"url": "/docs/developer-docs/consuming-midi-api.html",
"relUrl": "/developer-docs/consuming-midi-api.html"
- },"181": {
+ },"200": {
"doc": "Diagnostics Endpoints",
"title": "MIDI Diagnostic Endpoints",
"content": "Windows MIDI Services comes with three diagnostic endpoints, two of which are there for application development, testing, and debugging. ",
"url": "/docs/developer-docs/diagnostic-endpoints.html#midi-diagnostic-endpoints",
"relUrl": "/developer-docs/diagnostic-endpoints.html#midi-diagnostic-endpoints"
- },"182": {
+ },"201": {
"doc": "Diagnostics Endpoints",
"title": "Loopbacks A and B",
"content": "Windows MIDI Services comes with two loopback endpoints which are always present if the Windows service is running. These cannot be turned off by applications or configuration, and so may be relied upon by customer support, unit tests, and more. The Endpoint Device Ids are available as static members of the MidiEndpointDeviceInformation class . winrt::hstring MidiEndpointDeviceInformation::DiagnosticsLoopbackAEndpointId(); winrt::hstring MidiEndpointDeviceInformation::DiagnosticsLoopbackBEndpointId(); . By default, these endpoints are not returned by enumeration calls, because most applications would not want to present them to the user. However, you can include them in the MidiEndpointDeviceInformation::FindAll and MidiEndpointDeviceWatcher::CreateWatcher device filters by using the MidiEndpointDeviceInformationFilter enum value IncludeDiagnosticLoopback if your application has a diagnostic need for them. MidiEndpointDeviceInformationFilter::IncludeDiagnosticLoopback . Diagnostic Loopback Endpoints A and B are cross-wired so that any message sent out on loopback A will come in on loopback B, and any message sent out on B will come in on A. In this way, the loopbacks function as a global app-to-app MIDI implementation for testing. Note that there is only one instance of each endpoint in the system, so if multiple applications use the loopback, the messages will get mixed together like any other endpoint. TIP: The Diagnostic Loopback Endpoints are in place for testing and development only. Applications should not present them to users, or use them for communication outside of testing and debugging. Don’t expose the diagnostic loopback endpoints as part of the list of endpoints in a production DAW application. Special Timestamp Behavior . Normally, an incoming MIDI message will receive a new timestamp when it first arrives from a remote endpoint. In this way, you know exactly when the Windows service first “saw” the message. The loopback endpoints are special-cased so that they do not alter the original sent timestamp. The entire message and timestamp, is sent back exactly as it is received. If you send a message to a loopback with a timestamp of 0 (send immediately), it will come back with the same 0 timestamp. Similarly, if you specify an actual timestamp, that same timestamp will come back in the received message. The latter can be helpful in unit testing when you need to correlate a sent message with a received message, or you need to verify that the specific timestamp you sent was actually sent. If you need the more typical timestamp behavior, you can set up app-to-app MIDI virtual endpoints. Metadata Capture . The Loopback endpoints capture Endpoint and Function Block metadata just like any other endpoint. Because of this, you can change the name of the endpoint through in-protocol messages. If you do that, simply change it back later using the same type of message. Note: We’re working to purge the endpoint metadata cache on device reconnection or service restart, which would reset those properties and names. Currently, it persists across service and Windows restarts. ",
"url": "/docs/developer-docs/diagnostic-endpoints.html#loopbacks-a-and-b",
"relUrl": "/developer-docs/diagnostic-endpoints.html#loopbacks-a-and-b"
- },"183": {
+ },"202": {
"doc": "Diagnostics Endpoints",
"title": "Ping",
"content": "The ping endpoint is not normally returned through any enumeration. It is for internal use only, and should not be used by any applications. It recognizes only one type of proprietary message. Behavior and implementation of the Ping endpoint is subject to change and should not be relied upon by any code outside of the API. ",
"url": "/docs/developer-docs/diagnostic-endpoints.html#ping",
"relUrl": "/developer-docs/diagnostic-endpoints.html#ping"
- },"184": {
+ },"203": {
"doc": "Diagnostics Endpoints",
"title": "Diagnostics Endpoints",
"content": " ",
"url": "/docs/developer-docs/diagnostic-endpoints.html",
"relUrl": "/developer-docs/diagnostic-endpoints.html"
- },"185": {
+ },"204": {
"doc": "Endpoint Device Ids",
"title": "Endpoint Device Ids",
- "content": "The Endpoint Device Id (also referred to as a Device Id) is the way we identify individual devices and interfaces in Windows. Example for one of the built-in loopback endpoints: \\\\?\\SWD#MIDISRV#MIDIU_LOOPBACK_A#{e7cce071-3c03-423f-88d3-f1045d02552b} . | Part | Description | . | SWD | Software device | . | MIDISRV | The name of the enumerator. For Windows MIDI Services, this is the MidiSrv Windows Service | . | MIDIU_LOOPBACK_A | Arbitrary unique identification string provided by the transport. Typically includes a unique identifier. | . | GUID | The interface Id. For Windows MIDI Services, every interface is a bidirectional interface, even if the connected device is MIDI 1.0 with a single unidirectional interface. For MIDI 1.0 devices, you can look at the group terminal blocks to identify active groups/directions. For MIDI 2.0 devices, you can look at the function blocks for the same information and more. | . If you look at the device in Device Manager, and look at Details/Device Instance Path, you’ll see all of the information here except for the interface Id. When you enumerate devices through Windows::Devices::Enumeration, the interface Id is included and required. Tip: Although it was required in the past, we don’t recommend parsing these strings. If there’s information you need about the device which is not contained in the enumerated properties, please let us know and we’ll look into whether or not we can create a custom property to hold that. ",
+ "content": "The Endpoint Device Id (also referred to as a Device Id) is the way we identify individual devices and interfaces in Windows. Example for one of the built-in loopback endpoints: . \\\\?\\SWD#MIDISRV#MIDIU_DIAG_LOOPBACK_A#{e7cce071-3c03-423f-88d3-f1045d02552b} . | Part | Description | . | SWD | Software device. This is any device that is not a physical device connected to the PC, and which is created using the Software Device APIs. All MIDI endpoints are software devices and may or may not have a physical connected device as a parent. | . | MIDISRV | The name of the enumerator. For Windows MIDI Services, this is the MidiSrv Windows Service | . | MIDIU | Indicates a MIDI UMP interface. | . | DIAG | Mnemonic for the transport which created this device interface. | . | LOOPBACK_A | Arbitrary unique identification string provided by the transport. Typically includes a unique identifier like a serial number. It may also contain other information like the pin pairs used to provide the bidirectional communication. | . | MIDIU_DIAG_LOOPBACK_A | The entire string here is controlled by the transport. By convention it breaks down into the fields mentioned above, but that is not something you should count on. In general, parsing these strings is not recommended. | . | GUID | The interface Id. For Windows MIDI Services, every interface is a bidirectional interface, even if the connected device is MIDI 1.0 with a single unidirectional interface. For MIDI 1.0 devices, you can look at the group terminal blocks to identify active groups/directions. For MIDI 2.0 devices, you can look at the function blocks for the same information and more. | . If you look at the device in Device Manager, and look at Details/Device Instance Path, you’ll see all of the information here except for the interface Id. When you enumerate devices through Windows::Devices::Enumeration or through Windows MIDI Services, the interface Id is included and required. Tip: Although it was required in the past, we don’t recommend parsing these strings. If there’s information you need about the device which is not contained in the enumerated properties, please let us know and we’ll look into whether or not we can create a custom property to hold that. ",
"url": "/docs/developer-docs/endpoint-ids.html",
"relUrl": "/developer-docs/endpoint-ids.html"
- },"186": {
+ },"205": {
"doc": "Programming Languages FAQ",
"title": "Programming Languages and App Models FAQ",
"content": "This is a developer-focused FAQ. ",
"url": "/docs/developer-docs/faq-programming-languages.html#programming-languages-and-app-models-faq",
"relUrl": "/developer-docs/faq-programming-languages.html#programming-languages-and-app-models-faq"
- },"187": {
+ },"206": {
"doc": "Programming Languages FAQ",
"title": "WinRT",
"content": "Q: Why is the API and SDK WinRT instead of a set of C headers like classic APIs? Why not use classic COM? A: New APIs for Windows are required to be WinRT, unless there are really good reasons not to be. WinRT is enhanced COM with a richer type system with better support for use by most of the languages and frameworks used to develop Windows applications. Q: Does the fact that the API and SDK are WinRT mean they are sandboxed? A: No. WinRT is modern COM. The term has been overloaded in the past to also include an app model, Store requirements, and more. In this project, WinRT simply means the implementation flavor with support for projections. It does not impose any sandbox or other restrictions on consuming applications. Q: Why does the service plugin model use COM instead of WinRT? A: For our runtime discovery-based plugin model, “Classic” COM makes more sense. WinRT components need to be known at compile time. Q: Why do MIDI namespaces sometimes start with Microsoft instead of Windows? A: Anything targeted for delivery in-box can use Windows.Devices. Anything which is an additional component download for applications, like the SDK, use Microsoft as the top-level namespace as per our conventions. ",
"url": "/docs/developer-docs/faq-programming-languages.html#winrt",
"relUrl": "/developer-docs/faq-programming-languages.html#winrt"
- },"188": {
+ },"207": {
"doc": "Programming Languages FAQ",
"title": "Projections",
"content": "Q: Which projections will this project deliver? A: We will start with the basic projections: C++, C# (current .net versions), and JavaScript. We will add more (Rust, for example) as we proceed in development. We want to be as inclusive here as we can reasonably be. ",
"url": "/docs/developer-docs/faq-programming-languages.html#projections",
"relUrl": "/developer-docs/faq-programming-languages.html#projections"
- },"189": {
+ },"208": {
"doc": "Programming Languages FAQ",
"title": "App Models",
"content": "Q: What is the primary app model the API and SDK are targeting? A: Windows desktop apps of all types including C++, C#, Electron, and more. Q: Do the API and SDK support UWP Applications? A: During the initial testing rollout, the API is not built into Windows, and so may not be completely compatible with UWP apps. TBD which functions are usable from the UWP sandbox in the future, but we want to support as much as is possible. ",
"url": "/docs/developer-docs/faq-programming-languages.html#app-models",
"relUrl": "/developer-docs/faq-programming-languages.html#app-models"
- },"190": {
+ },"209": {
"doc": "Programming Languages FAQ",
"title": "Project Implementation Languages",
"content": "Q: Which languages are used in the project? A: Primarily, the project is C++ and C#. Q: Why is the API and SDK C++ instead of Rust? A: Rust supports WinRT, including authoring, through the rs/WinRT project. However, Rust does not currently support Arm64EC, which means apps on Arm64 devices which need to load x64 plugins (that is, most DAWs) would not be able to load the SDK into their process. Additionally, modern C++ can be used quite safely, it’s just not “safe by default” like Rust is. Q: Why is the API and SDK C++ instead of C#/.net? A: The majority of DAWs are written in C++ or similar languages. Although one can create WinRT components from C#, they carry along a runtime and garbage collection which most DAW developers do not want in their process. Additionally, C# does not support Arm64EC. Q: Why are the apps in C# /.net? A: C# is a great language for applications. Additionally, we want to encourage contributions from our enormous C#/.net development community. Q: Why is the Windows Service C++ instead of C#, Rust, or something else? A: Early prototypes of the service were in C#, which worked fine for most things, until you got into the kernel data transfer, integration with the PnP stack, and more. The implementation team already knows how to use those features and APIs, with great performance, in C++ based on their work with the audio services in Windows today, so the implementation is in C++. Q: Why does the driver have reimplementations of features we see in the standard library? A: In kernel mode drivers, the standard library is largely unavailable. ",
"url": "/docs/developer-docs/faq-programming-languages.html#project-implementation-languages",
"relUrl": "/developer-docs/faq-programming-languages.html#project-implementation-languages"
- },"191": {
+ },"210": {
"doc": "Programming Languages FAQ",
"title": "Programming Languages FAQ",
"content": " ",
"url": "/docs/developer-docs/faq-programming-languages.html",
"relUrl": "/developer-docs/faq-programming-languages.html"
- },"192": {
+ },"211": {
"doc": "Windows Midi Services",
"title": "Windows MIDI Services",
"content": "Source repo and developer releases on GitHub . Discord Server for discussion about this project . ",
"url": "/docs/#windows-midi-services",
"relUrl": "/#windows-midi-services"
- },"193": {
+ },"212": {
"doc": "Windows Midi Services",
"title": "Key Features",
"content": ". | Multi-client by default. Unless an endpoint is configured to not allow shared connections, or there is some issue around multi-client in a third-party driver, any endpoint (including MIDI 1.0 devices) can be used by multiple applications at the same time. So far, in our testing, we haven’t found any USB devices or drivers which cannot be multi-client. | Faster. In our testing, we’ve found that the new infrastructure is much faster at sending and receiving messages compared to the older API, even with plugins configured in the service. There are no built-in speed caps or throttling in Windows MIDI Services, even for older USB MIDI 1.0 devices. The driver is not limited USB full-speed, and supports USB 3.x speeds. | Lower Jitter. Along with higher speed comes lower jitter. This will vary by transport type (USB vs Network vs Virtual), and the device Windows is talking to, but the jitter is in the low microsecond range even without any compensation. | More Deterministic. Speaking of latency compensation, the new API enables timestamp-based message scheduling for outbound messages, and also will soon support Jitter Reduction timestamps for MIDI 2.0 devices which can use them. | Extensible. The service has been designed to be extensible by Microsoft and third-parties. New types of transports can be added at any time, including during prototyping of a new transport specification. (We’re working on Network MIDI 2.0, Bluetooth MIDI 1.0 and considering RTP, all using this model.) Similarly, message processing plugins can also be developed by Microsoft or third-parties and used for production and/or prototyping. No kernel driver experience required in most cases. | App-to-App and Virtual MIDI. Windows MIDI Services includes virtual / app-to-app MIDI 2.0 to enable lightning fast communication between apps on the PC. We’re also investigating flexible routing between any MIDI endpoints as a future feature. | Better tools. We supply the midi.exe Windows MIDI Services Console for developers and power users, or anyone comfortable with the command line. You can use it to monitor endpoints, send and receive messages, send/capture SysEx data and much more. We’ll deliver the MIDI Settings GUI app after our initial release. That app enables renaming devices, configuring your MIDI setup, testing, and more. | UMP-Centric. The new API fully embraces MIDI 2.0 and the Universal MIDI Packet format and handles all required translation in the service and driver. This makes the app model simple while ensuring all your existing devices continue to work. | Open Source. The source code is open and available to everyone under a permissive license. Not sure how something works? Want to create a transport but aren’t sure how we did it? Want to investigate a bug or contribute a feature? The code is there for you to explore. | . Note: Additionally MIDI CI functionality, which does not technically require OS support, will be coming after version 1.0. We intend to add helpers for profiles, property exchange, MUID tracking, and more. In the meantime, applications can send and receive MIDI CI messages without anything in their way, using custom code or third-party libraries. MIDI CI is just MIDI 1.0-compatible SysEx. ",
"url": "/docs/#key-features",
"relUrl": "/#key-features"
- },"194": {
+ },"213": {
"doc": "Windows Midi Services",
"title": "API Backwards Compatibility",
"content": "Our intention is for developers to begin adopting Windows MIDI Services in place of the older WinMM, WinRT, and (deprecated) DirectMusic APIs in their applications. All new MIDI features, transports, and more will be implemented in Windows MIDI Services and the new API. A select number of features, slightly more than their current baseline, will be available to WinMM and WinRT APIs through our backwards-compatibility shims and abstractions, but this is simply to ensure existing applications continue to function on systems using Windows MIDI Services. Please note that we are not providing backwards compatibility to support DirectMusic MIDI APIs. The existing MIDI APIs on Windows talk (almost) directly to MIDI 1.0 drivers through kernel calls. In Windows MIDI Services, the architecture is built around a central Windows Service, much like our audio system today. It also uses a much faster IO mechanism for communication with the USB driver vs what our MIDI 1.0 API uses today. This provides much more flexibility, including the potential for multi-client use, and good baseline speed with our new class driver. We are working on shims and abstractions which will allow some of the existing MIDI 1.0 APIs to talk to the service rather than directly to the driver. Here is where we currently stand with planned backwards compatibility. Backwards compatibility for WinMM and WinRT APIs will be a post-1.0 feature, but shortly after that first release. | API | What you should expect | . | Windows MIDI Services | This project. 100% of all supported features for MIDI 1.0 and MIDI 2.0, including multi-client. API/SDK uses UMP as its internal data format even for MIDI 1.0 devices. Transports and the service handle translation. | . | WinMM (Win32 API most apps use today) | Access to MIDI 1.0 and most MIDI 2.0 devices, at a MIDI 1.0 compatibility level only. It is possible we will add multi-client support here after our initial release. | . | WinRT (MIDI API Introduced with Windows 10) | Access to MIDI 1.0 and most MIDI 2.0 devices, at a MIDI 1.0 compatibility level only. It is possible we will add multi-client support here after our initial release. | . | DirectMusic | No compatibility planned. Not part of our testing. | . Note that we are also investigating and experimenting with how to best incorporate the existing in-box Roland GS / General MIDI Synth into this architecture. It’s likely we will handle it as an additional transport, but we need to test some of the MIDI file players today as many of them make assumptions about which synth index is the GS synth, so this compatibility may come after the initial release. ",
"url": "/docs/#api-backwards-compatibility",
"relUrl": "/#api-backwards-compatibility"
- },"195": {
+ },"214": {
"doc": "Windows Midi Services",
"title": "Resources",
"content": "Developer Materials . | Get started examples | API Documentation | Samples | Programming Languages FAQ | . Windows MIDI Services Console app . | Console overview | . Advanced Materials . | JSON Configuration File | . Relevant specifications . These are the updated MIDI 2.0 specifications which apply to this project today. | MIDI 2.0 UMP Specifications | . ",
"url": "/docs/#resources",
"relUrl": "/#resources"
- },"196": {
+ },"215": {
"doc": "Windows Midi Services",
"title": "Windows Midi Services",
"content": " ",
"url": "/docs/",
"relUrl": "/"
- },"197": {
+ },"216": {
"doc": "MIDI Console",
"title": "Windows MIDI Services Console",
"content": "If you have the midi console installed, you can invoke it from any command prompt using midi. We recommend using Windows Terminal for the best experience. ",
"url": "/docs/midi-console.html#windows-midi-services-console",
"relUrl": "/midi-console.html#windows-midi-services-console"
- },"198": {
+ },"217": {
"doc": "MIDI Console",
"title": "General Information",
"content": "Commands vs Options . MIDI Console commands are words with no symbol prefix. For example endpoint or send-message-file. Options are prefixed with two dashes if you use the full word, or a single dash if you use the single-letter abbreviation. For example --help or -h. There is no statement completion built in to the console, but there are some supported abbreviations for commands. These are not yet fully documented but are present in the Program.cs in the console source code. “Ports” vs “Streams” . In MIDI 1.0, specifically USB MIDI 1.0, a connected device would have a single input and single output stream. Inside that stream are packets of data with virtual cable numbers. Those numbers (16 total at most) identify the “port” the data is going to. Operating systems would then translate those into input and output ports. Those cable numbers were hidden from users. MIDI 2.0 does not have a concept of a port. Instead, you always work with the stream itself. The group number, which is in the MIDI message now, is the moral equivalent of that cable number. So where you may have seen a device with 5 input and 5 output ports in the past, you will now see a single bidirectional UMP Endpoint stream with 5 input groups and 5 output groups. We know this can take some getting used to, but it enables us to use MIDI 1.0 devices as though they are MIDI 2.0 devices, and provide a unified API. Help . Add the option --help or its short version -h to any command to get information and examples for that command. midi --help midi service --help midi enumerate --help midi enumerate endpoints --help . The --help option will always provide the most up-to-date list of commands and options supported by the MIDI Services Console. ",
"url": "/docs/midi-console.html#general-information",
"relUrl": "/midi-console.html#general-information"
- },"199": {
+ },"218": {
"doc": "MIDI Console",
"title": "Check the MIDI Service Health",
"content": "The heart of Windows MIDI Services is the Windows Service which processes and routes messages, creates endpoints, and more. The MIDI Services Console app includes a few commands to check the status and health of the service. Check MIDI Service Status . If you want to verify that the MIDI Service is running, you can check its status using the Service Control Manager, or through the MIDI Console. midi service status midi svc status . If you uset the --verbose or -v option, the console will display more information about the service. midi service status midi svc status . Ping the Service . If you want to verify that the service is transmitting and receiving messages, you can use the ping command, much like you would . midi service ping midi svc ping . This command also supports the --verbose or -v option to display the full results of the ping. It also supports a --count or -c parameter for the number of messages you want to send. Finally, the call supports a --timeout or -t parameter to set the timeout in milliseconds before the ping is considered to have failed. Here are examples of the command with various parameters. midi service ping --verbose midi service ping --verbose --count 20 --timeout 20000 . Stop / Start / Restart the Service . The MIDI console has three commands for managing the Windows service. These can be useful when developing or debugging service-side plugins. Note that these must be run from an Administrator console session. midi service stop midi service start midi service restart . ",
"url": "/docs/midi-console.html#check-the-midi-service-health",
"relUrl": "/midi-console.html#check-the-midi-service-health"
- },"200": {
+ },"219": {
"doc": "MIDI Console",
"title": "See the Current Timestamp and Frequency",
"content": "If you want to see the MIDI clock we’re using for timestamps and message scheduling, you can use the time command. It will display the current timestamp in ticks, and the number of ticks per second (the resolution) . midi time midi clock . ",
"url": "/docs/midi-console.html#see-the-current-timestamp-and-frequency",
"relUrl": "/midi-console.html#see-the-current-timestamp-and-frequency"
- },"201": {
+ },"220": {
"doc": "MIDI Console",
"title": "Enumerate (List) MIDI Entities",
"content": "A basic operation you may do with the tool is list the major entities (Endpoints and Plugins) in the system. The enumerate command has the aliases enum and list which may be used instead of the full enumerate command. Enumerate MIDI UMP Endpoints . The ump-endpoints parameter has the alias endpoints and the alias ump so either may be used with the same results. These commands are all equivalent: . midi enumerate ump-endpoints midi enumerate endpoints midi enum endpoints midi list endpoints midi list ump . All of the above statements will return a list of all the user-focused UMP endpoints on the system. Note: There are loopback endpoints A and B that are always available and are built into the service. They are crosswired to each other so that any message sent to A is received on B, and vice versa. They cannot be removed or disabled. Because these are more for support, testing, and developer scenarios, they are not returned from enumeration calls by default. Instead, you would supply the --include-loopback option for the enumeration commands. Enumerate Classic Byte-stream (MIDI 1.0) Endpoints . This uses the old WinRT API. Its primary reason for existance is so you can see what’s shown to older APIs vs what is shown for the new Windows MIDI Services API. As with the UMP endpoints, the commands have aliases, so the following are all equivalent . midi enumerate bytestream-endpoints midi enumerate legacy-endpoints midi enum legacy-endpoints midi list legacy . Enumerate Transport Plugins . TODO: This feature is actively in development. Enumerate Message Processing Plugins . TODO: This feature is actively in development. ",
"url": "/docs/midi-console.html#enumerate-list-midi-entities",
"relUrl": "/midi-console.html#enumerate-list-midi-entities"
- },"202": {
+ },"221": {
"doc": "MIDI Console",
"title": "Watch UMP Endpoints for Changes",
"content": "Enumerating endpoints gives you a snapshot of the list at a moment in time. Watching the endpoints will give you a constantly updating list, which reflects device add/remove as well as property updates. This is useful more for developers, or those who are using tools to modify endpoints and want to verify that the changes were reported. The watch-endpoints command has the alias watch, so these are equivalent: . midi watch-endpoints midi watch . Note that only UMP endpoints (or bytestream endpoints converted to UMP by the new USB driver and service) are watched for changes. The older MIDI API is not used here. When you want to stop watching the endpoints for changes, hit the escape key. ",
"url": "/docs/midi-console.html#watch-ump-endpoints-for-changes",
"relUrl": "/midi-console.html#watch-ump-endpoints-for-changes"
- },"203": {
+ },"222": {
"doc": "MIDI Console",
"title": "Single-Endpoint Commands",
"content": "There are a number of commands, including those for monitoring and sending messages, which operate on a single endpoint. In most any command which takes an Endpoint Device Id as a parameter, that parameter is optional. If you leave it out, and the command operates on a single endpoint, you will be prompted with a menu of available endpoints to work with. If you want to script the commands without requiring any user interaction, provide the endpoint device ID as the first parameter after the endpoint command. For example: . midi endpoint \\\\?\\SWD#MIDISRV#MIDIU_DIAG_LOOPBACK_B#{e7cce071-3c03-423f-88d3-f1045d02552b} properties --verbose . Get Detailed Endpoint Properties . In the Device Manager in Windows, you can only see a subset of properties for a device. The same goes with the pnputil utility. It can be useful to see all of the key properties of a MIDI Endpoint. Therefore, we’ve baked property reporting right into the MIDI Services Console. midi endpoint properties . By default, only key properties are displayed. If you want to see the complete list of all properties for the endpoint device, its container, and its parent device, add the --verbose parameter. midi endpoint properties --verbose . As with other endpoint commands, if you provide the endpoint device Id, it will be used. Otherwise, you will be prompted to select an endpoint. Monitor an Endpoint for Incoming Messages . By default, every UMP Endpoint in Windows MIDI Services is multi-client. That means that more than one application can open a connection to the endpoint and send and/or receive messages. This also makes it possible to monitor all the incoming messages on an endpoint, even when that endpoint is in use by another application. When run in verbose mode, the monitor will display each message as it arrives. It also displays helpful information about the type of the message, the group and channel when appropriate, the timestap offset (from the previous message if it was received recently), and more. This requires a fairly wide console window to allow formatting each message to take up only a single line. In a narrow window the format will be a bit ugly. We recommend using the Windows Terminal application, which has support for zooming in and out using the mouse wheel, different fonts, and more. When run without the --verbose option, the monitor displays only key data for the incoming messages. Default mode: . midi endpoint monitor . Verbose mode: . midi endpoint monitor --verbose . Saving messages to a file . When monitoring, you also have the option to save the messages to a file. This can be used to capture test data which you will send using the send-message-file command, or for storing something like a System Exclusive dump. midi endpoint monitor --capture-to-file %USERPROFILE%\\Documents\\MyMidiCapture.midi2 --annotate-capture --capture-field-delimiter Pipe . | The annotation option puts a comment before each message line, with additional details, including the timestamp. | The delimiter option enables you to specify how to delimit the MIDI words in the file. By default, the words are delimitated with spaces. | . The file you choose to write to will be appended to if it already exists. Use caution when specifying the file name, so that you don’t corrupt an unrelated file with this MIDI data. If no file extension is specified, the extension .midi2 will be automatically added to the filename. When you have completed monitoring an endpoint, hit the escape key to close the connection and the app. Send a Message from the Command Line . Sending a message to an endpoint is very helpful for testing, but can also be used in automation to, for example, change the current program, or set a MIDI CC value. It would be very easy for a person to build a batch file or PowerShell script which used midi.exe to synchronize different devices, or reset devices to a known state in preparation for a performance. The message data beyond the message type (first 4 bits) is not pre-validated, so the data can be anything. However, the number of 32 bit words must match the message type per the MIDI 2.0 specification. Send a single UMP32 message immediately . midi endpoint send-message 0x21234567 . Send a single UMP64 message ten times . midi endpoint send-message 0x41234567 0xDEADBEEF --count 10 . Send a single UMP64 message fifteen times, but with a delay of two seconds (2000 milliseconds) in between each message. Delays are in milliseconds because they are there primarily to prevent flooding with older devices. midi endpoint send-message 0x41234567 0xDEADBEEF --count 15 --pause 2000 . In general, we recommend sending messages in hexadecimal format (prefix 0x followed by 8 hexadecimal digits)as it is easier to visually inspect the information being sent. The 1-4 MIDI words are in order from left to right, from 1 to 4. Special debug messages . One thing that can be useful is to send otherwise valid UMP messages where the last word is incremented by 1 for each sent message. This helps to validate that all messages were received by your application, and in the correct order. Note that this requires a message type of at least two words. We don’t recommend sending Type F stream messages as those have the potential to corrupt data. Instead, a Type 4 MIDI 2.0 channel voice message is usually safer. midi endpoint send-message 0x41234567 0x00000000 --count 10000 --pause 2 --debug-auto-increment . When sent, you should see messages where the second word is updated from 0x00000000 through 0x00002710 (decimal 10000). We recommend the pause when sending large numbers of messages because a pause of 0 (“send as fast as possible”) can flood the buffers with more data than the client may be able to retrieve in time and may result in dropped messages. A warning is displayed when that possibility seems likely. Scheduling messages . NOTE: In current Developer Preview builds, message scheduling is turned off so the timestamp is ignored. Refer to the release notes. When sending messages, you have two options for timestamps: . --offset-microseconds is used to add a fixed time to each outgoing message so that it is scheduled that far into the future. Schedule a single UMP64 message 2 seconds from now (2 million microseconds). Offsets are in microseconds to provide more precise control compared to milliseconds. midi endpoint send-message 0x41234567 0xFEEDF00D --offset-microseconds 2000000 . You can also specify an absolute timestamp. Typically, this is used to be able to specify a timestamp of 0, which means to bypass any scheduling and send immediately. midi endpoint send-message 0x41234567 0xFEEDF00D --timestamp 0 . Of course, you can also use the midi time command to see the current timestamp, and then use that information to pick a future timestamp. Finally, if you do not specify a timestamp, the current time is used. Send a File full of Messages . If you want to send a file full of messages, for SysEx or testing, for example, the console has provision for this. The file needs to have one message per line, with 1-4 32 bit words as appropriate. There are options for delimeter (auto, space, comma, pipe, tab), word format (binary, hex, or decimal) as well as an option to change the group index. The latter is especially important when you have a SysEx file saved from one group and you want to send it on another group. The file name can include system variables which require expansion. midi endpoint send-message-file %userprofile%\\Documents\\SysExBank12.txt --new-group-index 5 . There are a number of options for this command both for the format it is reading, but also for the delay between messages (for older devices) and more. To get an explanation for each, type: . midi endpoint send-message-file --help . Here is one of the test files we use. It demonstrates comments, multiple representations for numbers, different delimeters, and more. # This is a test file for sending UMPs through Windows MIDI Services # It uses auto for the field delimiter so we can have different # delimiters on each line. Numeric format for this file is always hex. # The line above was empty. The next data line is a UMP32 0x22345678 # The messages aren't valid beyond their message type matching the number of words 0xF1345678 0x12345678 0x03263827 0x86753099 0xF2345678,0x12345678,0x86754321, 0x86753099 0xF3345678|0x12345678| 0x86754321|0x86753099 0x21345678 0x42345678 0x12341234 0x43345677 0x12341235 0x44345676 0x12341236 0x45345675 0x12341237 0x26989898 # The next two lines have different hex formatting 41345678h 12341234h 22989898h F3345678h 12345678h 86754321h 86753099h # The next lines have no hex formatting 41345678 12341234 22989898 # The next lines have inconsistent hex formatting 41345678 12341234 0xF2345678 12345678h 86754321 0x86753099 # bunch of empty lines above. And the file ends with a comment . Sending Endpoint Metadata Requests . The MIDI Services Console also makes it possible to send some common stream request messages without having to remember their exact format. Before sending the request, you may want to open another console window or tab with a device watcher active on the connected endpoint. This will tell you when the stored properties are changed. In addition, you may want to have a verbose monitoring tab/window open so you can see the response messages come back. These are primarily a convenience for developers. Note that in all the request commands, you may abbreviate request as req . Send a Function Block Request Message . In the command, you may abbreviate function-blocks as fb, functions, function or function-block. The singular versions are available to make the command make more sense when requesting a single block’s data. Request all function blocks from an endpoint . midi endpoint request function-blocks --all . Request a single function block . midi endpoint request function-blocks --function-block-number 3 . Note that you may abbreviate --function-block-number as -n or as --number . By default, you will request both the info notification and name notification messages. If you want to request only one of them, simply turn the other off. You must request at least one of the two types of messages. midi endpoint request function-blocks --all --request-name false midi endpoint request function-blocks --all --request-info false . Send an Endpoint Information Request Message . In the command, you may abbreviate endpoint-metadata as em or metadata. By default, you will request only the endpoint information notification. To request other types of information, specify the flag for that type, or simply use --all . Request all metadata notification messages . midi endpoint request endpoint-metadata --all . Request endpoint info (on by default) and name . midi endpoint request endpoint-metadata --name . Request only the name . midi endpoint request endpoint-metadata --name --endpoint-info false . Other request types . midi endpoint request endpoint-metadata --device-identity midi endpoint request endpoint-metadata --product-instance-id midi endpoint request endpoint-metadata --stream-configuration . Finally, note that you can provide a UMP version to send with the request. By default, the version is Major 1, Minor 1. The --ump-version-major and --ump-version-minor options are what you want to use here. ",
"url": "/docs/midi-console.html#single-endpoint-commands",
"relUrl": "/midi-console.html#single-endpoint-commands"
- },"204": {
+ },"223": {
"doc": "MIDI Console",
"title": "Technical Information",
"content": "The Windows MIDI Services Console app has been developed using C#, .NET 8, the MIT-licensed open source Spectre.Console library, and the Microsoft-developed open source C#/WinRT toolkit. The console uses the same Windows MIDI Services WinRT APIs available to other desktop applications. Its full source code is available on our Github repo. Pull-requests, feature requests, and bug reports welcome. The project is open source, but we request that instead of forking it to create your own version, you consider contributing to the project. ",
"url": "/docs/midi-console.html#technical-information",
"relUrl": "/midi-console.html#technical-information"
- },"205": {
+ },"224": {
"doc": "MIDI Console",
"title": "MIDI Console",
"content": " ",
"url": "/docs/midi-console.html",
"relUrl": "/midi-console.html"
- },"206": {
+ },"225": {
"doc": "MIDI 2.0 Implementation Details",
"title": "Implementation Details",
"content": "Specifications can be funny. As much as the MIDI Association, and all of us in it, try to be very specific and crisp on wording, there’s often room for interpretation. Most of these we work out among the various OS companies under the umbrella of the MIDI Association. But there are others were an approach may just not make sense on one OS or the other. Here are the ones that are Windows-specific, that you should be aware of as a developer. Of course, the full source code for Windows MIDI Services, including the USB MIDI 2.0 driver, is available in our repo, so you can review it at any time to better understand how a feature or function works. ",
"url": "/docs/developer-docs/midi2-implementation-details.html#implementation-details",
"relUrl": "/developer-docs/midi2-implementation-details.html#implementation-details"
- },"207": {
+ },"226": {
"doc": "MIDI 2.0 Implementation Details",
"title": "Discovery and Protocol Negotiation",
"content": "Windows MIDI Services supports only the UMP-based Endpoint Discovery and Protocol Negotiation. We do not implement the deprecated MIDI-CI equivalents. In addition, declaring the use of JR Timestamps in a USB MIDI 2.0 Group Terminal Block does not enable JR Timestamps in Windows MIDI Services. Instead, these must be negotiated using UMP-based Endpoint Discovery end Protocol Negotiation . ",
"url": "/docs/developer-docs/midi2-implementation-details.html#discovery-and-protocol-negotiation",
"relUrl": "/developer-docs/midi2-implementation-details.html#discovery-and-protocol-negotiation"
- },"208": {
+ },"227": {
"doc": "MIDI 2.0 Implementation Details",
"title": "UMP Endpoint Names for native MIDI 2.0 UMP format devices",
"content": "Although we make all the names available through the Enumeration API, we have an order of precedence we use when providing the recommended Name property value. In order from most preferred to least, we have: . | Any user-supplied endpoint name configured through the configuration files (these will be created by the MIDI Settings app in the future) | The name supplied through in-protocol Endpoint Name Notification messages | The name supplied by the transport plugin in the service. This is typically pulled from a device name supplied by the driver, or other transport-specific sources such as network advertising in the case of Network MIDI 2.0. | . When we create MIDI 1.0-compatible “ports” for these endpoints, we’ll use the Function Block Names if available and Group Terminal Block names if not. ",
"url": "/docs/developer-docs/midi2-implementation-details.html#ump-endpoint-names-for-native-midi-20-ump-format-devices",
"relUrl": "/developer-docs/midi2-implementation-details.html#ump-endpoint-names-for-native-midi-20-ump-format-devices"
- },"209": {
+ },"228": {
"doc": "MIDI 2.0 Implementation Details",
"title": "UMP Endpoint Names for MIDI 1.0 byte stream format devices",
"content": "The API also creates UMP endpoints for MIDI 1.0 devices. This happens two ways: . | If the device is assigned to the USB MIDI 2.0 driver (this is preferred) the driver creates Group Terminal Blocks for each “cable” (a “port” in MIDI 1.0 API speak). In the new driver, we use the iJack names, if provided, to name the Group Terminal Blocks. This is the best way to ensure your endpoint and Group Terminal Block names are correct. | If the device is assigned a third-party driver or the legacy MIDI 1.0 driver (not preferred in most cases), the service creates the Group Terminal Blocks using the same algorithm. However, because much less information is available to the service from the legacy drivers, the name may not be identical. | . The precedence for naming is the same as with MIDI 2.0 devices, with the exception of the Endpoint Name Notification, which doesn’t exist in MIDI 1.0. | Any user-supplied endpoint name | The name supplied through in-protocol Endpoint Name Notification messages | The name supplied by the transport plugin in the service. This is typically pulled from a device name supplied by the driver, or other transport-specific sources such as network advertising in the case of Network MIDI 2.0. | . ",
"url": "/docs/developer-docs/midi2-implementation-details.html#ump-endpoint-names-for-midi-10-byte-stream-format-devices",
"relUrl": "/developer-docs/midi2-implementation-details.html#ump-endpoint-names-for-midi-10-byte-stream-format-devices"
- },"210": {
+ },"229": {
"doc": "MIDI 2.0 Implementation Details",
"title": "iSerialNumber Really Helps",
"content": "If your device exposes a unique iSerialNumber, that will really help with retaining name and other information across physical USB connects and disconnects. We do our best to retain the correct information if you plug into the same physical port, but when you change ports, a device without an iSerialNumber essentially becomes a new device. This is not unique to Windows, but it’s important enough to mention here. More info and guidance in this blog post. ",
"url": "/docs/developer-docs/midi2-implementation-details.html#iserialnumber-really-helps",
"relUrl": "/developer-docs/midi2-implementation-details.html#iserialnumber-really-helps"
- },"211": {
+ },"230": {
"doc": "MIDI 2.0 Implementation Details",
"title": "MIDI 2.0 Implementation Details",
"content": " ",
diff --git a/docs/_site/config-json.html b/docs/_site/config-json.html
index aa681be2..05981021 100644
--- a/docs/_site/config-json.html
+++ b/docs/_site/config-json.html
@@ -1,11 +1,11 @@
It’s best to use the Settings application and the transport / processing plugins for Settings to manipulate the file. However, if you edit it by hand, here are some notes.
The File location is Restricted
The JSON configuration files are all stored in %allusersprofile%\Microsoft\MIDI which typically resolves to C:\ProgramData\Microsoft\MIDI. For security reasons, we don’t allow the file to be stored in any other location. However, you can have as many files in that folder as you want, and switch between them as needed.
The default config file is typically named Default.midiconfig.json. The actual name is stored in the registry under HKLM\SOFTWARE\Microsoft\Windows MIDI Services in the CurrentConfig value. This value must not contain any non-filename path characters (no backslashes, colons, etc.).
JSON is Case-Sensitive
JSON is typically case-sensitive for all keys. The Windows.Data.Json parser used by Windows MIDI Services is case-sensitive with no option to ignore case. That includes GUID values. For example, the following two values are not equivalent JSON keys:
The JSON config file is such that each transport owns its own schema within the bucket associated with its class ID (GUID). We do not impose a schema on the transports or other plugins. Therefore there is no formal JSON Schema for this file.
Here’s an example of a bare-bones file, with sections for three different transports.
{"header":{
@@ -28,7 +28,6 @@
{"_comment":"Virtual MIDI"}
-
},"endpointProcessingPluginSettings":{
@@ -43,21 +42,6 @@
"userSuppliedName":"Pete's Kontrol S61","userSuppliedDescription":"This is my most favorite MIDI 2.0 controller in the whole world!"}
- ...
+
},
-
Of those, the identification method SWD is the most important. This controls how we identify a matching device. In cases where the manufacturer doesn’t supply a unique iSerialNumber in USB, unplugging your device from one USB port and plugging it into another can result in a new Id. Similarly, if you have two or more of the same device, and they do not have unique serial numbers, it can be impossible for Windows to distinguish between them.
Valid values for the identification method prefix
SWD: : (The colon and trailing space are required). Use the full Windows Endpoint Device Interface Id. For example \\\\?\\SWD#MIDISRV#MIDIU_KS_BIDI_16024944077548273316_OUTPIN.0_INPIN.2#{e7cce071-3c03-423f-88d3-f1045d02552b}. (Note how the backslashes have to be escaped with additional backslashes.) If the device has an iSerialNumber or you never move it between USB ports, this tends to work fine.
(other methods to be added here when we implement them)
Valid properties you can set across all supported endpoints
Property
Type
Description
userSuppliedName
Quoted Text
The name you want to use for the endpoint. This will override the name displayed in correctly-coded applications, but won’t necessarily change what you see in Device Manager. These names should be relatively short so they display fully in all/most applications, but meaningful to you.
userSuppliedDescription
Quoted Text
A text description and/or notes about the endpoint. Applications may or may not use this data
forceSingleClientOnly
Boolean true/false (no quotes)
Most endpoints are multi-client (more than one application can use them simultaneously) by default. This setting is for forcing an endpoint to be single-client only (a value of true). It’s unusual to need this, but a typical use may be to disable multi-client for a device which has a custom driver which doesn’t gracefully handle multiple client applications at the same time.
Plugin-specific settings
This is not an exhaustive list, because the transport and processing plugins may be created by anyone.
Virtual MIDI
Virtual MIDI includes three different sections inside its transport bucket.
For the persistent configuration file, typically “add” is all that is specified, as it doesn’t make sense to update or remove endpoints or routing on service start.
NOTE: This document is not yet complete. We’ll add more details as the schemas are finalized
KS (USB etc) MIDI
TODO: Show how to update endpoint names and provide other properties here
\ No newline at end of file
+
Of those, the identification method SWD is the most important. This controls how we identify a matching device. In cases where the manufacturer doesn’t supply a unique iSerialNumber in USB, unplugging your device from one USB port and plugging it into another can result in a new Id. Similarly, if you have two or more of the same device, and they do not have unique serial numbers, it can be impossible for Windows to distinguish between them.
Valid values for the identification method prefix
SWD: : (The colon and trailing space are required). Use the full Windows Endpoint Device Interface Id. For example \\\\?\\SWD#MIDISRV#MIDIU_KS_BIDI_16024944077548273316_OUTPIN.0_INPIN.2#{e7cce071-3c03-423f-88d3-f1045d02552b}. (Note how the backslashes have to be escaped with additional backslashes.) If the device has an iSerialNumber or you never move it between USB ports, this tends to work fine.
(other methods to be added here when we implement them)
Valid properties you can set across all supported endpoints
Property
Type
Description
userSuppliedName
Quoted Text
The name you want to use for the endpoint. This will override the name displayed in correctly-coded applications, but won’t necessarily change what you see in Device Manager. These names should be relatively short so they display fully in all/most applications, but meaningful to you.
userSuppliedDescription
Quoted Text
A text description and/or notes about the endpoint. Applications may or may not use this data
forceSingleClientOnly
Boolean true/false (no quotes)
Most endpoints are multi-client (more than one application can use them simultaneously) by default. This setting is for forcing an endpoint to be single-client only (a value of true). It’s unusual to need this, but a typical use may be to disable multi-client for a device which has a custom driver which doesn’t gracefully handle multiple client applications at the same time.
Plugin-specific settings
This is not an exhaustive list, because the transport and processing plugins may be created by anyone.
Virtual MIDI
TODO: Provide examples for this
For the persistent configuration file, typically “add” is all that is specified, as it doesn’t make sense to update or remove endpoints or routing on service start.
NOTE: This document is not yet complete. We’ll add more details as the schemas are finalized
KS (USB etc) MIDI
TODO: Show how to update endpoint names and provide other properties here