diff --git a/build/staging/version/BundleInfo.wxi b/build/staging/version/BundleInfo.wxi
index 9f419730..ee1c9ca4 100644
--- a/build/staging/version/BundleInfo.wxi
+++ b/build/staging/version/BundleInfo.wxi
@@ -1,4 +1,4 @@
-
+
diff --git a/diagnostics/trace-logging/MidiServices.wprp b/diagnostics/trace-logging/MidiServices.wprp
index 1246cd8b..132724c0 100644
--- a/diagnostics/trace-logging/MidiServices.wprp
+++ b/diagnostics/trace-logging/MidiServices.wprp
@@ -1,8 +1,4 @@
-
diff --git a/docs/endpoints/virtual-loopback.md b/docs/endpoints/virtual-loopback.md
index 6ebf1303..6390f9b3 100644
--- a/docs/endpoints/virtual-loopback.md
+++ b/docs/endpoints/virtual-loopback.md
@@ -44,13 +44,13 @@ That out of the way, here's an example configuration section for the Virtual Loo
{
"name": "Perm Loopback 1A",
"description": "This is a loopback I created in the configuration file",
- "uniqueId": "3263827"
+ "uniqueIdentifier": "3263827"
},
"endpointB":
{
"name": "Perm Loopback 1B",
"description": "This is the b-side of the loopback I created in the configuration file",
- "uniqueId": "3263827"
+ "uniqueIdentifier": "3263827"
}
},
"{B21B4973-3F85-48A0-8BA3-B35F44683D36}":
@@ -60,13 +60,13 @@ That out of the way, here's an example configuration section for the Virtual Loo
{
"name": "Perm Loopback 2A",
"description": "This is a loopback I created in the configuration file",
- "uniqueId": "5150-1984"
+ "uniqueIdentifier": "5150-1984"
},
"endpointB":
{
"name": "Perm Loopback 2B",
"description": "This is the b-side of the loopback I created in the configuration file",
- "uniqueId": "OU812"
+ "uniqueIdentifier": "OU812"
}
}
}
diff --git a/samples/csharp-net/app-to-app-midi-cs/MidiSample.AppToAppMidi.csproj b/samples/csharp-net/app-to-app-midi-cs/MidiSample.AppToAppMidi.csproj
index e980fe6e..9438a45d 100644
--- a/samples/csharp-net/app-to-app-midi-cs/MidiSample.AppToAppMidi.csproj
+++ b/samples/csharp-net/app-to-app-midi-cs/MidiSample.AppToAppMidi.csproj
@@ -29,7 +29,7 @@
-
+
diff --git a/src/api/Abstraction/BleMidiAbstraction/Midi2.BluetoothMidiEndpointManager.cpp b/src/api/Abstraction/BleMidiAbstraction/Midi2.BluetoothMidiEndpointManager.cpp
index e7e5381c..7ecd3ea4 100644
--- a/src/api/Abstraction/BleMidiAbstraction/Midi2.BluetoothMidiEndpointManager.cpp
+++ b/src/api/Abstraction/BleMidiAbstraction/Midi2.BluetoothMidiEndpointManager.cpp
@@ -25,8 +25,6 @@ CMidi2BluetoothMidiEndpointManager::Initialize(
IUnknown* /*midiEndpointProtocolManager*/
)
{
- //OutputDebugString(L"" __FUNCTION__ " Enter");
-
TraceLoggingWrite(
MidiBluetoothMidiAbstractionTelemetryProvider::Provider(),
__FUNCTION__,
@@ -41,442 +39,24 @@ CMidi2BluetoothMidiEndpointManager::Initialize(
m_TransportAbstractionId = AbstractionLayerGUID; // this is needed so MidiSrv can instantiate the correct transport
m_ContainerId = m_TransportAbstractionId; // we use the transport ID as the container ID for convenience
- RETURN_IF_FAILED(CreateParentDevice());
-
- //if (ConfigurationJson != nullptr)
- //{
- // try
- // {
- // std::wstring json{ ConfigurationJson };
-
- // if (!json.empty())
- // {
- // m_jsonObject = json::JsonObject::Parse(json);
-
- // LOG_IF_FAILED(CreateConfiguredEndpoints(json));
- // }
- // }
- // catch (...)
- // {
- // OutputDebugString(L"Exception processing json for virtual MIDI abstraction");
-
- // // we return S_OK here because otherwise this prevents the service from starting up.
- // return S_OK;
- // }
-
- //}
- //else
- //{
- // // empty / null is fine. We just continue on.
-
- // OutputDebugString(L"Configuration json is null for virtual MIDI abstraction");
-
- // return S_OK;
- //}
+ //RETURN_IF_FAILED(CreateParentDevice());
return S_OK;
}
-void
-SwMidiParentDeviceCreateCallback(
- __in HSWDEVICE /*hSwDevice*/,
- __in HRESULT CreationResult,
- __in_opt PVOID pContext,
- __in_opt PCWSTR pszDeviceInstanceId
-)
-{
- if (pContext == nullptr)
- {
- // TODO: Should log this.
-
- return;
- }
-
- PPARENTDEVICECREATECONTEXT creationContext = (PPARENTDEVICECREATECONTEXT)pContext;
-
-
- // interface registration has started, assume failure
- creationContext->MidiParentDevice->SwDeviceState = SWDEVICESTATE::Failed;
-
- LOG_IF_FAILED(CreationResult);
-
- if (SUCCEEDED(CreationResult))
- {
- // success, mark the port as created
- creationContext->MidiParentDevice->SwDeviceState = SWDEVICESTATE::Created;
-
- // get the new device instance ID. This is usually modified from what we started with
- creationContext->MidiParentDevice->InstanceId = std::wstring(pszDeviceInstanceId);
- }
- else
- {
- OutputDebugString(L"" __FUNCTION__ " - CreationResult FAILURE");
- }
-
- // success or failure, signal we have completed.
- creationContext->CreationCompleted.SetEvent();
-}
-
HRESULT
CMidi2BluetoothMidiEndpointManager::CreateParentDevice()
{
- // the parent device parameters are set by the transport (this)
-
- std::wstring parentDeviceName{ TRANSPORT_PARENT_DEVICE_NAME };
- std::wstring parentDeviceId{ TRANSPORT_PARENT_ID };
-
- SW_DEVICE_CREATE_INFO CreateInfo = {};
- CreateInfo.cbSize = sizeof(CreateInfo);
- CreateInfo.pszInstanceId = parentDeviceId.c_str();
- CreateInfo.CapabilityFlags = SWDeviceCapabilitiesNone;
- CreateInfo.pszDeviceDescription = parentDeviceName.c_str();
-
- SW_DEVICE_CREATE_INFO* createInfo = (SW_DEVICE_CREATE_INFO*)&CreateInfo;
-
- if (m_ParentDevice != nullptr)
- {
- return S_OK;
- }
-
- m_ParentDevice = std::make_unique();
-
- RETURN_IF_NULL_ALLOC(m_ParentDevice);
-
- PARENTDEVICECREATECONTEXT creationContext;
-
- // lambdas can only be converted to a function pointer if they
- // don't do capture, so copy everything into the CREATECONTEXT
- // to share with the SwDeviceCreate callback.
- creationContext.MidiParentDevice = m_ParentDevice.get();
-
- //creationContext.InterfaceDevProperties = (DEVPROPERTY*)InterfaceDevProperties;
- //creationContext.IntPropertyCount = IntPropertyCount;
-
- m_ParentDevice->SwDeviceState = SWDEVICESTATE::CreatePending;
-
- //m_ParentDevice->InstanceId = createInfo->pszInstanceId;
-
- DEVPROP_BOOLEAN devPropTrue = DEVPROP_TRUE;
-
- DEVPROPERTY deviceDevProperties[] = {
- {{DEVPKEY_Device_PresenceNotForDevice, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropTrue)), &devPropTrue},
- {{DEVPKEY_Device_NoConnectSound, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropTrue)),&devPropTrue}
- };
-
-
- std::wstring rootDeviceId = LOOPBACK_PARENT_ROOT;
- std::wstring enumeratorName = TRANSPORT_ENUMERATOR;
-
- createInfo->pContainerId = &m_ContainerId;
-
- RETURN_IF_FAILED(SwDeviceCreate(
- enumeratorName.c_str(), // this really should come from the service
- rootDeviceId.c_str(), // root device
- createInfo,
- ARRAYSIZE(deviceDevProperties), // count of properties
- (DEVPROPERTY*)deviceDevProperties, // pointer to properties
- SwMidiParentDeviceCreateCallback, // callback
- &creationContext,
- wil::out_param(m_ParentDevice->SwDevice)));
-
- // wait for creation to complete
- creationContext.CreationCompleted.wait();
-
- // confirm we were able to register the interface
- RETURN_HR_IF(E_FAIL, m_ParentDevice->SwDeviceState != SWDEVICESTATE::Created);
return S_OK;
}
-#define MIDI_VIRTUAL_ENDPOINTS_ARRAY_KEY L"endpoints"
-
-#define MIDI_VIRTUAL_ENDPOINT_PROPERTY_NAME L"name"
-#define MIDI_VIRTUAL_ENDPOINT_PROPERTY_DESCRIPTION L"description"
-#define MIDI_VIRTUAL_ENDPOINT_PROPERTY_SMALLIMAGE L"smallImagePath"
-#define MIDI_VIRTUAL_ENDPOINT_PROPERTY_LARGEIMAGE L"largeImagePath"
-
-#define MIDI_JSON_UPDATE_NODE L"update"
-
-
-//json::JsonObject GetAddNode(json::JsonObject parent)
-//{
-// if (parent.HasKey(MIDI_JSON_ADD_NODE))
-// {
-// return parent.GetNamedObject(MIDI_JSON_ADD_NODE);
-// }
-// else
-// {
-// return nullptr;
-// }
-//}
-//
-//winrt::hstring GetStringValue(json::JsonObject parent, winrt::hstring key, winrt::hstring default)
-//{
-// if (parent.HasKey(key))
-// {
-// return parent.GetNamedString(key);
-// }
-// else
-// {
-// return default;
-// }
-//}
-
-_Use_decl_annotations_
-HRESULT
-CMidi2BluetoothMidiEndpointManager::CreateConfiguredEndpoints(
- std::wstring ConfigurationJson
-)
-{
- //// if nothing to configure, that's ok
- //if (ConfigurationJson.empty()) return S_OK;
-
- //try
- //{
- // auto jsonObject = json::JsonObject::Parse(ConfigurationJson);
-
-
- // // check to see if we have an "add" node. No point in checking for "update" or "remove" for initial configuration
- // auto addNode = GetAddNode(jsonObject);
-
- // if (addNode != nullptr && addNode.HasKey(MIDI_VIRTUAL_ENDPOINTS_ARRAY_KEY))
- // {
- // auto endpoints = addNode.GetNamedArray(MIDI_VIRTUAL_ENDPOINTS_ARRAY_KEY);
-
- // for (auto endpointElement : endpoints)
- // {
- // // GetObjectW here is because wingdi redefines it to GetObject. It's a stupid preprocessor conflict
- // try
- // {
- // auto endpoint = endpointElement.GetObjectW();
-
- // // auto key = endpoint.GetNamedString(MIDI_VIRTUAL_ENDPOINT_PROPERTY_KEY, L"");
- // auto name = endpoint.GetNamedString(MIDI_VIRTUAL_ENDPOINT_PROPERTY_NAME, L"");
- // auto uniqueIdentifier = endpoint.GetNamedString(MIDI_VIRTUAL_ENDPOINT_PROPERTY_UNIQUEID, L"");
- // // auto supportsMultiClient = endpoint.GetNamedBoolean(MIDI_VIRTUAL_ENDPOINT_PROPERTY_MULTICLIENT, true);
-
- // auto instanceId = TRANSPORT_MNEMONIC L"_" + uniqueIdentifier;
-
- // auto description = GetStringValue(endpoint, MIDI_VIRTUAL_ENDPOINT_PROPERTY_DESCRIPTION, L"");
- // auto smallImage = GetStringValue(endpoint, MIDI_VIRTUAL_ENDPOINT_PROPERTY_SMALLIMAGE, L"");
- // auto largeImage = GetStringValue(endpoint, MIDI_VIRTUAL_ENDPOINT_PROPERTY_LARGEIMAGE, L"");
-
- // bool multiclient = true; // TODO
- // bool virtualResponder = false; // TODO
-
-
- // // TODO: Need to add this to the table for routing, and also add the other properties to the function
- // CreateEndpoint(
- // (std::wstring)instanceId,
- // (std::wstring)uniqueIdentifier,
- // multiclient,
- // virtualResponder,
- // (std::wstring)name,
- // (std::wstring)largeImage,
- // (std::wstring)smallImage,
- // (std::wstring)description
- // );
- // }
- // catch (...)
- // {
- // // couldn't get an object. Garbage data
- // OutputDebugString(L"" __FUNCTION__ " Exception getting endpoint properties from json");
-
- // return E_FAIL;
- // }
- // }
- // }
- // else
- // {
- // // nothing to add
- // }
-
-
- //}
- //catch (...)
- //{
- // // exception parsing the json. It's likely empty or malformed
-
- // OutputDebugString(L"" __FUNCTION__ " Exception parsing JSON. Json string follows.");
- // OutputDebugString(ConfigurationJson.c_str());
-
- // TraceLoggingWrite(
- // MidiBluetoothMidiAbstractionTelemetryProvider::Provider(),
- // __FUNCTION__,
- // TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
- // TraceLoggingPointer(this, "this")
- // );
-
- // return E_FAIL;
- //}
-
- return S_OK;
-}
-
-// this will be called from the runtime endpoint creation interface
-
_Use_decl_annotations_
HRESULT
CMidi2BluetoothMidiEndpointManager::CreateEndpoint(
- std::wstring const InstanceId,
- std::wstring const UniqueId,
- bool const Multiclient,
- bool const /*IsVirtualEndpointResponder*/,
- std::wstring const Name,
- std::wstring const LargeImagePath,
- std::wstring const SmallImagePath,
- std::wstring const Description
)
{
- //put all of the devproperties we want into arrays and pass into ActivateEndpoint:
-
- std::wstring mnemonic(TRANSPORT_MNEMONIC);
- MidiFlow const flow = MidiFlow::MidiFlowBidirectional;
-
- DEVPROP_BOOLEAN devPropTrue = DEVPROP_TRUE;
- //DEVPROP_BOOLEAN devPropFalse = DEVPROP_FALSE;
-
- DEVPROP_BOOLEAN devPropMulticlient = Multiclient ? DEVPROP_TRUE : DEVPROP_FALSE;
- //DEVPROP_BOOLEAN devPropVirtualResponder = IsVirtualEndpointResponder ? DEVPROP_TRUE : DEVPROP_FALSE;
-
- BYTE nativeDataFormat = MIDI_PROP_NATIVEDATAFORMAT_BYTESTREAM;
-
- uint32_t endpointPurpose{};
-
- endpointPurpose = (uint32_t)MidiEndpointDevicePurposePropertyValue::NormalMessageEndpoint;
-
- DEVPROPERTY interfaceDevProperties[] = {
- {{DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((Name.length() + 1) * sizeof(WCHAR)), (PVOID)Name.c_str()},
-
- // essential to instantiate the right endpoint types
- {{PKEY_MIDI_AbstractionLayer, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_GUID, static_cast(sizeof(GUID)), (PVOID)&AbstractionLayerGUID },
-
- {{PKEY_MIDI_TransportMnemonic, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((mnemonic.length() + 1) * sizeof(WCHAR)), (PVOID)mnemonic.c_str()},
-
- {{PKEY_MIDI_NativeDataFormat, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BYTE, static_cast(sizeof(BYTE)), (PVOID)&nativeDataFormat},
-
- //{{PKEY_MIDI_UniqueIdentifier, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_STRING, static_cast((UniqueId.length() + 1) * sizeof(WCHAR)), (PVOID)UniqueId.c_str()},
-
- {{PKEY_MIDI_SupportsMulticlient, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropMulticlient)), (PVOID)&devPropMulticlient},
-
- {{PKEY_MIDI_TransportSuppliedEndpointName, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((Name.length() + 1) * sizeof(WCHAR)), (PVOID)Name.c_str()},
-
- {{PKEY_MIDI_EndpointDevicePurpose, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_UINT32, static_cast(sizeof(endpointPurpose)),(PVOID)&endpointPurpose},
-
-
- {{PKEY_MIDI_UserSuppliedLargeImagePath, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((LargeImagePath.length() + 1) * sizeof(WCHAR)), (PVOID)LargeImagePath.c_str() },
-
- {{PKEY_MIDI_UserSuppliedSmallImagePath, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((SmallImagePath.length() + 1) * sizeof(WCHAR)), (PVOID)SmallImagePath.c_str() },
-
- {{PKEY_MIDI_UserSuppliedDescription, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((Description.length() + 1) * sizeof(WCHAR)), (PVOID)Description.c_str() },
-
- {{PKEY_MIDI_UserSuppliedEndpointName, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((Name.length() + 1) * sizeof(WCHAR)), (PVOID)Name.c_str() }
- };
-
-
-
- // Additional metadata properties added here to avoid having to add them in every transport
-// and to ensure they are registered under the same identity that is creating the device
-// Several of these are later updated through discovery, user-supplied json metadata, etc.
- //DEVPROP_BOOLEAN devPropFalse = DEVPROP_FALSE;
- //uint8_t zeroByte = 0;
-
- //std::wstring emptyString = L"";
-
- //interfaceProperties.push_back({ {PKEY_MIDI_SupportsMultiClient, DEVPROP_STORE_SYSTEM, nullptr },
- // DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropTrue)), &devPropTrue });
-
- //// from endpoint discovery ============
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointSupportsMidi2Protocol, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropFalse)), &devPropFalse });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointSupportsMidi1Protocol, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropFalse)), &devPropFalse });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointSupportsReceivingJRTimestamps, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropFalse)), &devPropFalse });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointSupportsSendingJRTimestamps, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropFalse)), &devPropFalse });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointUmpVersionMajor, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BYTE, static_cast(sizeof(zeroByte)), &zeroByte });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointUmpVersionMinor, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BYTE, static_cast(sizeof(zeroByte)), &zeroByte });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointProvidedName, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_STRING, static_cast((emptyString.length() + 1) * sizeof(WCHAR)), (PVOID)emptyString.c_str() });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointProvidedProductInstanceId, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_STRING, static_cast((emptyString.length() + 1) * sizeof(WCHAR)), (PVOID)emptyString.c_str() });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_FunctionBlocksAreStatic, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropFalse)),&devPropFalse });
-
- ////interfaceProperties.push_back({ {PKEY_MIDI_DeviceIdentification, DEVPROP_STORE_SYSTEM, nullptr},
- //// DEVPROP_TYPE_BINARY, static_cast(0), });
-
-
- //// from function block discovery =============================
-
- ////interfaceProperties.push_back({ {PKEY_MIDI_FunctionBlocks, DEVPROP_STORE_SYSTEM, nullptr},
- //// DEVPROP_TYPE_BINARY, static_cast(0), &functionBlockCount });
-
-
-
-
- DEVPROPERTY deviceDevProperties[] = {
- {{DEVPKEY_Device_PresenceNotForDevice, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropTrue)), &devPropTrue},
- {{DEVPKEY_Device_NoConnectSound, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropTrue)),&devPropTrue}
- };
-
- SW_DEVICE_CREATE_INFO createInfo = {};
- createInfo.cbSize = sizeof(createInfo);
-
- createInfo.pszInstanceId = InstanceId.c_str();
- createInfo.CapabilityFlags = SWDeviceCapabilitiesNone;
- createInfo.pszDeviceDescription = Name.c_str();
-
-
- const ULONG deviceInterfaceIdMaxSize = 255;
- wchar_t newDeviceInterfaceId[deviceInterfaceIdMaxSize]{ 0 };
-
- RETURN_IF_FAILED(m_MidiDeviceManager->ActivateEndpoint(
- std::wstring(m_ParentDevice->InstanceId).c_str(), // parent instance Id
- true, // UMP-only
- flow, // MIDI Flow
- ARRAYSIZE(interfaceDevProperties),
- ARRAYSIZE(deviceDevProperties),
- (PVOID)interfaceDevProperties,
- (PVOID)deviceDevProperties,
- (PVOID)&createInfo,
- (LPWSTR)&newDeviceInterfaceId,
- deviceInterfaceIdMaxSize));
-
- OutputDebugString(__FUNCTION__ L": Created device interface id:");
- OutputDebugString(newDeviceInterfaceId);
-
- // store the created device in the device table, along with the interface id
-
-
return S_OK;
}
@@ -509,8 +89,6 @@ CMidi2BluetoothMidiEndpointManager::EnumCompatibleBluetoothDevices()
HRESULT
CMidi2BluetoothMidiEndpointManager::Cleanup()
{
- OutputDebugString(L"" __FUNCTION__ " Enter");
-
TraceLoggingWrite(
MidiBluetoothMidiAbstractionTelemetryProvider::Provider(),
__FUNCTION__,
diff --git a/src/api/Abstraction/BleMidiAbstraction/Midi2.BluetoothMidiEndpointManager.h b/src/api/Abstraction/BleMidiAbstraction/Midi2.BluetoothMidiEndpointManager.h
index 3207d2e8..8ee84ba3 100644
--- a/src/api/Abstraction/BleMidiAbstraction/Midi2.BluetoothMidiEndpointManager.h
+++ b/src/api/Abstraction/BleMidiAbstraction/Midi2.BluetoothMidiEndpointManager.h
@@ -8,58 +8,6 @@
#pragma once
-typedef enum _SWDEVICESTATE
-{
- NotCreated = 0, // SwDeviceCreate not yet called
- CreatePending, // SwDeviceCreate called successfully, but creation callback not yet invoked
- Created, // SwDeviceCreate creation callback has been invoked and device interface has been created
- Failed
-} SWDEVICESTATE;
-
-
-using unique_hswdevice = wil::unique_any;
-using unique_swd_string = wil::unique_any;
-
-
-class MidiUmpEndpointInfo
-{
-public:
- std::wstring Id{}; // the filter InterfaceId
- std::wstring InstanceId{}; // the MIDI instance id
- std::wstring ParentInstanceId{}; // The instance id of the parent device
- std::wstring Name{}; // friendly name for this device
- MidiFlow Flow{ MidiFlowBidirectional };
-
- // TODO: Pointer to the interface?
-
-};
-
-class MidiEndpointParentDeviceInfo
-{
-public:
- GUID InterfaceCategory{};
- SWDEVICESTATE SwDeviceState{ SWDEVICESTATE::NotCreated }; // SWD creation state
- unique_hswdevice SwDevice{}; // Handle to the SWD created for the MIDI port
- unique_swd_string DeviceInterfaceId{}; // SWD interface ID for the MIDI port
- std::wstring InstanceId{};
- std::wstring Name{}; // friendly name for this device
-
-};
-
-typedef struct _PARENTDEVICECREATECONTEXT
-{
- MidiEndpointParentDeviceInfo* MidiParentDevice{ nullptr };
- wil::unique_event CreationCompleted{ wil::EventOptions::None };
- DEVPROPERTY* InterfaceDevProperties{ nullptr };
- ULONG IntPropertyCount{};
-} PARENTDEVICECREATECONTEXT, * PPARENTDEVICECREATECONTEXT;
-
-
-// TODO: This class can implement another interface which takes in the json parameters
-// (or whatever we want) for naming the new endpoints. Then, the SDK can call that
-// interface to do the setup of the device. Or, there can be a common "runtime creatable transport"
-// interface that is called from the API. TBD. But can't break that interface with
-// the SDK, since the SDK ships with apps and could be older.
class CMidi2BluetoothMidiEndpointManager :
@@ -78,14 +26,7 @@ class CMidi2BluetoothMidiEndpointManager :
GUID m_TransportAbstractionId{};
HRESULT CreateEndpoint(
- _In_ std::wstring const InstanceId,
- _In_ std::wstring const UniqueId,
- _In_ bool const Multiclient,
- _In_ bool const IsVirtualEndpointResponder,
- _In_ std::wstring const Name,
- _In_ std::wstring const LargeImagePath,
- _In_ std::wstring const SmallImagePath,
- _In_ std::wstring const Description);
+);
HRESULT EnumCompatibleBluetoothDevices();
@@ -95,11 +36,4 @@ class CMidi2BluetoothMidiEndpointManager :
HRESULT CreateParentDevice();
wil::com_ptr_nothrow m_MidiDeviceManager;
-
- // TBD if we need to keep this here as well. The MidiDeviceManager has its own vector of endpoints
- std::vector> m_AvailableMidiUmpEndpoints;
-
- std::unique_ptr m_ParentDevice{ nullptr };
-
- json::JsonObject m_JsonObject{ nullptr };
};
diff --git a/src/api/Abstraction/BleMidiAbstraction/pch.h b/src/api/Abstraction/BleMidiAbstraction/pch.h
index ba8f194c..92fc32a4 100644
--- a/src/api/Abstraction/BleMidiAbstraction/pch.h
+++ b/src/api/Abstraction/BleMidiAbstraction/pch.h
@@ -69,7 +69,6 @@ namespace json = ::winrt::Windows::Data::Json;
// AbstractionUtilities
#include "endpoint_data_helpers.h"
#include "swd_property_builders.h"
-#include "swd_property_helpers.h"
#include "json_helpers.h"
#include "MidiDefs.h"
diff --git a/src/api/Abstraction/DiagnosticsAbstraction/Midi2.DiagnosticsEndpointManager.cpp b/src/api/Abstraction/DiagnosticsAbstraction/Midi2.DiagnosticsEndpointManager.cpp
index 2b453225..deaeaede 100644
--- a/src/api/Abstraction/DiagnosticsAbstraction/Midi2.DiagnosticsEndpointManager.cpp
+++ b/src/api/Abstraction/DiagnosticsAbstraction/Midi2.DiagnosticsEndpointManager.cpp
@@ -135,44 +135,6 @@ CMidi2DiagnosticsEndpointManager::CreateLoopbackEndpoint(
std::wstring friendlyName = internal::CalculateEndpointDevicePrimaryName(endpointName, L"", L"");
// all the standard properties we define for endpoints
- if (internal::AddStandardEndpointProperties(
- interfaceDeviceProperties,
- m_TransportAbstractionId,
- MidiEndpointDevicePurposePropertyValue::DiagnosticLoopback,
- friendlyName,
- mnemonic,
- endpointName,
- endpointDescription,
- L"",
- L"",
- UniqueId,
- MidiDataFormat::MidiDataFormat_UMP,
- MIDI_PROP_NATIVEDATAFORMAT_UMP,
- multiClient,
- requiresMetadataHandler,
- generateIncomingTimestamps
- ))
- {
- // all good. Add additional properties
- // additional properties for this abstraction
-
- // we clear this because it's not used for this abstraction.
- interfaceDeviceProperties.push_back(internal::BuildEmptyDevProperty(PKEY_MIDI_AssociatedUMP));
- }
- else
- {
- // unable to build properties
-
- TraceLoggingWrite(
- MidiDiagnosticsAbstractionTelemetryProvider::Provider(),
- __FUNCTION__,
- TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
- TraceLoggingPointer(this, "this"),
- TraceLoggingWideString(L"Unable to build standard endpoint properties list", "message")
- );
-
- return E_FAIL;
- }
DEVPROPERTY deviceDevProperties[] = {
{{DEVPKEY_Device_PresenceNotForDevice, DEVPROP_STORE_SYSTEM, nullptr},
@@ -193,10 +155,28 @@ CMidi2DiagnosticsEndpointManager::CreateLoopbackEndpoint(
wchar_t newDeviceInterfaceId[deviceInterfaceIdMaxSize]{ 0 };
+ MIDIENDPOINTCOMMONPROPERTIES commonProperties;
+ commonProperties.AbstractionLayerGuid = m_TransportAbstractionId;
+ commonProperties.EndpointPurpose = MidiEndpointDevicePurposePropertyValue::DiagnosticLoopback;
+ commonProperties.FriendlyName = friendlyName.c_str();
+ commonProperties.TransportMnemonic = mnemonic.c_str();
+ commonProperties.TransportSuppliedEndpointName = endpointName.c_str();
+ commonProperties.TransportSuppliedEndpointDescription = endpointDescription.c_str();
+ commonProperties.UserSuppliedEndpointName = L"";
+ commonProperties.UserSuppliedEndpointDescription = L"";
+ commonProperties.UniqueIdentifier = UniqueId.c_str();
+ commonProperties.SupportedDataFormats = MidiDataFormat::MidiDataFormat_UMP;
+ commonProperties.NativeDataFormat = MIDI_PROP_NATIVEDATAFORMAT_UMP;
+ commonProperties.SupportsMultiClient = multiClient;
+ commonProperties.RequiresMetadataHandler = requiresMetadataHandler;
+ commonProperties.GenerateIncomingTimestamps = generateIncomingTimestamps;
+
+
RETURN_IF_FAILED(m_MidiDeviceManager->ActivateEndpoint(
(PCWSTR)m_parentDeviceId.c_str(), // parent instance Id
true, // UMP-only
Flow, // MIDI Flow
+ &commonProperties,
(ULONG)interfaceDeviceProperties.size(),
ARRAYSIZE(deviceDevProperties),
(PVOID)interfaceDeviceProperties.data(),
@@ -205,7 +185,6 @@ CMidi2DiagnosticsEndpointManager::CreateLoopbackEndpoint(
(LPWSTR)&newDeviceInterfaceId,
deviceInterfaceIdMaxSize));
-
// now delete all the properties that have been discovered in-protocol
// we have to do this because they end up cached by PNP and come back
// when you recreate a device with the same Id. This is a real problem
@@ -256,47 +235,6 @@ CMidi2DiagnosticsEndpointManager::CreatePingEndpoint(
// no user or in-protocol data in this case
std::wstring friendlyName = internal::CalculateEndpointDevicePrimaryName(endpointName, L"", L"");
- // all the standard properties we define for endpoints
- if (internal::AddStandardEndpointProperties(
- interfaceDeviceProperties,
- m_TransportAbstractionId,
- MidiEndpointDevicePurposePropertyValue::DiagnosticPing,
- friendlyName,
- mnemonic,
- endpointName,
- endpointDescription,
- L"",
- L"",
- UniqueId,
- MidiDataFormat::MidiDataFormat_UMP,
- MIDI_PROP_NATIVEDATAFORMAT_UMP,
- multiClient,
- requiresMetadataHandler,
- generateIncomingTimestamps
- ))
- {
- // all good. Add additional properties
- // additional properties for this abstraction
-
- // we clear this because it's not used for this abstraction.
- interfaceDeviceProperties.push_back(internal::BuildEmptyDevProperty(PKEY_MIDI_AssociatedUMP));
-
- }
- else
- {
- // unable to build properties
-
- TraceLoggingWrite(
- MidiDiagnosticsAbstractionTelemetryProvider::Provider(),
- __FUNCTION__,
- TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
- TraceLoggingPointer(this, "this"),
- TraceLoggingWideString(L"Unable to build standard endpoint properties list", "message")
- );
-
- return E_FAIL;
- }
-
DEVPROPERTY deviceDevProperties[] = {
{{DEVPKEY_Device_PresenceNotForDevice, DEVPROP_STORE_SYSTEM, nullptr},
DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropTrue)), &devPropTrue},
@@ -315,10 +253,27 @@ CMidi2DiagnosticsEndpointManager::CreatePingEndpoint(
const ULONG deviceInterfaceIdMaxSize = 255;
wchar_t newDeviceInterfaceId[deviceInterfaceIdMaxSize]{ 0 };
+ MIDIENDPOINTCOMMONPROPERTIES commonProperties;
+ commonProperties.AbstractionLayerGuid = m_TransportAbstractionId;
+ commonProperties.EndpointPurpose = MidiEndpointDevicePurposePropertyValue::DiagnosticPing;
+ commonProperties.FriendlyName = friendlyName.c_str();
+ commonProperties.TransportMnemonic = mnemonic.c_str();
+ commonProperties.TransportSuppliedEndpointName = endpointName.c_str();
+ commonProperties.TransportSuppliedEndpointDescription = endpointDescription.c_str();
+ commonProperties.UserSuppliedEndpointName = L"";
+ commonProperties.UserSuppliedEndpointDescription = L"";
+ commonProperties.UniqueIdentifier = UniqueId.c_str();
+ commonProperties.SupportedDataFormats = MidiDataFormat::MidiDataFormat_UMP;
+ commonProperties.NativeDataFormat = MIDI_PROP_NATIVEDATAFORMAT_UMP;
+ commonProperties.SupportsMultiClient = multiClient;
+ commonProperties.RequiresMetadataHandler = requiresMetadataHandler;
+ commonProperties.GenerateIncomingTimestamps = generateIncomingTimestamps;
+
RETURN_IF_FAILED(m_MidiDeviceManager->ActivateEndpoint(
m_parentDeviceId.c_str(), // parent instance Id
true, // UMP-only
Flow, // MIDI Flow
+ &commonProperties,
(ULONG)interfaceDeviceProperties.size(),
ARRAYSIZE(deviceDevProperties),
(PVOID)interfaceDeviceProperties.data(),
diff --git a/src/api/Abstraction/DiagnosticsAbstraction/pch.h b/src/api/Abstraction/DiagnosticsAbstraction/pch.h
index 78cf4beb..b717611c 100644
--- a/src/api/Abstraction/DiagnosticsAbstraction/pch.h
+++ b/src/api/Abstraction/DiagnosticsAbstraction/pch.h
@@ -56,7 +56,6 @@
// AbstractionUtilities
#include "endpoint_data_helpers.h"
#include "swd_property_builders.h"
-#include "swd_property_helpers.h"
#include "json_helpers.h"
#include "MidiDefs.h"
diff --git a/src/api/Abstraction/KSAbstraction/Midi2.KSMidiEndpointManager.cpp b/src/api/Abstraction/KSAbstraction/Midi2.KSMidiEndpointManager.cpp
index 82add44a..34a9bf3e 100644
--- a/src/api/Abstraction/KSAbstraction/Midi2.KSMidiEndpointManager.cpp
+++ b/src/api/Abstraction/KSAbstraction/Midi2.KSMidiEndpointManager.cpp
@@ -398,12 +398,32 @@ HRESULT CMidi2KSMidiEndpointManager::OnDeviceAdded(DeviceWatcher watcher, Device
const ULONG deviceInterfaceIdMaxSize = 255;
wchar_t newDeviceInterfaceId[deviceInterfaceIdMaxSize]{ 0 };
+ // TODO: Move to this structure
+ //
+ PMIDIENDPOINTCOMMONPROPERTIES pCommonProperties = nullptr;
+ //MIDIENDPOINTCOMMONPROPERTIES commonProperties;
+ //commonProperties.AbstractionLayerGuid = m_TransportAbstractionId;
+ //commonProperties.EndpointPurpose = MidiEndpointDevicePurposePropertyValue::DiagnosticPing;
+ //commonProperties.FriendlyName = friendlyName.c_str();
+ //commonProperties.TransportMnemonic = mnemonic.c_str();
+ //commonProperties.TransportSuppliedEndpointName = endpointName.c_str();
+ //commonProperties.TransportSuppliedEndpointDescription = endpointDescription.c_str();
+ //commonProperties.UserSuppliedEndpointName = L"";
+ //commonProperties.UserSuppliedEndpointDescription = L"";
+ //commonProperties.UniqueIdentifier = UniqueId.c_str();
+ //commonProperties.SupportedDataFormats = MidiDataFormat::MidiDataFormat_UMP;
+ //commonProperties.NativeDataFormat = MIDI_PROP_NATIVEDATAFORMAT_UMP;
+ //commonProperties.SupportsMultiClient = multiClient;
+ //commonProperties.RequiresMetadataHandler = requiresMetadataHandler;
+ //commonProperties.GenerateIncomingTimestamps = generateIncomingTimestamps;
+
// log telemetry in the event activating the SWD for this pin has failed,
// but push forward with creation for other pins.
LOG_IF_FAILED(MidiPin->SwdCreation = m_MidiDeviceManager->ActivateEndpoint(
MidiPin->ParentInstanceId.c_str(),
MidiPin->CreateUMPOnly,
MidiPin->Flow,
+ pCommonProperties,
(ULONG) interfaceDevProperties.size(),
(ULONG) deviceDevProperties.size(),
(PVOID)interfaceDevProperties.data(),
diff --git a/src/api/Abstraction/LoopbackMidiAbstraction/AbstractionState.h b/src/api/Abstraction/LoopbackMidiAbstraction/AbstractionState.h
index 78d89dd2..abc57902 100644
--- a/src/api/Abstraction/LoopbackMidiAbstraction/AbstractionState.h
+++ b/src/api/Abstraction/LoopbackMidiAbstraction/AbstractionState.h
@@ -31,7 +31,7 @@ class AbstractionState
return m_configurationManager;
}
- std::shared_ptr GetEndpointTable()
+ std::shared_ptr GetEndpointTable()
{
return m_endpointTable;
}
@@ -58,5 +58,5 @@ class AbstractionState
wil::com_ptr m_endpointManager;
wil::com_ptr m_configurationManager;
- std::shared_ptr m_endpointTable = std::make_shared();
+ std::shared_ptr m_endpointTable = std::make_shared();
};
\ No newline at end of file
diff --git a/src/api/Abstraction/LoopbackMidiAbstraction/Midi2.LoopbackMidiBidi.cpp b/src/api/Abstraction/LoopbackMidiAbstraction/Midi2.LoopbackMidiBidi.cpp
index 1e46e486..e587f6b2 100644
--- a/src/api/Abstraction/LoopbackMidiAbstraction/Midi2.LoopbackMidiBidi.cpp
+++ b/src/api/Abstraction/LoopbackMidiAbstraction/Midi2.LoopbackMidiBidi.cpp
@@ -31,6 +31,9 @@ CMidi2LoopbackMidiBiDi::Initialize(
m_callbackContext = Context;
m_endpointId = internal::NormalizeEndpointInterfaceIdWStringCopy(endpointId);
+ m_associationId = internal::GetSwdPropertyVirtualEndpointAssociationId(m_endpointId);
+
+
HRESULT hr = S_OK;
// TODO: This should use SWD properties and not a string search
@@ -44,12 +47,14 @@ CMidi2LoopbackMidiBiDi::Initialize(
TraceLoggingLevel(WINEVENT_LEVEL_INFO),
TraceLoggingPointer(this, "this"),
TraceLoggingWideString(L"Initializing Side-A BiDi", "message"),
- TraceLoggingWideString(m_endpointId.c_str(), "endpoint id")
+ TraceLoggingWideString(m_endpointId.c_str(), "endpoint id"),
+ TraceLoggingWideString(m_associationId.c_str(), "association id")
);
m_callback = Callback;
m_isEndpointA = true;
+
}
else if (internal::EndpointInterfaceIdContainsString(m_endpointId, MIDI_PERM_LOOP_INSTANCE_ID_B_PREFIX) ||
internal::EndpointInterfaceIdContainsString(m_endpointId, MIDI_TEMP_LOOP_INSTANCE_ID_B_PREFIX))
@@ -60,7 +65,8 @@ CMidi2LoopbackMidiBiDi::Initialize(
TraceLoggingLevel(WINEVENT_LEVEL_INFO),
TraceLoggingPointer(this, "this"),
TraceLoggingWideString(L"Initializing Side-B BiDi", "message"),
- TraceLoggingWideString(m_endpointId.c_str(), "endpoint id")
+ TraceLoggingWideString(m_endpointId.c_str(), "endpoint id"),
+ TraceLoggingWideString(m_associationId.c_str(), "association id")
);
m_callback = Callback;
@@ -77,10 +83,39 @@ CMidi2LoopbackMidiBiDi::Initialize(
TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
TraceLoggingPointer(this, "this"),
TraceLoggingWideString(L"We don't understand the endpoint Id", "message"),
- TraceLoggingWideString(m_endpointId.c_str(), "endpoint id")
- );
+ TraceLoggingWideString(m_endpointId.c_str(), "endpoint id"),
+ TraceLoggingWideString(m_associationId.c_str(), "association id")
+ );
+
+ return E_FAIL;
+ }
+
+ // register this endpoint as part of a loopback device
- hr = E_FAIL;
+ auto device = AbstractionState::Current().GetEndpointTable()->GetDevice(m_associationId);
+
+ if (device)
+ {
+ if (m_isEndpointA)
+ {
+ device->RegisterEndpointA(this);
+ }
+ else
+ {
+ device->RegisterEndpointB(this);
+ }
+ }
+ else
+ {
+ TraceLoggingWrite(
+ MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_INFO),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(L"Unable to find matching device in device table", "message"),
+ TraceLoggingWideString(m_endpointId.c_str(), "endpoint id"),
+ TraceLoggingWideString(m_associationId.c_str(), "association id")
+ );
}
return hr;
@@ -115,7 +150,8 @@ CMidi2LoopbackMidiBiDi::SendMidiMessage(
__FUNCTION__,
TraceLoggingLevel(WINEVENT_LEVEL_INFO),
TraceLoggingPointer(this, "this"),
- TraceLoggingWideString(m_endpointId.c_str(), "endpoint id")
+ TraceLoggingWideString(m_endpointId.c_str(), "endpoint id"),
+ TraceLoggingBool(m_isEndpointA, "is endpoint A")
);
RETURN_HR_IF_NULL(E_INVALIDARG, Message);
@@ -130,6 +166,19 @@ CMidi2LoopbackMidiBiDi::SendMidiMessage(
{
return device->SendMessageAToB(Message, Size, Position, m_callbackContext);
}
+ else
+ {
+ TraceLoggingWrite(
+ MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(m_endpointId.c_str(), "endpoint id"),
+ TraceLoggingWideString(L"Send A to B : Unable to find endpoint device in table", "message")
+ );
+
+ return E_FAIL;
+ }
}
else
{
@@ -140,6 +189,19 @@ CMidi2LoopbackMidiBiDi::SendMidiMessage(
{
return device->SendMessageBToA(Message, Size, Position, m_callbackContext);
}
+ else
+ {
+ TraceLoggingWrite(
+ MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(m_endpointId.c_str(), "endpoint id"),
+ TraceLoggingWideString(L"Send B to A : Unable to find endpoint device in table", "message")
+ );
+
+ return E_FAIL;
+ }
}
return S_OK;
diff --git a/src/api/Abstraction/LoopbackMidiAbstraction/Midi2.LoopbackMidiConfigurationManager.cpp b/src/api/Abstraction/LoopbackMidiAbstraction/Midi2.LoopbackMidiConfigurationManager.cpp
index 843cee60..ca0de42a 100644
--- a/src/api/Abstraction/LoopbackMidiAbstraction/Midi2.LoopbackMidiConfigurationManager.cpp
+++ b/src/api/Abstraction/LoopbackMidiAbstraction/Midi2.LoopbackMidiConfigurationManager.cpp
@@ -12,7 +12,7 @@
_Use_decl_annotations_
HRESULT
CMidi2LoopbackMidiConfigurationManager::Initialize(
- GUID AbstractionId,
+ GUID AbstractionId,
IUnknown* MidiDeviceManager
)
{
@@ -82,13 +82,11 @@ CMidi2LoopbackMidiConfigurationManager::UpdateConfiguration(
std::wstring instanceIdPrefixB = IsFromConfigurationFile ? MIDI_PERM_LOOP_INSTANCE_ID_B_PREFIX : MIDI_TEMP_LOOP_INSTANCE_ID_B_PREFIX;
// we should probably set a property based on this as well.
-
-
- auto createObject = internal::JsonGetObjectProperty(jsonObject, MIDI_CONFIG_JSON_ENDPOINT_LOOPBACK_DEVICES_CREATE_KEY, json::JsonObject{});
+ auto createObject = jsonObject.GetNamedObject(MIDI_CONFIG_JSON_ENDPOINT_LOOPBACK_DEVICES_CREATE_KEY, nullptr);
// Create ----------------------------------
- if (createObject.Size() > 0)
+ if (createObject != nullptr && createObject.Size() > 0)
{
auto o = createObject.First();
@@ -97,80 +95,162 @@ CMidi2LoopbackMidiConfigurationManager::UpdateConfiguration(
std::shared_ptr definitionA = std::make_shared();
std::shared_ptr definitionB = std::make_shared();
- auto associationObj = o.Current().Value().as();
+ // get the association string (GUID) name
+ auto associationKey = o.Current().Key();
+ //json::JsonObject associationObj;
- definitionA->AssociationId = o.Current().Key();
+ auto associationObj = o.Current().Value().GetObject();
- auto endpointAObject = internal::JsonGetObjectProperty(associationObj, MIDI_CONFIG_JSON_ENDPOINT_LOOPBACK_DEVICE_ENDPOINT_A_KEY, nullptr);
- auto endpointBObject = internal::JsonGetObjectProperty(associationObj, MIDI_CONFIG_JSON_ENDPOINT_LOOPBACK_DEVICE_ENDPOINT_B_KEY, nullptr);
+ //if (!o.Current().Value().try_as(associationObj))
+ //{
+ // TraceLoggingWrite(
+ // MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ // __FUNCTION__,
+ // TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
+ // TraceLoggingPointer(this, "this"),
+ // TraceLoggingWideString(L"Unable to read the property as a json object", "message"),
+ // TraceLoggingWideString(associationKey.c_str(), "key")
+ // TraceLoggingWideString(o.Current().Value().Stringify(), "stringify")
+ // );
- if (endpointAObject != nullptr && endpointBObject != nullptr)
- {
- definitionA->EndpointName = internal::JsonGetWStringProperty(endpointAObject, MIDI_CONFIG_JSON_ENDPOINT_COMMON_NAME_PROPERTY, L"");
- definitionA->EndpointName = internal::JsonGetWStringProperty(endpointAObject, MIDI_CONFIG_JSON_ENDPOINT_COMMON_DESCRIPTION_PROPERTY, L"");
- definitionA->EndpointName = internal::JsonGetWStringProperty(endpointAObject, MIDI_CONFIG_JSON_ENDPOINT_COMMON_UNIQUE_ID_PROPERTY, L"");
- definitionA->InstanceIdPrefix = instanceIdPrefixA;
+ // internal::JsonStringifyObjectToOutParam(responseObject, &Response);
- definitionB->EndpointName = internal::JsonGetWStringProperty(endpointBObject, MIDI_CONFIG_JSON_ENDPOINT_COMMON_NAME_PROPERTY, L"");
- definitionB->EndpointName = internal::JsonGetWStringProperty(endpointBObject, MIDI_CONFIG_JSON_ENDPOINT_COMMON_DESCRIPTION_PROPERTY, L"");
- definitionB->EndpointName = internal::JsonGetWStringProperty(endpointBObject, MIDI_CONFIG_JSON_ENDPOINT_COMMON_UNIQUE_ID_PROPERTY, L"");
- definitionB->InstanceIdPrefix = instanceIdPrefixB;
+ // return E_FAIL;
+ //}
+
+ if (associationObj)
+ {
+ definitionA->AssociationId = associationKey;
+ definitionB->AssociationId = definitionA->AssociationId;
- if (SUCCEEDED(AbstractionState::Current().GetEndpointManager()->CreateEndpointPair(definitionA, definitionB)))
- {
- TraceLoggingWrite(
- MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
- __FUNCTION__,
- TraceLoggingLevel(WINEVENT_LEVEL_INFO),
- TraceLoggingPointer(this, "this"),
- TraceLoggingWideString(L"Loopback endpoint pair created", "message")
- );
-
- // all good
-
- internal::JsonSetBoolProperty(
- responseObject,
- MIDI_CONFIG_JSON_ENDPOINT_LOOPBACK_DEVICE_RESPONSE_SUCCESS_PROPERTY_KEY,
- true);
-
- // update the return json with the new Ids
- internal::JsonSetWStringProperty(
- responseObject,
- MIDI_CONFIG_JSON_ENDPOINT_LOOPBACK_DEVICE_RESPONSE_CREATED_ENDPOINT_A_ID_KEY,
- definitionA->CreatedEndpointInterfaceId);
+ auto endpointAObject = associationObj.GetNamedObject(MIDI_CONFIG_JSON_ENDPOINT_LOOPBACK_DEVICE_ENDPOINT_A_KEY, nullptr);
+ auto endpointBObject = associationObj.GetNamedObject(MIDI_CONFIG_JSON_ENDPOINT_LOOPBACK_DEVICE_ENDPOINT_B_KEY, nullptr);
- internal::JsonSetWStringProperty(
- responseObject,
- MIDI_CONFIG_JSON_ENDPOINT_LOOPBACK_DEVICE_RESPONSE_CREATED_ENDPOINT_B_ID_KEY,
- definitionB->CreatedEndpointInterfaceId);
+ if (endpointAObject != nullptr && endpointBObject != nullptr)
+ {
+ definitionA->EndpointName = endpointAObject.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_COMMON_NAME_PROPERTY, L"");
+ definitionA->EndpointDescription = endpointAObject.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_COMMON_DESCRIPTION_PROPERTY, L"");
+ definitionA->EndpointUniqueIdentifier = endpointAObject.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_COMMON_UNIQUE_ID_PROPERTY, L"");
+ definitionA->InstanceIdPrefix = instanceIdPrefixA;
+
+ definitionB->EndpointName = endpointBObject.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_COMMON_NAME_PROPERTY, L"");
+ definitionB->EndpointDescription = endpointBObject.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_COMMON_DESCRIPTION_PROPERTY, L"");
+ definitionB->EndpointUniqueIdentifier = endpointBObject.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_COMMON_UNIQUE_ID_PROPERTY, L"");
+ definitionB->InstanceIdPrefix = instanceIdPrefixB;
+
+
+ if (definitionA->EndpointName.empty() || definitionB->EndpointName.empty())
+ {
+ TraceLoggingWrite(
+ MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(L"Endpoint name missing or empty", "message")
+ );
+
+ internal::JsonStringifyObjectToOutParam(responseObject, &Response);
+
+ return E_FAIL;
+ }
+
+
+ if (definitionA->EndpointUniqueIdentifier.empty() || definitionB->EndpointUniqueIdentifier.empty())
+ {
+ TraceLoggingWrite(
+ MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(L"Unique identifier missing or empty", "message")
+ );
+
+ internal::JsonStringifyObjectToOutParam(responseObject, &Response);
+
+ return E_FAIL;
+ }
+
+
+ if (SUCCEEDED(AbstractionState::Current().GetEndpointManager()->CreateEndpointPair(definitionA, definitionB)))
+ {
+ TraceLoggingWrite(
+ MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_INFO),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(L"Loopback endpoint pair created", "message")
+ );
+
+ // all good
+
+ internal::JsonSetBoolProperty(
+ responseObject,
+ MIDI_CONFIG_JSON_ENDPOINT_LOOPBACK_DEVICE_RESPONSE_SUCCESS_PROPERTY_KEY,
+ true);
+
+ // update the return json with the new Ids
+
+ internal::JsonSetWStringProperty(
+ responseObject,
+ MIDI_CONFIG_JSON_ENDPOINT_LOOPBACK_DEVICE_RESPONSE_CREATED_ENDPOINT_A_ID_KEY,
+ definitionA->CreatedEndpointInterfaceId);
+
+ internal::JsonSetWStringProperty(
+ responseObject,
+ MIDI_CONFIG_JSON_ENDPOINT_LOOPBACK_DEVICE_RESPONSE_CREATED_ENDPOINT_B_ID_KEY,
+ definitionB->CreatedEndpointInterfaceId);
+ }
+ else
+ {
+ // we failed to create the endpoints. Exit and return a fail.
+ TraceLoggingWrite(
+ MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(L"Failed to create endpoints", "message")
+ );
+
+ internal::JsonStringifyObjectToOutParam(responseObject, &Response);
+
+ return E_FAIL;
+ }
}
else
{
- // we failed to create the endpoints. Exit and return a fail.
+ // couldn't get the endpointA or endpointB objects. Exit and return a fail
+
TraceLoggingWrite(
MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
__FUNCTION__,
TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
TraceLoggingPointer(this, "this"),
- TraceLoggingWideString(L"Failed to create endpoints", "message")
+ TraceLoggingWideString(associationKey.c_str(), "association key"),
+ TraceLoggingWideString(L"Failed to get one or both endpoints from the JSON", "message")
);
+ internal::JsonStringifyObjectToOutParam(responseObject, &Response);
+
+ return E_FAIL;
+
}
}
else
{
- // couldn't get the endpointA or endpointB objects. Exit and return a fail
-
TraceLoggingWrite(
MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
__FUNCTION__,
TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
TraceLoggingPointer(this, "this"),
- TraceLoggingWideString(L"Failed to get one or both endpoints from the JSON", "message")
+ TraceLoggingWideString(associationKey.c_str(), "association key"),
+ TraceLoggingWideString(L"Unable to convert association id property to a JsonObject", "message")
);
+ internal::JsonStringifyObjectToOutParam(responseObject, &Response);
+
+ return E_FAIL;
}
o.MoveNext();
@@ -210,6 +290,22 @@ CMidi2LoopbackMidiConfigurationManager::UpdateConfiguration(
// // TODO : Update endpoints
//}
+ internal::JsonStringifyObjectToOutParam(responseObject, &Response);
+
+ return S_OK;
+
+ }
+ catch (const std::exception& e)
+ {
+ TraceLoggingWrite(
+ MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(L"std exception processing json", "message"),
+ TraceLoggingString(e.what(), "exception"),
+ TraceLoggingWideString(ConfigurationJsonSection, "json")
+ );
}
catch (...)
{
@@ -218,13 +314,9 @@ CMidi2LoopbackMidiConfigurationManager::UpdateConfiguration(
__FUNCTION__,
TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
TraceLoggingPointer(this, "this"),
- TraceLoggingWideString(L"Exception processing json", "message"),
+ TraceLoggingWideString(L"Other exception processing json", "message"),
TraceLoggingWideString(ConfigurationJsonSection, "json")
);
-
- internal::JsonStringifyObjectToOutParam(responseObject, &Response);
-
- return E_FAIL;
}
// return the json with the information the client will need
diff --git a/src/api/Abstraction/LoopbackMidiAbstraction/Midi2.LoopbackMidiEndpointManager.cpp b/src/api/Abstraction/LoopbackMidiAbstraction/Midi2.LoopbackMidiEndpointManager.cpp
index a1d7b276..dd9212b3 100644
--- a/src/api/Abstraction/LoopbackMidiAbstraction/Midi2.LoopbackMidiEndpointManager.cpp
+++ b/src/api/Abstraction/LoopbackMidiAbstraction/Midi2.LoopbackMidiEndpointManager.cpp
@@ -159,8 +159,8 @@ CMidi2LoopbackMidiEndpointManager::CreateSingleEndpoint(
TraceLoggingLevel(WINEVENT_LEVEL_INFO),
TraceLoggingPointer(this, "this"),
TraceLoggingWideString(definition->AssociationId.c_str(), "association id"),
- TraceLoggingWideString(definition->EndpointUniqueIdentifier.c_str(), "unique identifier"),
TraceLoggingWideString(definition->InstanceIdPrefix.c_str(), "prefix"),
+ TraceLoggingWideString(definition->EndpointUniqueIdentifier.c_str(), "unique identifier"),
TraceLoggingWideString(definition->EndpointName.c_str(), "name"),
TraceLoggingWideString(definition->EndpointDescription.c_str(), "description")
);
@@ -183,52 +183,32 @@ CMidi2LoopbackMidiEndpointManager::CreateSingleEndpoint(
std::vector interfaceDeviceProperties{};
- bool requiresMetadataHandler = false;
- bool multiClient = true;
- bool generateIncomingTimestamps = true;
-
// no user or in-protocol data in this case
std::wstring friendlyName = internal::CalculateEndpointDevicePrimaryName(endpointName, L"", L"");
- // all the standard properties we define for endpoints
- if (internal::AddStandardEndpointProperties(
- interfaceDeviceProperties,
- m_TransportAbstractionId,
- MidiEndpointDevicePurposePropertyValue::NormalMessageEndpoint,
- friendlyName,
- mnemonic,
- endpointName,
- endpointDescription,
- L"",
- L"",
- definition->EndpointUniqueIdentifier,
- MidiDataFormat::MidiDataFormat_UMP,
- MIDI_PROP_NATIVEDATAFORMAT_UMP,
- multiClient,
- requiresMetadataHandler,
- generateIncomingTimestamps
- ))
- {
- // additional properties for this abstraction
- // we clear this because it's not used for this abstraction.
- interfaceDeviceProperties.push_back(internal::BuildEmptyDevProperty(PKEY_MIDI_AssociatedUMP));
+ bool requiresMetadataHandler = false;
+ bool multiClient = true;
+ bool generateIncomingTimestamps = true;
- // this is needed for the loopback endpoints to have a relationship with each other
- interfaceDeviceProperties.push_back(internal::BuildWStringDevProperty(PKEY_MIDI_VirtualMidiEndpointAssociator, definition->AssociationId));
- }
- else
- {
- TraceLoggingWrite(
- MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
- __FUNCTION__,
- TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
- TraceLoggingPointer(this, "this"),
- TraceLoggingWideString(L"Unable to build standard endpoint properties list", "message")
- );
- return E_FAIL;
- }
+ TraceLoggingWrite(
+ MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(definition->AssociationId.c_str(), "association id"),
+ TraceLoggingWideString(definition->EndpointUniqueIdentifier.c_str(), "unique identifier"),
+ TraceLoggingWideString(L"Adding endpoint properties"),
+ TraceLoggingWideString(friendlyName.c_str(), "friendlyName"),
+ TraceLoggingWideString(mnemonic.c_str(), "mnemonic"),
+ TraceLoggingWideString(endpointName.c_str(), "endpointName"),
+ TraceLoggingWideString(endpointDescription.c_str(), "endpointName")
+ );
+
+ // this is needed for the loopback endpoints to have a relationship with each other
+ interfaceDeviceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_VirtualMidiEndpointAssociator, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_STRING, (ULONG)(sizeof(wchar_t) * (definition->AssociationId.size() + 1)), (PVOID)definition->AssociationId.c_str() });
// Device properties
@@ -248,16 +228,45 @@ CMidi2LoopbackMidiEndpointManager::CreateSingleEndpoint(
createInfo.pszInstanceId = instanceId.c_str();
createInfo.CapabilityFlags = SWDeviceCapabilitiesNone;
- createInfo.pszDeviceDescription = endpointName.c_str();
+ createInfo.pszDeviceDescription = friendlyName.c_str();
const ULONG deviceInterfaceIdMaxSize = 255;
wchar_t newDeviceInterfaceId[deviceInterfaceIdMaxSize]{ 0 };
+ TraceLoggingWrite(
+ MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(definition->AssociationId.c_str(), "association id"),
+ TraceLoggingWideString(definition->EndpointUniqueIdentifier.c_str(), "unique identifier"),
+ TraceLoggingWideString(instanceId.c_str(), "instance id"),
+ TraceLoggingWideString(L"Activating endpoint")
+ );
+
+ MIDIENDPOINTCOMMONPROPERTIES commonProperties;
+ commonProperties.AbstractionLayerGuid = m_TransportAbstractionId;
+ commonProperties.EndpointPurpose = MidiEndpointDevicePurposePropertyValue::NormalMessageEndpoint;
+ commonProperties.FriendlyName = friendlyName.c_str();
+ commonProperties.TransportMnemonic = mnemonic.c_str();
+ commonProperties.TransportSuppliedEndpointName = endpointName.c_str();
+ commonProperties.TransportSuppliedEndpointDescription = endpointDescription.c_str();
+ commonProperties.UserSuppliedEndpointName = nullptr;
+ commonProperties.UserSuppliedEndpointDescription = nullptr;
+ commonProperties.UniqueIdentifier = definition->EndpointUniqueIdentifier.c_str();
+ commonProperties.SupportedDataFormats = MidiDataFormat::MidiDataFormat_UMP;
+ commonProperties.NativeDataFormat = MIDI_PROP_NATIVEDATAFORMAT_UMP;
+ commonProperties.SupportsMultiClient = multiClient;
+ commonProperties.RequiresMetadataHandler = requiresMetadataHandler;
+ commonProperties.GenerateIncomingTimestamps = generateIncomingTimestamps;
+
+
RETURN_IF_FAILED(m_MidiDeviceManager->ActivateEndpoint(
(PCWSTR)m_parentDeviceId.c_str(), // parent instance Id
true, // UMP-only
MidiFlow::MidiFlowBidirectional, // MIDI Flow
+ &commonProperties,
(ULONG)interfaceDeviceProperties.size(),
ARRAYSIZE(deviceDevProperties),
(PVOID)interfaceDeviceProperties.data(),
@@ -267,6 +276,18 @@ CMidi2LoopbackMidiEndpointManager::CreateSingleEndpoint(
deviceInterfaceIdMaxSize));
+ TraceLoggingWrite(
+ MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(definition->AssociationId.c_str(), "association id"),
+ TraceLoggingWideString(definition->EndpointUniqueIdentifier.c_str(), "unique identifier"),
+ TraceLoggingWideString(newDeviceInterfaceId, "new device interface id"),
+ TraceLoggingWideString(L"Endpoint activated")
+ );
+
+
// now delete all the properties that have been discovered in-protocol
// we have to do this because they end up cached by PNP and come back
// when you recreate a device with the same Id. This is a real problem
@@ -276,12 +297,21 @@ CMidi2LoopbackMidiEndpointManager::CreateSingleEndpoint(
// we need this for removal later
definition->CreatedShortClientInstanceId = instanceId;
-
definition->CreatedEndpointInterfaceId = internal::NormalizeEndpointInterfaceIdWStringCopy(newDeviceInterfaceId);
//MidiEndpointTable::Current().AddCreatedEndpointDevice(entry);
//MidiEndpointTable::Current().AddCreatedClient(entry.VirtualEndpointAssociationId, entry.CreatedClientEndpointId);
+ TraceLoggingWrite(
+ MidiLoopbackMidiAbstractionTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(definition->AssociationId.c_str(), "association id"),
+ TraceLoggingWideString(definition->EndpointUniqueIdentifier.c_str(), "unique identifier"),
+ TraceLoggingWideString(L"Done")
+ );
+
return S_OK;
}
@@ -308,8 +338,16 @@ CMidi2LoopbackMidiEndpointManager::CreateEndpointPair(
{
if (SUCCEEDED(CreateSingleEndpoint(definitionB)))
{
+ // all good now. Create the device table entry.
+
+ auto associationId = definitionA->AssociationId;
+
+ auto device = MidiLoopbackDevice{};
+
+ device.DefinitionA = *definitionA;
+ device.DefinitionB = *definitionB;
- // all good now
+ AbstractionState::Current().GetEndpointTable()->SetDevice(associationId, device);
}
else
diff --git a/src/api/Abstraction/LoopbackMidiAbstraction/MidiLoopbackDeviceTable.h b/src/api/Abstraction/LoopbackMidiAbstraction/MidiLoopbackDeviceTable.h
index a8b67b28..389ebace 100644
--- a/src/api/Abstraction/LoopbackMidiAbstraction/MidiLoopbackDeviceTable.h
+++ b/src/api/Abstraction/LoopbackMidiAbstraction/MidiLoopbackDeviceTable.h
@@ -10,7 +10,7 @@
#pragma once
-class MidiEndpointTable
+class MidiLoopbackDeviceTable
{
public:
diff --git a/src/api/Abstraction/LoopbackMidiAbstraction/pch.h b/src/api/Abstraction/LoopbackMidiAbstraction/pch.h
index ca66d19a..94f64b1f 100644
--- a/src/api/Abstraction/LoopbackMidiAbstraction/pch.h
+++ b/src/api/Abstraction/LoopbackMidiAbstraction/pch.h
@@ -20,9 +20,6 @@
#include
#include
#include
-//#include
-
-//namespace json = ::winrt::Windows::Data::Json;
#include
@@ -67,12 +64,19 @@
#include "strsafe.h"
#include "wstring_util.h"
+//#pragma push_macro("GetObject")
+#undef GetObject
+#include
+namespace json = ::winrt::Windows::Data::Json;
+//#pragma pop_macro("GetObject")
+
+
// AbstractionUtilities
#include "endpoint_data_helpers.h"
#include "swd_property_builders.h"
-#include "swd_property_helpers.h"
#include "json_helpers.h"
+#include "swd_shared.h"
#include "MidiDefs.h"
#include "MidiDataFormat.h"
diff --git a/src/api/Abstraction/NetworkMidiAbstraction/pch.h b/src/api/Abstraction/NetworkMidiAbstraction/pch.h
index 4e822a25..d5145785 100644
--- a/src/api/Abstraction/NetworkMidiAbstraction/pch.h
+++ b/src/api/Abstraction/NetworkMidiAbstraction/pch.h
@@ -59,7 +59,6 @@ namespace json = ::winrt::Windows::Data::Json;
// AbstractionUtilities
#include "endpoint_data_helpers.h"
#include "swd_property_builders.h"
-#include "swd_property_helpers.h"
#include "json_helpers.h"
#include "MidiDefs.h"
diff --git a/src/api/Abstraction/SampleAbstraction/pch.h b/src/api/Abstraction/SampleAbstraction/pch.h
index 286ecad1..9f95eac3 100644
--- a/src/api/Abstraction/SampleAbstraction/pch.h
+++ b/src/api/Abstraction/SampleAbstraction/pch.h
@@ -41,7 +41,6 @@
// AbstractionUtilities
#include "endpoint_data_helpers.h"
#include "swd_property_builders.h"
-#include "swd_property_helpers.h"
#include "json_helpers.h"
#include "MidiDefs.h"
diff --git a/src/api/Abstraction/VirtualMidiAbstraction/Midi2.VirtualMidiAbstraction.vcxproj b/src/api/Abstraction/VirtualMidiAbstraction/Midi2.VirtualMidiAbstraction.vcxproj
index b6a569dc..7fef3cb1 100644
--- a/src/api/Abstraction/VirtualMidiAbstraction/Midi2.VirtualMidiAbstraction.vcxproj
+++ b/src/api/Abstraction/VirtualMidiAbstraction/Midi2.VirtualMidiAbstraction.vcxproj
@@ -282,7 +282,6 @@
-
@@ -303,7 +302,6 @@
-
diff --git a/src/api/Abstraction/VirtualMidiAbstraction/Midi2.VirtualMidiAbstraction.vcxproj.filters b/src/api/Abstraction/VirtualMidiAbstraction/Midi2.VirtualMidiAbstraction.vcxproj.filters
index 1c9c29dc..0190308f 100644
--- a/src/api/Abstraction/VirtualMidiAbstraction/Midi2.VirtualMidiAbstraction.vcxproj.filters
+++ b/src/api/Abstraction/VirtualMidiAbstraction/Midi2.VirtualMidiAbstraction.vcxproj.filters
@@ -33,9 +33,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -82,9 +79,6 @@
Header Files
-
- Header Files
-
Header Files
diff --git a/src/api/Abstraction/VirtualMidiAbstraction/Midi2.VirtualMidiEndpointManager.cpp b/src/api/Abstraction/VirtualMidiAbstraction/Midi2.VirtualMidiEndpointManager.cpp
index 0aef21ac..c3382a44 100644
--- a/src/api/Abstraction/VirtualMidiAbstraction/Midi2.VirtualMidiEndpointManager.cpp
+++ b/src/api/Abstraction/VirtualMidiAbstraction/Midi2.VirtualMidiEndpointManager.cpp
@@ -246,48 +246,10 @@ CMidi2VirtualMidiEndpointManager::CreateClientVisibleEndpoint(
// no user or in-protocol data in this case
std::wstring friendlyName = internal::CalculateEndpointDevicePrimaryName(endpointName, L"", L"");
- // all the standard properties we define for endpoints
- if (internal::AddStandardEndpointProperties(
- interfaceDeviceProperties,
- m_TransportAbstractionId,
- MidiEndpointDevicePurposePropertyValue::NormalMessageEndpoint,
- friendlyName,
- mnemonic,
- endpointName,
- endpointDescription,
- L"",
- L"",
- entry.ShortUniqueId,
- MidiDataFormat::MidiDataFormat_UMP,
- MIDI_PROP_NATIVEDATAFORMAT_UMP,
- multiClient,
- requiresMetadataHandler,
- generateIncomingTimestamps
- ))
- {
- // all good. Add additional properties
- // additional properties for this abstraction
-
- // we clear this because it's not used for this abstraction.
- interfaceDeviceProperties.push_back(internal::BuildEmptyDevProperty(PKEY_MIDI_AssociatedUMP));
-
- // this is needed for the loopback endpoints to have a relationship with each other
- interfaceDeviceProperties.push_back(internal::BuildWStringDevProperty(PKEY_MIDI_VirtualMidiEndpointAssociator, entry.VirtualEndpointAssociationId));
- }
- else
- {
- // unable to build properties
+ // this is needed for the loopback endpoints to have a relationship with each other
+ interfaceDeviceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_VirtualMidiEndpointAssociator, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_STRING, (ULONG)(sizeof(wchar_t) * (entry.VirtualEndpointAssociationId.size() + 1)), (PVOID)entry.VirtualEndpointAssociationId.c_str() });
- TraceLoggingWrite(
- MidiVirtualMidiAbstractionTelemetryProvider::Provider(),
- __FUNCTION__,
- TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
- TraceLoggingPointer(this, "this"),
- TraceLoggingWideString(L"Unable to build standard endpoint properties list", "message")
- );
-
- return E_FAIL;
- }
DEVPROPERTY deviceDevProperties[] = {
{{DEVPKEY_Device_PresenceNotForDevice, DEVPROP_STORE_SYSTEM, nullptr},
@@ -309,10 +271,28 @@ CMidi2VirtualMidiEndpointManager::CreateClientVisibleEndpoint(
const ULONG deviceInterfaceIdMaxSize = 255;
wchar_t newDeviceInterfaceId[deviceInterfaceIdMaxSize]{ 0 };
+
+ MIDIENDPOINTCOMMONPROPERTIES commonProperties;
+ commonProperties.AbstractionLayerGuid = m_TransportAbstractionId;
+ commonProperties.EndpointPurpose = MidiEndpointDevicePurposePropertyValue::NormalMessageEndpoint;
+ commonProperties.FriendlyName = friendlyName.c_str();
+ commonProperties.TransportMnemonic = mnemonic.c_str();
+ commonProperties.TransportSuppliedEndpointName = endpointName.c_str();
+ commonProperties.TransportSuppliedEndpointDescription = endpointDescription.c_str();
+ commonProperties.UserSuppliedEndpointName = L"";
+ commonProperties.UserSuppliedEndpointDescription = L"";
+ commonProperties.UniqueIdentifier = entry.ShortUniqueId.c_str();
+ commonProperties.SupportedDataFormats = MidiDataFormat::MidiDataFormat_UMP;
+ commonProperties.NativeDataFormat = MIDI_PROP_NATIVEDATAFORMAT_UMP;
+ commonProperties.SupportsMultiClient = multiClient;
+ commonProperties.RequiresMetadataHandler = requiresMetadataHandler;
+ commonProperties.GenerateIncomingTimestamps = generateIncomingTimestamps;
+
RETURN_IF_FAILED(m_MidiDeviceManager->ActivateEndpoint(
(PCWSTR)m_parentDeviceId.c_str(), // parent instance Id
true, // UMP-only
MidiFlow::MidiFlowBidirectional, // MIDI Flow
+ &commonProperties,
(ULONG)interfaceDeviceProperties.size(),
ARRAYSIZE(deviceDevProperties),
(PVOID)interfaceDeviceProperties.data(),
@@ -374,48 +354,10 @@ CMidi2VirtualMidiEndpointManager::CreateDeviceSideEndpoint(
// no user or in-protocol data in this case
std::wstring friendlyName = internal::CalculateEndpointDevicePrimaryName(endpointName, L"", L"");
- // all the standard properties we define for endpoints
- if (internal::AddStandardEndpointProperties(
- interfaceDeviceProperties,
- m_TransportAbstractionId,
- MidiEndpointDevicePurposePropertyValue::VirtualDeviceResponder,
- friendlyName,
- mnemonic,
- endpointName,
- endpointDescription,
- L"",
- L"",
- entry.ShortUniqueId,
- MidiDataFormat::MidiDataFormat_UMP,
- MIDI_PROP_NATIVEDATAFORMAT_UMP,
- multiClient,
- requiresMetadataHandler,
- generateIncomingTimestamps
- ))
- {
- // all good. Add additional properties
- // additional properties for this abstraction
- // we clear this because it's not used for this abstraction.
- interfaceDeviceProperties.push_back(internal::BuildEmptyDevProperty(PKEY_MIDI_AssociatedUMP));
+ interfaceDeviceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_VirtualMidiEndpointAssociator, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_STRING, (ULONG)(sizeof(wchar_t) * (entry.VirtualEndpointAssociationId.size() + 1)), (PVOID)entry.VirtualEndpointAssociationId.c_str() });
- // this is needed for the loopback endpoints to have a relationship with each other
- interfaceDeviceProperties.push_back(internal::BuildWStringDevProperty(PKEY_MIDI_VirtualMidiEndpointAssociator, entry.VirtualEndpointAssociationId));
- }
- else
- {
- // unable to build properties
-
- TraceLoggingWrite(
- MidiVirtualMidiAbstractionTelemetryProvider::Provider(),
- __FUNCTION__,
- TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
- TraceLoggingPointer(this, "this"),
- TraceLoggingWideString(L"Unable to build standard endpoint properties list", "message")
- );
-
- return E_FAIL;
- }
DEVPROPERTY deviceDevProperties[] = {
{{DEVPKEY_Device_PresenceNotForDevice, DEVPROP_STORE_SYSTEM, nullptr},
@@ -442,10 +384,30 @@ CMidi2VirtualMidiEndpointManager::CreateDeviceSideEndpoint(
+
+
+ MIDIENDPOINTCOMMONPROPERTIES commonProperties;
+ commonProperties.AbstractionLayerGuid = m_TransportAbstractionId;
+ commonProperties.EndpointPurpose = MidiEndpointDevicePurposePropertyValue::VirtualDeviceResponder;
+ commonProperties.FriendlyName = friendlyName.c_str();
+ commonProperties.TransportMnemonic = mnemonic.c_str();
+ commonProperties.TransportSuppliedEndpointName = endpointName.c_str();
+ commonProperties.TransportSuppliedEndpointDescription = endpointDescription.c_str();
+ commonProperties.UserSuppliedEndpointName = L"";
+ commonProperties.UserSuppliedEndpointDescription = L"";
+ commonProperties.UniqueIdentifier = entry.ShortUniqueId.c_str();
+ commonProperties.SupportedDataFormats = MidiDataFormat::MidiDataFormat_UMP;
+ commonProperties.NativeDataFormat = MIDI_PROP_NATIVEDATAFORMAT_UMP;
+ commonProperties.SupportsMultiClient = multiClient;
+ commonProperties.RequiresMetadataHandler = requiresMetadataHandler;
+ commonProperties.GenerateIncomingTimestamps = generateIncomingTimestamps;
+
+
RETURN_IF_FAILED(m_MidiDeviceManager->ActivateEndpoint(
(PCWSTR)m_parentDeviceId.c_str(), // parent instance Id
true, // UMP-only
MidiFlow::MidiFlowBidirectional, // MIDI Flow
+ &commonProperties,
(ULONG)interfaceDeviceProperties.size(),
ARRAYSIZE(deviceDevProperties),
(PVOID)interfaceDeviceProperties.data(),
diff --git a/src/api/Abstraction/VirtualMidiAbstraction/MidiEndpointTable.cpp b/src/api/Abstraction/VirtualMidiAbstraction/MidiEndpointTable.cpp
index 843f21ea..e6bd523e 100644
--- a/src/api/Abstraction/VirtualMidiAbstraction/MidiEndpointTable.cpp
+++ b/src/api/Abstraction/VirtualMidiAbstraction/MidiEndpointTable.cpp
@@ -72,7 +72,7 @@ MidiEndpointTable::OnClientConnected(
// look up the association ID in SWD properties
- auto associationId = GetSwdPropertyVirtualEndpointAssociationId(clientEndpointInterfaceId);
+ auto associationId = internal::GetSwdPropertyVirtualEndpointAssociationId(clientEndpointInterfaceId);
if (associationId != L"")
{
@@ -126,7 +126,7 @@ MidiEndpointTable::OnClientDisconnected(
try
{
- std::wstring associationId = GetSwdPropertyVirtualEndpointAssociationId(clientEndpointInterfaceId);
+ std::wstring associationId = internal::GetSwdPropertyVirtualEndpointAssociationId(clientEndpointInterfaceId);
if (associationId != L"")
{
@@ -185,7 +185,7 @@ HRESULT MidiEndpointTable::OnDeviceConnected(std::wstring deviceEndpointInterfac
try
{
// look up the association ID in SWD properties
- auto associationId = GetSwdPropertyVirtualEndpointAssociationId(deviceEndpointInterfaceId);
+ auto associationId = internal::GetSwdPropertyVirtualEndpointAssociationId(deviceEndpointInterfaceId);
if (associationId != L"")
{
@@ -290,7 +290,7 @@ HRESULT MidiEndpointTable::OnDeviceDisconnected(std::wstring deviceEndpointInter
{
if (AbstractionState::Current().GetEndpointManager() != nullptr)
{
- std::wstring associationId = GetSwdPropertyVirtualEndpointAssociationId(deviceEndpointInterfaceId);
+ std::wstring associationId = internal::GetSwdPropertyVirtualEndpointAssociationId(deviceEndpointInterfaceId);
if (associationId != L"")
{
diff --git a/src/api/Abstraction/VirtualMidiAbstraction/pch.h b/src/api/Abstraction/VirtualMidiAbstraction/pch.h
index 14dd5612..5f908c1f 100644
--- a/src/api/Abstraction/VirtualMidiAbstraction/pch.h
+++ b/src/api/Abstraction/VirtualMidiAbstraction/pch.h
@@ -70,7 +70,6 @@
// AbstractionUtilities
#include "endpoint_data_helpers.h"
#include "swd_property_builders.h"
-#include "swd_property_helpers.h"
#include "json_helpers.h"
#include "MidiDefs.h"
diff --git a/src/api/Abstraction/VirtualMidiAbstraction/swd_shared.cpp b/src/api/Abstraction/VirtualMidiAbstraction/swd_shared.cpp
deleted file mode 100644
index 241723fe..00000000
--- a/src/api/Abstraction/VirtualMidiAbstraction/swd_shared.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License
-// ============================================================================
-// This is part of the Windows MIDI Services App API and should be used
-// in your Windows application via an official binary distribution.
-// Further information: https://github.com/microsoft/MIDI/
-// ============================================================================
-
-
-#include "pch.h"
-
-#include "swd_shared.h"
-
-_Use_decl_annotations_
-std::wstring GetStringSwdProperty(std::wstring deviceInterfaceId, std::wstring propertyName, std::wstring defaultValue)
-{
- auto propertyKey = winrt::to_hstring(propertyName.c_str());
-
- auto additionalProperties = winrt::single_threaded_vector();
- additionalProperties.Append(propertyKey);
-
-
- auto deviceInfo = winrt::Windows::Devices::Enumeration::DeviceInformation::CreateFromIdAsync(
- winrt::to_hstring(deviceInterfaceId.c_str()),
- additionalProperties,
- winrt::Windows::Devices::Enumeration::DeviceInformationKind::DeviceInterface).get();
-
- auto prop = deviceInfo.Properties().Lookup(propertyKey);
-
- if (prop)
- {
- OutputDebugString(__FUNCTION__ L" found property");
-
- // this interface is pointing to a UMP interface, so use that instance id.
- return (winrt::unbox_value(prop)).c_str();
- }
- else
- {
- OutputDebugString(__FUNCTION__ L" didn't find property");
- // default to any
- return defaultValue;
- }
-
-}
-
-
-_Use_decl_annotations_
-std::wstring GetSwdPropertyVirtualEndpointAssociationId(std::wstring deviceInterfaceId)
-{
- std::wstring cleanId = internal::NormalizeEndpointInterfaceIdWStringCopy(deviceInterfaceId);
-
- return internal::ToUpperTrimmedWStringCopy(GetStringSwdProperty(cleanId, STRING_PKEY_MIDI_VirtualMidiEndpointAssociator, L""));
-}
-
-
-_Use_decl_annotations_
-std::wstring GetSwdPropertyInstanceId(std::wstring deviceInterfaceId)
-{
- std::wstring cleanId = internal::NormalizeEndpointInterfaceIdWStringCopy(deviceInterfaceId);
-
- return internal::NormalizeDeviceInstanceIdWStringCopy(GetStringSwdProperty(cleanId, L"System.Devices.DeviceInstanceId", L""));
-}
diff --git a/src/api/Abstraction/VirtualMidiAbstraction/swd_shared.h b/src/api/Abstraction/VirtualMidiAbstraction/swd_shared.h
deleted file mode 100644
index 379cf197..00000000
--- a/src/api/Abstraction/VirtualMidiAbstraction/swd_shared.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License
-// ============================================================================
-// This is part of the Windows MIDI Services App API and should be used
-// in your Windows application via an official binary distribution.
-// Further information: https://github.com/microsoft/MIDI/
-// ============================================================================
-
-// TODO: Post-NAMM, move this to a lib that all projects share
-
-#pragma once
-
-std::wstring GetSwdStringProperty(_In_ std::wstring deviceInterfaceId, _In_ std::wstring propertyName, _In_ std::wstring defaultValue);
-
-std::wstring GetSwdPropertyVirtualEndpointAssociationId(_In_ std::wstring deviceInterfaceId);
-
-std::wstring GetSwdPropertyInstanceId(_In_ std::wstring deviceInterfaceId);
diff --git a/src/api/Abstraction/VirtualPatchBayAbstraction/Midi2.VirtualPatchBayEndpointManager.cpp b/src/api/Abstraction/VirtualPatchBayAbstraction/Midi2.VirtualPatchBayEndpointManager.cpp
index 932f4949..4aa7ba0f 100644
--- a/src/api/Abstraction/VirtualPatchBayAbstraction/Midi2.VirtualPatchBayEndpointManager.cpp
+++ b/src/api/Abstraction/VirtualPatchBayAbstraction/Midi2.VirtualPatchBayEndpointManager.cpp
@@ -41,7 +41,7 @@ CMidi2VirtualPatchBayEndpointManager::Initialize(
m_TransportAbstractionId = AbstractionLayerGUID; // this is needed so MidiSrv can instantiate the correct transport
m_ContainerId = m_TransportAbstractionId; // we use the transport ID as the container ID for convenience
- RETURN_IF_FAILED(CreateParentDevice());
+// RETURN_IF_FAILED(CreateParentDevice());
@@ -51,424 +51,11 @@ CMidi2VirtualPatchBayEndpointManager::Initialize(
-void SwMidiParentDeviceCreateCallback(
- __in HSWDEVICE /*hSwDevice*/,
- __in HRESULT CreationResult,
- __in_opt PVOID pContext,
- __in_opt PCWSTR pszDeviceInstanceId)
-{
- if (pContext == nullptr)
- {
- // TODO: Should log this.
-
- return;
- }
-
- PPARENTDEVICECREATECONTEXT creationContext = (PPARENTDEVICECREATECONTEXT)pContext;
-
-
- // interface registration has started, assume failure
- creationContext->MidiParentDevice->SwDeviceState = SWDEVICESTATE::Failed;
-
- LOG_IF_FAILED(CreationResult);
-
- if (SUCCEEDED(CreationResult))
- {
- // success, mark the port as created
- creationContext->MidiParentDevice->SwDeviceState = SWDEVICESTATE::Created;
-
- // get the new device instance ID. This is usually modified from what we started with
- creationContext->MidiParentDevice->InstanceId = std::wstring(pszDeviceInstanceId);
- }
- else
- {
- OutputDebugString(L"" __FUNCTION__ " - CreationResult FAILURE");
- }
-
- // success or failure, signal we have completed.
- creationContext->CreationCompleted.SetEvent();
-}
-
-
-
-HRESULT
-CMidi2VirtualPatchBayEndpointManager::CreateParentDevice()
-{
- // the parent device parameters are set by the transport (this)
-
- std::wstring parentDeviceName{ TRANSPORT_PARENT_DEVICE_NAME };
- std::wstring parentDeviceId{ TRANSPORT_PARENT_ID };
-
- SW_DEVICE_CREATE_INFO CreateInfo = {};
- CreateInfo.cbSize = sizeof(CreateInfo);
- CreateInfo.pszInstanceId = parentDeviceId.c_str();
- CreateInfo.CapabilityFlags = SWDeviceCapabilitiesNone;
- CreateInfo.pszDeviceDescription = parentDeviceName.c_str();
-
- SW_DEVICE_CREATE_INFO* createInfo = (SW_DEVICE_CREATE_INFO*)&CreateInfo;
-
- if (m_ParentDevice != nullptr)
- {
- return S_OK;
- }
-
- m_ParentDevice = std::make_unique();
-
- RETURN_IF_NULL_ALLOC(m_ParentDevice);
-
- PARENTDEVICECREATECONTEXT creationContext;
-
- // lambdas can only be converted to a function pointer if they
- // don't do capture, so copy everything into the CREATECONTEXT
- // to share with the SwDeviceCreate callback.
- creationContext.MidiParentDevice = m_ParentDevice.get();
-
- //creationContext.InterfaceDevProperties = (DEVPROPERTY*)InterfaceDevProperties;
- //creationContext.IntPropertyCount = IntPropertyCount;
-
- m_ParentDevice->SwDeviceState = SWDEVICESTATE::CreatePending;
-
- //m_ParentDevice->InstanceId = createInfo->pszInstanceId;
-
- DEVPROP_BOOLEAN devPropTrue = DEVPROP_TRUE;
-
- DEVPROPERTY deviceDevProperties[] = {
- {{DEVPKEY_Device_PresenceNotForDevice, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropTrue)), &devPropTrue},
- {{DEVPKEY_Device_NoConnectSound, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropTrue)),&devPropTrue}
- };
-
-
- std::wstring rootDeviceId = LOOPBACK_PARENT_ROOT;
- std::wstring enumeratorName = TRANSPORT_ENUMERATOR;
-
- createInfo->pContainerId = &m_ContainerId;
-
- RETURN_IF_FAILED(SwDeviceCreate(
- enumeratorName.c_str(), // this really should come from the service
- rootDeviceId.c_str(), // root device
- createInfo,
- ARRAYSIZE(deviceDevProperties), // count of properties
- (DEVPROPERTY*)deviceDevProperties, // pointer to properties
- SwMidiParentDeviceCreateCallback, // callback
- &creationContext,
- wil::out_param(m_ParentDevice->SwDevice)));
-
- // wait for creation to complete
- creationContext.CreationCompleted.wait();
-
- // confirm we were able to register the interface
- RETURN_HR_IF(E_FAIL, m_ParentDevice->SwDeviceState != SWDEVICESTATE::Created);
-
- return S_OK;
-}
-
-
-#define MIDI_VIRTUAL_ENDPOINTS_ARRAY_KEY L"endpoints"
-
-#define MIDI_VIRTUAL_ENDPOINT_PROPERTY_KEY L"key"
-#define MIDI_VIRTUAL_ENDPOINT_PROPERTY_NAME L"name"
-#define MIDI_VIRTUAL_ENDPOINT_PROPERTY_UNIQUEID L"uniqueIdentifier"
-#define MIDI_VIRTUAL_ENDPOINT_PROPERTY_MULTICLIENT L"supportsMulticlient"
-#define MIDI_VIRTUAL_ENDPOINT_PROPERTY_DESCRIPTION L"description"
-#define MIDI_VIRTUAL_ENDPOINT_PROPERTY_SMALLIMAGE L"smallImagePath"
-#define MIDI_VIRTUAL_ENDPOINT_PROPERTY_LARGEIMAGE L"largeImagePath"
-
-
-
-
-#define MIDI_JSON_ADD_NODE L"add"
-#define MIDI_JSON_UPDATE_NODE L"update"
-#define MIDI_JSON_REMOVE_NODE L"remove"
-
-
-json::JsonObject GetAddNode(
- json::JsonObject Parent
-)
-{
- if (Parent.HasKey(MIDI_JSON_ADD_NODE))
- {
- return Parent.GetNamedObject(MIDI_JSON_ADD_NODE);
- }
- else
- {
- return nullptr;
- }
-}
-
-winrt::hstring GetStringValue(
- json::JsonObject Parent,
- winrt::hstring Key,
- winrt::hstring Default)
-{
- if (Parent.HasKey(Key))
- {
- return Parent.GetNamedString(Key);
- }
- else
- {
- return Default;
- }
-}
-
-_Use_decl_annotations_
-HRESULT
-CMidi2VirtualPatchBayEndpointManager::CreateConfiguredEndpoints(
- std::wstring ConfigurationJson
-)
-{
- // if nothing to configure, that's ok
- if (ConfigurationJson.empty()) return S_OK;
-
- try
- {
- auto jsonObject = json::JsonObject::Parse(ConfigurationJson);
-
-
- // check to see if we have an "add" node. No point in checking for "update" or "remove" for initial configuration
- auto addNode = GetAddNode(jsonObject);
-
- if (addNode != nullptr && addNode.HasKey(MIDI_VIRTUAL_ENDPOINTS_ARRAY_KEY))
- {
- auto endpoints = addNode.GetNamedArray(MIDI_VIRTUAL_ENDPOINTS_ARRAY_KEY);
-
- for (auto endpointElement : endpoints)
- {
- // GetObjectW here is because wingdi redefines it to GetObject. It's a stupid preprocessor conflict
- try
- {
- auto endpoint = endpointElement.GetObjectW();
-
- // auto key = endpoint.GetNamedString(MIDI_VIRTUAL_ENDPOINT_PROPERTY_KEY, L"");
- auto name = endpoint.GetNamedString(MIDI_VIRTUAL_ENDPOINT_PROPERTY_NAME, L"");
- auto uniqueIdentifier = endpoint.GetNamedString(MIDI_VIRTUAL_ENDPOINT_PROPERTY_UNIQUEID, L"");
- // auto supportsMultiClient = endpoint.GetNamedBoolean(MIDI_VIRTUAL_ENDPOINT_PROPERTY_MULTICLIENT, true);
-
- auto instanceId = TRANSPORT_MNEMONIC L"_" + uniqueIdentifier;
-
- auto description = GetStringValue(endpoint, MIDI_VIRTUAL_ENDPOINT_PROPERTY_DESCRIPTION, L"");
- auto smallImage = GetStringValue(endpoint, MIDI_VIRTUAL_ENDPOINT_PROPERTY_SMALLIMAGE, L"");
- auto largeImage = GetStringValue(endpoint, MIDI_VIRTUAL_ENDPOINT_PROPERTY_LARGEIMAGE, L"");
-
- bool multiclient = true; // TODO
- bool virtualResponder = false; // TODO
-
-
- // TODO: Need to add this to the table for routing, and also add the other properties to the function
- CreateEndpoint(
- (std::wstring)instanceId,
- (std::wstring)uniqueIdentifier,
- multiclient,
- virtualResponder,
- (std::wstring)name,
- (std::wstring)largeImage,
- (std::wstring)smallImage,
- (std::wstring)description
- );
- }
- catch (...)
- {
- // couldn't get an object. Garbage data
- OutputDebugString(L"" __FUNCTION__ " Exception getting endpoint properties from json");
-
- return E_FAIL;
- }
- }
- }
- else
- {
- // nothing to add
- }
-
-
- }
- catch (...)
- {
- // exception parsing the json. It's likely empty or malformed
-
- OutputDebugString(L"" __FUNCTION__ " Exception parsing JSON. Json string follows.");
- OutputDebugString(ConfigurationJson.c_str());
-
- TraceLoggingWrite(
- MidiVirtualPatchBayAbstractionTelemetryProvider::Provider(),
- __FUNCTION__,
- TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
- TraceLoggingPointer(this, "this")
- );
-
- return E_FAIL;
- }
-
- return S_OK;
-}
-
-// this will be called from the runtime endpoint creation interface
-
_Use_decl_annotations_
HRESULT
CMidi2VirtualPatchBayEndpointManager::CreateEndpoint(
- std::wstring const InstanceId,
- std::wstring const UniqueId,
- bool const Multiclient,
- bool const IsVirtualEndpointResponder,
- std::wstring const Name,
- std::wstring const LargeImagePath,
- std::wstring const SmallImagePath,
- std::wstring const Description
)
{
- //put all of the devproperties we want into arrays and pass into ActivateEndpoint:
-
- std::wstring mnemonic(TRANSPORT_MNEMONIC);
- MidiFlow const flow = MidiFlow::MidiFlowBidirectional;
-
- DEVPROP_BOOLEAN devPropTrue = DEVPROP_TRUE;
- //DEVPROP_BOOLEAN devPropFalse = DEVPROP_FALSE;
-
- DEVPROP_BOOLEAN devPropMulticlient = Multiclient ? DEVPROP_TRUE : DEVPROP_FALSE;
- //DEVPROP_BOOLEAN devPropVirtualResponder = IsVirtualEndpointResponder ? DEVPROP_TRUE : DEVPROP_FALSE;
-
- uint32_t endpointPurpose{};
-
- if (IsVirtualEndpointResponder)
- {
- endpointPurpose = (uint32_t)MidiEndpointDevicePurposePropertyValue::VirtualDeviceResponder;
- }
- else
- {
- endpointPurpose = (uint32_t)MidiEndpointDevicePurposePropertyValue::NormalMessageEndpoint;
- }
-
- BYTE nativeDataFormat = MIDI_PROP_NATIVEDATAFORMAT_UMP;
-
- DEVPROPERTY interfaceDevProperties[] = {
- {{DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((Name.length() + 1) * sizeof(WCHAR)), (PVOID)Name.c_str()},
-
- // essential to instantiate the right endpoint types
- {{PKEY_MIDI_AbstractionLayer, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_GUID, static_cast(sizeof(GUID)), (PVOID)&AbstractionLayerGUID },
-
- {{PKEY_MIDI_TransportMnemonic, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((mnemonic.length() + 1) * sizeof(WCHAR)), (PVOID)mnemonic.c_str()},
-
- {{PKEY_MIDI_NativeDataFormat, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BYTE, static_cast(sizeof(BYTE)), (PVOID)&nativeDataFormat},
-
- //{{PKEY_MIDI_UniqueIdentifier, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_STRING, static_cast((UniqueId.length() + 1) * sizeof(WCHAR)), (PVOID)UniqueId.c_str()},
-
- {{PKEY_MIDI_SupportsMulticlient, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropMulticlient)), (PVOID)&devPropMulticlient},
-
- {{PKEY_MIDI_TransportSuppliedEndpointName, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((Name.length() + 1) * sizeof(WCHAR)), (PVOID)Name.c_str()},
-
- {{PKEY_MIDI_EndpointDevicePurpose, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_UINT32, static_cast(sizeof(endpointPurpose)),(PVOID)&endpointPurpose},
-
-
- {{PKEY_MIDI_UserSuppliedLargeImagePath, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((LargeImagePath.length() + 1) * sizeof(WCHAR)), (PVOID)LargeImagePath.c_str() },
-
- {{PKEY_MIDI_UserSuppliedSmallImagePath, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((SmallImagePath.length() + 1) * sizeof(WCHAR)), (PVOID)SmallImagePath.c_str() },
-
- {{PKEY_MIDI_UserSuppliedDescription, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((Description.length() + 1) * sizeof(WCHAR)), (PVOID)Description.c_str() },
-
- {{PKEY_MIDI_UserSuppliedEndpointName, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((Name.length() + 1) * sizeof(WCHAR)), (PVOID)Name.c_str() }
- };
-
-
-
- // Additional metadata properties added here to avoid having to add them in every transport
-// and to ensure they are registered under the same identity that is creating the device
-// Several of these are later updated through discovery, user-supplied json metadata, etc.
- //DEVPROP_BOOLEAN devPropFalse = DEVPROP_FALSE;
- //uint8_t zeroByte = 0;
-
- //std::wstring emptyString = L"";
-
- //interfaceProperties.push_back({ {PKEY_MIDI_SupportsMultiClient, DEVPROP_STORE_SYSTEM, nullptr },
- // DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropTrue)), &devPropTrue });
-
- //// from endpoint discovery ============
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointSupportsMidi2Protocol, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropFalse)), &devPropFalse });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointSupportsMidi1Protocol, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropFalse)), &devPropFalse });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointSupportsReceivingJRTimestamps, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropFalse)), &devPropFalse });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointSupportsSendingJRTimestamps, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropFalse)), &devPropFalse });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointUmpVersionMajor, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BYTE, static_cast(sizeof(zeroByte)), &zeroByte });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointUmpVersionMinor, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BYTE, static_cast(sizeof(zeroByte)), &zeroByte });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointProvidedName, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_STRING, static_cast((emptyString.length() + 1) * sizeof(WCHAR)), (PVOID)emptyString.c_str() });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_EndpointProvidedProductinstanceId, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_STRING, static_cast((emptyString.length() + 1) * sizeof(WCHAR)), (PVOID)emptyString.c_str() });
-
- //interfaceProperties.push_back({ {PKEY_MIDI_FunctionBlocksAreStatic, DEVPROP_STORE_SYSTEM, nullptr},
- // DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropFalse)),&devPropFalse });
-
- ////interfaceProperties.push_back({ {PKEY_MIDI_DeviceIdentification, DEVPROP_STORE_SYSTEM, nullptr},
- //// DEVPROP_TYPE_BINARY, static_cast(0), });
-
-
- //// from function block discovery =============================
-
- ////interfaceProperties.push_back({ {PKEY_MIDI_FunctionBlocks, DEVPROP_STORE_SYSTEM, nullptr},
- //// DEVPROP_TYPE_BINARY, static_cast(0), &functionBlockCount });
-
-
-
-
- DEVPROPERTY deviceDevProperties[] = {
- {{DEVPKEY_Device_PresenceNotForDevice, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropTrue)), &devPropTrue},
- {{DEVPKEY_Device_NoConnectSound, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(devPropTrue)),&devPropTrue}
- };
-
- SW_DEVICE_CREATE_INFO createInfo = {};
- createInfo.cbSize = sizeof(createInfo);
-
- createInfo.pszInstanceId = InstanceId.c_str();
- createInfo.CapabilityFlags = SWDeviceCapabilitiesNone;
- createInfo.pszDeviceDescription = Name.c_str();
-
-
- const ULONG deviceInterfaceIdMaxSize = 255;
- wchar_t newDeviceInterfaceId[deviceInterfaceIdMaxSize]{ 0 };
-
- RETURN_IF_FAILED(m_MidiDeviceManager->ActivateEndpoint(
- std::wstring(m_ParentDevice->InstanceId).c_str(), // parent instance Id
- true, // UMP-only
- flow, // MIDI Flow
- ARRAYSIZE(interfaceDevProperties),
- ARRAYSIZE(deviceDevProperties),
- (PVOID)interfaceDevProperties,
- (PVOID)deviceDevProperties,
- (PVOID)&createInfo,
- (LPWSTR)&newDeviceInterfaceId,
- deviceInterfaceIdMaxSize));
-
- OutputDebugString(__FUNCTION__ L": Created device interface id:");
- OutputDebugString(newDeviceInterfaceId);
-
- // store the created device in the device table, along with the interface id
@@ -476,48 +63,6 @@ CMidi2VirtualPatchBayEndpointManager::CreateEndpoint(
}
-
-//_Use_decl_annotations_
-//HRESULT
-//CMidi2VirtualPatchBayEndpointManager::UpdateConfiguration(LPCWSTR configurationJson)
-//{
-// UNREFERENCED_PARAMETER(configurationJson);
-//
-//
-// //if (ConfigurationJson != nullptr)
-// //{
-// // try
-// // {
-// // std::wstring json{ ConfigurationJson };
-//
-// // if (!json.empty())
-// // {
-// // m_jsonObject = json::JsonObject::Parse(json);
-//
-// // LOG_IF_FAILED(CreateConfiguredEndpoints(json));
-// // }
-// // }
-// // catch (...)
-// // {
-// // OutputDebugString(L"Exception processing json for virtual MIDI abstraction");
-//
-// // // we return S_OK here because otherwise this prevents the service from starting up.
-// // return S_OK;
-// // }
-//
-// //}
-// //else
-// //{
-// // // empty / null is fine. We just continue on.
-//
-// // OutputDebugString(L"Configuration json is null for virtual MIDI abstraction");
-//
-// // return S_OK;
-// //}
-//
-// return S_OK;
-//}
-
HRESULT
CMidi2VirtualPatchBayEndpointManager::Cleanup()
{
@@ -534,16 +79,3 @@ CMidi2VirtualPatchBayEndpointManager::Cleanup()
return S_OK;
}
-
-//
-//_Use_decl_annotations_
-//HRESULT
-//CMidi2VirtualPatchBayEndpointManager::ApplyConfiguration(
-// LPCWSTR /*configurationJson*/,
-// LPWSTR /*resultJson*/
-//)
-//{
-// return E_NOTIMPL;
-//}
-
-
diff --git a/src/api/Abstraction/VirtualPatchBayAbstraction/Midi2.VirtualPatchBayEndpointManager.h b/src/api/Abstraction/VirtualPatchBayAbstraction/Midi2.VirtualPatchBayEndpointManager.h
index 6d4e4d26..fd1ab7da 100644
--- a/src/api/Abstraction/VirtualPatchBayAbstraction/Midi2.VirtualPatchBayEndpointManager.h
+++ b/src/api/Abstraction/VirtualPatchBayAbstraction/Midi2.VirtualPatchBayEndpointManager.h
@@ -8,51 +8,6 @@
#pragma once
-typedef enum _SWDEVICESTATE
-{
- NotCreated = 0, // SwDeviceCreate not yet called
- CreatePending, // SwDeviceCreate called successfully, but creation callback not yet invoked
- Created, // SwDeviceCreate creation callback has been invoked and device interface has been created
- Failed
-} SWDEVICESTATE;
-
-
-using unique_hswdevice = wil::unique_any;
-using unique_swd_string = wil::unique_any;
-
-
-class MidiUmpEndpointInfo
-{
-public:
- std::wstring Id{}; // the filter InterfaceId
- std::wstring InstanceId{}; // the MIDI instance id
- std::wstring ParentInstanceId{}; // The instance id of the parent device
- std::wstring Name{}; // friendly name for this device
- MidiFlow Flow{ MidiFlowBidirectional };
-
- // TODO: Pointer to the interface?
-
-};
-
-class MidiEndpointParentDeviceInfo
-{
-public:
- GUID InterfaceCategory{};
- SWDEVICESTATE SwDeviceState{ SWDEVICESTATE::NotCreated }; // SWD creation state
- unique_hswdevice SwDevice{}; // Handle to the SWD created for the MIDI port
- unique_swd_string DeviceInterfaceId{}; // SWD interface ID for the MIDI port
- std::wstring InstanceId{};
- std::wstring Name{}; // friendly name for this device
-
-};
-
-typedef struct _PARENTDEVICECREATECONTEXT
-{
- MidiEndpointParentDeviceInfo* MidiParentDevice{ nullptr };
- wil::unique_event CreationCompleted{ wil::EventOptions::None };
- DEVPROPERTY* InterfaceDevProperties{ nullptr };
- ULONG IntPropertyCount{};
-} PARENTDEVICECREATECONTEXT, * PPARENTDEVICECREATECONTEXT;
// TODO: This class can implement another interface which takes in the json parameters
@@ -72,36 +27,16 @@ class CMidi2VirtualPatchBayEndpointManager :
STDMETHOD(Initialize(_In_ IUnknown*, _In_ IUnknown*));
STDMETHOD(Cleanup)();
- //STDMETHOD(ApplyConfiguration(
- // _In_ LPCWSTR configurationJson,
- // _Out_ LPWSTR resultJson
- //));
-
private:
GUID m_ContainerId{};
GUID m_TransportAbstractionId{};
HRESULT CreateEndpoint(
- _In_ std::wstring const InstanceId,
- _In_ std::wstring const UniqueId,
- _In_ bool const Multiclient,
- _In_ bool const IsVirtualEndpointResponder,
- _In_ std::wstring const Name,
- _In_ std::wstring const LargeImagePath,
- _In_ std::wstring const SmallImagePath,
- _In_ std::wstring const Description
);
- HRESULT CreateConfiguredEndpoints(_In_ std::wstring ConfigurationJson);
- HRESULT CreateParentDevice();
+ //HRESULT CreateParentDevice();
wil::com_ptr_nothrow m_MidiDeviceManager;
- // TBD if we need to keep this here as well. The MidiDeviceManager has its own vector of endpoints
- std::vector> m_AvailableMidiUmpEndpoints;
-
- std::unique_ptr m_ParentDevice{ nullptr };
-
- json::JsonObject m_JsonObject{ nullptr };
};
diff --git a/src/api/Abstraction/VirtualPatchBayAbstraction/pch.h b/src/api/Abstraction/VirtualPatchBayAbstraction/pch.h
index 133b72d9..c159d2d1 100644
--- a/src/api/Abstraction/VirtualPatchBayAbstraction/pch.h
+++ b/src/api/Abstraction/VirtualPatchBayAbstraction/pch.h
@@ -67,7 +67,6 @@ namespace json = ::winrt::Windows::Data::Json;
// AbstractionUtilities
#include "endpoint_data_helpers.h"
#include "swd_property_builders.h"
-#include "swd_property_helpers.h"
#include "json_helpers.h"
#include "MidiDefs.h"
diff --git a/src/api/Client/Midi2Client/pch.h b/src/api/Client/Midi2Client/pch.h
index 05f123f2..d49afd87 100644
--- a/src/api/Client/Midi2Client/pch.h
+++ b/src/api/Client/Midi2Client/pch.h
@@ -49,7 +49,6 @@ namespace json = ::winrt::Windows::Data::Json;
// AbstractionUtilities
#include "endpoint_data_helpers.h"
#include "swd_property_builders.h"
-#include "swd_property_helpers.h"
#include "json_helpers.h"
// shared
diff --git a/src/api/Inc/MidiDefs.h b/src/api/Inc/MidiDefs.h
index e91c8349..32b22944 100644
--- a/src/api/Inc/MidiDefs.h
+++ b/src/api/Inc/MidiDefs.h
@@ -1,4 +1,11 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License
+// ============================================================================
+// This is part of the Windows MIDI Services App API and should be used
+// in your Windows application via an official binary distribution.
+// Further information: https://github.com/microsoft/MIDI/
+// ============================================================================
+
#pragma once
@@ -153,17 +160,6 @@ DEFINE_MIDIDEVPROPKEY(PKEY_MIDI_SerialNumber, 53); // DEVPROP_TYPE_STRING
// Major Known Endpoint Types =====================================================================
// Starts at 100
-// If you change these, you should also update
-// the WinRT MidiEndpointDevicePurpose enum, which is projected through the API
-enum MidiEndpointDevicePurposePropertyValue
-{
- NormalMessageEndpoint = 0,
- VirtualDeviceResponder = 100,
- InBoxGeneralMidiSynth = 400,
- DiagnosticLoopback = 500,
- DiagnosticPing = 510,
-};
-
// Valid values are in MidiEndpointDevicePurposePropertyValue
#define STRING_PKEY_MIDI_EndpointDevicePurpose MIDI_STRING_PKEY_GUID MIDI_STRING_PKEY_PID_SEPARATOR L"100"
DEFINE_MIDIDEVPROPKEY(PKEY_MIDI_EndpointDevicePurpose, 100); // DEVPROP_TYPE_ uint32
diff --git a/src/api/Inc/MidiKS.h b/src/api/Inc/MidiKS.h
index 8939e1b6..601fd146 100644
--- a/src/api/Inc/MidiKS.h
+++ b/src/api/Inc/MidiKS.h
@@ -1,4 +1,11 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License
+// ============================================================================
+// This is part of the Windows MIDI Services App API and should be used
+// in your Windows application via an official binary distribution.
+// Further information: https://github.com/microsoft/MIDI/
+// ============================================================================
+
#pragma once
// copied from wdm.h
diff --git a/src/api/Inc/MidiKSCommon.h b/src/api/Inc/MidiKSCommon.h
index 8f6844d1..0d402992 100644
--- a/src/api/Inc/MidiKSCommon.h
+++ b/src/api/Inc/MidiKSCommon.h
@@ -1,4 +1,11 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License
+// ============================================================================
+// This is part of the Windows MIDI Services App API and should be used
+// in your Windows application via an official binary distribution.
+// Further information: https://github.com/microsoft/MIDI/
+// ============================================================================
+
#pragma once
diff --git a/src/api/Inc/MidiKSDef.h b/src/api/Inc/MidiKSDef.h
index 1ef1a141..391b3569 100644
--- a/src/api/Inc/MidiKSDef.h
+++ b/src/api/Inc/MidiKSDef.h
@@ -1,4 +1,11 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License
+// ============================================================================
+// This is part of the Windows MIDI Services App API and should be used
+// in your Windows application via an official binary distribution.
+// Further information: https://github.com/microsoft/MIDI/
+// ============================================================================
+
#pragma once
diff --git a/src/api/Inc/MidiXProc.h b/src/api/Inc/MidiXProc.h
index d3d5c554..8855944d 100644
--- a/src/api/Inc/MidiXProc.h
+++ b/src/api/Inc/MidiXProc.h
@@ -1,4 +1,11 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License
+// ============================================================================
+// This is part of the Windows MIDI Services App API and should be used
+// in your Windows application via an official binary distribution.
+// Further information: https://github.com/microsoft/MIDI/
+// ============================================================================
+
#pragma once
using unique_mmcss_handle = wil::unique_any;
diff --git a/src/api/Inc/loopback_ids.h b/src/api/Inc/loopback_ids.h
index 9fc12b84..1732aee3 100644
--- a/src/api/Inc/loopback_ids.h
+++ b/src/api/Inc/loopback_ids.h
@@ -1,3 +1,11 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License
+// ============================================================================
+// This is part of the Windows MIDI Services App API and should be used
+// in your Windows application via an official binary distribution.
+// Further information: https://github.com/microsoft/MIDI/
+// ============================================================================
+
#pragma once
#define MIDI_DIAGNOSTICS_LOOPBACK_BIDI_ID_A L"\\\\?\\SWD#MIDISRV#MIDIU_DIAG_LOOPBACK_A#{e7cce071-3c03-423f-88d3-f1045d02552b}"
diff --git a/src/api/Inc/midi_timestamp.h b/src/api/Inc/midi_timestamp.h
index 0f9fb2bd..bae87b53 100644
--- a/src/api/Inc/midi_timestamp.h
+++ b/src/api/Inc/midi_timestamp.h
@@ -1,3 +1,11 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License
+// ============================================================================
+// This is part of the Windows MIDI Services App API and should be used
+// in your Windows application via an official binary distribution.
+// Further information: https://github.com/microsoft/MIDI/
+// ============================================================================
+
#pragma once
#include
diff --git a/src/api/Inc/midi_ump.h b/src/api/Inc/midi_ump.h
index 6b5904e3..c8ff4c4f 100644
--- a/src/api/Inc/midi_ump.h
+++ b/src/api/Inc/midi_ump.h
@@ -1,3 +1,11 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License
+// ============================================================================
+// This is part of the Windows MIDI Services App API and should be used
+// in your Windows application via an official binary distribution.
+// Further information: https://github.com/microsoft/MIDI/
+// ============================================================================
+
#pragma once
#include
diff --git a/src/api/Libs/AbstractionUtilities/AbstractionUtilities.vcxproj b/src/api/Libs/AbstractionUtilities/AbstractionUtilities.vcxproj
index 0fe62fc4..1b3209bf 100644
--- a/src/api/Libs/AbstractionUtilities/AbstractionUtilities.vcxproj
+++ b/src/api/Libs/AbstractionUtilities/AbstractionUtilities.vcxproj
@@ -170,9 +170,9 @@
+
-
@@ -185,6 +185,7 @@
Create
+
diff --git a/src/api/Libs/AbstractionUtilities/AbstractionUtilities.vcxproj.filters b/src/api/Libs/AbstractionUtilities/AbstractionUtilities.vcxproj.filters
index 8e128b2d..912f99c2 100644
--- a/src/api/Libs/AbstractionUtilities/AbstractionUtilities.vcxproj.filters
+++ b/src/api/Libs/AbstractionUtilities/AbstractionUtilities.vcxproj.filters
@@ -27,7 +27,7 @@
Header Files
-
+
Header Files
@@ -47,5 +47,8 @@
Source Files
+
+ Source Files
+
\ No newline at end of file
diff --git a/src/api/Libs/AbstractionUtilities/inc/swd_property_builders.h b/src/api/Libs/AbstractionUtilities/inc/swd_property_builders.h
index c7a7b9d7..6b3a456c 100644
--- a/src/api/Libs/AbstractionUtilities/inc/swd_property_builders.h
+++ b/src/api/Libs/AbstractionUtilities/inc/swd_property_builders.h
@@ -17,26 +17,6 @@
namespace Windows::Devices::Midi2::Internal
{
- DEVPROPERTY BuildWStringDevProperty(
- _In_ DEVPROPKEY const key,
- _In_ std::wstring const& value);
-
- DEVPROPERTY BuildUInt32DevProperty(
- _In_ DEVPROPKEY const key,
- _In_ uint32_t const& value);
-
- DEVPROPERTY BuildByteDevProperty(
- _In_ DEVPROPKEY const key,
- _In_ uint8_t const& value);
-
- DEVPROPERTY BuildGuidDevProperty(
- _In_ DEVPROPKEY const key,
- _In_ GUID const& value);
-
- DEVPROPERTY BuildBooleanDevProperty(
- _In_ DEVPROPKEY const key,
- _In_ bool const& value);
-
DEVPROPERTY BuildEmptyDevProperty(
_In_ DEVPROPKEY const key);
diff --git a/src/api/Libs/AbstractionUtilities/inc/swd_property_helpers.h b/src/api/Libs/AbstractionUtilities/inc/swd_property_helpers.h
deleted file mode 100644
index cae230ef..00000000
--- a/src/api/Libs/AbstractionUtilities/inc/swd_property_helpers.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License
-// ============================================================================
-// This is part of the Windows MIDI Services App API and should be used
-// in your Windows application via an official binary distribution.
-// Further information: https://github.com/microsoft/MIDI/
-// ============================================================================
-
-#pragma once
-
-#ifndef SWD_PROPERTY_HELPERS_H
-#define SWD_PROPERTY_HELPERS_H
-
-#include "MidiDefs.h"
-#include "MidiDataFormat.h"
-
-namespace Windows::Devices::Midi2::Internal
-{
- bool AddStandardEndpointProperties(
- _In_ std::vector& interfaceDeviceProperties,
-
- _In_ GUID const& abstractionLayerGuid,
- _In_ MidiEndpointDevicePurposePropertyValue const& endpointPurpose,
-
- _In_ std::wstring const& friendlyName,
-
- _In_ std::wstring const& transportMnemonic,
- _In_ std::wstring const& transportSuppliedEndpointName,
- _In_ std::wstring const& transportSuppliedEndpointDescription,
-
- _In_ std::wstring const& userSuppliedEndpointName,
- _In_ std::wstring const& userSuppliedEndpointDescription,
-
- _In_ std::wstring const& uniqueIdentifier,
-
- _In_ MidiDataFormat const& supportedDataFormats,
- _In_ BYTE const& nativeDataFormat,
-
- _In_ bool const& supportsMultiClient,
- _In_ bool const& requiresMetadataHandler,
- _In_ bool const& generateIncomingTimestamps
- );
-
-
-}
-
-#endif
\ No newline at end of file
diff --git a/src/api/Libs/AbstractionUtilities/inc/swd_shared.h b/src/api/Libs/AbstractionUtilities/inc/swd_shared.h
new file mode 100644
index 00000000..1a100b14
--- /dev/null
+++ b/src/api/Libs/AbstractionUtilities/inc/swd_shared.h
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License
+// ============================================================================
+// This is part of the Windows MIDI Services App API and should be used
+// in your Windows application via an official binary distribution.
+// Further information: https://github.com/microsoft/MIDI/
+// ============================================================================
+
+
+#include
+#include
+
+
+#pragma once
+
+namespace Windows::Devices::Midi2::Internal
+{
+
+ std::wstring GetSwdStringProperty(_In_ std::wstring deviceInterfaceId, _In_ std::wstring propertyName, _In_ std::wstring defaultValue);
+
+ std::wstring GetSwdPropertyVirtualEndpointAssociationId(_In_ std::wstring deviceInterfaceId);
+
+ std::wstring GetSwdPropertyInstanceId(_In_ std::wstring deviceInterfaceId);
+}
\ No newline at end of file
diff --git a/src/api/Libs/AbstractionUtilities/src/pch.h b/src/api/Libs/AbstractionUtilities/src/pch.h
index d313325c..b8fd2bd2 100644
--- a/src/api/Libs/AbstractionUtilities/src/pch.h
+++ b/src/api/Libs/AbstractionUtilities/src/pch.h
@@ -18,7 +18,6 @@
#include
-
#include
#include
@@ -53,8 +52,8 @@ namespace internal = ::Windows::Devices::Midi2::Internal;
#include "endpoint_data_helpers.h"
#include "swd_property_builders.h"
-#include "swd_property_helpers.h"
#include "json_helpers.h"
+#include "swd_shared.h"
#endif //PCH_H
diff --git a/src/api/Libs/AbstractionUtilities/src/swd_property_builders.cpp b/src/api/Libs/AbstractionUtilities/src/swd_property_builders.cpp
index fa51c4c5..04647332 100644
--- a/src/api/Libs/AbstractionUtilities/src/swd_property_builders.cpp
+++ b/src/api/Libs/AbstractionUtilities/src/swd_property_builders.cpp
@@ -10,49 +10,6 @@
namespace Windows::Devices::Midi2::Internal
{
- _Use_decl_annotations_
- DEVPROPERTY BuildWStringDevProperty(DEVPROPKEY const key, std::wstring const& value)
- {
- auto cleanValue = internal::TrimmedWStringCopy(value);
-
- return DEVPROPERTY{ {key, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_STRING, static_cast((cleanValue.length() + 1) * sizeof(WCHAR)), (PVOID)cleanValue.c_str() };
- }
-
- _Use_decl_annotations_
- DEVPROPERTY BuildUInt32DevProperty(DEVPROPKEY const key, uint32_t const& value)
- {
-
- return DEVPROPERTY{ {key, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_UINT32, static_cast(sizeof(value)), (PVOID)&value };
- }
-
- _Use_decl_annotations_
- DEVPROPERTY BuildByteDevProperty(DEVPROPKEY const key, uint8_t const& value)
- {
-
- return DEVPROPERTY{ {key, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BYTE, static_cast(sizeof(value)), (PVOID)&value };
- }
-
- _Use_decl_annotations_
- DEVPROPERTY BuildGuidDevProperty(DEVPROPKEY const key, GUID const& value)
- {
-
- return DEVPROPERTY{ {key, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_GUID, static_cast(sizeof(GUID)), (PVOID)&value };
- }
-
- _Use_decl_annotations_
- DEVPROPERTY BuildBooleanDevProperty(DEVPROPKEY const key, bool const& value)
- {
- DEVPROP_BOOLEAN propVal = value ? DEVPROP_TRUE : DEVPROP_FALSE;
-
- return DEVPROPERTY{ {key, DEVPROP_STORE_SYSTEM, nullptr},
- DEVPROP_TYPE_BOOLEAN, static_cast(sizeof(propVal)), (PVOID)&propVal };
-
- }
-
_Use_decl_annotations_
DEVPROPERTY BuildEmptyDevProperty(DEVPROPKEY const key)
{
@@ -60,9 +17,4 @@ namespace Windows::Devices::Midi2::Internal
DEVPROP_TYPE_EMPTY, 0, nullptr };
}
-
-
-
-
-
}
diff --git a/src/api/Libs/AbstractionUtilities/src/swd_property_helpers.cpp b/src/api/Libs/AbstractionUtilities/src/swd_property_helpers.cpp
index 800d7c8d..9d9cf050 100644
--- a/src/api/Libs/AbstractionUtilities/src/swd_property_helpers.cpp
+++ b/src/api/Libs/AbstractionUtilities/src/swd_property_helpers.cpp
@@ -12,81 +12,48 @@
namespace Windows::Devices::Midi2::Internal
{
-
-
-
-
-
-
+ // NOTE: The parameters in here are all passed to the API by ref, so the
+ // calling code needs to keep them around until the device creation returns.
_Use_decl_annotations_
bool AddStandardEndpointProperties(
- std::vector& interfaceDeviceProperties,
-
- GUID const& abstractionLayerGuid,
- MidiEndpointDevicePurposePropertyValue const& endpointPurpose,
- std::wstring const& friendlyName,
-
- std::wstring const& transportMnemonic,
- std::wstring const& transportSuppliedEndpointName,
- std::wstring const& transportSuppliedEndpointDescription,
-
- std::wstring const& userSuppliedEndpointName,
- std::wstring const& userSuppliedEndpointDescription,
-
- std::wstring const& uniqueIdentifier,
-
- MidiDataFormat const& supportedDataFormats,
- BYTE const& nativeDataFormat,
-
- bool const& supportsMultiClient,
- bool const& requiresMetadataHandler,
- bool const& generateIncomingTimestamps
)
{
try
{
- interfaceDeviceProperties.push_back(BuildGuidDevProperty(PKEY_MIDI_AbstractionLayer, abstractionLayerGuid));
- interfaceDeviceProperties.push_back(BuildUInt32DevProperty(PKEY_MIDI_EndpointDevicePurpose, endpointPurpose));
-
- interfaceDeviceProperties.push_back(BuildWStringDevProperty(DEVPKEY_DeviceInterface_FriendlyName, friendlyName));
-
- // transport information
+ //interfaceDeviceProperties.push_back(BuildGuidDevProperty(PKEY_MIDI_AbstractionLayer, abstractionLayerGuid));
+ //interfaceDeviceProperties.push_back(BuildUInt32DevProperty(PKEY_MIDI_EndpointDevicePurpose, endpointPurpose));
- interfaceDeviceProperties.push_back(BuildWStringDevProperty(PKEY_MIDI_TransportMnemonic, transportMnemonic));
- interfaceDeviceProperties.push_back(BuildWStringDevProperty(PKEY_MIDI_TransportSuppliedEndpointName, transportSuppliedEndpointName));
- interfaceDeviceProperties.push_back(BuildWStringDevProperty(PKEY_MIDI_TransportSuppliedDescription, transportSuppliedEndpointDescription));
+ //interfaceDeviceProperties.push_back(BuildWStringDevProperty(DEVPKEY_DeviceInterface_FriendlyName, friendlyName));
- interfaceDeviceProperties.push_back(BuildWStringDevProperty(PKEY_MIDI_SerialNumber, uniqueIdentifier));
+ ////// transport information
+ //interfaceDeviceProperties.push_back(BuildWStringDevProperty(PKEY_MIDI_TransportMnemonic, transportMnemonic));
+ //interfaceDeviceProperties.push_back(BuildWStringDevProperty(PKEY_MIDI_TransportSuppliedEndpointName, transportSuppliedEndpointName));
+ //interfaceDeviceProperties.push_back(BuildWStringDevProperty(PKEY_MIDI_TransportSuppliedDescription, transportSuppliedEndpointDescription));
- // user-supplied information, if available
+ //interfaceDeviceProperties.push_back(BuildWStringDevProperty(PKEY_MIDI_SerialNumber, uniqueIdentifier));
- if (!userSuppliedEndpointName.empty())
- {
- interfaceDeviceProperties.push_back(BuildWStringDevProperty(PKEY_MIDI_UserSuppliedEndpointName, userSuppliedEndpointName));
- }
- if (!userSuppliedEndpointDescription.empty())
- {
- interfaceDeviceProperties.push_back(BuildWStringDevProperty(PKEY_MIDI_UserSuppliedDescription, userSuppliedEndpointDescription));
- }
+ //// user-supplied information, if available
+ //interfaceDeviceProperties.push_back(BuildWStringDevProperty(PKEY_MIDI_UserSuppliedEndpointName, userSuppliedEndpointName));
+ //interfaceDeviceProperties.push_back(BuildWStringDevProperty(PKEY_MIDI_UserSuppliedDescription, userSuppliedEndpointDescription));
- // data format. These each have different uses. Native format is the device's format. Supported
- // format is how we talk to it from the service (the driver may translate to UMP, for example)
- interfaceDeviceProperties.push_back(BuildByteDevProperty(PKEY_MIDI_NativeDataFormat, nativeDataFormat));
- interfaceDeviceProperties.push_back(BuildUInt32DevProperty(PKEY_MIDI_SupportedDataFormats, supportedDataFormats));
+ //// data format. These each have different uses. Native format is the device's format. Supported
+ //// format is how we talk to it from the service (the driver may translate to UMP, for example)
- // behavior
+ //interfaceDeviceProperties.push_back(BuildByteDevProperty(PKEY_MIDI_NativeDataFormat, nativeDataFormat));
+ //interfaceDeviceProperties.push_back(BuildUInt32DevProperty(PKEY_MIDI_SupportedDataFormats, supportedDataFormats));
- interfaceDeviceProperties.push_back(BuildBooleanDevProperty(PKEY_MIDI_GenerateIncomingTimestamp, generateIncomingTimestamps));
- interfaceDeviceProperties.push_back(BuildBooleanDevProperty(PKEY_MIDI_EndpointRequiresMetadataHandler, requiresMetadataHandler));
+ //// behavior
+ //interfaceDeviceProperties.push_back(BuildBooleanDevProperty(PKEY_MIDI_GenerateIncomingTimestamp, generateIncomingTimestamps));
+ //interfaceDeviceProperties.push_back(BuildBooleanDevProperty(PKEY_MIDI_EndpointRequiresMetadataHandler, requiresMetadataHandler));
- interfaceDeviceProperties.push_back(BuildBooleanDevProperty(PKEY_MIDI_SupportsMulticlient, supportsMultiClient));
+ //interfaceDeviceProperties.push_back(BuildBooleanDevProperty(PKEY_MIDI_SupportsMulticlient, supportsMultiClient));
return true;
}
diff --git a/src/api/Libs/AbstractionUtilities/src/swd_shared.cpp b/src/api/Libs/AbstractionUtilities/src/swd_shared.cpp
new file mode 100644
index 00000000..385f46c5
--- /dev/null
+++ b/src/api/Libs/AbstractionUtilities/src/swd_shared.cpp
@@ -0,0 +1,66 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License
+// ============================================================================
+// This is part of the Windows MIDI Services App API and should be used
+// in your Windows application via an official binary distribution.
+// Further information: https://github.com/microsoft/MIDI/
+// ============================================================================
+
+
+#include "pch.h"
+
+#include "swd_shared.h"
+
+namespace Windows::Devices::Midi2::Internal
+{
+
+ _Use_decl_annotations_
+ std::wstring GetStringSwdProperty(std::wstring deviceInterfaceId, std::wstring propertyName, std::wstring defaultValue)
+ {
+ auto propertyKey = winrt::to_hstring(propertyName.c_str());
+
+ auto additionalProperties = winrt::single_threaded_vector();
+ additionalProperties.Append(propertyKey);
+
+
+ auto deviceInfo = winrt::Windows::Devices::Enumeration::DeviceInformation::CreateFromIdAsync(
+ winrt::to_hstring(deviceInterfaceId.c_str()),
+ additionalProperties,
+ winrt::Windows::Devices::Enumeration::DeviceInformationKind::DeviceInterface).get();
+
+ auto prop = deviceInfo.Properties().Lookup(propertyKey);
+
+ if (prop)
+ {
+ OutputDebugString(__FUNCTION__ L" found property");
+
+ // this interface is pointing to a UMP interface, so use that instance id.
+ return (winrt::unbox_value(prop)).c_str();
+ }
+ else
+ {
+ OutputDebugString(__FUNCTION__ L" didn't find property");
+ // default to any
+ return defaultValue;
+ }
+
+ }
+
+
+ _Use_decl_annotations_
+ std::wstring GetSwdPropertyVirtualEndpointAssociationId(std::wstring deviceInterfaceId)
+ {
+ std::wstring cleanId = internal::NormalizeEndpointInterfaceIdWStringCopy(deviceInterfaceId);
+
+ return internal::ToUpperTrimmedWStringCopy(GetStringSwdProperty(cleanId, STRING_PKEY_MIDI_VirtualMidiEndpointAssociator, L""));
+ }
+
+
+ _Use_decl_annotations_
+ std::wstring GetSwdPropertyInstanceId(std::wstring deviceInterfaceId)
+ {
+ std::wstring cleanId = internal::NormalizeEndpointInterfaceIdWStringCopy(deviceInterfaceId);
+
+ return internal::NormalizeDeviceInstanceIdWStringCopy(GetStringSwdProperty(cleanId, L"System.Devices.DeviceInstanceId", L""));
+ }
+}
\ No newline at end of file
diff --git a/src/api/Service/Exe/MidiDeviceManager.cpp b/src/api/Service/Exe/MidiDeviceManager.cpp
index 5990cee5..cbe03a21 100644
--- a/src/api/Service/Exe/MidiDeviceManager.cpp
+++ b/src/api/Service/Exe/MidiDeviceManager.cpp
@@ -344,9 +344,6 @@ CMidiDeviceManager::ActivateVirtualParentDevice
return S_OK;
}
-
-
-
_Use_decl_annotations_
HRESULT
CMidiDeviceManager::ActivateEndpoint
@@ -354,13 +351,14 @@ CMidiDeviceManager::ActivateEndpoint
PCWSTR ParentInstanceId,
BOOL UMPOnly,
MidiFlow MidiFlow,
+ PMIDIENDPOINTCOMMONPROPERTIES CommonProperties,
ULONG IntPropertyCount,
ULONG DevPropertyCount,
PVOID InterfaceDevProperties,
PVOID DeviceDevProperties,
PVOID CreateInfo,
PWSTR CreatedDeviceInterfaceId,
- ULONG CreatedDeviceInterfaceIdCharCount
+ ULONG CreatedDeviceInterfaceIdWCharCount
)
{
TraceLoggingWrite(
@@ -385,9 +383,9 @@ CMidiDeviceManager::ActivateEndpoint
return false;
}) != m_MidiPorts.end();
- if (CreatedDeviceInterfaceId != nullptr && CreatedDeviceInterfaceIdCharCount > 0)
+ if (CreatedDeviceInterfaceId != nullptr && CreatedDeviceInterfaceIdWCharCount > 0)
{
- CreatedDeviceInterfaceId[CreatedDeviceInterfaceIdCharCount - 1] = (wchar_t)0;
+ CreatedDeviceInterfaceId[CreatedDeviceInterfaceIdWCharCount - 1] = (wchar_t)0;
}
@@ -397,6 +395,103 @@ CMidiDeviceManager::ActivateEndpoint
}
else
{
+ std::vector allInterfaceProperties{};
+
+ if (IntPropertyCount > 0)
+ {
+ // copy the incoming array into a vector so that we can add additional items.
+ std::vector suppliedInterfaceProperties((DEVPROPERTY*)InterfaceDevProperties, (DEVPROPERTY*)(InterfaceDevProperties) + IntPropertyCount);
+
+ // copy to the main vector that we're going to keep using. There's
+ // probably a better way to do both init and move in a single step
+ // without having two vectors.
+ allInterfaceProperties.insert(
+ allInterfaceProperties.begin(),
+ suppliedInterfaceProperties.begin(),
+ suppliedInterfaceProperties.end()
+ );
+ }
+
+ DEVPROP_BOOLEAN devPropTrue = DEVPROP_TRUE;
+ DEVPROP_BOOLEAN devPropFalse = DEVPROP_FALSE;
+
+
+ // Build common properties so these are consistent from endpoint to endpoint
+ if (CommonProperties != nullptr)
+ {
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_AbstractionLayer, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_GUID, (ULONG)(sizeof(GUID)), (PVOID)(&CommonProperties->AbstractionLayerGuid) });
+
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_EndpointDevicePurpose, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_UINT32, (ULONG)(sizeof(UINT32)), (PVOID)(&CommonProperties->EndpointPurpose) });
+
+ if (CommonProperties->FriendlyName != nullptr && wcslen(CommonProperties->FriendlyName) != 0)
+ {
+ allInterfaceProperties.push_back(DEVPROPERTY{ {DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_STRING, (ULONG)(sizeof(wchar_t) * (wcslen(CommonProperties->FriendlyName) + 1)), (PVOID)CommonProperties->FriendlyName });
+ }
+
+ // transport information
+
+ if (CommonProperties->TransportMnemonic != nullptr && wcslen(CommonProperties->TransportMnemonic) != 0)
+ {
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_TransportMnemonic, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_STRING, (ULONG)(sizeof(wchar_t) * (wcslen(CommonProperties->TransportMnemonic) + 1)), (PVOID)CommonProperties->TransportMnemonic });
+ }
+
+ if (CommonProperties->TransportSuppliedEndpointName != nullptr && wcslen(CommonProperties->TransportSuppliedEndpointName) != 0)
+ {
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_TransportSuppliedEndpointName, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_STRING, (ULONG)(sizeof(wchar_t) * (wcslen(CommonProperties->TransportSuppliedEndpointName) + 1)), (PVOID)CommonProperties->TransportSuppliedEndpointName });
+ }
+
+ if (CommonProperties->TransportSuppliedEndpointDescription != nullptr && wcslen(CommonProperties->TransportSuppliedEndpointDescription) != 0)
+ {
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_TransportSuppliedDescription, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_STRING, (ULONG)(sizeof(wchar_t) * (wcslen(CommonProperties->TransportSuppliedEndpointDescription) + 1)), (PVOID)CommonProperties->TransportSuppliedEndpointDescription });
+ }
+
+ if (CommonProperties->UniqueIdentifier != nullptr && wcslen(CommonProperties->UniqueIdentifier) != 0)
+ {
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_SerialNumber, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_STRING, (ULONG)(sizeof(wchar_t) * (wcslen(CommonProperties->UniqueIdentifier) + 1)), (PVOID)CommonProperties->UniqueIdentifier });
+ }
+
+ // user-supplied information, if available
+
+ if (CommonProperties->UserSuppliedEndpointName != nullptr && wcslen(CommonProperties->UserSuppliedEndpointName) != 0)
+ {
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_UserSuppliedEndpointName, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_STRING, (ULONG)(sizeof(wchar_t) * (wcslen(CommonProperties->UserSuppliedEndpointName) + 1)), (PVOID)CommonProperties->UserSuppliedEndpointName });
+ }
+
+ if (CommonProperties->UserSuppliedEndpointDescription != nullptr && wcslen(CommonProperties->UserSuppliedEndpointDescription) != 0)
+ {
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_UserSuppliedDescription, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_STRING, (ULONG)(sizeof(wchar_t) * (wcslen(CommonProperties->UserSuppliedEndpointDescription) + 1)), (PVOID)CommonProperties->UserSuppliedEndpointDescription });
+ }
+
+ // data format. These each have different uses. Native format is the device's format. Supported
+ // format is how we talk to it from the service (the driver may translate to UMP, for example)
+
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_NativeDataFormat, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_BYTE, (ULONG)(sizeof(BYTE)), (PVOID)(&CommonProperties->NativeDataFormat) });
+
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_SupportedDataFormats, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_UINT32, (ULONG)(sizeof(UINT32)), (PVOID)(&CommonProperties->SupportedDataFormats) });
+
+ // behavior
+
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_GenerateIncomingTimestamp, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_BOOLEAN, (ULONG)(sizeof(DEVPROP_BOOLEAN)), (PVOID)(CommonProperties->GenerateIncomingTimestamps ? &devPropTrue : &devPropFalse) });
+
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_EndpointRequiresMetadataHandler, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_BOOLEAN, (ULONG)(sizeof(DEVPROP_BOOLEAN)), (PVOID)(CommonProperties->RequiresMetadataHandler ? &devPropTrue : &devPropFalse) });
+
+ allInterfaceProperties.push_back(DEVPROPERTY{ {PKEY_MIDI_SupportsMulticlient, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_BOOLEAN, (ULONG)(sizeof(DEVPROP_BOOLEAN)), (PVOID)(CommonProperties->SupportsMultiClient ? &devPropTrue : &devPropFalse) });
+ }
+
std::wstring deviceInterfaceId{ 0 };
auto cleanupOnFailure = wil::scope_exit([&]()
@@ -406,7 +501,17 @@ CMidiDeviceManager::ActivateEndpoint
});
// Activate the UMP version of this endpoint.
- RETURN_IF_FAILED(ActivateEndpointInternal(ParentInstanceId, nullptr, FALSE, MidiFlow, IntPropertyCount, DevPropertyCount, (DEVPROPERTY*)InterfaceDevProperties, (DEVPROPERTY*)DeviceDevProperties, (SW_DEVICE_CREATE_INFO*)CreateInfo, &deviceInterfaceId));
+ RETURN_IF_FAILED(ActivateEndpointInternal(
+ ParentInstanceId,
+ nullptr,
+ FALSE,
+ MidiFlow,
+ (ULONG)allInterfaceProperties.size(),
+ DevPropertyCount,
+ (DEVPROPERTY*)(allInterfaceProperties.data()),
+ (DEVPROPERTY*)DeviceDevProperties,
+ (SW_DEVICE_CREATE_INFO*)CreateInfo,
+ &deviceInterfaceId));
if (!UMPOnly)
{
@@ -414,23 +519,54 @@ CMidiDeviceManager::ActivateEndpoint
if (MidiFlow == MidiFlowBidirectional)
{
// if this is a bidirectional endpoint, it gets an in and an out midi 1 swd's.
- RETURN_IF_FAILED(ActivateEndpointInternal(ParentInstanceId, deviceInterfaceId.c_str(), TRUE, MidiFlowOut, IntPropertyCount, DevPropertyCount, (DEVPROPERTY*)InterfaceDevProperties, (DEVPROPERTY*)DeviceDevProperties, (SW_DEVICE_CREATE_INFO*)CreateInfo, nullptr));
- RETURN_IF_FAILED(ActivateEndpointInternal(ParentInstanceId, deviceInterfaceId.c_str(), TRUE, MidiFlowIn, IntPropertyCount, DevPropertyCount, (DEVPROPERTY*)InterfaceDevProperties, (DEVPROPERTY*)DeviceDevProperties, (SW_DEVICE_CREATE_INFO*)CreateInfo, nullptr));
+ RETURN_IF_FAILED(ActivateEndpointInternal(
+ ParentInstanceId,
+ deviceInterfaceId.c_str(),
+ TRUE,
+ MidiFlowOut,
+ (ULONG)allInterfaceProperties.size(),
+ DevPropertyCount,
+ (DEVPROPERTY*)(allInterfaceProperties.data()),
+ (DEVPROPERTY*)DeviceDevProperties,
+ (SW_DEVICE_CREATE_INFO*)CreateInfo,
+ nullptr));
+
+ RETURN_IF_FAILED(ActivateEndpointInternal(
+ ParentInstanceId,
+ deviceInterfaceId.c_str(),
+ TRUE,
+ MidiFlowIn,
+ (ULONG)allInterfaceProperties.size(),
+ DevPropertyCount,
+ (DEVPROPERTY*)(allInterfaceProperties.data()),
+ (DEVPROPERTY*)DeviceDevProperties,
+ (SW_DEVICE_CREATE_INFO*)CreateInfo,
+ nullptr));
}
else
{
- RETURN_IF_FAILED(ActivateEndpointInternal(ParentInstanceId, deviceInterfaceId.c_str(), TRUE, MidiFlow, IntPropertyCount, DevPropertyCount, (DEVPROPERTY*)InterfaceDevProperties, (DEVPROPERTY*)DeviceDevProperties, (SW_DEVICE_CREATE_INFO*)CreateInfo, nullptr));
+ RETURN_IF_FAILED(ActivateEndpointInternal(
+ ParentInstanceId,
+ deviceInterfaceId.c_str(),
+ TRUE,
+ MidiFlow,
+ (ULONG)allInterfaceProperties.size(),
+ DevPropertyCount,
+ (DEVPROPERTY*)(allInterfaceProperties.data()),
+ (DEVPROPERTY*)DeviceDevProperties,
+ (SW_DEVICE_CREATE_INFO*)CreateInfo,
+ nullptr));
}
}
// return the created device interface Id. This is needed for anything that will
// do a match in the Ids from Windows.Devices.Enumeration
- if (CreatedDeviceInterfaceId != nullptr && CreatedDeviceInterfaceIdCharCount > 0)
+ if (CreatedDeviceInterfaceId != nullptr && CreatedDeviceInterfaceIdWCharCount > 0)
{
//memset((byte*)CreatedDeviceInterfaceId, 0, CreatedDeviceInterfaceIdBufferSize * sizeof(wchar_t));
- deviceInterfaceId.copy(CreatedDeviceInterfaceId, CreatedDeviceInterfaceIdCharCount - 1);
+ deviceInterfaceId.copy(CreatedDeviceInterfaceId, CreatedDeviceInterfaceIdWCharCount - 1);
- CreatedDeviceInterfaceId[CreatedDeviceInterfaceIdCharCount - 1] = (wchar_t)0;
+ CreatedDeviceInterfaceId[CreatedDeviceInterfaceIdWCharCount - 1] = (wchar_t)0;
}
cleanupOnFailure.release();
@@ -461,9 +597,11 @@ CMidiDeviceManager::ActivateEndpointInternal
__FUNCTION__,
TraceLoggingLevel(WINEVENT_LEVEL_INFO),
TraceLoggingPointer(this, "this"),
- TraceLoggingWideString(ParentInstanceId),
- TraceLoggingWideString(AssociatedInstanceId),
- TraceLoggingBool(MidiOne)
+ TraceLoggingWideString(ParentInstanceId, "parent instance id"),
+ TraceLoggingWideString(AssociatedInstanceId, "associated instance id"),
+ TraceLoggingBool(MidiOne, "midi 1"),
+ TraceLoggingULong(IntPropertyCount, "interface prop count"),
+ TraceLoggingULong(DevPropertyCount, "device prop count")
);
@@ -480,6 +618,13 @@ CMidiDeviceManager::ActivateEndpointInternal
interfaceProperties.push_back({ {PKEY_MIDI_AssociatedUMP, DEVPROP_STORE_SYSTEM, nullptr},
DEVPROP_TYPE_STRING, static_cast((wcslen(AssociatedInstanceId) + 1) * sizeof(WCHAR)), (PVOID)AssociatedInstanceId });
}
+ else
+ {
+ // necessary for cases where this was previously set and cached
+
+ interfaceProperties.push_back({ {PKEY_MIDI_AssociatedUMP, DEVPROP_STORE_SYSTEM, nullptr},
+ DEVPROP_TYPE_EMPTY, 0, nullptr });
+ }
DEVPROP_BOOLEAN devPropTrue = DEVPROP_TRUE;
@@ -493,7 +638,7 @@ CMidiDeviceManager::ActivateEndpointInternal
midiPort->InstanceId = internal::NormalizeDeviceInstanceIdWStringCopy(CreateInfo->pszInstanceId);
midiPort->MidiFlow = MidiFlow;
- midiPort->Enumerator = MidiOne?AUDIO_DEVICE_ENUMERATOR : MIDI_DEVICE_ENUMERATOR;
+ midiPort->Enumerator = MidiOne ? AUDIO_DEVICE_ENUMERATOR : MIDI_DEVICE_ENUMERATOR;
if (MidiOne)
{
@@ -563,7 +708,6 @@ CMidiDeviceManager::ActivateEndpointInternal
TraceLoggingPointer(this, "this"),
TraceLoggingWideString(L"Already exists"),
TraceLoggingWideString(ParentInstanceId),
- TraceLoggingWideString(AssociatedInstanceId),
TraceLoggingBool(MidiOne)
);
@@ -586,9 +730,48 @@ CMidiDeviceManager::ActivateEndpointInternal
SwMidiPortCreateCallback(item->get()->SwDevice.get(), S_OK, &creationContext, nullptr);
}
}
+ else
+ {
+ TraceLoggingWrite(
+ MidiSrvTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(L"SwDeviceCreate failed", "message"),
+ TraceLoggingWideString(ParentInstanceId),
+ TraceLoggingBool(MidiOne)
+ );
+ }
// confirm we were able to register the interface
+
+ if (FAILED(midiPort->hr))
+ {
+ TraceLoggingWrite(
+ MidiSrvTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingHResult(midiPort->hr, "hresult"),
+ TraceLoggingWideString(L"SwDeviceCreate returned a failed HR", "message"),
+ TraceLoggingWideString(ParentInstanceId),
+ TraceLoggingBool(MidiOne)
+ );
+ }
RETURN_IF_FAILED(midiPort->hr);
+
+ if (midiPort->SwDeviceState != SWDEVICESTATE::Created)
+ {
+ TraceLoggingWrite(
+ MidiSrvTelemetryProvider::Provider(),
+ __FUNCTION__,
+ TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
+ TraceLoggingPointer(this, "this"),
+ TraceLoggingWideString(L"SwDeviceState != SWDEVICESTATE::Created", "message"),
+ TraceLoggingWideString(ParentInstanceId),
+ TraceLoggingBool(MidiOne)
+ );
+ }
RETURN_HR_IF(E_FAIL, midiPort->SwDeviceState != SWDEVICESTATE::Created);
if (DeviceInterfaceId)
diff --git a/src/api/Service/Exe/stdafx.h b/src/api/Service/Exe/stdafx.h
index 6de275e1..9e089d9c 100644
--- a/src/api/Service/Exe/stdafx.h
+++ b/src/api/Service/Exe/stdafx.h
@@ -19,6 +19,7 @@
#include
#include
+#include
#include
#include
#include
@@ -50,7 +51,6 @@
// AbstractionUtilities
#include "endpoint_data_helpers.h"
#include "swd_property_builders.h"
-#include "swd_property_helpers.h"
#include "json_helpers.h"
// Main definitions
diff --git a/src/api/Service/Inc/MidiDeviceManager.h b/src/api/Service/Inc/MidiDeviceManager.h
index 918b19ca..94f803e4 100644
--- a/src/api/Service/Inc/MidiDeviceManager.h
+++ b/src/api/Service/Inc/MidiDeviceManager.h
@@ -98,13 +98,14 @@ class CMidiDeviceManager :
_In_ PCWSTR,
_In_ BOOL,
_In_ MidiFlow,
+ _In_ PMIDIENDPOINTCOMMONPROPERTIES,
_In_ ULONG,
_In_ ULONG,
_In_ PVOID,
_In_ PVOID,
_In_ PVOID,
_Out_writes_opt_z_(CreatedSwDeviceInterfaceIdCharCount) PWSTR CreatedDeviceInterfaceId,
- _In_ ULONG CreatedSwDeviceInterfaceIdCharCount
+ _In_ ULONG CreatedSwDeviceInterfaceIdWCharCount
);
STDMETHOD(DeactivateEndpoint)(_In_ PCWSTR);
@@ -143,6 +144,7 @@ class CMidiDeviceManager :
private:
+
HRESULT ActivateEndpointInternal(
_In_ PCWSTR,
_In_opt_ PCWSTR,
diff --git a/src/api/idl/MidiDeviceManagerInterface.idl b/src/api/idl/MidiDeviceManagerInterface.idl
index 007d51d9..5804b2b3 100644
--- a/src/api/idl/MidiDeviceManagerInterface.idl
+++ b/src/api/idl/MidiDeviceManagerInterface.idl
@@ -12,6 +12,44 @@ import "unknwn.idl";
import "MidiFlow.idl";
import "MidiDataFormat.idl";
+// If you change these, you should also update
+// the WinRT MidiEndpointDevicePurpose enum, which is projected through the API
+typedef enum
+{
+ NormalMessageEndpoint = 0,
+ VirtualDeviceResponder = 100,
+ InBoxGeneralMidiSynth = 400,
+ DiagnosticLoopback = 500,
+ DiagnosticPing = 510,
+} MidiEndpointDevicePurposePropertyValue;
+
+
+// This is used when creating a device endpoint from an abstraction
+typedef struct
+{
+ GUID AbstractionLayerGuid;
+ MidiEndpointDevicePurposePropertyValue EndpointPurpose;
+
+ LPCWSTR FriendlyName;
+
+ LPCWSTR TransportMnemonic;
+ LPCWSTR TransportSuppliedEndpointName;
+ LPCWSTR TransportSuppliedEndpointDescription;
+
+ LPCWSTR UserSuppliedEndpointName;
+ LPCWSTR UserSuppliedEndpointDescription;
+
+ LPCWSTR UniqueIdentifier;
+
+ MidiDataFormat SupportedDataFormats;
+ BYTE NativeDataFormat;
+
+ BOOL SupportsMultiClient;
+ BOOL RequiresMetadataHandler;
+ BOOL GenerateIncomingTimestamps;
+} MIDIENDPOINTCOMMONPROPERTIES, *PMIDIENDPOINTCOMMONPROPERTIES;
+
+
[
object,
local,
@@ -34,13 +72,14 @@ interface IMidiDeviceManagerInterface : IUnknown
[in] LPCWSTR ParentInstanceId,
[in] BOOL UMPOnly,
[in] MidiFlow MidiFlow,
+ [in] PMIDIENDPOINTCOMMONPROPERTIES CommonProperties,
[in] ULONG IntPropertyCount,
[in] ULONG DevPropertyCount,
[in, annotation("_In_opt_")] PVOID InterfaceDevProperties,
[in, annotation("_In_opt_")] PVOID DeviceDevProperties,
[in, annotation("_In_opt_")] PVOID CreateInfo,
- [out, annotation("_Out_writes_opt_z_(CreatedSwDeviceInterfaceIdCharCount)")] LPWSTR CreatedSwDeviceInterfaceId,
- [in] ULONG CreatedSwDeviceInterfaceIdCharCount
+ [out, annotation("_Out_writes_opt_z_(CreatedSwDeviceInterfaceIdWCharCount)")] LPWSTR CreatedSwDeviceInterfaceId,
+ [in] ULONG CreatedSwDeviceInterfaceIdWCharCount
);
HRESULT UpdateEndpointProperties(