Skip to content

Commit

Permalink
Merge pull request #325 from microsoft/pete-dev
Browse files Browse the repository at this point in the history
Doc and sample updates
  • Loading branch information
Psychlist1972 authored Apr 21, 2024
2 parents 0e8744f + 73e9e8f commit aa03ac2
Show file tree
Hide file tree
Showing 17 changed files with 187 additions and 166 deletions.
8 changes: 5 additions & 3 deletions docs/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The Windows.Devices.Midi2 types are documented in these pages.

Typical API workflow:

1. **Check for Windows MIDI Services availability**. Windows MIDI Services is not available on older versions of Windows, or on devices like Xbox, Hololens, and others. The first step is to make a call to check for availability of the services on Windows. If Windows MIDI Services is not available, you may want to fall back to an older MIDI API, or simply inform the user and terminate the application.
1. **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.
2. **Connect to an endpoint**. Typically, you'll get the endpoint's id through the enumeration functions.
3. **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.
Expand All @@ -20,6 +21,10 @@ Typical API workflow:

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.)

## Service

The MidiService class is a utility class which provides access to health and status information related to the MidiSrv Service. This is also where you can check to see if Windows MIDI Services is available on this PC.

## Session

Interaction with a MIDI Endpoint always starts with creating a session.
Expand Down Expand Up @@ -52,6 +57,3 @@ A virtual device is the mechanism through which app-to-app MIDI works through th

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.

## Service

The MidiService class is a utility class which provides access to health and status information related to the MidiSrv Service.
61 changes: 27 additions & 34 deletions docs/api/service/MidiService.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,57 +8,50 @@ has_children: false

# MidiService

## Remarks

The MidiService class contains a number of static functions which enable working with the service outside of a specific session.

## Static Functions : Reporting
### Service Health

| Static Function | Description |
|---|---|
| `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. |
| `IsAvailable()` | Returns true of Windows MIDI Services is available on this PC. Calling this function is typically the first step in using Windows MIDI Services in your application. |
| `PingService(UInt8)` | Send the specified count of ping messages to the ping endpoint and report on the status and time. Return if the responses are not received in an internally calculated timeout period. |
| `PingService(UInt8, UInt32)` | Send the specified count of ping messages to the ping endpoint and report on the status and time. Return if responses are not received in the specified timeout period (milliseconds). |

## Static Functions : Loopback Endpoints

| Static Function | Description |
|---|---|
| `CreateTemporaryLoopbackEndpoints(associationId, endpointA, endpointB)` | Create a pair of loopback endpoints which will live until removed through the API or the service is restarted. |
| `RemoveTemporaryLoopbackEndpoints(associationId)` | Remove a pair of temporary loopback endpoints. |
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.

Applications creating endpoints for app-to-app MIDI should generally use the Virtual Device support built into the API. However, applications may need to create lightweight loopback endpoints without the protocol negotiation, MIDI 2.0 discovery process, and lifetime management provided by the Virtual Device support. For those scenarios, we have a simple loopback endpoint type.
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.

Loopback endpoints created by the user and stored in the configuration file will persist after the service is restarted or the PC rebooted. Loopback endpoints created through this API call are temporary, and will disappear if the service is restarted. In both cases, this feature requires that the loopback endpoint transport is installed and enabled.
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.

## Static Functions : Runtime Configuration
Here's an example of ping responses through the MIDI console app

| Static Function | Description |
|---|---|
| `UpdateTransportPluginConfiguration(configurationUpdate)` | Sends an update to the service to be used by a transport plugin ("Abstraction") |
| `UpdateProcessingPluginConfiguration(configurationUpdate)` | Sends an update to the service to be used by a message processing plugin ("Transform") |
![MIDI Console Ping](./console-ping.png)

For plugins which support updates at runtime, developers of those plugins should create configuration WinRT types which implement the required configuration interfaces, and create the JSON that is used in the service. In this way, third-party service transport and message processing plugins can be created and configured without changes to the API.
### Reporting

> Note: In version 1 of the API, only transports can be configured at runtime. We're working on enabling configuration of message processing plugins. The API is a no-op.
| `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. |

## Static Functions : Service Health
### Loopback Endpoints

| 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. |
| `CreateTemporaryLoopbackEndpoints(Guid, MidiServiceLoopbackEndpointDefinition, MidiServiceLoopbackEndpointDefinition)` | Create a pair of loopback endpoints which will live until removed through the API or the service is restarted. |
| `RemoveTemporaryLoopbackEndpoints(Guid)` | Remove a pair of temporary loopback endpoints when provided their association Id Guid. |

### The ping process
Applications creating endpoints for app-to-app MIDI should generally use the Virtual Device support built into the API. However, applications may need to create lightweight loopback endpoints without the protocol negotiation, MIDI 2.0 discovery process, and lifetime management provided by the Virtual Device support. For those scenarios, we have a simple loopback endpoint type.

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.
Loopback endpoints created by the user and stored in the configuration file will persist after the service is restarted or the PC rebooted. Loopback endpoints created through this API call are temporary, and will disappear if the service is restarted. In both cases, this feature requires that the loopback endpoint transport is installed and enabled.

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.
### Runtime Configuration

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.
| `UpdateTransportPluginConfiguration(IMidiServiceTransportPluginConfiguration)` | Sends an update to the service to be used by a transport plugin ("Abstraction") |
| `UpdateProcessingPluginConfiguration(IMidiServiceMessageProcessingPluginConfiguration)` | Sends an update to the service to be used by a message processing plugin ("Transform") |

Here's an example of ping responses through the MIDI console app
For plugins which support updates at runtime, developers of those plugins should create configuration WinRT types which implement the required configuration interfaces, and create the JSON that is used in the service. In this way, third-party service transport and message processing plugins can be created and configured without changes to the API.

![MIDI Console Ping](./console-ping.png)
> Note: In version 1 of the API, only transports can be configured at runtime. We're working on enabling configuration of message processing plugins. The API is a no-op.
## IDL
## See also

[MidiService IDL](https://github.com/microsoft/MIDI/blob/main/src/api/Client/Midi2Client/MidiService.idl)
[MidiService IDL](https://github.com/microsoft/MIDI/blob/main/src/api/Client/Midi2Client/MidiService.idl)
3 changes: 1 addition & 2 deletions docs/api/service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ has_children: true

# Service

The MidiService class is a utility class which provides access to health and status information related to the MidiSrv Service.

The MidiService class is a utility class which provides access to health and status information related to the MidiSrv Service. This is also where you can check to see if Windows MIDI Services is available on this PC.
26 changes: 11 additions & 15 deletions docs/api/simple-types/MidiChannel.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,29 @@ has_children: false

# MidiChannel

The MidiChannel class is used to provide formatting and data validation for MIDI 1.0 and MIDI 2.0 channels.
## Remarks

The `MidiChannel` class is used to provide formatting and data validation for MIDI 1.0 and MIDI 2.0 channels. For clarity, the 0-15 value used in all messages is the `Index` and the 1-16 value those are mapped to for user display, is the `NumberForDisplay`.

## Constructors

| `MidiChannel` | Create an empty MidiChannel object (Index 0) |
| `MidiChannel(UInt8)` | Create a MidiChannel with the specified channel Index (0-15) |

## Properties

| Property | Description |
| --------------- | ----------- |
| `Index` | The data value, or channel Index (0-15) |
| `NumberForDisplay` | The number that should be displayed in any UI. (1-16) |

## Static Properties

| Static Property | Description |
| --------------- | ----------- |
| `LabelShort` | Returns the localized abbreviation. For example, "Ch" in English. |
| `LabelFull` | Returns the localized full name. For example, "Channel" in English. |

## Functions

| Function | Description |
| --------------- | ----------- |
| `MidiChannel()` | Constructs an empty `MidiChannel` |
| `MidiChannel(index)` | Constructs a `MidiChannel` with the specified index |
## Static Methods

## Static Functions
| `IsValidChannelIndex(UInt8)` | Verifies that the provided index is valid (between 0 and 15) |

| Static Function | Description |
| --------------- | ----------- |
| `IsValidChannelIndex(index)` | Verifies that the provided index is valid (between 0 and 15) |
## See also

[MidiChannel IDL](https://github.com/microsoft/MIDI/blob/main/src/api/Client/Midi2Client/MidiChannel.idl)
28 changes: 12 additions & 16 deletions docs/api/simple-types/MidiGroup.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,29 @@ has_children: false

# MidiGroup

The `MidiGroup` class is used to provide formatting and data validation for UMP (Universal MIDI Packet) groups.
## Remarks

The `MidiGroup` class is used to provide formatting and data validation for MIDI 2.0 groups. For clarity, the 0-15 value used in all messages is the `Index` and the 1-16 value those are mapped to for user display, is the `NumberForDisplay`.

## Constructors

| `MidiGroup` | Create an empty MidiGroup object (Index 0) |
| `MidiChannel(UInt8)` | Create a MidiChannel with the specified channel Index (0-15) |

## Properties

| Property | Description |
| --------------- | ----------- |
| `Index` | The data value, or group Index (0-15) |
| `Index` | The data value, or channel Index (0-15) |
| `NumberForDisplay` | The number that should be displayed in any UI. (1-16) |

## Static Properties

| Static Property | Description |
| --------------- | ----------- |
| `LabelShort` | Returns the localized abbreviation. For example, "Gr" in English. |
| `LabelFull` | Returns the localized full name. For example, "Group" in English. |

## Functions

| Function | Description |
| --------------- | ----------- |
| `MidiGroup()` | Constructs an empty `MidiGroup` |
| `MidiGroup(index)` | Constructs a `MidiGroup` with the specified index |
## Static Methods

## Static Functions
| `IsValidGroupIndex(UInt8)` | Verifies that the provided index is valid (between 0 and 15) |

| Static Function | Description |
| --------------- | ----------- |
| `IsValidGroupIndex(index)` | Verifies that the provided index is valid (between 0 and 15) |
## See also

[MidiGroup IDL](https://github.com/microsoft/MIDI/blob/main/src/api/Client/Midi2Client/MidiGroup.idl)
43 changes: 21 additions & 22 deletions docs/api/simple-types/MidiUniqueId.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,42 @@ has_children: false

# MidiUniqueId

The `MidiUniqueId` class is used to provide formatting and data validation for MIDI-CI MUID types used in Function Blocks and MIDI CI transactions.
## Remarks

The `MidiUniqueId` class is used to provide formatting and data validation for MIDI-CI MUID (MIDI Unique Id) 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.

## Constructors

| `MidiUniqueId()` | Constructs an empty `MidiUniqueId` |
| `MidiUniqueId(UInt32)` | Constructs the `MidiUniqueId` from the given 28 bit integer |
| `MidiUniqueId(UInt8, UInt8, UInt8, UInt8)` | Constructs a `MidiUniqueId` with the specified seven-bit bytes |

## Properties

| 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 |
| `Byte1` | The data value for byte 1 of the MUID (LSB) |
| `Byte2` | The data value for byte 2 of the MUID (second-most LSB) |
| `Byte3` | The data value for byte 3 of the MUID (second-most MSB) |
| `Byte4` | The data value for byte 4 of the MUID (MSB) |
| `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 |
| `IsBroadcast` | True if this is the broadcast MUID value from the MIDI CI specification |
| `IsReserved` | True if this is the reserved MUID value from the MIDI CI specification |

## Static Properties

| Static Property | Description |
| --------------- | ----------- |
| `LabelShort` | Returns the localized abbreviation. |
| `LabelFull` | Returns the localized full name. |

## Functions

| 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 |
| `LabelShort` | Returns the localized abbreviation for use in UI. |
| `LabelFull` | Returns the localized full name for use in UI. |

## Static Functions
## Static Methods

| Function | Description |
| --------------- | ----------- |
| `CreateBroadcast()` | Constructs a broadcast `MidiUniqueId` |
| `CreateRandom()` | Constructs a random `MidiUniqueId` |
| `CreateBroadcast()` | Constructs a broadcast `MidiUniqueId` per the MIDI CI specification |
| `CreateRandom()` | Constructs a random `MidiUniqueId` per the MIDI CI specification |

## See also

[MidiUniqueId IDL](https://github.com/microsoft/MIDI/blob/main/src/api/Client/Midi2Client/MidiUniqueId.idl)
1 change: 0 additions & 1 deletion docs/api/simple-types/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,3 @@ has_children: true
# Simple Types

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.

Loading

0 comments on commit aa03ac2

Please sign in to comment.