Skip to content

Commit

Permalink
Merge pull request #321 from microsoft/pete-dev
Browse files Browse the repository at this point in the history
More DP6 prep updates
  • Loading branch information
Psychlist1972 authored Apr 18, 2024
2 parents 4f1885e + 7c6a48b commit e8d8430
Show file tree
Hide file tree
Showing 35 changed files with 362 additions and 283 deletions.
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 6 arm64" ?>
<?define SetupVersionNumber="1.0.24107.2219" ?>
<?define SetupVersionNumber="1.0.24109.1831" ?>
</Include>
6 changes: 6 additions & 0 deletions diagnostics/trace-logging/MidiServices.wprp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
<EventProvider Id="EventProvider_SchedulerTransform" Name="*Microsoft.Windows.Midi2.SchedulerTransform"/>
<EventProvider Id="EventProvider_UMP2BSTransform" Name="*Microsoft.Windows.Midi2.UMP2BSTransform"/>

<EventProvider Id="EventProvider_SettingsApp" Name="*Microsoft.Midi.Settings"/>
<EventProvider Id="EventProvider_ConsoleApp" Name="*Microsoft.Midi.Console"/>

<Profile Id="MidiSrv.Verbose.File" Name="MidiSrv" DetailLevel="Verbose" Description="Windows MIDI Services trace profile" LoggingMode="File">
<Collectors>
Expand All @@ -52,6 +54,10 @@
<EventProviderId Value="EventProvider_JitterReductionListenerTransform"/>
<EventProviderId Value="EventProvider_SchedulerTransform"/>
<EventProviderId Value="EventProvider_UMP2BSTransform"/>

<EventProviderId Value="EventProvider_SettingsApp"/>
<EventProviderId Value="EventProvider_ConsoleApp"/>

</EventProviders>
</EventCollectorId>
</Collectors>
Expand Down
34 changes: 31 additions & 3 deletions docs/api/enumeration/MidiEndpointDeviceWatcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,40 @@ Create a `MidiEndpointDeviceWatcher` on a background thread, and use the interna

| 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. |
| `Added(source, deviceInformationAddedEventArgs)` | A new endpoint has been added. |
| `Removed(source, deviceInformationRemovedEventArgs)` | An endpoint has been removed. |
| `Updated(source deviceInformationUpdatedEventArgs)` | 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. |

## Endpoint connectivity detection

Whether and when an event fires depends upon the underlying transport. In the case of USB, in the service, we have a lower-level device watcher checking for the USB disconnects. When we receive one, we add/remove/update the software devices as appropriate. This, in turn, causes these events to fire in the API.

**All Windows MIDI Services endpoints are enumerated and tied to the lifetime of the Windows service.** Shutting down the Windows service will cause all enumerated devices to disconnect and raise the watcher removed events.

### USB

When the USB stack disconnects a device, we see it as a device disconnect. This can happen when the USB device is physically disconnected, when it is powered down, or when the PC is put into suspend and disconnects all USB devices. When the PC wakes from suspend, and the USB stack notifies us that the device is reconnected, it reappears and you can then reconnect to it.

### Bluetooth MIDI

The Blueooth MIDI stack has more of a delay, depending upon how often the device is checked for connectivity. It may be a few seconds before a powered-down BLE MIDI device triggers a disconnect/remove event.

Other network MIDI transports are likely to work in a similar way.

### Virtual Device (app to app) MIDI

In the case of the virtual device MIDI feature, when the hosting application closes the device-side connection, the device is removed and the appropriate event fires.

### Loopback (app to app) MIDI

Loopback endpoints (other than the two diagnostic loopbacks built-in for testing/development) are controlled through either the API or the configuration file. Those created through the configuration file never go away, so there is no removed event fired. Those created through the API can be created/removed through the API at any time, and so will have the appropriate events fire off.

## What happens when an endpoint is disconnected

When an endpoint is disconnected due to the parent device going away, all client connections are closed, and the device connection in the service is also closed. The cross-process message queues are torn down, and any messages there, in the outbound scheduler, or otherwise in the service pipelines are lost.

## IDL

[MidiEndpointDeviceWatcher IDL](https://github.com/microsoft/MIDI/blob/main/src/api/Client/Midi2Client/MidiEndpointDeviceWatcher.idl)
4 changes: 2 additions & 2 deletions docs/other-developer-docs/best-practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ Most apps need to display device and endpoint connection information to their us

### 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.
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 `Windows::Devices::Midi2::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.
There's no API or service reason to require a customer to reboot or reload/restart a MIDI DAW or other application to see newly added endpoints.

### Don't include diagnostics endpoints for most apps

Expand Down
3 changes: 1 addition & 2 deletions src/oob-setup/main-bundle/Bundle.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,9 @@
<!-- Installer custom action uses .NET 4.8. WiX doesn't support .NET non-fx -->
<PackageGroupRef Id="NetFx48RedistAsPrereq" />


<!-- C++ Runtime. The x64 download contains both Arm64 and X64 versions -->

<!-- TODO: Add /quiet to both of these -->

<ExePackage
DisplayName="Microsoft Visual C++ Runtime"
SourceFile="$(DependenciesSourceRootFolder)\VC_redist.x64.exe"
Expand Down
97 changes: 97 additions & 0 deletions src/user-tools/midi-console/Midi/LoggingService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation.Diagnostics;


namespace Microsoft.Devices.Midi2.ConsoleApp
{
public class LoggingService
{
private LoggingChannel _loggingChannel;

private static LoggingService? _current;

public static LoggingService Current
{
get
{
if (_current == null)
_current = new LoggingService();

return _current;
}
}


public LoggingService()
{
var channelId = new Guid("ce8536f1-a223-5028-7c7f-c64452906687");
// guid from: PS> [System.Diagnostics.Tracing.EventSource]::new("Microsoft.Midi.Console").Guid

_loggingChannel = new LoggingChannel("MIDI Console", null, channelId);
}

private string BuildEventName(string filePath, string memberName)
{
//var fileName = Path.GetFileName(filePath);

var className = Path.GetFileNameWithoutExtension(filePath);

return $"{className}::{memberName}";
}


public void LogError(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "")
{
string eventName = BuildEventName(filePath, memberName);

var fields = new LoggingFields();
fields.AddString("file name", filePath);
fields.AddString("message", message);

_loggingChannel.LogEvent(eventName, fields, LoggingLevel.Error);
}

public void LogError(string message, Exception ex, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "")
{
string eventName = BuildEventName(filePath, memberName);

var fields = new LoggingFields();
fields.AddString("file name", filePath);
fields.AddString("message", message);
fields.AddString("exception", ex.ToString());

_loggingChannel.LogEvent(eventName, fields, LoggingLevel.Error);
}


public void LogWarning(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "")
{
string eventName = BuildEventName(filePath, memberName);

var fields = new LoggingFields();
fields.AddString("file name", filePath);
fields.AddString("message", message);

_loggingChannel.LogEvent(eventName, fields, LoggingLevel.Warning);
}

public void LogInfo(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "")
{
string eventName = BuildEventName(filePath, memberName);

var fields = new LoggingFields();
fields.AddString("file name", filePath);
fields.AddString("message", message);

_loggingChannel.LogEvent(eventName, fields, LoggingLevel.Information);
}

}
}
1 change: 1 addition & 0 deletions src/user-tools/midi-console/Midi/Midi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.7" />
<PackageReference Include="Spectre.Console" Version="0.48.1-preview.0.38" />
<PackageReference Include="Spectre.Console.Cli" Version="0.48.1-preview.0.38" />
Expand Down
6 changes: 6 additions & 0 deletions src/user-tools/midi-console/Midi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
Console.InputEncoding = System.Text.Encoding.UTF8;
Console.OutputEncoding = System.Text.Encoding.UTF8;

AppDomain.CurrentDomain.UnhandledException += (s, e) =>
{
LoggingService.Current.LogError(e.ToString()!);
};


var app = new CommandApp();

app.Configure(config =>
Expand Down
18 changes: 5 additions & 13 deletions src/user-tools/midi-settings/Microsoft.Midi.Settings/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public App()
// Other Activation Handlers

// Services
services.AddSingleton<ILoggingService, LoggingService>();

services.AddSingleton<ILocalSettingsService, LocalSettingsService>();
services.AddSingleton<IGeneralSettingsService, GeneralSettingsService>();

Expand All @@ -74,11 +76,6 @@ public App()
services.AddTransient<SettingsViewModel>();
services.AddTransient<SettingsPage>();

services.AddTransient<ContentGridDetailViewModel>();
services.AddTransient<ContentGridDetailPage>();
services.AddTransient<ContentGridViewModel>();
services.AddTransient<ContentGridPage>();

services.AddTransient<ShellPage>();
services.AddTransient<ShellViewModel>();

Expand Down Expand Up @@ -128,18 +125,16 @@ public App()
Build();

UnhandledException += App_UnhandledException;

//App.GetService<ILoggingService>().LogError("This is a test message");
}

private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
{
// TODO: Log and handle exceptions as appropriate.
// https://docs.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.application.unhandledexception.

System.Diagnostics.EventLog.WriteEntry("Windows MIDI Services Settings", e.ToString());

// TEMP!
e.Handled = true;

App.GetService<ILoggingService>().LogError(e.Message);
}

protected async override void OnLaunched(LaunchActivatedEventArgs args)
Expand All @@ -148,10 +143,7 @@ protected async override void OnLaunched(LaunchActivatedEventArgs args)

await App.GetService<IActivationService>().ActivateAsync(args);


// force construction
var current = AppState.Current;


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Microsoft.Midi.Settings.Config

internal class ConfigFile
{
private JsonObject _jsonObject;
// private JsonObject _jsonObject;

//public JsonObject GetEndpointTransportPluginSettingsForTransport(Guid transportId)
//{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ internal class EndpointConfigMetadataPayload : IMidiServiceTransportPluginConfig
{
public bool IsFromConfigurationFile => true;

public JsonObject SettingsJson { get; private set; }
public JsonObject? SettingsJson { get; private set; }

public Guid TransportId { get; private set; }

private string _newName;
private string _newDescription;
private string _newSmallImagePath;
private string _newLargeImagePath;
private readonly string _newName;
private readonly string _newDescription;
private readonly string _newSmallImagePath;
private readonly string _newLargeImagePath;

public EndpointConfigMetadataPayload(Guid transportId, string newName, string newDescription, string newSmallImagePath, string newLargeImagePath)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Extensions.Logging;

namespace Microsoft.Midi.Settings.Contracts.Services
{
public interface ILoggingService
{
void LogError(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "");

void LogError(string message, Exception ex, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "");

void LogWarning(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "");

void LogInfo(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "");

}



}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.240109" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.TraceSource" Version="8.0.0" />
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.7" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240404000" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
Expand Down
Loading

0 comments on commit e8d8430

Please sign in to comment.