diff --git a/get-started/midi-developers/app-developers/docs/README.md b/get-started/midi-developers/app-developers/docs/README.md index 63c80e613..bebe0edd6 100644 --- a/get-started/midi-developers/app-developers/docs/README.md +++ b/get-started/midi-developers/app-developers/docs/README.md @@ -2,46 +2,8 @@ API and other documentation which will eventually be used in either the Microsoft.com docs portal, or in a github site. Format is markdown. Work on the docs has not really started. We will lean heavily on the samples to help wth explanations. -## Some basics - -The API, SDK, tools, service, drivers, and more are being developed with some guidelines about how apps could/should interact with MIDI on Windows. In no specific order or organization, here's a high-level look at what we plan to do here. In most cases, the MIDI API provides raw, and not easily used information, but the MIDI SDK provides everything an application needs to use the API in a way compatible with the MIDI Association MIDI 2.0 Implementation Guide. - -Both the MIDI API and the SDK are Windows Runtime (WinRT) components. - -* [Using WinRT Components from Desktop Applications](https://blogs.windows.com/windowsdeveloper/2019/04/30/enhancing-non-packaged-desktop-apps-using-windows-runtime-components/) - -### Enumeration - -MIDI 2.0 enumeration involves both physically connected devices discoverable through PnP, as well as in-protocol information. - -#### Enumerate UMP Endpoints - -Windows.Devices.Enumeration provides the classes required to enumerate MIDI devices, and to watch for add/removal of devices, as it. We're building upon that and use the SDK to interpret the enumerated information as well as provide additional information about the devices. - -#### Get Group Block or Function Block information for a UMP Endpoint - -Function blocks could be requested through in-protocol UMP messages. Our intent is that applications not do this themselves, but that they use an SDK call to request this information. That gives us flexibility in how we can provide this information for older devices, and also reduce the number of Function Block information request calls. - -Group Block information is provided by the USB driver, and passed through the API to the SDK. - -### Names and Formatting - -MIDI 2.0 naming of entities is more complex than it was with MIDI 1.0. Names can be sourced from different places through both enumeration and in-protocol messages. We would like to keep names consistent across applications and Windows. To that end, the SDK includes code to provide formatted, and when appropriate, localized names for entities. - -#### Format Function Block, Group Block, UMP Endpoint names - -The SDK will provide properties with this information formatted per the implementation guide. - -#### Format Group and Channel names - -The SDK has calls to enumerate Groups and Channels using data provided by MIDI 2.0 and MIDI CI. The results are formatted as per the MIDI 2.0 implementation guide and with the correct number transition (0-15 indexes changed to 1-16 for display, Channel names listed when available, Function Block names included with the group, etc.) - -### USB MIDI 2.0 UMP Endpoints - -#### Support more than one UMP Endpoint on a MIDI 2.0 USB device - -We recommend you use a separate MIDI interface for each UMP Endpoint exposed by a USB device. This makes it easier to correctly association group blocks and with the resulting UMP Endpoints. Our driver does not support multiple UMP Endpoints on a single interface. - -#### Use both Function Blocks and Group Blocks - -The MIDI Association implementation guide has information on using both function blocks and group blocks together. These need to be logically consistent and not overlap in incompatible ways. This is especially important for how macOS uses these entities, so we don't want to have them represented differently on the operating systems. +| Page | Description | +| ------------- | --------------------- | +| [consuming-midi-sdk.md](consuming-midi-sdk.md) | Information on how to use the SDK in your own apps | +| [building-midi-sdk.md](building-midi-sdk.md) | Basics on what's needed in case you want to build the SDK yourself | +| [general-info.md](general-info.md) | Some early general information about the SDK | diff --git a/get-started/midi-developers/app-developers/docs/building-midi-sdk.md b/get-started/midi-developers/app-developers/docs/building-midi-sdk.md new file mode 100644 index 000000000..9f24a5b0d --- /dev/null +++ b/get-started/midi-developers/app-developers/docs/building-midi-sdk.md @@ -0,0 +1,41 @@ +# Building the MIDI SDK for yourself + +The Windows MIDI Services SDK 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. + +Normally, you'll just one of the SDK packages. However, if you wish to build it for yourself, this document explains how. + +## Prerequisites + +To build the SDK you need to use Visual Studio 2022 and C++/WinRT + +* 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) +* Boost 1.82 or higher installed in %BOOST_ROOT% (and that environment variable set, of course) + * The same environment variable as $(BOOST_ROOT) needs to be in your VC++ include location for all build configurations. +* C++/WinRT will be installed via NuGet + +## Folder Structure + +Here's the structure on my developer PC. + +`github\microsoft\midi` is the root of the repo. Inside that, the src, get-started, etc. folders from GitHub. + +`github\microsoft\midi\publish` is a folder that doesn't appear in the repo, but is referenced by the NuGet build. This is where the NuGet packages end up + +`github\microsoft\midi\src\app-dev-sdk\_build` is the build target location for SDK projects. This is where the NuGet packaging steps expect to find the binaries for packaging. + +## Building + +The midi-sdk solution is the main solution for building, well, the MIDI SDK. It includes the correct `runsettings` for tests, and the `Directory.Build.props` files for the build layout. + +For the native projects, note that 32 Bit Arm and x86 (32 bit) architectures are not supported by this project. You may build for x64, Arm64, (and in the future, Arm64EC). We are intentionally not building for 32 bit architectures here. + +NuGet packages are set to pick up only Release output, not Debug. To get it all going, do a batch build of the supported architectures. + +## Tests + +To run the Catch2 unit tests, you'll need the Catch2 Test Adapter VSIX installed. It's called `Test Adapter for Catch2` and is available in the Visual Studio Marketplace. + +Open the Test Explorer and then build the full solution if tests do not appear in it. You can then execute tests. diff --git a/get-started/midi-developers/app-developers/docs/consuming-midi-sdk.md b/get-started/midi-developers/app-developers/docs/consuming-midi-sdk.md index 1fa79c4de..3608c6cb6 100644 --- a/get-started/midi-developers/app-developers/docs/consuming-midi-sdk.md +++ b/get-started/midi-developers/app-developers/docs/consuming-midi-sdk.md @@ -10,6 +10,7 @@ To use the SDK (or underlying API) your application language and tools must be a * 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. @@ -47,6 +48,8 @@ When run outside the tools, you'll need to be prepared to either use a packaged ### Problem locating header files +**First, REBuild your project (not just Build) after adding or updating the SDK NuGet package.** I'm working on the correct targets file to enable normal incremental build to generate the header file based on the winmd, but it's not functioning at the moment. Of course, I'm assuming you have the C++/WinRT NuGet package already installed in your project. + If your project cannot resolve the header files, you may be running into [this bug](https://github.com/microsoft/cppwinrt/issues/593). That bug should be fixed, but there are instances, it seems, where it still crops up. If that happens, and you've verified that it's not a problem with the WinMD missing from your project (it's more typically an issue with a reference), you can add `$(GeneratedFilesDir)` to the include path for your project. CPPWinRT.exe creates the winrt/namespace-name.h files in the Generated Files/winrt folder based upon the referenced winmd. @@ -57,23 +60,18 @@ Add the C++/WinRT Nuget package to your C++ project in Visual Studio. This insta 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 /publish for all NuGet packages - -The next step will become unnecessary once the package structure is sorted. It's a silly step, and restricts you to a single architecture at the moment, but needed right now. - -* Right-click the project in Visual Studio, and add a reference -* Browse to the packages folder for your project, and into the folder for the NuGet package you installed -* Navigate to the runtimes\win10-x64\native folder -* Add the reference to the .winmd from there. Both the .winmd and the .dll are located in that same folder, which is important. If the files are not side by side, type activation will fail. +* 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 /publish for all NuGet packages. Specifically `D:\peteb\Documents\GitHub\microsoft\midi\publish\` 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. (If you do not want to do this, you'll need to manually set up the cppwinrt tools as part of your build process). > Tip: you can look at the SDK tests for up-to-date project files which target the SDKs in the same solution -[Read through this page](https://learn.microsoft.com/windows/uwp/cpp-and-winrt-apis/consume-apis), specifically the "If the API is implemented in a Windows Runtime component". For the SDK, the calls are NOT in a Windows namespace, although that section can be useful to read. +[Read through this page](https://learn.microsoft.com/windows/uwp/cpp-and-winrt-apis/consume-apis), specifically the "If the API is implemented in a Windows Runtime component". **For the MIDI SDK, the calls are NOT in a Windows namespace, although that section can be useful to read.** 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](https://github.com/microsoft/midi/get-started/midi-developers/app-developers/samples/cpp-winrt/) * [Introduction to C++/WinRT](https://learn.microsoft.com/windows/uwp/cpp-and-winrt-apis/) * [C++/WinRT on GitHub](https://github.com/microsoft/cppwinrt) @@ -82,6 +80,8 @@ After that, you reference the types as you would anything else in C++. Only the ## Consuming from C# Desktop App +**NOTE: In the current SDK builds, .NET Consumption is not working** + Please note any .NET-specifics called out in the package release. Some early packages do not support C#/ .NET. Your project will currently need to target .NET 7 or above. We are considering support for .NET Framework and lower versions of .NET like .NET 6. However, that is neither confirmed nor promised. @@ -99,7 +99,7 @@ The package contains the .NET (C#) projection for .NET 7 and above. You will sti Support for this is not yet in place. We are evaluating. -## Consuming from RS +## Consuming from Rust / RS We will provide more information in the future. However, you will follow a similar approach to C++ using RS/WinRT instead of C++/WinRT. Note that teh 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.** diff --git a/get-started/midi-developers/app-developers/docs/general-info.md b/get-started/midi-developers/app-developers/docs/general-info.md new file mode 100644 index 000000000..63c80e613 --- /dev/null +++ b/get-started/midi-developers/app-developers/docs/general-info.md @@ -0,0 +1,47 @@ +# Documentation + +API and other documentation which will eventually be used in either the Microsoft.com docs portal, or in a github site. Format is markdown. Work on the docs has not really started. We will lean heavily on the samples to help wth explanations. + +## Some basics + +The API, SDK, tools, service, drivers, and more are being developed with some guidelines about how apps could/should interact with MIDI on Windows. In no specific order or organization, here's a high-level look at what we plan to do here. In most cases, the MIDI API provides raw, and not easily used information, but the MIDI SDK provides everything an application needs to use the API in a way compatible with the MIDI Association MIDI 2.0 Implementation Guide. + +Both the MIDI API and the SDK are Windows Runtime (WinRT) components. + +* [Using WinRT Components from Desktop Applications](https://blogs.windows.com/windowsdeveloper/2019/04/30/enhancing-non-packaged-desktop-apps-using-windows-runtime-components/) + +### Enumeration + +MIDI 2.0 enumeration involves both physically connected devices discoverable through PnP, as well as in-protocol information. + +#### Enumerate UMP Endpoints + +Windows.Devices.Enumeration provides the classes required to enumerate MIDI devices, and to watch for add/removal of devices, as it. We're building upon that and use the SDK to interpret the enumerated information as well as provide additional information about the devices. + +#### Get Group Block or Function Block information for a UMP Endpoint + +Function blocks could be requested through in-protocol UMP messages. Our intent is that applications not do this themselves, but that they use an SDK call to request this information. That gives us flexibility in how we can provide this information for older devices, and also reduce the number of Function Block information request calls. + +Group Block information is provided by the USB driver, and passed through the API to the SDK. + +### Names and Formatting + +MIDI 2.0 naming of entities is more complex than it was with MIDI 1.0. Names can be sourced from different places through both enumeration and in-protocol messages. We would like to keep names consistent across applications and Windows. To that end, the SDK includes code to provide formatted, and when appropriate, localized names for entities. + +#### Format Function Block, Group Block, UMP Endpoint names + +The SDK will provide properties with this information formatted per the implementation guide. + +#### Format Group and Channel names + +The SDK has calls to enumerate Groups and Channels using data provided by MIDI 2.0 and MIDI CI. The results are formatted as per the MIDI 2.0 implementation guide and with the correct number transition (0-15 indexes changed to 1-16 for display, Channel names listed when available, Function Block names included with the group, etc.) + +### USB MIDI 2.0 UMP Endpoints + +#### Support more than one UMP Endpoint on a MIDI 2.0 USB device + +We recommend you use a separate MIDI interface for each UMP Endpoint exposed by a USB device. This makes it easier to correctly association group blocks and with the resulting UMP Endpoints. Our driver does not support multiple UMP Endpoints on a single interface. + +#### Use both Function Blocks and Group Blocks + +The MIDI Association implementation guide has information on using both function blocks and group blocks together. These need to be logically consistent and not overlap in incompatible ways. This is especially important for how macOS uses these entities, so we don't want to have them represented differently on the operating systems. diff --git a/get-started/midi-developers/app-developers/samples/cpp-winrt/sdk-client-basics/main.cpp b/get-started/midi-developers/app-developers/samples/cpp-winrt/sdk-client-basics/main.cpp index 6f1ccbd4a..fe2e9fdb9 100644 --- a/get-started/midi-developers/app-developers/samples/cpp-winrt/sdk-client-basics/main.cpp +++ b/get-started/midi-developers/app-developers/samples/cpp-winrt/sdk-client-basics/main.cpp @@ -16,23 +16,29 @@ int main() { init_apartment(); - // check for presence of compatible Windows MIDI Services + std::cout << "Checking for MIDI Services" << std::endl; - WindowsMidiServicesCheckError err; - bool servicesOk = MidiServices::CheckForWindowsMidiServices(err); + // check for presence of compatible Windows MIDI Services + auto checkResult = MidiServices::CheckForWindowsMidiServices(); // proceed only if MIDI services is present and compatible. Your own application may decide // to fall back to WinRT/WinMM MIDI 1.0 APIs, or to prompt the user to install the latest // version of Windows MIDI Services - if (servicesOk) + if (checkResult == WindowsMidiServicesCheckResult::PresentAndUsable) { + std::cout << "MIDI Services Present and usable" << std::endl; + // create the MIDI session, giving us access to Windows MIDI Services. An app may open // more than one session. If so, the session name should be meaningful to the user, like // the name of a browser tab, or a project. + std::cout << "Creating session settings." << std::endl; + MidiSessionSettings sessionSettings = MidiSessionSettings::Default(); + std::cout << "Creating session." << std::endl; + auto session = MidiSession::CreateNewSession(L"Sample Session", sessionSettings); // you can ask for MIDI 1.0 Byte Stream devices, MIDI 2.0 UMP devices, or both. Note that Some MIDI 2.0 @@ -40,6 +46,8 @@ int main() // Note that every device uses UMP through this API, but it can be helpful to know when a device is // a MIDI 1.0 device at the main interface level. + std::cout << "Creating Device Selector." << std::endl; + hstring deviceSelector = MidiEndpointConnection::GetDeviceSelector(); // Enumerate UMP endpoints. Note that per C++, main cannot be a co-routine, @@ -48,11 +56,15 @@ int main() // MidiDeviceInformation instances, and to simplify calling code (reducing need for apps to // incorporate async handling). + std::cout << "Enumerating through Windows::Devices::Enumeration." << std::endl; + Windows::Foundation::IAsyncOperation op = DeviceInformation::FindAllAsync(deviceSelector); DeviceInformationCollection endpointDevices = op.get(); if (endpointDevices.Size() > 0) { + std::cout << "MIDI Endpoints were found (not really, but pretending they are for now)." << std::endl; + // We're going to just pick the first one we find. Normally, you'd have the user pick from a list // or you'd otherwise have an Id at hand. DeviceInformation selectedEndpointInformation = endpointDevices.GetAt(0); @@ -60,18 +72,21 @@ int main() // if we want the additional properties that are available to us, we can wrap the // DeviceInformation object with a MIDI-specific one. You can also skip this and call the CreatFromId // method directly on MidiDeviceInformation if you have an Id handy. - MidiDeviceInformation selectedMidiEndpointInformation = MidiDeviceInformation::FromDeviceInformation(selectedEndpointInformation); +// MidiDeviceInformation selectedMidiEndpointInformation = MidiDeviceInformation::FromDeviceInformation(selectedEndpointInformation); //selectedMidiEndpointInformation.DeviceThumbnail(); //selectedMidiEndpointInformation.EndpointDataFormat(); // ... // then you connect to the UMP endpoint - auto endpoint = session.ConnectToEndpoint(selectedMidiEndpointInformation.Id(), true, MidiEndpointConnectOptions::Default()); + std::cout << "Connecting to UMP Endpoint." << std::endl; + + //auto endpoint = session.ConnectToEndpoint(selectedMidiEndpointInformation.Id(), MidiEndpointConnectOptions::Default()); + auto endpoint = session.ConnectToEndpoint(L"foobarbaz", MidiEndpointConnectOptions::Default()); // after connecting, you can send and receive messages - auto writer = endpoint.GetMessageWriter(); +// auto writer = endpoint.GetMessageWriter(); // writer.WriteUmpWithTimestamp(...); @@ -80,6 +95,7 @@ int main() else { // no MIDI endpoints found. We'll just bail here + std::cout << "No MIDI Endpoints were found." << std::endl; } // close the session, detaching all Windows MIDI Services resources and closing all connections @@ -88,12 +104,17 @@ int main() } else { - if (err == WindowsMidiServicesCheckError::NotPresent) + if (checkResult == WindowsMidiServicesCheckResult::NotPresent) { + std::cout << "MIDI Services Not Present" << std::endl; + // allow the user to install the minimum required version } - else if (err == WindowsMidiServicesCheckError::IncompatibleVersion) + else if (checkResult == WindowsMidiServicesCheckResult::IncompatibleVersion) { + std::cout << "MIDI Present, but is not a compatible version." << std::endl; + std::cout << "Here you would prompt the user to install the latest version from " << winrt::to_string(MidiServices::LatestMidiServicesInstallUri().ToString()) << std::endl; + // allow the user to install the minimum required version } } diff --git a/get-started/midi-developers/app-developers/samples/cpp-winrt/sdk-client-basics/packages.config b/get-started/midi-developers/app-developers/samples/cpp-winrt/sdk-client-basics/packages.config index d1334dc57..b7c817786 100644 --- a/get-started/midi-developers/app-developers/samples/cpp-winrt/sdk-client-basics/packages.config +++ b/get-started/midi-developers/app-developers/samples/cpp-winrt/sdk-client-basics/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/get-started/midi-developers/app-developers/samples/cpp-winrt/sdk-client-basics/sdk-client-basics.vcxproj b/get-started/midi-developers/app-developers/samples/cpp-winrt/sdk-client-basics/sdk-client-basics.vcxproj index 22f712e91..0f4a629b0 100644 --- a/get-started/midi-developers/app-developers/samples/cpp-winrt/sdk-client-basics/sdk-client-basics.vcxproj +++ b/get-started/midi-developers/app-developers/samples/cpp-winrt/sdk-client-basics/sdk-client-basics.vcxproj @@ -1,6 +1,6 @@ - + @@ -147,16 +147,10 @@ - - - packages\Microsoft.Devices.Midi2.Core.1.0.0-preview.1-0064\runtimes\win10-x64\native\Microsoft.Devices.Midi2.winmd - true - - - + @@ -165,7 +159,7 @@ - - + + \ No newline at end of file diff --git a/src/app-dev-sdk/sdk-core-cpp-winrt-tests/DummyTests.cpp b/src/app-dev-sdk/sdk-core-cpp-winrt-tests/DummyTests.cpp deleted file mode 100644 index 2ef0272bc..000000000 --- a/src/app-dev-sdk/sdk-core-cpp-winrt-tests/DummyTests.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "pch.h" - -#include "catch_amalgamated.hpp" - -using namespace winrt; -using namespace Microsoft::Devices::Midi2; - -namespace DummyTests -{ - - TEST_CASE("Create test class and set a property") - { - DummyTestClass obj; - - const uint32_t val = 200; - - obj.SomeProperty(val); - - REQUIRE((bool)(obj.SomeProperty() == val)); - } - - TEST_CASE("Load up UMPs") - { - const uint32_t countUmp = 10; - - DummyTestClass obj{}; - - obj.LoadDummyUmps(countUmp); - - REQUIRE((bool)(obj.Umps().Size() == countUmp)); - } - - -} diff --git a/src/app-dev-sdk/sdk-core-cpp-winrt-tests/ServiceTests.cpp b/src/app-dev-sdk/sdk-core-cpp-winrt-tests/ServiceTests.cpp index c1027f8df..d999bf55e 100644 --- a/src/app-dev-sdk/sdk-core-cpp-winrt-tests/ServiceTests.cpp +++ b/src/app-dev-sdk/sdk-core-cpp-winrt-tests/ServiceTests.cpp @@ -2,46 +2,64 @@ #include "catch_amalgamated.hpp" +#include + using namespace winrt; using namespace Microsoft::Devices::Midi2; -TEST_CASE("Check for Windows MIDI Services", "[MidiServices.CheckForWindowsMidiServices]") +TEST_CASE("Check MIDI Services Properties") { - // fails until implemented - REQUIRE(false); + SECTION("Check for Windows MIDI Services") + { + REQUIRE_NOTHROW(MidiServices::CheckForWindowsMidiServices()); + } - //REQUIRE((bool)(obj.SomeProperty() == val)); -} + SECTION("Get installed Windows MIDI Services Version") + { + REQUIRE_NOTHROW(MidiServices::GetInstalledWindowsMidiServicesVersion()); -TEST_CASE("Get installed Windows MIDI Services Version", "[MidiServices.GetInstalledWindowsMidiServicesVersion]") -{ - // fails until implemented - REQUIRE(false); - //REQUIRE((bool)(obj.SomeProperty() == val)); -} + hstring version = MidiServices::GetInstalledWindowsMidiServicesVersion(); -TEST_CASE("Get SDK Version", "[MidiServices.GetSdkVersion]") -{ - // fails until implemented - REQUIRE(false); + std::cout << "Windows MIDI Services API/Service Version: " << winrt::to_string(version) << std::endl; - //REQUIRE((bool)(obj.SomeProperty() == val)); -} + REQUIRE(version != L""); + } -TEST_CASE("Get Latest MIDI Services Installer URI", "[MidiServices.LatestMidiServicesInstallUri]") -{ - // fails until implemented - REQUIRE(false); + SECTION("Get SDK Version") + { + REQUIRE_NOTHROW(MidiServices::SdkVersion()); + + hstring version = MidiServices::SdkVersion(); + + std::cout << "SDK Version: " << winrt::to_string(version) << std::endl; + + REQUIRE(version != L""); + } + + SECTION("Get Latest MIDI Services Installer URI") + { + REQUIRE_NOTHROW(MidiServices::LatestMidiServicesInstallUri()); + + auto uri = MidiServices::LatestMidiServicesInstallUri(); + + std::cout << "Installer URI: " << winrt::to_string(uri.ToString()) << std::endl; + } - //REQUIRE((bool)(obj.SomeProperty() == val)); } -TEST_CASE("Get Installed Transports", "[MidiServices.GetInstalledTransports]") + +TEST_CASE("Access MIDI Services Transports") { - // fails until implemented - REQUIRE(false); + SECTION("Get installed transports") + { + REQUIRE_NOTHROW(MidiServices::GetInstalledTransports()); + + auto transports = MidiServices::GetInstalledTransports(); + + // zero installed transports is, in theory, a passing case, but we're going to ignore that + REQUIRE(transports.Size() > 0); + } - //REQUIRE((bool)(obj.SomeProperty() == val)); } diff --git a/src/app-dev-sdk/sdk-core-cpp-winrt-tests/SessionTests.cpp b/src/app-dev-sdk/sdk-core-cpp-winrt-tests/SessionTests.cpp index 6a39c36d9..37f0b4bfd 100644 --- a/src/app-dev-sdk/sdk-core-cpp-winrt-tests/SessionTests.cpp +++ b/src/app-dev-sdk/sdk-core-cpp-winrt-tests/SessionTests.cpp @@ -2,17 +2,83 @@ #include "catch_amalgamated.hpp" +#include +#include + using namespace winrt; using namespace Microsoft::Devices::Midi2; +// Note: These will be exposed by properties in the future + +#define MIDI_SDK_LOOPBACK_SIM1_ENDPOINT_ID L"SWD\\MIDISDK\\MIDI_LOOPBACK1.LOOP20" +#define MIDI_SDK_LOOPBACK_SIM2_ENDPOINT_ID L"SWD\\MIDISDK\\MIDI_LOOPBACK2.LOOP20" -TEST_CASE("Create session") +TEST_CASE("Create new session and endpoints") { auto settings = MidiSessionSettings::Default(); auto session = MidiSession::CreateNewSession(L"Test Session Name", settings); + REQUIRE((bool)(session.IsOpen())); + + SECTION("Timestamps") + { + SECTION("MIDI timestamp appears to work") + { + std::cout << "Current timestamp: " << session.GetMidiTimestamp() << std::endl; + std::cout << "Current timestamp: " << session.GetMidiTimestamp() << std::endl; + std::cout << "Current timestamp: " << session.GetMidiTimestamp() << std::endl; + std::cout << "Current timestamp: " << session.GetMidiTimestamp() << std::endl; + } + + SECTION("MIDI frequency appears to work") + { + std::cout << "Timestamp Frequency: " << session.GetMidiTimestampFrequency() << std::endl; + } + + } + + SECTION("Endpoints") + { + hstring id1 = MIDI_SDK_LOOPBACK_SIM1_ENDPOINT_ID; + hstring id2 = MIDI_SDK_LOOPBACK_SIM2_ENDPOINT_ID; + + SECTION("Creating the local in-proc loopback endpoint works") + { + + REQUIRE((bool)(session.Connections().Size() == 0)); + + auto conn1 = session.ConnectToEndpoint(id1, MidiEndpointConnectOptions::Default()); + + REQUIRE((bool)(session.Connections().Size() == 1)); + + std::cout << "Endpoint 1 Id " << winrt::to_string(conn1.DeviceId()) << std::endl; + REQUIRE((bool)(conn1.DeviceId() == id1)); + + auto conn2 = session.ConnectToEndpoint(id2, MidiEndpointConnectOptions::Default()); + + + REQUIRE((bool)(session.Connections().Size() == 2)); + + std::cout << "Endpoint 2 Id " << winrt::to_string(conn2.DeviceId()) << std::endl; + REQUIRE((bool)(conn2.DeviceId() == id2)); + + std::for_each( + begin(session.Connections()), + end(session.Connections()), + [](const winrt::Windows::Foundation::Collections::IKeyValuePair& kvp) + { + hstring key = kvp.Key(); + + std::cout << "Endpoint Key in Map: " << winrt::to_string(key) << std::endl; + } + ); + + + + } + + } - //REQUIRE((bool)(obj.SomeProperty() == val)); } diff --git a/src/app-dev-sdk/sdk-core-cpp-winrt-tests/sdk-core-cpp-winrt-tests.vcxproj b/src/app-dev-sdk/sdk-core-cpp-winrt-tests/sdk-core-cpp-winrt-tests.vcxproj index 73c8eb51c..9f67418bc 100644 --- a/src/app-dev-sdk/sdk-core-cpp-winrt-tests/sdk-core-cpp-winrt-tests.vcxproj +++ b/src/app-dev-sdk/sdk-core-cpp-winrt-tests/sdk-core-cpp-winrt-tests.vcxproj @@ -125,7 +125,6 @@ - Create diff --git a/src/app-dev-sdk/sdk-core-cpp-winrt-tests/sdk-core-cpp-winrt-tests.vcxproj.filters b/src/app-dev-sdk/sdk-core-cpp-winrt-tests/sdk-core-cpp-winrt-tests.vcxproj.filters index 0f82d3d47..422476006 100644 --- a/src/app-dev-sdk/sdk-core-cpp-winrt-tests/sdk-core-cpp-winrt-tests.vcxproj.filters +++ b/src/app-dev-sdk/sdk-core-cpp-winrt-tests/sdk-core-cpp-winrt-tests.vcxproj.filters @@ -9,9 +9,6 @@ Tests - - TempTests - Tests @@ -27,9 +24,6 @@ - - {fbfc8fff-af3f-4456-b52b-3b6c75bd3672} - {e34a5f67-984a-4f18-8ccd-0bcce7fd5ba9} diff --git a/src/app-dev-sdk/sdk-core-projection-cs/nuget/Microsoft.Devices.Midi2.Core.nuspec b/src/app-dev-sdk/sdk-core-projection-cs/nuget/Microsoft.Devices.Midi2.Core.nuspec index 320867efd..0de456efb 100644 --- a/src/app-dev-sdk/sdk-core-projection-cs/nuget/Microsoft.Devices.Midi2.Core.nuspec +++ b/src/app-dev-sdk/sdk-core-projection-cs/nuget/Microsoft.Devices.Midi2.Core.nuspec @@ -2,7 +2,7 @@ Microsoft.Devices.Midi2.Core - 1.0.0-preview.1-0064 + 1.0.0-preview.1-0084 Microsoft Corporation Windows MIDI Services core application SDK. Minimum package necessary to use Windows MIDI Services from an app. MIT @@ -31,8 +31,8 @@ - - + + diff --git a/src/app-dev-sdk/sdk-core-projection-cs/nuget/Microsoft.Devices.Midi2.Core.props b/src/app-dev-sdk/sdk-core-projection-cs/nuget/Microsoft.Devices.Midi2.Core.props index f7177cc11..14c7c6b97 100644 --- a/src/app-dev-sdk/sdk-core-projection-cs/nuget/Microsoft.Devices.Midi2.Core.props +++ b/src/app-dev-sdk/sdk-core-projection-cs/nuget/Microsoft.Devices.Midi2.Core.props @@ -1,13 +1,26 @@  - + + + + + + ---> \ No newline at end of file diff --git a/src/app-dev-sdk/sdk-core-projection-cs/nuget/Microsoft.Devices.Midi2.Core.targets b/src/app-dev-sdk/sdk-core-projection-cs/nuget/Microsoft.Devices.Midi2.Core.targets index 138935aff..072757950 100644 --- a/src/app-dev-sdk/sdk-core-projection-cs/nuget/Microsoft.Devices.Midi2.Core.targets +++ b/src/app-dev-sdk/sdk-core-projection-cs/nuget/Microsoft.Devices.Midi2.Core.targets @@ -1,29 +1,55 @@  - - - x86 - $(Platform) - - - - - - + + + + + - - - - - Always - %(Filename)%(Extension) - + + + + + + + + + Microsoft.Devices.Midi2.dll + + + + + + PreserveNewest + %(Filename)%(Extension) + + + + + + - + + +