Skip to content

Commit

Permalink
Merge pull request #270 from microsoft/pete-dev
Browse files Browse the repository at this point in the history
Plumbing changes for loopback and runtime config
  • Loading branch information
Psychlist1972 authored Feb 12, 2024
2 parents 0cf4de7 + ac56c50 commit 358391f
Show file tree
Hide file tree
Showing 139 changed files with 3,485 additions and 1,159 deletions.
1 change: 1 addition & 0 deletions build/staging/reg/WinRTActivationEntries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class RegistryEntries
new RegEntry{ ClassName="Windows.Devices.Midi2.IMidiEndpointConnectionStatics", ActivationType=0, Threading=0, TrustLevel=0 },
new RegEntry{ ClassName="Windows.Devices.Midi2.MidiService", ActivationType=0, Threading=0, TrustLevel=0 },
new RegEntry{ ClassName="Windows.Devices.Midi2.IMidiServiceStatics", ActivationType=0, Threading=0, TrustLevel=0 },
new RegEntry{ ClassName="Windows.Devices.Midi2.MidiServiceLoopbackEndpointDefinition", ActivationType=0, Threading=0, TrustLevel=0 },
new RegEntry{ ClassName="Windows.Devices.Midi2.MidiClock", ActivationType=0, Threading=0, TrustLevel=0 },
new RegEntry{ ClassName="Windows.Devices.Midi2.IMidiClockStatics", ActivationType=0, Threading=0, TrustLevel=0 },
new RegEntry{ ClassName="Windows.Devices.Midi2.MidiChannel", ActivationType=0, Threading=0, TrustLevel=0 },
Expand Down
5 changes: 5 additions & 0 deletions build/staging/reg/WinRTActivationEntries.xml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@
threading="Both"
trustLevel="Base"
/>
<class
activatableClassId="Windows.Devices.Midi2.MidiServiceLoopbackEndpointDefinition"
threading="Both"
trustLevel="Base"
/>
<class
activatableClassId="Windows.Devices.Midi2.MidiClock"
threading="Both"
Expand Down
2 changes: 1 addition & 1 deletion build/staging/version/BundleInfo.wxi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Include>
<?define SetupVersionName="Developer Preview 5" ?>
<?define SetupVersionNumber="1.0.24041.0202" ?>
<?define SetupVersionNumber="1.0.24043.0221" ?>
</Include>
2 changes: 2 additions & 0 deletions diagnostics/trace-logging/MidiServices.wprp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<EventProvider Id="EventProvider_VirtualPatchBayAbstraction" Name="*Microsoft.Windows.Midi2.VirtualPatchBayAbstraction"/>
<EventProvider Id="EventProvider_NetworkMidiAbstraction" Name="*Microsoft.Windows.Midi2.NetworkMidiAbstraction"/>
<EventProvider Id="EventProvider_BluetoothMidiAbstraction" Name="*Microsoft.Windows.Midi2.BluetoothMidiAbstraction"/>
<EventProvider Id="EventProvider_LoopbackMidiAbstraction" Name="*Microsoft.Windows.Midi2.LoopbackMidiAbstraction"/>

<EventProvider Id="EventProvider_API" Name="*Windows.Devices.Midi2.Api"/>

Expand All @@ -45,6 +46,7 @@
<EventProviderId Value="EventProvider_VirtualPatchBayAbstraction"/>
<EventProviderId Value="EventProvider_NetworkMidiAbstraction"/>
<EventProviderId Value="EventProvider_BluetoothMidiAbstraction"/>
<EventProviderId Value="EventProvider_LoopbackMidiAbstraction"/>

<EventProviderId Value="EventProvider_API"/>

Expand Down
42 changes: 31 additions & 11 deletions docs/developer-docs/Windows.Devices.Midi2/service/MidiService.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,44 @@ has_children: false

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

## Static Functions
## Static Functions : Reporting

| 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](../../../config-json.md) |

## A note on the ping process
## 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. |

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.

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.

## Static Functions : Runtime Configuration

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

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.

> Note: In version 1 of the API, only transports can be configured at runtime. We're working on enabling configuration of message processing plugins.
## Static Functions : Service Health

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

### The ping process

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.

Expand All @@ -33,12 +59,6 @@ Here's an example of ping responses through the MIDI console app

![MIDI Console Ping](./console-ping.png)

## A note on updating runtime configuration

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.

## IDL

[MidiService IDL](https://github.com/microsoft/MIDI/blob/main/src/api/Client/Midi2Client/MidiService.idl)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
layout: api_page
title: MidiServiceConfigurationResponseStatus
parent: Service
grand_parent: Windows.Devices.Midi2 API
has_children: false
---

# MidiServiceConfigurationResponseStatus Enumeration

Indicates success or failure mode for configuring an endpoint or message processing plugin in the service.

## Properties

| Property | Value | Description |
| -------- | ------- | ------ |
| `Success` | `0` | The entire operation succeeded |
| `ErrorTargetNotFound` | `404` | The target of the change was not found. This could be the plugin itself, or if the configuration requires an endpoint, the endpoint instance. |
| `ErrorJsonNullOrEmpty` | `600` | The supplied JSON was null or empty. |
| `ErrorProcessingJson` | `601` | The supplied JSON was invalid in some way. It could be malformed or have missing required data or keys. |
| `ErrorNotImplemented` | `2600` | One or more of the requests are not implemented by the service or by the plugin. |
| `ErrorOther` | `9999` | All other errors |

## IDL

[MidiServiceConfigurationResponseStatus IDL](https://github.com/microsoft/MIDI/blob/main/src/api/Client/Midi2Client/MidiServiceConfigurationResponseStatusEnum.idl)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
layout: api_page
title: MidiServiceLoopbackEndpointDefinition
parent: Service
grand_parent: Windows.Devices.Midi2 API
has_children: false
---

# MidiServiceLoopbackEndpointDefinition

This class defines the properties of an endpoint which can be created at runtime. For example, a loopback endpoint.

## Properties

| Property | Description |
|---|---|
| `Name` | The name of the endpoint. |
| `UniqueId` | A short unique identifier for this endpoint. This is used in creating the id. Keep to 32 characters or fewer (32 characters is the length of a no-symbols GUID). If, when combined with the generated loopback A/B differentiator prefix, this id is not unique among all loopback endpoints, endpoint creation will fail. |
| `Description` | Optional description for the endpoint |

## IDL

[MidiServiceLoopbackEndpointDefinition IDL](https://github.com/microsoft/MIDI/blob/main/src/api/Client/Midi2Client/MidiServiceLoopbackEndpointDefinition.idl)

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
layout: api_page
title: MidiServiceLoopbackEndpointCreationResult
parent: Service
grand_parent: Windows.Devices.Midi2 API
has_children: false
---

# MidiServiceLoopbackEndpointCreationResult

This class represents the results of an attempt to create runtime loopback endpoints

## Properties

| Property | Description |
|---|---|
| `Success` | True if the creation of both endpoints was a success |
| `AssociatioNId` | The GUID which associatiates the two endpoints. Provided during creation time. |
| `EndpointDeviceIdA` | The full endpoint device id `\\SWD\...` for the endpoint identified as the "A" side of the loopback |
| `EndpointDeviceIdB` | The full endpoint device id `\\SWD\...` for the endpoint identified as the "B" side of the loopback |

## IDL

[MidiServiceLoopbackEndpointCreationResult IDL](https://github.com/microsoft/MIDI/blob/main/src/api/Client/Midi2Client/MidiServiceLoopbackEndpointCreationResult.idl)

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ has_children: false

This class represents a single ping message response. This is used to assess health and performance of the Windows service.

## Static Functions
## Properties

| Property | Description |
|---|---|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ has_children: false

This class represents a summary of the ping attempts against the Windows service.

## Static Functions
## Properties

| Property | Description |
|---|---|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ has_children: false

This class represents an open connection in a Windows MIDI Services session. This is an informational class only for reporting system-wide connection usage.

## Static Functions
## Properties

| Property | Description |
|---|---|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ has_children: false

This class represents an open Windows MIDI Services session.

## Static Functions
## Properties

| Property | Description |
|---|---|
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
layout: page
title: Endpoint Device Ids
parent: Windows Midi Services
parent: Transport Types
grandparent: Windows Midi Services
has_children: false
---

Expand Down
2 changes: 1 addition & 1 deletion docs/endpoints/kernel-streaming.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ layout: page
title: Kernel Streaming
parent: Transport Types
grandparent: Windows MIDI Services
has_children: true
has_children: false
---

# Kernel Streaming
Expand Down
2 changes: 1 addition & 1 deletion docs/endpoints/virtual-device-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ layout: page
title: Virtual Device App
parent: Transport Types
grandparent: Windows MIDI Services
has_children: true
has_children: false
---

# Virtual Device App
Expand Down
59 changes: 56 additions & 3 deletions docs/endpoints/virtual-loopback.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ layout: page
title: Virtual Loopback
parent: Transport Types
grandparent: Windows MIDI Services
has_children: true
has_children: false
---

# Virtual Loopback
Expand All @@ -25,14 +25,67 @@ If you want to have loopback endpoints which are always available for routing be

As with all configuration file changes, we recommend using the Windows MIDI Services Settings application, once we make that available. For now, you may edit the JSON directly. But please note that JSON is quite unforgiving: the format is specific, and all keys (including the GUIDs and property names) are case-sensitive. In addition, there's no usable provision for comments in a JSON file, so we can't include examples in the file itself.

That out of the way, here's the configuration section for the Virtual Loopback MIDI endpoints.
That out of the way, here's an example configuration section for the Virtual Loopback MIDI endpoints.

```json

todo
"endpointTransportPluginSettings":
{
"{942BF02D-93C0-4EA8-B03E-D51156CA75E1}":
{
"_comment": "Loopback MIDI",

"create":
{
"{0C1B3439-593F-4B7A-8950-4698D97B0897}":
{
"_comment" : "the above GUID is the unique association Id for this pair",
"endpointA":
{
"name": "Perm Loopback 1A",
"description": "This is a loopback I created in the configuration file",
"uniqueId": "3263827"
},
"endpointB":
{
"name": "Perm Loopback 1B",
"description": "This is the b-side of the loopback I created in the configuration file",
"uniqueId": "3263827"
}
},
"{B21B4973-3F85-48A0-8BA3-B35F44683D36}":
{
"_comment" : "the above GUID is the unique association Id for this pair",
"endpointA":
{
"name": "Perm Loopback 2A",
"description": "This is a loopback I created in the configuration file",
"uniqueId": "5150-1984"
},
"endpointB":
{
"name": "Perm Loopback 2B",
"description": "This is the b-side of the loopback I created in the configuration file",
"uniqueId": "OU812"
}
}
}
}
}
```

Each loopback endpoint pair is identified by a GUID for the association id. The association GUID must be a valid unique GUID and shall not be an empty (all zeroes) GUID.

| Key | Description |
| -------- | ----- |
| (Association Id) | Unique GUID for this pair of endpoints. The GUID itself is the property key under the "create" node. |
| endpointA | Data for the first endpoint |
| endpointB | Data for the second endpoint |
| (endpoint) name | Required. This becomes the transport-supplied name for the loopback endpoint. |
| (endpoint) description | Optional. This becomes the transport-supplied description for the loopback endpoint. |
| (endpoint) uniqueId | Required. This is a short (32 characters or fewer) case-insensitive unique Id for the endpoint. When combined with the loopback A/B prefixes in the service, it must be unique across all loopback endpoints in Windows. You can use the same unique id for each endpoint in the same pair, but not the same as other pairs. |


# Implementation

Internally, the Virtual Loopback is implemented as two endpoints which are cross-wired, so anything sent to Loopback A arrives on the input of Loopback B, and vice versa. Each declared pair has an exclusive relationship, and there's no practical limit to the number of loopback pairs you can define.
Expand Down
Loading

0 comments on commit 358391f

Please sign in to comment.