Skip to content

Commit

Permalink
Merge pull request #230 from microsoft/pete-dev
Browse files Browse the repository at this point in the history
Fix issue 227
  • Loading branch information
Psychlist1972 authored Jan 18, 2024
2 parents 8845ea7 + 8b0a833 commit 04bcefa
Show file tree
Hide file tree
Showing 24 changed files with 441 additions and 252 deletions.
62 changes: 49 additions & 13 deletions build/build.cake
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
#tool nuget:?package=NuGet.CommandLine&version=5.10
#addin nuget:?package=Cake.Compression&version=0.3.0


//#addin nuget:?package=Cake.Compression&version=0.3.0

// ===========================================================================================
string setupVersionName = "Developer Preview 4";

// ===========================================================================================



Expand Down Expand Up @@ -163,7 +162,8 @@ Task("SetupEnvironment")
// Copy key output files from VSFiles to staging to allow building installer
var outputDir = System.IO.Path.Combine(apiAndServiceSolutionDir, "VSFiles", plat.ToString(), configuration);
var apiHeaderDir = System.IO.Path.Combine(apiAndServiceSolutionDir, "VSFiles\\intermediate\\Windows.Devices.Midi2", plat.ToString(), configuration, "GeneratedFiles\\winrt");
var generatedFilesDir = System.IO.Path.Combine(apiAndServiceSolutionDir, "VSFiles", "intermediate", "Windows.Devices.Midi2", plat.ToString(), configuration, "GeneratedFiles", "winrt");
//var apiHeaderDir = System.IO.Path.Combine(apiAndServiceSolutionDir, "VSFiles\\intermediate\\Windows.Devices.Midi2", plat.ToString(), configuration, "GeneratedFiles\\winrt");
Information("\nCopying service and API for " + plat.ToString());
Expand All @@ -186,16 +186,36 @@ Task("SetupEnvironment")
CopyFiles(System.IO.Path.Combine(outputDir, "WinRTActivationEntries.txt"), copyToDir);
// copy the C++ header for the API
CopyFiles(System.IO.Path.Combine(apiHeaderDir, "Windows.Devices.Midi2.h"), copyToDir);
CopyFiles(System.IO.Path.Combine(generatedFilesDir, "Windows.Devices.Midi2.h"), copyToDir);
// copy the API Header and the .winmd to the "API bare" folder
var apiBareCopyToDir = System.IO.Path.Combine(releaseRootDir, "API");
var apiBareCopyToDir = System.IO.Path.Combine(releaseRootDir, "api");
if (!DirectoryExists(apiBareCopyToDir))
CreateDirectory(apiBareCopyToDir);
if (!DirectoryExists(System.IO.Path.Combine(apiBareCopyToDir, "winrt")))
CreateDirectory(System.IO.Path.Combine(apiBareCopyToDir, "winrt"));
if (!DirectoryExists(System.IO.Path.Combine(apiBareCopyToDir, "winrt", "impl")))
CreateDirectory(System.IO.Path.Combine(apiBareCopyToDir, "winrt", "impl"));
CopyFiles(System.IO.Path.Combine(copyToDir, "Windows.Devices.Midi2.h"), apiBareCopyToDir);
CopyFiles(System.IO.Path.Combine(generatedFilesDir, "base.h"), System.IO.Path.Combine(apiBareCopyToDir, "winrt/"));
CopyFiles(System.IO.Path.Combine(generatedFilesDir, "Windows.Devices.h"), System.IO.Path.Combine(apiBareCopyToDir, "winrt/"));
CopyFiles(System.IO.Path.Combine(generatedFilesDir, "impl/Windows.Devices.Enumeration.2.h"), System.IO.Path.Combine(apiBareCopyToDir, "winrt/impl/"));
CopyFiles(System.IO.Path.Combine(generatedFilesDir, "impl/Windows.Devices.Midi.2.h"), System.IO.Path.Combine(apiBareCopyToDir, "winrt/impl/"));
CopyFiles(System.IO.Path.Combine(generatedFilesDir, "impl/Windows.Foundation.2.h"), System.IO.Path.Combine(apiBareCopyToDir, "winrt/impl/"));
CopyFiles(System.IO.Path.Combine(generatedFilesDir, "impl/Windows.Foundation.Collections.2.h"), System.IO.Path.Combine(apiBareCopyToDir, "winrt/impl/"));
CopyFiles(System.IO.Path.Combine(generatedFilesDir, "impl/Windows.Devices.Midi2.2.h"), System.IO.Path.Combine(apiBareCopyToDir, "winrt/impl/"));
CopyFiles(System.IO.Path.Combine(copyToDir, "Windows.Devices.Midi2.dll"), apiBareCopyToDir);
CopyFiles(System.IO.Path.Combine(copyToDir, "Windows.Devices.Midi2.winmd"), apiBareCopyToDir);
CopyFiles(System.IO.Path.Combine(copyToDir, "Windows.Devices.Midi2.pri"), apiBareCopyToDir);
Expand Down Expand Up @@ -455,7 +475,7 @@ Task("PackSDKProjection")

Task("BuildConsoleApp")
.IsDependentOn("PackAPIProjection")
.IsDependentOn("PackSDKProjection")
/* .IsDependentOn("PackSDKProjection") */
.DoesForEach(platformTargets, plat =>
{
// TODO: Update nuget ref in console app to the new version
Expand Down Expand Up @@ -565,14 +585,14 @@ Task("BuildSettingsApp")
});


string finalSetupName = string.Empty;

Task("BuildInstaller")
.IsDependentOn("SetupEnvironment")
.IsDependentOn("BuildServiceAndAPI")
.IsDependentOn("BuildApiActivationRegEntriesCSharp")
.IsDependentOn("BuildSDK")
.IsDependentOn("BuildSettingsApp")
/* .IsDependentOn("BuildSDK") */
/* .IsDependentOn("BuildSettingsApp") */
.IsDependentOn("BuildConsoleApp")
.DoesForEach(platformTargets, plat =>
{
Expand Down Expand Up @@ -640,7 +660,7 @@ Task("BuildInstaller")
writer.WriteLine("</Include>");
}
string finalSetupName = $"Windows MIDI Services {setupVersionName} {setupBuildPlatform} {setupBuildFullVersionString}.exe";
finalSetupName = $"Windows MIDI Services {setupVersionName} {setupBuildPlatform} {setupBuildFullVersionString}.exe";
var buildSettings = new DotNetBuildSettings
{
Expand Down Expand Up @@ -674,6 +694,9 @@ Task("BuildInstaller")
CopyFiles(System.IO.Path.Combine(consoleOnlySetupProjectDir, "bin", plat.ToString(), "Release", "*.msi"), releaseStandAloneInstallerFolder);
CopyFiles(System.IO.Path.Combine(settingsOnlySetupProjectDir, "bin", plat.ToString(), "Release", "*.msi"), releaseStandAloneInstallerFolder);
});


Expand All @@ -689,6 +712,14 @@ Task("CopyAPIArtifacts")
CopyFiles(System.IO.Path.Combine(apiStagingDir, "Windows.Devices.Midi2.dll"), apiReleaseArtifactsFolder);
CopyFiles(System.IO.Path.Combine(apiStagingDir, "Windows.Devices.Midi2.pri"), apiReleaseArtifactsFolder);
CopyFiles(System.IO.Path.Combine(apiStagingDir, "Windows.Devices.Midi2.h"), apiReleaseArtifactsFolder);
CopyFiles(System.IO.Path.Combine(apiStagingDir, "winrt/base.h"), System.IO.Path.Combine(apiReleaseArtifactsFolder, "winrt/"));
CopyFiles(System.IO.Path.Combine(apiStagingDir, "winrt/Windows.Devices.h"), System.IO.Path.Combine(apiReleaseArtifactsFolder, "winrt/"));
CopyFiles(System.IO.Path.Combine(apiStagingDir, "winrt/impl/Windows.Devices.Enumeration.2.h"), System.IO.Path.Combine(apiReleaseArtifactsFolder, "winrt/impl/"));
CopyFiles(System.IO.Path.Combine(apiStagingDir, "winrt/impl/Windows.Devices.Midi.2.h"), System.IO.Path.Combine(apiReleaseArtifactsFolder, "winrt/impl/"));
CopyFiles(System.IO.Path.Combine(apiStagingDir, "winrt/impl/Windows.Foundation.2.h"), System.IO.Path.Combine(apiReleaseArtifactsFolder, "winrt/impl/"));
CopyFiles(System.IO.Path.Combine(apiStagingDir, "winrt/impl/Windows.Foundation.Collections.2.h"), System.IO.Path.Combine(apiReleaseArtifactsFolder, "winrt/impl/"));
CopyFiles(System.IO.Path.Combine(apiStagingDir, "winrt/impl/Windows.Devices.Midi2.2.h"), System.IO.Path.Combine(apiReleaseArtifactsFolder, "winrt/impl/"));
});

Expand All @@ -701,7 +732,12 @@ Task("Default")
.IsDependentOn("BuildApiActivationRegEntriesInternal")
.IsDependentOn("BuildInstaller")
.IsDependentOn("CopyAPIArtifacts")
;
.Does(() =>
{
Information("\n\nInstaller >> \"" + finalSetupName + "\"\n\n");
});



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 4" ?>
<?define SetupVersionNumber="1.0.24017.2041" ?>
<?define SetupVersionNumber="1.0.24018.1827" ?>
</Include>
Binary file added diagnostics/trace-logging/TraceCaptureFile.etl
Binary file not shown.
1 change: 1 addition & 0 deletions get-started/midi-developers/app-developers/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ API and other documentation which will eventually be used in the Microsoft Learn
| Page | Description |
| ------------- | --------------------- |
| [midi-api-types.md](midi-api-types.md) | Overview of all the major types in the API |
| [timestamps.md](timestamps.md) | Details about Timestamps in Windows MIDI Services |
| [consuming-midi-api.md](consuming-midi-api.md) | How to build against the API |
| [diagnostic-endpoints.md](diagnostic-endpoints.md) | Behavior and use of the diagnostic loopback and ping endpoints |
| [best-practices.md](best-practices-endpoints.md) | Best practices and tips when using the API |
Expand Down
16 changes: 16 additions & 0 deletions get-started/midi-developers/app-developers/docs/timestamps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# MIDI Clock and Timestamps

## The MidiClock Type

The Windows::Devices::Midi2::MidiClock type provides access to the system-wide MIDI Timestamp system. Timestamps are high-resultion tick counts which can be converted to offsets in seconds or fractions of seconds, but do not represent a real-world time of day without additional tracking with an external reference clock (`GetSystemTimePreciseAsFileTime`, for example).


## High-resolution timestamps

Windows MIDI Services currently uses the high-resolution 64 bit QueryPerformanceCounter type.

On most systems, the resolution is 100ns per tick, and so takes around 30,000 years to roll over. You do not need to worry about it wrapping around to zero, instead you can rely on the ticks to increase.

You can learn more about high-resolution timestamps in Windows at [https://aka.ms/miditimestamp](https://aka.ms/miditimestamp).

It's unlikely that we will change from QueryPerformanceCounter to another mechanism in the future. But the contract with applications is the MidiClock type. If you want to ensure your applications continue to work across revisions, always use `MidiClock::Now()` to acquire a timestamp, and use the other `MidiClock` methods for calculating ticks per second
Original file line number Diff line number Diff line change
Expand Up @@ -142,21 +142,53 @@ CMidi2LoopbackMidiBiDi::SendMidiMessage(
LONGLONG Timestamp
)
{
TraceLoggingWrite(
MidiDiagnosticsAbstractionTelemetryProvider::Provider(),
__FUNCTION__,
TraceLoggingLevel(WINEVENT_LEVEL_INFO),
TraceLoggingPointer(this, "this")
);


RETURN_HR_IF_NULL(E_INVALIDARG, Message);
RETURN_HR_IF(E_INVALIDARG, Size < sizeof(uint32_t));

if (m_IsPing)
{
TraceLoggingWrite(
MidiDiagnosticsAbstractionTelemetryProvider::Provider(),
__FUNCTION__,
TraceLoggingLevel(WINEVENT_LEVEL_INFO),
TraceLoggingPointer(this, "this"),
TraceLoggingWideString(L"Sending Ping")
);

RETURN_HR_IF_NULL(E_POINTER, m_PingMidiDevice);
return m_PingMidiDevice->SendMidiMessage(Message, Size, Timestamp);
}
else if (m_IsEndpointA)
{
TraceLoggingWrite(
MidiDiagnosticsAbstractionTelemetryProvider::Provider(),
__FUNCTION__,
TraceLoggingLevel(WINEVENT_LEVEL_INFO),
TraceLoggingPointer(this, "this"),
TraceLoggingWideString(L"Sending From Loopback A to B")
);

RETURN_HR_IF_NULL(E_POINTER, m_LoopbackMidiDevice);
return m_LoopbackMidiDevice->SendMidiMessageFromAToB(Message, Size, Timestamp);
}
else
{
TraceLoggingWrite(
MidiDiagnosticsAbstractionTelemetryProvider::Provider(),
__FUNCTION__,
TraceLoggingLevel(WINEVENT_LEVEL_INFO),
TraceLoggingPointer(this, "this"),
TraceLoggingWideString(L"Sending From Loopback B to A")
);

RETURN_HR_IF_NULL(E_POINTER, m_LoopbackMidiDevice);
return m_LoopbackMidiDevice->SendMidiMessageFromBToA(Message, Size, Timestamp);
}
Expand All @@ -171,6 +203,13 @@ CMidi2LoopbackMidiBiDi::Callback(
LONGLONG
)
{
TraceLoggingWrite(
MidiDiagnosticsAbstractionTelemetryProvider::Provider(),
__FUNCTION__,
TraceLoggingLevel(WINEVENT_LEVEL_INFO),
TraceLoggingPointer(this, "this")
);

RETURN_HR_IF_NULL(E_INVALIDARG, Message);
RETURN_HR_IF_NULL(E_POINTER, m_Callback);
RETURN_HR_IF(E_INVALIDARG, Size < sizeof(uint32_t));
Expand Down
1 change: 1 addition & 0 deletions src/api/Abstraction/DiagnosticsAbstraction/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ DllMain(
{
if (Reason == DLL_PROCESS_ATTACH)
{
OutputDebugString(__FUNCTION__ L" Setting Diagnostics Abstraction error logging.\n");
wil::SetResultTelemetryFallback(MidiDiagnosticsAbstractionTelemetryProvider::FallbackTelemetryCallback);
}

Expand Down
2 changes: 1 addition & 1 deletion src/api/Abstraction/MidiSrvAbstraction/Midi2.MidiSrv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ CMidi2MidiSrv::Initialize(

//creationParams.BufferSize = PAGE_SIZE; // original
//creationParams.BufferSize = 512; // Set this for debugging see https://github.com/microsoft/MIDI/issues/182 for all the drama :)
creationParams.BufferSize = PAGE_SIZE * 4;
creationParams.BufferSize = PAGE_SIZE * 2;


RETURN_IF_FAILED(GetMidiSrvBindingHandle(&bindingHandle));
Expand Down
8 changes: 7 additions & 1 deletion src/api/Client/Midi2Client/MidiClock.idl
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ namespace Windows.Devices.Midi2
// returns the units per second for the timestamp
static UInt64 TimestampFrequency{ get; };

// convenience function
// convenience functions
//static Double ConvertTimestampToNanoseconds(MIDI_TIMESTAMP timestampValue); // TODO post-NAMM 2024
static Double ConvertTimestampToMicroseconds(MIDI_TIMESTAMP timestampValue);
static Double ConvertTimestampToMilliseconds(MIDI_TIMESTAMP timestampValue);
//static Double ConvertTimestampToSeconds(MIDI_TIMESTAMP timestampValue); // TODO post-NAMM 2024

// these can offset to the future or the past, which is why the offset is signed
static MIDI_TIMESTAMP OffsetTimestampByTicks(MIDI_TIMESTAMP timestampValue, Int64 offsetTicks);
Expand All @@ -37,6 +39,10 @@ namespace Windows.Devices.Midi2
// synchronizing timestamps to wall clock time, as much as that is possible






}
}

26 changes: 13 additions & 13 deletions src/api/Client/Midi2Client/MidiEndpointConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ namespace winrt::Windows::Devices::Midi2::implementation
}
catch (winrt::hresult_error const& ex)
{
internal::LogHresultError(__FUNCTION__, L" hresult exception initializing endpoint.", ex);
internal::LogHresultError(__FUNCTION__, L"hresult exception initializing endpoint.", ex);

return false;
}
Expand Down Expand Up @@ -214,7 +214,7 @@ namespace winrt::Windows::Devices::Midi2::implementation
}
catch (winrt::hresult_error const& ex)
{
internal::LogHresultError(__FUNCTION__, L" hresult exception initializing endpoint interface. Service may be unavailable.", ex);
internal::LogHresultError(__FUNCTION__, L"hresult exception initializing endpoint interface. Service may be unavailable.", ex);

m_endpointAbstraction = nullptr;

Expand All @@ -223,7 +223,7 @@ namespace winrt::Windows::Devices::Midi2::implementation
}
else
{
internal::LogGeneralError(__FUNCTION__, L" Endpoint interface is nullptr");
internal::LogGeneralError(__FUNCTION__, L"Endpoint interface is nullptr");

return false;
}
Expand All @@ -239,7 +239,7 @@ namespace winrt::Windows::Devices::Midi2::implementation

void MidiEndpointConnection::Close()
{
internal::LogInfo(__FUNCTION__, L"Connection Close ");
internal::LogInfo(__FUNCTION__, L"Connection Close");

if (m_closeHasBeenCalled) return;

Expand Down Expand Up @@ -281,7 +281,7 @@ namespace winrt::Windows::Devices::Midi2::implementation

void MidiEndpointConnection::InitializePlugins() noexcept
{
internal::LogInfo(__FUNCTION__, L"Initializing message processing plugins ");
internal::LogInfo(__FUNCTION__, L"Initializing message processing plugins");

for (const auto& plugin : m_messageProcessingPlugins)
{
Expand Down Expand Up @@ -389,7 +389,7 @@ namespace winrt::Windows::Devices::Midi2::implementation
midi2::MidiSendMessageResult MidiEndpointConnection::SendMessageStruct(
internal::MidiTimestamp timestamp,
midi2::MidiMessageStruct const& message,
uint8_t wordCount)
uint8_t wordCount) noexcept
{
internal::LogInfo(__FUNCTION__, L"Sending message struct");

Expand Down Expand Up @@ -485,7 +485,7 @@ namespace winrt::Windows::Devices::Midi2::implementation
const internal::MidiTimestamp timestamp,
winrt::Windows::Foundation::IMemoryBuffer const& buffer,
const uint32_t byteOffset,
const uint8_t byteLength)
const uint8_t byteLength) noexcept
{
internal::LogInfo(__FUNCTION__, L"Sending message buffer");

Expand Down Expand Up @@ -547,7 +547,7 @@ namespace winrt::Windows::Devices::Midi2::implementation
winrt::array_view<uint32_t const> words,
uint32_t const startIndex,
uint8_t const wordCount
)
) noexcept
{
internal::LogInfo(__FUNCTION__, L"Sending message word array");

Expand Down Expand Up @@ -604,7 +604,7 @@ namespace winrt::Windows::Devices::Midi2::implementation
_Use_decl_annotations_
midi2::MidiSendMessageResult MidiEndpointConnection::SendMessageWords(
internal::MidiTimestamp const timestamp,
uint32_t const word0)
uint32_t const word0) noexcept
{
internal::LogInfo(__FUNCTION__, L"Sending message words (1)");

Expand Down Expand Up @@ -656,7 +656,7 @@ namespace winrt::Windows::Devices::Midi2::implementation
midi2::MidiSendMessageResult MidiEndpointConnection::SendMessageWords(
internal::MidiTimestamp const timestamp,
uint32_t const word0,
uint32_t const word1)
uint32_t const word1) noexcept
{
internal::LogInfo(__FUNCTION__, L"Sending message words (2)");

Expand Down Expand Up @@ -712,7 +712,7 @@ namespace winrt::Windows::Devices::Midi2::implementation
internal::MidiTimestamp const timestamp,
uint32_t const word0,
uint32_t const word1,
uint32_t const word2)
uint32_t const word2) noexcept
{
internal::LogInfo(__FUNCTION__, L"Sending message words (3)");

Expand Down Expand Up @@ -771,7 +771,7 @@ namespace winrt::Windows::Devices::Midi2::implementation
uint32_t const word0,
uint32_t const word1,
uint32_t const word2,
uint32_t const word3)
uint32_t const word3) noexcept
{
internal::LogInfo(__FUNCTION__, L"Sending message words (4)");

Expand Down Expand Up @@ -826,7 +826,7 @@ namespace winrt::Windows::Devices::Midi2::implementation

_Use_decl_annotations_
midi2::MidiSendMessageResult MidiEndpointConnection::SendMessagePacket(
midi2::IMidiUniversalPacket const& message)
midi2::IMidiUniversalPacket const& message) noexcept
{
internal::LogInfo(__FUNCTION__, L"Sending message packet");

Expand Down
Loading

0 comments on commit 04bcefa

Please sign in to comment.