From 91fcb68e76f0f0c24d402c1224e599c229b4892f Mon Sep 17 00:00:00 2001 From: Pete Brown Date: Tue, 26 Nov 2024 00:52:22 -0500 Subject: [PATCH 01/10] Add IStringable.ToString() as well as plural constants to key types --- src/app-sdk/winrt/MidiChannel.cpp | 4 +++ src/app-sdk/winrt/MidiChannel.h | 12 ++++--- src/app-sdk/winrt/MidiChannel.idl | 5 ++- src/app-sdk/winrt/MidiEndpointConnection.cpp | 5 +++ src/app-sdk/winrt/MidiEndpointConnection.h | 2 ++ src/app-sdk/winrt/MidiEndpointConnection.idl | 3 +- .../winrt/MidiEndpointDeviceInformation.cpp | 17 +++++++++ .../winrt/MidiEndpointDeviceInformation.h | 2 ++ .../winrt/MidiEndpointDeviceInformation.idl | 2 +- src/app-sdk/winrt/MidiFunctionBlock.cpp | 34 ++++++++++++++++-- src/app-sdk/winrt/MidiFunctionBlock.h | 23 ++++++++---- src/app-sdk/winrt/MidiFunctionBlock.idl | 10 ++++-- src/app-sdk/winrt/MidiGroup.cpp | 5 ++- src/app-sdk/winrt/MidiGroup.h | 14 ++++---- src/app-sdk/winrt/MidiGroup.idl | 6 ++-- src/app-sdk/winrt/MidiGroupTerminalBlock.cpp | 28 ++++++++++++++- src/app-sdk/winrt/MidiGroupTerminalBlock.h | 25 ++++++++----- src/app-sdk/winrt/MidiGroupTerminalBlock.idl | 10 ++++-- src/app-sdk/winrt/MidiSession.cpp | 5 +++ src/app-sdk/winrt/MidiSession.h | 3 ++ src/app-sdk/winrt/MidiSession.idl | 2 +- src/app-sdk/winrt/MidiUniqueId.cpp | 5 +++ src/app-sdk/winrt/MidiUniqueId.h | 13 +++++-- src/app-sdk/winrt/MidiUniqueId.idl | 4 ++- src/app-sdk/winrt/MidiVirtualDevice.cpp | 2 +- src/app-sdk/winrt/Resources.rc | Bin 23364 -> 25240 bytes src/app-sdk/winrt/resource.h | 25 ++++++++++--- 27 files changed, 216 insertions(+), 50 deletions(-) diff --git a/src/app-sdk/winrt/MidiChannel.cpp b/src/app-sdk/winrt/MidiChannel.cpp index 82bea9c16..0176b3731 100644 --- a/src/app-sdk/winrt/MidiChannel.cpp +++ b/src/app-sdk/winrt/MidiChannel.cpp @@ -14,5 +14,9 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation { + winrt::hstring MidiChannel::ToString() + { + return winrt::to_hstring(std::format("{} {}", winrt::to_string(midi2::MidiChannel::ShortLabel()), DisplayValue())); + } } diff --git a/src/app-sdk/winrt/MidiChannel.h b/src/app-sdk/winrt/MidiChannel.h index 947ea8d2c..7f56a0ee4 100644 --- a/src/app-sdk/winrt/MidiChannel.h +++ b/src/app-sdk/winrt/MidiChannel.h @@ -14,19 +14,23 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation { struct MidiChannel : MidiChannelT { - //MidiChannel() = default; + static winrt::hstring ShortLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_CHANNEL_SHORT); } + static winrt::hstring ShortLabelPlural() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_CHANNEL_SHORT_PLURAL); } + static winrt::hstring LongLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_CHANNEL_FULL); } + static winrt::hstring LongLabelPlural() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_CHANNEL_FULL_PLURAL); } + + MidiChannel() noexcept { Index(0); } MidiChannel(_In_ uint8_t index) noexcept { Index(index); } uint8_t Index() const noexcept { return m_index; } void Index(_In_ uint8_t value) noexcept { m_index = (value & 0x0F); } - static winrt::hstring ShortLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_CHANNEL_SHORT); } - static winrt::hstring LongLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_CHANNEL_FULL); } - uint8_t DisplayValue() const noexcept { return m_index + 1; } static bool IsValidIndex(_In_ uint8_t const index) noexcept { return index >= 0 && index <= 15; } + // IStringable + winrt::hstring ToString(); private: uint8_t m_index{ 0 }; diff --git a/src/app-sdk/winrt/MidiChannel.idl b/src/app-sdk/winrt/MidiChannel.idl index 95a18a291..58c626f0b 100644 --- a/src/app-sdk/winrt/MidiChannel.idl +++ b/src/app-sdk/winrt/MidiChannel.idl @@ -10,12 +10,15 @@ namespace Microsoft.Windows.Devices.Midi2 { [default_interface] - runtimeclass MidiChannel + runtimeclass MidiChannel : Windows.Foundation.IStringable { + MidiChannel(); MidiChannel(UInt8 index); static String ShortLabel{ get; }; + static String ShortLabelPlural{ get; }; static String LongLabel{ get; }; + static String LongLabelPlural{ get; }; UInt8 Index; UInt8 DisplayValue{ get; }; diff --git a/src/app-sdk/winrt/MidiEndpointConnection.cpp b/src/app-sdk/winrt/MidiEndpointConnection.cpp index 7b2ad3bc7..87d802bd6 100644 --- a/src/app-sdk/winrt/MidiEndpointConnection.cpp +++ b/src/app-sdk/winrt/MidiEndpointConnection.cpp @@ -13,6 +13,11 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation { + winrt::hstring MidiEndpointConnection::ToString() + { + return ConnectedEndpointDeviceId(); + } + _Use_decl_annotations_ bool MidiEndpointConnection::InternalInitialize( winrt::guid sessionId, diff --git a/src/app-sdk/winrt/MidiEndpointConnection.h b/src/app-sdk/winrt/MidiEndpointConnection.h index 467996fdf..3b55f52df 100644 --- a/src/app-sdk/winrt/MidiEndpointConnection.h +++ b/src/app-sdk/winrt/MidiEndpointConnection.h @@ -45,6 +45,8 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation void Tag(_In_ foundation::IInspectable value) noexcept { m_tag = value; } + winrt::hstring ToString(); + midi2::MidiSendMessageResults SendSingleMessagePacket( _In_ midi2::IMidiUniversalPacket const& ump) noexcept; diff --git a/src/app-sdk/winrt/MidiEndpointConnection.idl b/src/app-sdk/winrt/MidiEndpointConnection.idl index 302dfcdb1..0b6b72d06 100644 --- a/src/app-sdk/winrt/MidiEndpointConnection.idl +++ b/src/app-sdk/winrt/MidiEndpointConnection.idl @@ -17,7 +17,8 @@ namespace Microsoft.Windows.Devices.Midi2 { [default_interface] runtimeclass MidiEndpointConnection : IMidiMessageReceivedEventSource, - IMidiEndpointConnectionSource + IMidiEndpointConnectionSource, + Windows.Foundation.IStringable { static String GetDeviceSelector(); diff --git a/src/app-sdk/winrt/MidiEndpointDeviceInformation.cpp b/src/app-sdk/winrt/MidiEndpointDeviceInformation.cpp index b85433ac6..4bb445898 100644 --- a/src/app-sdk/winrt/MidiEndpointDeviceInformation.cpp +++ b/src/app-sdk/winrt/MidiEndpointDeviceInformation.cpp @@ -13,6 +13,23 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation { + winrt::hstring MidiEndpointDeviceInformation::ToString() + { + winrt::hstring baseName{ }; + + if (Name().empty()) + { + // TODO: Move to resources + baseName = baseName + L"Unnamed endpoint"; + } + else + { + baseName = baseName + Name(); + } + + return baseName; + } + #define MIDI_DEVICE_PARENT_PROPERTY_KEY L"System.Devices.Parent" winrt::Windows::Devices::Enumeration::DeviceInformation MidiEndpointDeviceInformation::GetContainerDeviceInformation() const noexcept diff --git a/src/app-sdk/winrt/MidiEndpointDeviceInformation.h b/src/app-sdk/winrt/MidiEndpointDeviceInformation.h index 00eaaa6fd..dc84b7e0e 100644 --- a/src/app-sdk/winrt/MidiEndpointDeviceInformation.h +++ b/src/app-sdk/winrt/MidiEndpointDeviceInformation.h @@ -77,6 +77,8 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation collections::IMapView Properties() { return m_properties.GetView(); } + winrt::hstring ToString(); + bool UpdateFromDeviceInformation( _In_ winrt::Windows::Devices::Enumeration::DeviceInformation const& deviceInformation) noexcept; diff --git a/src/app-sdk/winrt/MidiEndpointDeviceInformation.idl b/src/app-sdk/winrt/MidiEndpointDeviceInformation.idl index 98632870c..74c7e7311 100644 --- a/src/app-sdk/winrt/MidiEndpointDeviceInformation.idl +++ b/src/app-sdk/winrt/MidiEndpointDeviceInformation.idl @@ -24,7 +24,7 @@ import "MidiEndpointDeviceInformationFiltersEnum.idl"; namespace Microsoft.Windows.Devices.Midi2 { [default_interface] - runtimeclass MidiEndpointDeviceInformation + runtimeclass MidiEndpointDeviceInformation : Windows.Foundation.IStringable { static MidiEndpointDeviceInformation CreateFromEndpointDeviceId(String endpointDeviceId); diff --git a/src/app-sdk/winrt/MidiFunctionBlock.cpp b/src/app-sdk/winrt/MidiFunctionBlock.cpp index 6f6828d59..6ecd274c8 100644 --- a/src/app-sdk/winrt/MidiFunctionBlock.cpp +++ b/src/app-sdk/winrt/MidiFunctionBlock.cpp @@ -12,9 +12,37 @@ #include "MidiFunctionBlock.h" #include "MidiFunctionBlock.g.cpp" +#include "MidiGroup.h" namespace winrt::Microsoft::Windows::Devices::Midi2::implementation { + winrt::hstring MidiFunctionBlock::ToString() + { + winrt::hstring baseName{ midi2::MidiFunctionBlock::LongLabel() }; + + if (Name().empty()) + { + // TODO: Move to resources + baseName = baseName + L"(Unnamed)"; + } + else + { + baseName = baseName + Name(); + } + + if (m_numberOfGroupsSpanned != 1) + { + baseName = baseName + std::format(L" ({} {} to {})", MidiGroup::LongLabelPlural(), m_firstGroup.DisplayValue(), (m_firstGroup.Index() + m_numberOfGroupsSpanned)); + } + else + { + baseName = baseName + std::format(L" ({} {})", MidiGroup::LongLabel(), m_firstGroup.DisplayValue()); + } + + return baseName; + } + + #if false _Use_decl_annotations_ bool MidiFunctionBlock::UpdateFromMessages(collections::IIterable messages) noexcept @@ -115,7 +143,7 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation if (json.HasKey(JSON_KEY_FB_UIHINT)) m_uiHint = (MidiFunctionBlockUIHint)json.GetNamedNumber(JSON_KEY_FB_UIHINT, (int)MidiFunctionBlockUIHint::Unknown); if (json.HasKey(JSON_KEY_FB_MIDI10)) m_midi10Connection = (MidiFunctionBlockRepresentsMidi10Connection)json.GetNamedNumber(JSON_KEY_FB_MIDI10, (int)MidiFunctionBlockRepresentsMidi10Connection::Not10); if (json.HasKey(JSON_KEY_FB_DIRECTION)) m_direction = (MidiFunctionBlockDirection)json.GetNamedNumber(JSON_KEY_FB_DIRECTION, (int)MidiFunctionBlockDirection::Undefined); - if (json.HasKey(JSON_KEY_FB_FIRSTGROUP)) m_firstGroupIndex = (uint8_t)json.GetNamedNumber(JSON_KEY_FB_FIRSTGROUP, 0); + if (json.HasKey(JSON_KEY_FB_FIRSTGROUP)) m_firstGroup = winrt::make((uint8_t)json.GetNamedNumber(JSON_KEY_FB_FIRSTGROUP, 0)); if (json.HasKey(JSON_KEY_FB_NUMGROUPSSPANNED)) m_numberOfGroupsSpanned = (uint8_t)json.GetNamedNumber(JSON_KEY_FB_NUMGROUPSSPANNED, 0); if (json.HasKey(JSON_KEY_FB_MIDICIFORMAT)) m_midiCIMessageVersionFormat = (uint8_t)json.GetNamedNumber(JSON_KEY_FB_MIDICIFORMAT, 0); @@ -152,7 +180,7 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation jsonObject.SetNamedValue(JSON_KEY_FB_UIHINT, json::JsonValue::CreateNumberValue((int)UIHint())); jsonObject.SetNamedValue(JSON_KEY_FB_MIDI10, json::JsonValue::CreateNumberValue((int)RepresentsMidi10Connection())); jsonObject.SetNamedValue(JSON_KEY_FB_DIRECTION, json::JsonValue::CreateNumberValue((int)Direction())); - jsonObject.SetNamedValue(JSON_KEY_FB_FIRSTGROUP, json::JsonValue::CreateNumberValue(FirstGroupIndex())); + jsonObject.SetNamedValue(JSON_KEY_FB_FIRSTGROUP, json::JsonValue::CreateNumberValue(FirstGroup().Index())); jsonObject.SetNamedValue(JSON_KEY_FB_NUMGROUPSSPANNED, json::JsonValue::CreateNumberValue(GroupCount())); jsonObject.SetNamedValue(JSON_KEY_FB_MIDICIFORMAT, json::JsonValue::CreateNumberValue(MidiCIMessageVersionFormat())); @@ -166,7 +194,7 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation m_number = prop.BlockNumber; m_isActive = prop.IsActive; m_direction = (midi2::MidiFunctionBlockDirection)prop.Direction; - m_firstGroupIndex = prop.FirstGroup; + m_firstGroup = winrt::make(prop.FirstGroup); m_numberOfGroupsSpanned = prop.NumberOfGroupsSpanned; m_maxSysEx8Streams = prop.MaxSysEx8Streams; m_uiHint = (midi2::MidiFunctionBlockUIHint)prop.UIHint; diff --git a/src/app-sdk/winrt/MidiFunctionBlock.h b/src/app-sdk/winrt/MidiFunctionBlock.h index 1d096711d..cf667ca50 100644 --- a/src/app-sdk/winrt/MidiFunctionBlock.h +++ b/src/app-sdk/winrt/MidiFunctionBlock.h @@ -17,6 +17,13 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation { MidiFunctionBlock() = default; + static winrt::hstring ShortLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_FUNCTION_BLOCK_SHORT); } + static winrt::hstring ShortLabelPlural() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_FUNCTION_BLOCK_SHORT_PLURAL); } + static winrt::hstring LongLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_FUNCTION_BLOCK_FULL); } + static winrt::hstring LongLabelPlural() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_FUNCTION_BLOCK_FULL_PLURAL); } + + + bool IsReadOnly() { return m_isReadOnly; } uint8_t Number() const noexcept { return m_number; } @@ -43,15 +50,16 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation uint8_t MaxSystemExclusive8Streams() const noexcept { return m_maxSysEx8Streams; } void MaxSystemExclusive8Streams(_In_ uint8_t const value) noexcept { if (!m_isReadOnly) m_maxSysEx8Streams = value; } - uint8_t FirstGroupIndex() { return m_firstGroupIndex; } - void FirstGroupIndex(_In_ uint8_t const value) noexcept { if (!m_isReadOnly) m_firstGroupIndex = value; } + midi2::MidiGroup FirstGroup() const noexcept { return m_firstGroup; } + void FirstGroup(_In_ midi2::MidiGroup const& value) noexcept { if (!m_isReadOnly) m_firstGroup = value; } - uint8_t GroupCount() { return m_numberOfGroupsSpanned; } + uint8_t GroupCount() const noexcept { return m_numberOfGroupsSpanned; } void GroupCount(_In_ uint8_t const value) noexcept { if (!m_isReadOnly) m_numberOfGroupsSpanned = value; } - bool IncludesGroup(_In_ midi2::MidiGroup const& group) { return group.Index() >= FirstGroupIndex() && group.Index() < FirstGroupIndex() + GroupCount(); } + bool IncludesGroup(_In_ midi2::MidiGroup const& group) const noexcept { return (group.Index() >= m_firstGroup.Index()) && (group.Index() < m_firstGroup.Index() + GroupCount()); } + winrt::hstring ToString(); bool UpdateFromJson(_In_ winrt::Windows::Data::Json::JsonObject const json) noexcept; @@ -62,8 +70,8 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation bool UpdateFromDevPropertyStruct(_In_ MidiFunctionBlockProperty prop); - void InternalSetName(_In_ winrt::hstring name) { m_name = name; } - void InternalSetisReadOnly(_In_ bool isReadOnly) { m_isReadOnly = isReadOnly; } + void InternalSetName(_In_ winrt::hstring name) noexcept { m_name = name; } + void InternalSetisReadOnly(_In_ bool isReadOnly) noexcept { m_isReadOnly = isReadOnly; } private: bool m_isReadOnly{ false }; @@ -76,7 +84,8 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation uint8_t m_midiCIMessageVersionFormat{ 0 }; uint8_t m_maxSysEx8Streams{ 0 }; - uint8_t m_firstGroupIndex{ 0 }; + //uint8_t m_firstGroupIndex{ 0 }; + midi2::MidiGroup m_firstGroup; uint8_t m_numberOfGroupsSpanned{ 0 }; }; diff --git a/src/app-sdk/winrt/MidiFunctionBlock.idl b/src/app-sdk/winrt/MidiFunctionBlock.idl index 4d782e527..80c9541ca 100644 --- a/src/app-sdk/winrt/MidiFunctionBlock.idl +++ b/src/app-sdk/winrt/MidiFunctionBlock.idl @@ -16,10 +16,15 @@ import "MidiGroup.idl"; namespace Microsoft.Windows.Devices.Midi2 { [default_interface] - runtimeclass MidiFunctionBlock + runtimeclass MidiFunctionBlock : Windows.Foundation.IStringable { MidiFunctionBlock(); + static String ShortLabel{ get; }; + static String ShortLabelPlural{ get; }; + static String LongLabel{ get; }; + static String LongLabelPlural{ get; }; + Boolean IsReadOnly { get; }; UInt8 Number; @@ -32,7 +37,8 @@ namespace Microsoft.Windows.Devices.Midi2 MidiFunctionBlockRepresentsMidi10Connection RepresentsMidi10Connection; - UInt8 FirstGroupIndex; + MidiGroup FirstGroup; + //UInt8 FirstGroupIndex; UInt8 GroupCount; Boolean IncludesGroup(MidiGroup group); diff --git a/src/app-sdk/winrt/MidiGroup.cpp b/src/app-sdk/winrt/MidiGroup.cpp index 528662376..3b0870f94 100644 --- a/src/app-sdk/winrt/MidiGroup.cpp +++ b/src/app-sdk/winrt/MidiGroup.cpp @@ -15,5 +15,8 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation { - + winrt::hstring MidiGroup::ToString() + { + return winrt::to_hstring(std::format("{} {}", winrt::to_string(midi2::MidiGroup::ShortLabel()), DisplayValue())); + } } diff --git a/src/app-sdk/winrt/MidiGroup.h b/src/app-sdk/winrt/MidiGroup.h index 65043950a..df5c2f99f 100644 --- a/src/app-sdk/winrt/MidiGroup.h +++ b/src/app-sdk/winrt/MidiGroup.h @@ -15,19 +15,21 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation { struct MidiGroup : MidiGroupT { - //MidiGroup() = default; - MidiGroup(_In_ uint8_t index) noexcept { Index(index); } + static winrt::hstring ShortLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_GROUP_SHORT); } + static winrt::hstring ShortLabelPlural() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_GROUP_SHORT_PLURAL); } + static winrt::hstring LongLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_GROUP_FULL); } + static winrt::hstring LongLabelPlural() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_GROUP_FULL_PLURAL); } + MidiGroup() noexcept { Index(0); } + MidiGroup(_In_ uint8_t index) noexcept { Index(index); } uint8_t Index() const noexcept { return m_index; } void Index(_In_ uint8_t value) noexcept { m_index = (value & 0x0F); } - static winrt::hstring ShortLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_GROUP_SHORT); } - static winrt::hstring LongLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_GROUP_FULL); } - - uint8_t DisplayValue() const noexcept { return m_index + 1; } + // IStringable + winrt::hstring ToString(); static bool IsValidIndex(_In_ uint8_t const index) noexcept { return index >= 0 && index <= 15; } diff --git a/src/app-sdk/winrt/MidiGroup.idl b/src/app-sdk/winrt/MidiGroup.idl index c224eae0d..beb8c0576 100644 --- a/src/app-sdk/winrt/MidiGroup.idl +++ b/src/app-sdk/winrt/MidiGroup.idl @@ -10,13 +10,15 @@ namespace Microsoft.Windows.Devices.Midi2 { [default_interface] - runtimeclass MidiGroup + runtimeclass MidiGroup : Windows.Foundation.IStringable { - //MidiGroup(); + MidiGroup(); MidiGroup(UInt8 index); static String ShortLabel{ get; }; + static String ShortLabelPlural{ get; }; static String LongLabel{ get; }; + static String LongLabelPlural{ get; }; UInt8 Index; UInt8 DisplayValue{ get; }; diff --git a/src/app-sdk/winrt/MidiGroupTerminalBlock.cpp b/src/app-sdk/winrt/MidiGroupTerminalBlock.cpp index 60dc3bce4..dca8595f0 100644 --- a/src/app-sdk/winrt/MidiGroupTerminalBlock.cpp +++ b/src/app-sdk/winrt/MidiGroupTerminalBlock.cpp @@ -13,6 +13,32 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation { + winrt::hstring MidiGroupTerminalBlock::ToString() + { + winrt::hstring baseName{ midi2::MidiFunctionBlock::LongLabel() }; + + if (Name().empty()) + { + // TODO: Move to resources + baseName = baseName + L"(Unnamed)"; + } + else + { + baseName = baseName + Name(); + } + + if (m_block.GroupCount != 1) + { + baseName = baseName + std::format(L" ({} {} to {})", MidiGroup::LongLabelPlural(), m_block.FirstGroupIndex + 1, m_block.FirstGroupIndex + m_block.GroupCount); + } + else + { + baseName = baseName + std::format(L" ({} {})", MidiGroup::LongLabel(), m_block.FirstGroupIndex + 1); + } + + return baseName; + } + // this conversion will never be 100% because the GTBs just contain slightly // different data than Function Blocks. However, it will provide enough information // to enable consuming code to represent the GTB properly in the absence of @@ -26,7 +52,7 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation fb->IsActive(true); fb->Number(max(0, m_block.Number - 1)); // group terminal blocks are numbered 1-255. Function blocks start with 0 as the id. fb->Name(m_block.Name.c_str()); - fb->FirstGroupIndex(m_block.FirstGroupIndex); + fb->FirstGroup(winrt::make(m_block.FirstGroupIndex)); fb->GroupCount(m_block.GroupCount); switch ((midi2::MidiGroupTerminalBlockDirection)m_block.Direction) diff --git a/src/app-sdk/winrt/MidiGroupTerminalBlock.h b/src/app-sdk/winrt/MidiGroupTerminalBlock.h index 62aad25ec..efe8cf2e6 100644 --- a/src/app-sdk/winrt/MidiGroupTerminalBlock.h +++ b/src/app-sdk/winrt/MidiGroupTerminalBlock.h @@ -10,21 +10,26 @@ #pragma once #include "MidiGroupTerminalBlock.g.h" - namespace winrt::Microsoft::Windows::Devices::Midi2::implementation { struct MidiGroupTerminalBlock : MidiGroupTerminalBlockT { MidiGroupTerminalBlock() = default; + static winrt::hstring ShortLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_GROUP_TERMINAL_BLOCK_SHORT); } + static winrt::hstring ShortLabelPlural() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_GROUP_TERMINAL_BLOCK_SHORT_PLURAL); } + static winrt::hstring LongLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_GROUP_TERMINAL_BLOCK_FULL); } + static winrt::hstring LongLabelPlural() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_GROUP_TERMINAL_BLOCK_FULL_PLURAL); } + uint8_t Number() { return m_block.Number; } winrt::hstring Name() { return m_block.Name.c_str(); } midi2::MidiGroupTerminalBlockDirection Direction() { return (midi2::MidiGroupTerminalBlockDirection)m_block.Direction; } midi2::MidiGroupTerminalBlockProtocol Protocol() { return (midi2::MidiGroupTerminalBlockProtocol)m_block.Protocol; } - uint8_t FirstGroupIndex() { return m_block.FirstGroupIndex; } + midi2::MidiGroup FirstGroup() const noexcept { return winrt::make(m_block.FirstGroupIndex); } + uint8_t GroupCount() { return m_block.GroupCount; } - bool IncludesGroup(_In_ midi2::MidiGroup const& group) { return group.Index() >= FirstGroupIndex() && group.Index() < FirstGroupIndex() + GroupCount(); } + bool IncludesGroup(_In_ midi2::MidiGroup const& group) { return group.Index() >= m_block.FirstGroupIndex && group.Index() < m_block.FirstGroupIndex + GroupCount(); } uint16_t MaxDeviceInputBandwidthIn4KBitsPerSecondUnits() { return m_block.MaxInputBandwidth; } @@ -39,6 +44,8 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation midi2::MidiFunctionBlock AsEquivalentFunctionBlock(); + winrt::hstring ToString(); + private: internal::GroupTerminalBlockInternal m_block; @@ -47,9 +54,9 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation }; } -//namespace MIDI_CPP_NAMESPACE::factory_implementation -//{ -// struct MidiGroupTerminalBlock : MidiGroupTerminalBlockT -// { -// }; -//} +namespace winrt::Microsoft::Windows::Devices::Midi2::factory_implementation +{ + struct MidiGroupTerminalBlock : MidiGroupTerminalBlockT + { + }; +} diff --git a/src/app-sdk/winrt/MidiGroupTerminalBlock.idl b/src/app-sdk/winrt/MidiGroupTerminalBlock.idl index 2a9110f2a..9b593f42b 100644 --- a/src/app-sdk/winrt/MidiGroupTerminalBlock.idl +++ b/src/app-sdk/winrt/MidiGroupTerminalBlock.idl @@ -12,12 +12,18 @@ import "MidiGroupTerminalBlockProtocolEnum.idl"; import "MidiGroup.idl"; import "MidiFunctionBlock.idl"; +import "MidiGroup.idl"; namespace Microsoft.Windows.Devices.Midi2 { [default_interface] - runtimeclass MidiGroupTerminalBlock + runtimeclass MidiGroupTerminalBlock : Windows.Foundation.IStringable { + static String ShortLabel{ get; }; + static String ShortLabelPlural{ get; }; + static String LongLabel{ get; }; + static String LongLabelPlural{ get; }; + UInt8 Number{ get; }; String Name{ get; }; @@ -25,7 +31,7 @@ namespace Microsoft.Windows.Devices.Midi2 MidiGroupTerminalBlockDirection Direction { get; }; MidiGroupTerminalBlockProtocol Protocol { get; }; - UInt8 FirstGroupIndex{ get; }; + MidiGroup FirstGroup{ get; }; UInt8 GroupCount{ get; }; Boolean IncludesGroup(MidiGroup group); diff --git a/src/app-sdk/winrt/MidiSession.cpp b/src/app-sdk/winrt/MidiSession.cpp index f111be34d..b15741515 100644 --- a/src/app-sdk/winrt/MidiSession.cpp +++ b/src/app-sdk/winrt/MidiSession.cpp @@ -18,6 +18,11 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation { + winrt::hstring MidiSession::ToString() + { + return Name(); + } + _Use_decl_annotations_ midi2::MidiSession MidiSession::Create( winrt::hstring const& sessionName diff --git a/src/app-sdk/winrt/MidiSession.h b/src/app-sdk/winrt/MidiSession.h index 9c591f618..0a2be5e79 100644 --- a/src/app-sdk/winrt/MidiSession.h +++ b/src/app-sdk/winrt/MidiSession.h @@ -59,6 +59,9 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::implementation _Success_(return == true) bool InternalStart(); + + winrt::hstring ToString(); + private: // this helps us clean up when/if a client crashes or otherwise // doesn't clean up its session before closing diff --git a/src/app-sdk/winrt/MidiSession.idl b/src/app-sdk/winrt/MidiSession.idl index ec75749c6..f4b6a4cfa 100644 --- a/src/app-sdk/winrt/MidiSession.idl +++ b/src/app-sdk/winrt/MidiSession.idl @@ -13,7 +13,7 @@ import "IMidiEndpointConnectionSettings.idl"; namespace Microsoft.Windows.Devices.Midi2 { [default_interface] - runtimeclass MidiSession : Windows.Foundation.IClosable + runtimeclass MidiSession : Windows.Foundation.IClosable, Windows.Foundation.IStringable { Guid SessionId { get; }; String Name{ get; }; diff --git a/src/app-sdk/winrt/MidiUniqueId.cpp b/src/app-sdk/winrt/MidiUniqueId.cpp index 4a6dd8293..71583de44 100644 --- a/src/app-sdk/winrt/MidiUniqueId.cpp +++ b/src/app-sdk/winrt/MidiUniqueId.cpp @@ -13,6 +13,11 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::CapabilityInquiry::implementation { + winrt::hstring MidiUniqueId::ToString() + { + return winrt::to_hstring(std::format("{} {}", winrt::to_string(MidiUniqueId::LongLabel()), AsCombined28BitValue())); + } + ci::MidiUniqueId MidiUniqueId::CreateBroadcast() { //return winrt::make(MIDI_MUID_BROADCAST); diff --git a/src/app-sdk/winrt/MidiUniqueId.h b/src/app-sdk/winrt/MidiUniqueId.h index 77fd8ce34..3009b4bdc 100644 --- a/src/app-sdk/winrt/MidiUniqueId.h +++ b/src/app-sdk/winrt/MidiUniqueId.h @@ -23,6 +23,12 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::CapabilityInquiry::implemen { struct MidiUniqueId : MidiUniqueIdT { + static winrt::hstring ShortLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_MUID_SHORT); } + static winrt::hstring ShortLabelPlural() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_MUID_SHORT_PLURAL); } + static winrt::hstring LongLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_MUID_FULL); } + static winrt::hstring LongLabelPlural() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_MUID_FULL_PLURAL); } + + MidiUniqueId() = default; MidiUniqueId( @@ -56,11 +62,12 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::CapabilityInquiry::implemen uint8_t Byte4() const noexcept { return m_byte4; } void Byte4(_In_ uint8_t value) noexcept { m_byte4 = internal::CleanupByte7(value); } - static winrt::hstring ShortLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_MUID_SHORT); } - static winrt::hstring LongLabel() { return internal::ResourceGetHString(IDS_MIDI_COMMON_LABEL_MUID_FULL); } - uint32_t AsCombined28BitValue () const noexcept; + // IStringable + winrt::hstring ToString(); + + bool IsBroadcast() noexcept { return (AsCombined28BitValue() == MIDI_MUID_BROADCAST); } bool IsReserved() noexcept { return AsCombined28BitValue() >= MIDI_MUID_RESERVED_START && AsCombined28BitValue() <= MIDI_MUID_RESERVED_END; } diff --git a/src/app-sdk/winrt/MidiUniqueId.idl b/src/app-sdk/winrt/MidiUniqueId.idl index ab63b0a37..4c47049c2 100644 --- a/src/app-sdk/winrt/MidiUniqueId.idl +++ b/src/app-sdk/winrt/MidiUniqueId.idl @@ -10,14 +10,16 @@ namespace Microsoft.Windows.Devices.Midi2.CapabilityInquiry { [default_interface] - runtimeclass MidiUniqueId + runtimeclass MidiUniqueId : Windows.Foundation.IStringable { MidiUniqueId(); MidiUniqueId(UInt32 combined28BitValue); MidiUniqueId(UInt8 sevenBitByte1, UInt8 sevenBitByte2, UInt8 sevenBitByte3, UInt8 sevenBitByte4); static String ShortLabel{ get; }; + static String ShortLabelPlural{ get; }; static String LongLabel{ get; }; + static String LongLabelPlural{ get; }; static MidiUniqueId CreateBroadcast(); static MidiUniqueId CreateRandom(); diff --git a/src/app-sdk/winrt/MidiVirtualDevice.cpp b/src/app-sdk/winrt/MidiVirtualDevice.cpp index ac25a34aa..cb540a225 100644 --- a/src/app-sdk/winrt/MidiVirtualDevice.cpp +++ b/src/app-sdk/winrt/MidiVirtualDevice.cpp @@ -185,7 +185,7 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Virtual::impleme fb.UIHint(), fb.RepresentsMidi10Connection(), fb.Direction(), - fb.FirstGroupIndex(), + fb.FirstGroup().Index(), fb.GroupCount(), fb.MidiCIMessageVersionFormat(), fb.MaxSystemExclusive8Streams() diff --git a/src/app-sdk/winrt/Resources.rc b/src/app-sdk/winrt/Resources.rc index b6fa1998c27f6aa71401c134402b2ec70e3e87bb..0fb72ca79e89a7224c762527c40c860ae76f24b9 100644 GIT binary patch delta 761 zcmaJ<%TB^j6r8RIw0A==1&Ic_VbK^}n3#y60m7r9RnfX8NK7<7AQFGTKhU%BGfYfe zxsm7x_zA9b=P!6#+CZx%XVK=~b7tnu+_z`x;az(CmT7xEO(R7kOU|tIun!AII6#%Z zNfi7_^1oXaG_-JyA#O0DzLEDQ75xxx?D3p~C`NR4OrP=>wZ$eCl&lDKQ(0M|V`G_7 zcZ#7KpFhx0$0^42s{AlcWvR)EEw0c6b@e=Lh_sKV-HVhOBa-e!PI6@#^wL^Q_;6&K zIyq|ATanLcB4-k=0Zr7XD#~te9JN^rXx*+-4DXz&jL8eR3M^UaI%u$!Hcae#LG<|6 zVtec8@RGs0QDePOI4}n%9ML7taD_fD_@qW1wHQRTwHSS-b&5ZY-0^p2b%Vw8fx1u_ je;?2PI$7-y1Dwx4t;S-$ncg@?*3RC3q;gLaaclnqJzSCL delta 34 pcmbPnl<~+m#tkpHC*R Date: Wed, 27 Nov 2024 15:53:57 -0500 Subject: [PATCH 02/10] Update diagnostics --- .nuke/build.schema.json | 6 +- build/nuke_build/Build.cs | 10 + build/staging/version/BundleInfo.wxi | 2 +- .../version/WindowsMidiServicesVersion.cs | 6 +- .../version/WindowsMidiServicesVersion.h | 6 +- .../basics/client-basics-cpp.vcxproj | 2 +- samples/cpp-winrt/basics/packages.config | 2 +- .../loopback-endpoints-cpp.vcxproj | 2 +- .../loopback-endpoints/packages.config | 2 +- samples/cpp-winrt/send-speed/packages.config | 2 +- .../send-speed/send-speed-cpp.vcxproj | 2 +- .../static-enum-endpoints/packages.config | 2 +- .../static-enum-endpoints-cpp.vcxproj | 2 +- .../cpp-winrt/watch-endpoints/packages.config | 2 +- .../watch-endpoints-cpp.vcxproj | 2 +- .../Midi2.NetworkMidiConfigurationManager.cpp | 208 +++++++++--------- .../Midi2.VirtualPatchBayTransport.vcxproj | 2 +- ...2.VirtualPatchBayTransport.vcxproj.filters | 40 ++-- src/app-sdk/mididiag/mididiag.vcxproj | 2 +- src/app-sdk/mididiag/packages.config | 2 +- src/app-sdk/midiusbinfo/midiusbinfo.vcxproj | 2 +- src/app-sdk/midiusbinfo/packages.config | 2 +- src/dev-tools/reg-helpers/midi-list-reg.ps1 | 63 +++++- .../api-package/WindowsMidiServices.wxs | 6 +- .../Endpoint/EndpointPropertiesCommand.cs | 26 +-- .../Enumerate/EnumEndpointsCommand.cs | 4 +- 26 files changed, 230 insertions(+), 177 deletions(-) diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index 22430dba3..a39174aee 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -79,7 +79,8 @@ "BuildSettingsApp", "BuildUserToolsSharedComponents", "CreateVersionIncludes", - "Prerequisites" + "Prerequisites", + "ZipPowershellDevUtilities" ] } }, @@ -104,7 +105,8 @@ "BuildSettingsApp", "BuildUserToolsSharedComponents", "CreateVersionIncludes", - "Prerequisites" + "Prerequisites", + "ZipPowershellDevUtilities" ] } }, diff --git a/build/nuke_build/Build.cs b/build/nuke_build/Build.cs index 42a5a8b26..5be548828 100644 --- a/build/nuke_build/Build.cs +++ b/build/nuke_build/Build.cs @@ -1536,6 +1536,15 @@ void UpdatePackagesConfigForCPPProject(string configFilePath) + Target ZipPowershellDevUtilities => _ => _ + .DependsOn(Prerequisites) + .DependsOn(CreateVersionIncludes) + .Executes(() => + { + var regHelpersFolder = RootDirectory / "src" / "dev-tools" / "reg-helpers"; + + regHelpersFolder.ZipTo(ThisReleaseFolder / $"dev-pre-setup-scripts.zip"); + }); @@ -1553,6 +1562,7 @@ void UpdatePackagesConfigForCPPProject(string configFilePath) // .DependsOn(BuildAndPackageElectronProjection) .DependsOn(BuildCppSamples) .DependsOn(BuildCSharpSamples) + .DependsOn(ZipPowershellDevUtilities) .Executes(() => { if (BuiltInBoxInstallers.Count > 0) diff --git a/build/staging/version/BundleInfo.wxi b/build/staging/version/BundleInfo.wxi index c21264d0c..240a54ee5 100644 --- a/build/staging/version/BundleInfo.wxi +++ b/build/staging/version/BundleInfo.wxi @@ -1,4 +1,4 @@ - + diff --git a/build/staging/version/WindowsMidiServicesVersion.cs b/build/staging/version/WindowsMidiServicesVersion.cs index 0f7fd0b25..6b655b3d3 100644 --- a/build/staging/version/WindowsMidiServicesVersion.cs +++ b/build/staging/version/WindowsMidiServicesVersion.cs @@ -6,12 +6,12 @@ public static class MidiBuildInformation { public const string Source = "GitHub Preview"; public const string Name = "Developer Preview 8"; - public const string BuildFullVersion = "1.0.2-preview-8.241125-206"; + public const string BuildFullVersion = "1.0.2-preview-8.241127-1315"; public const string VersionMajor = "1"; public const string VersionMinor = "0"; public const string VersionRevision = "2"; - public const string VersionDateNumber = "241125"; - public const string VersionTimeNumber = "206"; + public const string VersionDateNumber = "241127"; + public const string VersionTimeNumber = "1315"; } } diff --git a/build/staging/version/WindowsMidiServicesVersion.h b/build/staging/version/WindowsMidiServicesVersion.h index 378839a1c..3cc3c22b8 100644 --- a/build/staging/version/WindowsMidiServicesVersion.h +++ b/build/staging/version/WindowsMidiServicesVersion.h @@ -5,12 +5,12 @@ #define WINDOWS_MIDI_SERVICES_BUILD_SOURCE L"GitHub Preview" #define WINDOWS_MIDI_SERVICES_BUILD_VERSION_NAME L"Developer Preview 8" -#define WINDOWS_MIDI_SERVICES_BUILD_VERSION_FULL L"1.0.2-preview-8.241125-206" +#define WINDOWS_MIDI_SERVICES_BUILD_VERSION_FULL L"1.0.2-preview-8.241127-1315" #define WINDOWS_MIDI_SERVICES_BUILD_VERSION_MAJOR L"1" #define WINDOWS_MIDI_SERVICES_BUILD_VERSION_MINOR L"0" #define WINDOWS_MIDI_SERVICES_BUILD_VERSION_REVISION L"2" -#define WINDOWS_MIDI_SERVICES_BUILD_VERSION_DATE_NUMBER L"241125" -#define WINDOWS_MIDI_SERVICES_BUILD_VERSION_TIME_NUMBER L"206" +#define WINDOWS_MIDI_SERVICES_BUILD_VERSION_DATE_NUMBER L"241127" +#define WINDOWS_MIDI_SERVICES_BUILD_VERSION_TIME_NUMBER L"1315" #endif diff --git a/samples/cpp-winrt/basics/client-basics-cpp.vcxproj b/samples/cpp-winrt/basics/client-basics-cpp.vcxproj index 890f6f2f4..d8af6da7f 100644 --- a/samples/cpp-winrt/basics/client-basics-cpp.vcxproj +++ b/samples/cpp-winrt/basics/client-basics-cpp.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241125-206 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 true true false diff --git a/samples/cpp-winrt/basics/packages.config b/samples/cpp-winrt/basics/packages.config index 1d4c0819f..9ca35a8fd 100644 --- a/samples/cpp-winrt/basics/packages.config +++ b/samples/cpp-winrt/basics/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/samples/cpp-winrt/loopback-endpoints/loopback-endpoints-cpp.vcxproj b/samples/cpp-winrt/loopback-endpoints/loopback-endpoints-cpp.vcxproj index 035bfd55d..8d2ce5104 100644 --- a/samples/cpp-winrt/loopback-endpoints/loopback-endpoints-cpp.vcxproj +++ b/samples/cpp-winrt/loopback-endpoints/loopback-endpoints-cpp.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241125-206 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 true true true diff --git a/samples/cpp-winrt/loopback-endpoints/packages.config b/samples/cpp-winrt/loopback-endpoints/packages.config index 1d4c0819f..9ca35a8fd 100644 --- a/samples/cpp-winrt/loopback-endpoints/packages.config +++ b/samples/cpp-winrt/loopback-endpoints/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/samples/cpp-winrt/send-speed/packages.config b/samples/cpp-winrt/send-speed/packages.config index 1d4c0819f..9ca35a8fd 100644 --- a/samples/cpp-winrt/send-speed/packages.config +++ b/samples/cpp-winrt/send-speed/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/samples/cpp-winrt/send-speed/send-speed-cpp.vcxproj b/samples/cpp-winrt/send-speed/send-speed-cpp.vcxproj index a582f70a1..4f63dfad0 100644 --- a/samples/cpp-winrt/send-speed/send-speed-cpp.vcxproj +++ b/samples/cpp-winrt/send-speed/send-speed-cpp.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241125-206 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 true true true diff --git a/samples/cpp-winrt/static-enum-endpoints/packages.config b/samples/cpp-winrt/static-enum-endpoints/packages.config index 1d4c0819f..9ca35a8fd 100644 --- a/samples/cpp-winrt/static-enum-endpoints/packages.config +++ b/samples/cpp-winrt/static-enum-endpoints/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/samples/cpp-winrt/static-enum-endpoints/static-enum-endpoints-cpp.vcxproj b/samples/cpp-winrt/static-enum-endpoints/static-enum-endpoints-cpp.vcxproj index e3a50d0d0..e41cc22a0 100644 --- a/samples/cpp-winrt/static-enum-endpoints/static-enum-endpoints-cpp.vcxproj +++ b/samples/cpp-winrt/static-enum-endpoints/static-enum-endpoints-cpp.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241125-206 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 true true true diff --git a/samples/cpp-winrt/watch-endpoints/packages.config b/samples/cpp-winrt/watch-endpoints/packages.config index 1d4c0819f..9ca35a8fd 100644 --- a/samples/cpp-winrt/watch-endpoints/packages.config +++ b/samples/cpp-winrt/watch-endpoints/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/samples/cpp-winrt/watch-endpoints/watch-endpoints-cpp.vcxproj b/samples/cpp-winrt/watch-endpoints/watch-endpoints-cpp.vcxproj index 1ee722dca..728d33c50 100644 --- a/samples/cpp-winrt/watch-endpoints/watch-endpoints-cpp.vcxproj +++ b/samples/cpp-winrt/watch-endpoints/watch-endpoints-cpp.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241125-206 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 true true true diff --git a/src/api/Transport/UdpNetworkMidi2Transport/Midi2.NetworkMidiConfigurationManager.cpp b/src/api/Transport/UdpNetworkMidi2Transport/Midi2.NetworkMidiConfigurationManager.cpp index 1ff44aa09..85d9993a1 100644 --- a/src/api/Transport/UdpNetworkMidi2Transport/Midi2.NetworkMidiConfigurationManager.cpp +++ b/src/api/Transport/UdpNetworkMidi2Transport/Midi2.NetworkMidiConfigurationManager.cpp @@ -40,7 +40,8 @@ CMidi2NetworkMidiConfigurationManager::Initialize( -MidiNetworkHostAuthentication MidiNetworkHostAuthenticationFromJsonString(_In_ winrt::hstring const& jsonString) +MidiNetworkHostAuthentication +MidiNetworkHostAuthenticationFromJsonString(_In_ winrt::hstring const& jsonString) { auto value = internal::ToLowerTrimmedHStringCopy(jsonString); @@ -64,7 +65,8 @@ MidiNetworkHostAuthentication MidiNetworkHostAuthenticationFromJsonString(_In_ w } -MidiNetworkHostConnectionPolicy MidiNetworkHostConnectionPolicyFromJsonString(_In_ winrt::hstring const& jsonString) +MidiNetworkHostConnectionPolicy +MidiNetworkHostConnectionPolicyFromJsonString(_In_ winrt::hstring const& jsonString) { auto value = internal::ToLowerTrimmedHStringCopy(jsonString); @@ -88,6 +90,7 @@ MidiNetworkHostConnectionPolicy MidiNetworkHostConnectionPolicyFromJsonString(_I } +// TODO: Move all strings to resources _Use_decl_annotations_ HRESULT @@ -171,9 +174,6 @@ CMidi2NetworkMidiConfigurationManager::UpdateConfiguration( // if we're passed a null or empty json, we just quietly exit if (configurationJsonSection == nullptr) return S_OK; - // default to failure - - // Json Format for network UDP midi // //{ @@ -254,154 +254,152 @@ CMidi2NetworkMidiConfigurationManager::UpdateConfiguration( } auto createArray = jsonObject.GetNamedArray(MIDI_CONFIG_JSON_ENDPOINT_COMMON_CREATE_KEY, nullptr); + auto updateArray = jsonObject.GetNamedArray(MIDI_CONFIG_JSON_ENDPOINT_COMMON_UPDATE_KEY, nullptr); + auto removeArray = jsonObject.GetNamedArray(MIDI_CONFIG_JSON_ENDPOINT_COMMON_REMOVE_KEY, nullptr); - if (createArray == nullptr || createArray.Size() == 0) - { - // nothing in the array. Maybe we're looking at update or delete - - // TODO: Set the response to something meaningful here - - internal::JsonStringifyObjectToOutParam(responseObject, response); - - // once we enable update/delete we need to move this - return S_OK; - } - - - // iterate through all the work we need to do. Just - // "create" instructions, in this case. - for (uint32_t i = 0; i < createArray.Size(); i++) + if (createArray != nullptr && createArray.Size() > 0) { - auto jsonEntry = (createArray.GetObjectAt(i)); - - if (jsonEntry) + // iterate through all the work we need to do. Just + // "create" instructions, in this case. + for (uint32_t i = 0; i < createArray.Size(); i++) { - // are we defining a host? - if (auto hostEntry = jsonEntry.GetNamedObject(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_HOST_KEY, nullptr); hostEntry != nullptr) - { - MidiNetworkHostDefinition definition; - winrt::hstring validationErrorMessage{}; + auto jsonEntry = (createArray.GetObjectAt(i)); - // currently, UDP is the only allowed protocol + if (jsonEntry) + { + // are we defining a host? + if (auto hostEntry = jsonEntry.GetNamedObject(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_HOST_KEY, nullptr); hostEntry != nullptr) + { + MidiNetworkHostDefinition definition; + winrt::hstring validationErrorMessage{}; - auto protocol = internal::ToLowerTrimmedHStringCopy(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_NETWORK_PROTOCOL_KEY, MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_NETWORK_PROTOCOL_VALUE_UDP)); + // currently, UDP is the only allowed protocol - if (protocol != MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_NETWORK_PROTOCOL_VALUE_UDP) - { - validationErrorMessage = L"Invalid network protocol '" + protocol + L"' specified."; + auto protocol = internal::ToLowerTrimmedHStringCopy(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_NETWORK_PROTOCOL_KEY, MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_NETWORK_PROTOCOL_VALUE_UDP)); - } + if (protocol != MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_NETWORK_PROTOCOL_VALUE_UDP) + { + validationErrorMessage = L"Invalid network protocol '" + protocol + L"' specified."; - definition.EntryIdentifier = internal::TrimmedHStringCopy(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_ENTRY_IDENTIFIER_KEY, L"")); + } - definition.UmpEndpointName = internal::TrimmedHStringCopy(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_COMMON_NAME_PROPERTY, L"")); - definition.ProductInstanceId = internal::TrimmedHStringCopy(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_PRODUCT_INSTANCE_ID_PROPERTY, L"")); + definition.EntryIdentifier = internal::TrimmedHStringCopy(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_ENTRY_IDENTIFIER_KEY, L"")); - definition.Authentication = MidiNetworkHostAuthenticationFromJsonString(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_HOST_AUTHENTICATION_KEY, L"")); - definition.ConnectionPolicy = MidiNetworkHostConnectionPolicyFromJsonString(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_CONNECTION_POLICY_KEY, L"")); + definition.UmpEndpointName = internal::TrimmedHStringCopy(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_COMMON_NAME_PROPERTY, L"")); + definition.ProductInstanceId = internal::TrimmedHStringCopy(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_PRODUCT_INSTANCE_ID_PROPERTY, L"")); - // read the list of ip info - if (definition.ConnectionPolicy != MidiNetworkHostConnectionPolicy::PolicyAllowAllConnections) - { - auto addressArray = hostEntry.GetNamedArray(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_CONNECTION_POLICY_IPV4_ADDRESSES_KEY); + definition.Authentication = MidiNetworkHostAuthenticationFromJsonString(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_HOST_AUTHENTICATION_KEY, L"")); + definition.ConnectionPolicy = MidiNetworkHostConnectionPolicyFromJsonString(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_CONNECTION_POLICY_KEY, L"")); - for (uint32_t j = 0; j < addressArray.Size(); j++) + // read the list of ip info + if (definition.ConnectionPolicy != MidiNetworkHostConnectionPolicy::PolicyAllowAllConnections) { - auto addressEntry = addressArray.GetStringAt(j); - - HostName address(addressEntry); + auto addressArray = hostEntry.GetNamedArray(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_CONNECTION_POLICY_IPV4_ADDRESSES_KEY); - definition.IpAddresses.push_back(address); - } - } + for (uint32_t j = 0; j < addressArray.Size(); j++) + { + auto addressEntry = addressArray.GetStringAt(j); - // read authentication information - if (definition.Authentication != MidiNetworkHostAuthentication::NoAuthentication) - { + HostName address(addressEntry); - if (definition.Authentication == MidiNetworkHostAuthentication::PasswordAuthentication) - { - // TODO: Read the password vault key - } - else if (definition.Authentication == MidiNetworkHostAuthentication::UserAuthentication) - { - // TODO: Read username/password vault key - } - else - { - // no authentication provided + definition.IpAddresses.push_back(address); + } } - } + // read authentication information + if (definition.Authentication != MidiNetworkHostAuthentication::NoAuthentication) + { - // generate host name and other info + if (definition.Authentication == MidiNetworkHostAuthentication::PasswordAuthentication) + { + // TODO: Read the password vault key + } + else if (definition.Authentication == MidiNetworkHostAuthentication::UserAuthentication) + { + // TODO: Read username/password vault key + } + else + { + // no authentication provided + } + } - auto serviceInstanceNamePrefix = internal::TrimmedHStringCopy(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_SERVICE_INSTANCE_NAME_KEY, L"")); + // generate host name and other info - // if the provided service instance name is empty, default to - // machine name. If that name is already in use, add an additional - // disambiguation value - if (serviceInstanceNamePrefix.empty()) - { - std::wstring buffer{}; - DWORD bufferSize = MAX_COMPUTERNAME_LENGTH + 1; - buffer.resize(bufferSize); + auto serviceInstanceNamePrefix = internal::TrimmedHStringCopy(hostEntry.GetNamedString(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_SERVICE_INSTANCE_NAME_KEY, L"")); - bool validName = GetComputerName(buffer.data(), &bufferSize); - if (validName) + // if the provided service instance name is empty, default to + // machine name. If that name is already in use, add an additional + // disambiguation value + if (serviceInstanceNamePrefix.empty()) { - serviceInstanceNamePrefix = buffer; + std::wstring buffer{}; + DWORD bufferSize = MAX_COMPUTERNAME_LENGTH + 1; + buffer.resize(bufferSize); + + bool validName = GetComputerName(buffer.data(), &bufferSize); + if (validName) + { + serviceInstanceNamePrefix = buffer; + } } - } - definition.ServiceInstanceName = serviceInstanceNamePrefix; + definition.ServiceInstanceName = serviceInstanceNamePrefix; - // TODO: See if the serviceInstanceName is already in use. If so, add a disambiguation number. Keep trying until unused one is found + // TODO: See if the serviceInstanceName is already in use. If so, add a disambiguation number. Keep trying until unused one is found - // validate the entry + // validate the entry - if (SUCCEEDED(ValidateHostDefinition(definition, validationErrorMessage))) - { - // create the host + if (SUCCEEDED(ValidateHostDefinition(definition, validationErrorMessage))) + { + // create the host + + auto host = std::make_shared(); - auto host = std::make_shared(); + RETURN_HR_IF_NULL(E_POINTER, host); + RETURN_IF_FAILED(host->Initialize(definition)); - RETURN_HR_IF_NULL(E_POINTER, host); - RETURN_IF_FAILED(host->Initialize(definition)); + // add to our collection of hosts + TransportState::Current().AddHost(host); + + // start the network host asynchonously + RETURN_IF_FAILED(host->Start()); + } + else + { + // invalid entry + } - // TODO: add to our collection of hosts - TransportState::Current().AddHost(host); - - // start the network host - RETURN_IF_FAILED(host->Start()); } - else + else if (auto clientEntry = jsonEntry.GetNamedObject(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_CLIENT_KEY, nullptr); clientEntry != nullptr) { - // invalid entry + // TODO: Add to the client reconnect table } - - - } - else if (auto clientEntry = jsonEntry.GetNamedObject(MIDI_CONFIG_JSON_ENDPOINT_NETWORK_MIDI_CLIENT_KEY, nullptr); clientEntry != nullptr) - { - // TODO: Add to the client reconnect table } - } } + if (updateArray != nullptr && updateArray.Size() > 0) + { + // TODO: Implement update + } + + if (removeArray != nullptr && removeArray.Size() > 0) + { + // TODO: Implement remove + } + + //responseObject.SetNamedValue( // MIDI_CONFIG_JSON_ENDPOINT_VIRTUAL_DEVICE_RESPONSE_CREATED_DEVICES_ARRAY_KEY, // createdDevicesResponseArray); - // TODO: Process all "update" and "remove" instructions - TraceLoggingWrite( MidiNetworkMidiTransportTelemetryProvider::Provider(), diff --git a/src/api/Transport/VirtualPatchbay/Midi2.VirtualPatchBayTransport.vcxproj b/src/api/Transport/VirtualPatchbay/Midi2.VirtualPatchBayTransport.vcxproj index 0dd31f940..a79804b58 100644 --- a/src/api/Transport/VirtualPatchbay/Midi2.VirtualPatchBayTransport.vcxproj +++ b/src/api/Transport/VirtualPatchbay/Midi2.VirtualPatchBayTransport.vcxproj @@ -287,7 +287,7 @@ - + diff --git a/src/api/Transport/VirtualPatchbay/Midi2.VirtualPatchBayTransport.vcxproj.filters b/src/api/Transport/VirtualPatchbay/Midi2.VirtualPatchBayTransport.vcxproj.filters index 17305ef28..b2973b0f7 100644 --- a/src/api/Transport/VirtualPatchbay/Midi2.VirtualPatchBayTransport.vcxproj.filters +++ b/src/api/Transport/VirtualPatchbay/Midi2.VirtualPatchBayTransport.vcxproj.filters @@ -24,9 +24,6 @@ Source Files - - Source Files - Source Files @@ -36,9 +33,6 @@ Source Files - - Source Files - Source Files @@ -48,15 +42,21 @@ Source Files + + Source Files + + + Source Files + - + + Source Files - + Resource Files - @@ -71,12 +71,6 @@ Header Files - - Header Files - - - Header Files - Header Files @@ -86,9 +80,6 @@ Header Files - - Header Files - Header Files @@ -98,17 +89,26 @@ Header Files + + Header Files + + + Header Files + + + Header Files + - + Resource Files - + Source Files diff --git a/src/app-sdk/mididiag/mididiag.vcxproj b/src/app-sdk/mididiag/mididiag.vcxproj index 34e96b6d6..bea533c1a 100644 --- a/src/app-sdk/mididiag/mididiag.vcxproj +++ b/src/app-sdk/mididiag/mididiag.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241125-206 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 true true true diff --git a/src/app-sdk/mididiag/packages.config b/src/app-sdk/mididiag/packages.config index f115fcd8f..e478c2039 100644 --- a/src/app-sdk/mididiag/packages.config +++ b/src/app-sdk/mididiag/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/app-sdk/midiusbinfo/midiusbinfo.vcxproj b/src/app-sdk/midiusbinfo/midiusbinfo.vcxproj index 987fe84f8..58e4c440b 100644 --- a/src/app-sdk/midiusbinfo/midiusbinfo.vcxproj +++ b/src/app-sdk/midiusbinfo/midiusbinfo.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241125-206 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 true true true diff --git a/src/app-sdk/midiusbinfo/packages.config b/src/app-sdk/midiusbinfo/packages.config index f115fcd8f..e478c2039 100644 --- a/src/app-sdk/midiusbinfo/packages.config +++ b/src/app-sdk/midiusbinfo/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/dev-tools/reg-helpers/midi-list-reg.ps1 b/src/dev-tools/reg-helpers/midi-list-reg.ps1 index dcdfb37ed..ddc6fbad6 100644 --- a/src/dev-tools/reg-helpers/midi-list-reg.ps1 +++ b/src/dev-tools/reg-helpers/midi-list-reg.ps1 @@ -2,7 +2,7 @@ function Show-MidiRegInproc32([String] $key, [String] $comment) { - Write-Host $comment.PadRight(30) -NoNewline -ForegroundColor DarkGray + Write-Host $comment.PadRight(22) -NoNewline -ForegroundColor DarkCyan #Write-Host " : " -NoNewline -ForegroundColor White $info = Get-ItemProperty -Path $key -Name "(default)" -ErrorAction SilentlyContinue @@ -13,19 +13,62 @@ } else { - Write-Host $info."(default)" -ForegroundColor DarkCyan + Write-Host $info."(default)" -ForegroundColor Cyan } } - Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{0f273b18-e372-4d95-87ac-c31c3d22e937}\InprocServer32" "KS Aggregate Transport" - Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{26FA740D-469C-4D33-BEB1-3885DE7D6DF1}\InprocServer32" "KS Transport" - Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{942BF02D-93C0-4EA8-B03E-D51156CA75E1}\InprocServer32" "Loopback Transport" - Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{8FEAAD91-70E1-4A19-997A-377720A719C1}\InprocServer32" "Virtual MIDI Transport" - Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{ac9b5417-3fe0-4e62-960f-034ee4235a1a}\InprocServer32" "Diagnostics Transport" - Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{2BA15E4E-5417-4A66-85B8-2B2260EFBC84}\InprocServer32" "Main Midisrv Transport" + Write-Host + Write-Host "Windows MIDI Services Developer Component Registration List" -ForegroundColor DarkCyan + Write-Host "".PadRight(75,'=') -ForegroundColor DarkGray + Write-Host "This queries the registry for current Windows MIDI Services registrations." -ForegroundColor DarkCyan + Write-Host "If the paths include System32, you are using in-box components and not the." -ForegroundColor DarkCyan + Write-Host "developer preview versions from GitHub. To install the bits from GitHub, " -ForegroundColor DarkCyan + Write-Host "you will need to run the dev-prep script before running the installer." -ForegroundColor DarkCyan + Write-Host + + + # display info about the MIDI Service that is installed - Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{A8798C54-6066-45F0-9ADB-648BC0641ABF}\InprocServer32" "Bytestream 2 UMP Transform" - Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{96121591-8D68-479F-9B48-2BF0B90113F7}\InprocServer32" "UMP 2 Bytestream Transform" + Write-Host + Write-Host "Windows Service " -ForegroundColor DarkGray + + $service = Get-Service -Name "midisrv" -ErrorAction SilentlyContinue + + if ($service -eq $null) + { + Write-Host "Midisrv service is not present. " -ForegroundColor DarkGray + } + else + { + Write-Host $service.DisplayName.PadRight(22) -NoNewline -ForegroundColor DarkCyan + Write-Host $service.BinaryPathName -ForegroundColor Cyan + } + + # Now all the registry entries for COM objects used by the service. This list must be + # Manually maintained + + Write-Host + Write-Host "API Interface " -ForegroundColor DarkGray + Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{2BA15E4E-5417-4A66-85B8-2B2260EFBC84}\InprocServer32" "Midisrv" + + Write-Host + Write-Host "V1.0 In-Box Transports " -ForegroundColor DarkGray + Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{0f273b18-e372-4d95-87ac-c31c3d22e937}\InprocServer32" "KS Aggregate (MIDI 1)" + Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{26FA740D-469C-4D33-BEB1-3885DE7D6DF1}\InprocServer32" "KS (UMP)" + Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{942BF02D-93C0-4EA8-B03E-D51156CA75E1}\InprocServer32" "Loopback" + Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{8FEAAD91-70E1-4A19-997A-377720A719C1}\InprocServer32" "Virtual MIDI" + Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{ac9b5417-3fe0-4e62-960f-034ee4235a1a}\InprocServer32" "Diagnostics" + + Write-Host + Write-Host "Preview Transports " -ForegroundColor DarkGray + Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{c95dcd1f-cde3-4c2d-913c-528cb8a4cbe6}\InprocServer32" "Network MIDI 2.0" + + Write-Host + Write-Host "V1.0 In-Box Transforms " -ForegroundColor DarkGray + Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{A8798C54-6066-45F0-9ADB-648BC0641ABF}\InprocServer32" "Bytestream 2 UMP" + Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{96121591-8D68-479F-9B48-2BF0B90113F7}\InprocServer32" "UMP 2 Bytestream" Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{a42cde44-7fa9-4597-a8ee-b40b96bcddb1}\InprocServer32" "Message Scheduler" Show-MidiRegInproc32 "Registry::HKEY_CLASSES_ROOT\CLSID\{dc638b31-cf31-48ed-9e79-02740bf5d013}\InprocServer32" "Protocol Downscaler" + + diff --git a/src/oob-setup/api-package/WindowsMidiServices.wxs b/src/oob-setup/api-package/WindowsMidiServices.wxs index 0e62d687c..f3d9c81a0 100644 --- a/src/oob-setup/api-package/WindowsMidiServices.wxs +++ b/src/oob-setup/api-package/WindowsMidiServices.wxs @@ -84,6 +84,7 @@ + - - + diff --git a/src/user-tools/midi-console/Midi/Commands/Endpoint/EndpointPropertiesCommand.cs b/src/user-tools/midi-console/Midi/Commands/Endpoint/EndpointPropertiesCommand.cs index 29e586d51..ad49d20ba 100644 --- a/src/user-tools/midi-console/Midi/Commands/Endpoint/EndpointPropertiesCommand.cs +++ b/src/user-tools/midi-console/Midi/Commands/Endpoint/EndpointPropertiesCommand.cs @@ -249,13 +249,13 @@ public override int Execute(CommandContext context, Settings settings) if (functionBlock.GroupCount == 1) { functionInformation += - $"[grey]{Strings.CommonStringGroupSingular}[/] {functionBlock.FirstGroupIndex + 1} ({Strings.CommonStringIndexSingular} {functionBlock.FirstGroupIndex})"; + $"[grey]{Strings.CommonStringGroupSingular}[/] {functionBlock.FirstGroup.DisplayValue} ({Strings.CommonStringIndexSingular} {functionBlock.FirstGroup.Index})"; } else { - int stopGroupIndex = functionBlock.FirstGroupIndex + functionBlock.GroupCount - 1; + int stopGroupIndex = functionBlock.FirstGroup.Index + functionBlock.GroupCount - 1; functionInformation += - $"[grey]{Strings.CommonStringGroupPlural}[/] {functionBlock.FirstGroupIndex + 1}-{stopGroupIndex + 1} ({Strings.CommonStringIndexPlural} {functionBlock.FirstGroupIndex}-{stopGroupIndex})"; + $"[grey]{Strings.CommonStringGroupPlural}[/] {functionBlock.FirstGroup.DisplayValue}-{stopGroupIndex + 1} ({Strings.CommonStringIndexPlural} {functionBlock.FirstGroup.Index}-{stopGroupIndex})"; } @@ -286,17 +286,17 @@ public override int Execute(CommandContext context, Settings settings) table.AddEmptyRow(); table.AddRow(Strings.PropertyTablePropertyLabelFunctionBlock, AnsiMarkupFormatter.FormatBlockNumber(functionBlock.Number) + " " + AnsiMarkupFormatter.FormatBlockName(functionBlock.Name)); table.AddRow(Strings.PropertyTablePropertyLabelFunctionBlockActive, functionBlock.IsActive.ToString()); - table.AddRow(Strings.PropertyTablePropertyLabelFunctionBlockFirstGroupIndex, functionBlock.FirstGroupIndex.ToString()); + table.AddRow(Strings.PropertyTablePropertyLabelFunctionBlockFirstGroupIndex, functionBlock.FirstGroup.Index.ToString()); table.AddRow(Strings.PropertyTablePropertyLabelFunctionBlockGroupCount, functionBlock.GroupCount.ToString()); if (functionBlock.GroupCount == 1) { - table.AddRow(Strings.CommonStringGroupSingular, $"{functionBlock.FirstGroupIndex + 1} ({Strings.CommonStringIndexSingular} {functionBlock.FirstGroupIndex})"); + table.AddRow(Strings.CommonStringGroupSingular, $"{functionBlock.FirstGroup.DisplayValue} ({Strings.CommonStringIndexSingular} {functionBlock.FirstGroup.Index})"); } else { - int stopGroupIndex = functionBlock.FirstGroupIndex + functionBlock.GroupCount - 1; - table.AddRow(Strings.CommonStringGroupPlural, $"{functionBlock.FirstGroupIndex + 1}-{stopGroupIndex + 1} ({Strings.CommonStringIndexPlural} {functionBlock.FirstGroupIndex}-{stopGroupIndex})"); + int stopGroupIndex = functionBlock.FirstGroup.Index + functionBlock.GroupCount - 1; + table.AddRow(Strings.CommonStringGroupPlural, $"{functionBlock.FirstGroup.DisplayValue}-{stopGroupIndex + 1} ({Strings.CommonStringIndexPlural} {functionBlock.FirstGroup.Index}-{stopGroupIndex})"); } if (settings.Verbose) @@ -353,13 +353,13 @@ public override int Execute(CommandContext context, Settings settings) if (groupTerminalBlock.GroupCount == 1) { groupInformation += - $"[grey]{Strings.CommonStringGroupSingular}[/] {groupTerminalBlock.FirstGroupIndex + 1} ({Strings.CommonStringIndexSingular} {groupTerminalBlock.FirstGroupIndex})"; + $"[grey]{Strings.CommonStringGroupSingular}[/] {groupTerminalBlock.FirstGroup.DisplayValue} ({Strings.CommonStringIndexSingular} {groupTerminalBlock.FirstGroup.Index})"; } else { - int stopGroupIndex = groupTerminalBlock.FirstGroupIndex + groupTerminalBlock.GroupCount - 1; + int stopGroupIndex = groupTerminalBlock.FirstGroup.Index + groupTerminalBlock.GroupCount - 1; groupInformation += - $"[grey]{Strings.CommonStringGroupPlural}[/] {groupTerminalBlock.FirstGroupIndex + 1}-{stopGroupIndex + 1} ({Strings.CommonStringIndexPlural} {groupTerminalBlock.FirstGroupIndex}-{stopGroupIndex})"; + $"[grey]{Strings.CommonStringGroupPlural}[/] {groupTerminalBlock.FirstGroup.DisplayValue}-{stopGroupIndex + 1} ({Strings.CommonStringIndexPlural} {groupTerminalBlock.FirstGroup.Index}-{stopGroupIndex})"; } @@ -379,12 +379,12 @@ public override int Execute(CommandContext context, Settings settings) if (groupTerminalBlock.GroupCount == 1) { - table.AddRow(Strings.CommonStringGroupSingular, $"{groupTerminalBlock.FirstGroupIndex + 1} ({Strings.CommonStringIndexSingular} {groupTerminalBlock.FirstGroupIndex})"); + table.AddRow(Strings.CommonStringGroupSingular, $"{groupTerminalBlock.FirstGroup.DisplayValue} ({Strings.CommonStringIndexSingular} {groupTerminalBlock.FirstGroup.Index})"); } else { - int stopGroupIndex = groupTerminalBlock.FirstGroupIndex + groupTerminalBlock.GroupCount - 1; - table.AddRow(Strings.CommonStringGroupPlural, $"{groupTerminalBlock.FirstGroupIndex + 1}-{stopGroupIndex + 1} ({Strings.CommonStringIndexPlural} {groupTerminalBlock.FirstGroupIndex}-{stopGroupIndex})"); + int stopGroupIndex = groupTerminalBlock.FirstGroup.Index + groupTerminalBlock.GroupCount - 1; + table.AddRow(Strings.CommonStringGroupPlural, $"{groupTerminalBlock.FirstGroup.DisplayValue}-{stopGroupIndex + 1} ({Strings.CommonStringIndexPlural} {groupTerminalBlock.FirstGroup.Index}-{stopGroupIndex})"); } table.AddRow(Strings.PropertyTablePropertyLabelGTBGroupCount, groupTerminalBlock.GroupCount.ToString()); diff --git a/src/user-tools/midi-console/Midi/Commands/Enumerate/EnumEndpointsCommand.cs b/src/user-tools/midi-console/Midi/Commands/Enumerate/EnumEndpointsCommand.cs index 6ebd7387f..9e5fdc141 100644 --- a/src/user-tools/midi-console/Midi/Commands/Enumerate/EnumEndpointsCommand.cs +++ b/src/user-tools/midi-console/Midi/Commands/Enumerate/EnumEndpointsCommand.cs @@ -184,7 +184,7 @@ private void DisplayEndpointInformationFormatted(Table table, Settings settings, blockTable.AddRow( AnsiMarkupFormatter.FormatBlockName(block.Name), block.Direction.ToString(), - AnsiMarkupFormatter.FormatGroupSpan(block.FirstGroupIndex, block.GroupCount), + AnsiMarkupFormatter.FormatGroupSpan(block.FirstGroup.Index, block.GroupCount), block.IsActive.ToString() ); } @@ -206,7 +206,7 @@ private void DisplayEndpointInformationFormatted(Table table, Settings settings, blockTable.AddRow( AnsiMarkupFormatter.FormatBlockName(block.Name), block.Direction.ToString(), - AnsiMarkupFormatter.FormatGroupSpan(block.FirstGroupIndex, block.GroupCount) + AnsiMarkupFormatter.FormatGroupSpan(block.FirstGroup.Index, block.GroupCount) ); } From 3833d39fed6f2c854013b44d57c97552920ffe7a Mon Sep 17 00:00:00 2001 From: Pete Brown Date: Wed, 27 Nov 2024 20:41:39 -0500 Subject: [PATCH 03/10] Update notes about winrt::init_apartment() in cpp samples --- samples/cpp-winrt/basics/main.cpp | 7 ++++++- samples/cpp-winrt/loopback-endpoints/main.cpp | 6 ++++++ samples/cpp-winrt/send-speed/main.cpp | 6 ++++++ samples/cpp-winrt/static-enum-endpoints/main.cpp | 6 ++++++ samples/cpp-winrt/watch-endpoints/main.cpp | 6 ++++++ 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/samples/cpp-winrt/basics/main.cpp b/samples/cpp-winrt/basics/main.cpp index ad4b7ed42..a848916f8 100644 --- a/samples/cpp-winrt/basics/main.cpp +++ b/samples/cpp-winrt/basics/main.cpp @@ -39,7 +39,12 @@ namespace init = Microsoft::Windows::Devices::Midi2::Initialization; int main() { - // initialize the threading before calling the bootstrapper or any WinRT code + // initialize the thread before calling the bootstrapper or any WinRT code. You may also + // be able to leave this out and call RoInitialize() or CoInitializeEx() before creating + // the initializer. + //winrt::init_apartment(winrt::apartment_type::single_threaded); + + // MTA by default winrt::init_apartment(); // this is the initializer in the bootstrapper hpp file diff --git a/samples/cpp-winrt/loopback-endpoints/main.cpp b/samples/cpp-winrt/loopback-endpoints/main.cpp index c3d20bc97..f968021ed 100644 --- a/samples/cpp-winrt/loopback-endpoints/main.cpp +++ b/samples/cpp-winrt/loopback-endpoints/main.cpp @@ -84,6 +84,12 @@ bool CreateLoopbackEndpoints() int main() { + // initialize the thread before calling the bootstrapper or any WinRT code. You may also + // be able to leave this out and call RoInitialize() or CoInitializeEx() before creating + // the initializer. + //winrt::init_apartment(winrt::apartment_type::single_threaded); + + // MTA by default winrt::init_apartment(); // this is the initializer in the bootstrapper hpp file diff --git a/samples/cpp-winrt/send-speed/main.cpp b/samples/cpp-winrt/send-speed/main.cpp index c4ed73d2a..37ff5da8e 100644 --- a/samples/cpp-winrt/send-speed/main.cpp +++ b/samples/cpp-winrt/send-speed/main.cpp @@ -58,6 +58,12 @@ void DisplaySingleResult(std::wstring label, uint64_t totalTime, uint64_t errorC int main() { + // initialize the thread before calling the bootstrapper or any WinRT code. You may also + // be able to leave this out and call RoInitialize() or CoInitializeEx() before creating + // the initializer. + //winrt::init_apartment(winrt::apartment_type::single_threaded); + + // MTA by default winrt::init_apartment(); // this is the initializer in the bootstrapper hpp file diff --git a/samples/cpp-winrt/static-enum-endpoints/main.cpp b/samples/cpp-winrt/static-enum-endpoints/main.cpp index f684c935e..f8144abd7 100644 --- a/samples/cpp-winrt/static-enum-endpoints/main.cpp +++ b/samples/cpp-winrt/static-enum-endpoints/main.cpp @@ -37,6 +37,12 @@ std::string BooleanToString(bool value) int main() { + // initialize the thread before calling the bootstrapper or any WinRT code. You may also + // be able to leave this out and call RoInitialize() or CoInitializeEx() before creating + // the initializer. + //winrt::init_apartment(winrt::apartment_type::single_threaded); + + // MTA by default winrt::init_apartment(); // this is the initializer in the bootstrapper hpp file diff --git a/samples/cpp-winrt/watch-endpoints/main.cpp b/samples/cpp-winrt/watch-endpoints/main.cpp index d1174997c..3251b597a 100644 --- a/samples/cpp-winrt/watch-endpoints/main.cpp +++ b/samples/cpp-winrt/watch-endpoints/main.cpp @@ -40,6 +40,12 @@ std::string BooleanToString(bool value) int main() { + // initialize the thread before calling the bootstrapper or any WinRT code. You may also + // be able to leave this out and call RoInitialize() or CoInitializeEx() before creating + // the initializer. + //winrt::init_apartment(winrt::apartment_type::single_threaded); + + // MTA by default winrt::init_apartment(); // this is the initializer in the bootstrapper hpp file From d08433801f7cdd9337d543f8f523e7d2b0e12afb Mon Sep 17 00:00:00 2001 From: Pete Brown Date: Wed, 27 Nov 2024 20:41:44 -0500 Subject: [PATCH 04/10] Update midi-pre-install-reg-steps.ps1 --- src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 b/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 index bfdc738de..eaebe90a2 100644 --- a/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 +++ b/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 @@ -131,7 +131,7 @@ if ($confirmation -eq 'y' -or $confirmation -eq 'Y') if (Get-Process -Name "midisrv" -ErrorAction SilentlyContinue) { - Stop-Process -Name -Force "midisrv" + Stop-Process -Name "midisrv" -Force Write-Host "Stopped midisrv process" -ForegroundColor DarkCyan } else From 9afe46367c0c314c3e98710b3840347b8e7cefd0 Mon Sep 17 00:00:00 2001 From: Pete Brown Date: Thu, 28 Nov 2024 13:04:11 -0500 Subject: [PATCH 05/10] Update midi-pre-install-reg-steps.ps1 --- .../reg-helpers/midi-pre-install-reg-steps.ps1 | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 b/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 index eaebe90a2..3a474c741 100644 --- a/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 +++ b/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 @@ -7,6 +7,8 @@ # https://powertoe.wordpress.com/2010/08/28/controlling-registry-acl-permissions-with-powershell/ +#Requires -RunAsAdministrator +#Requires -Version 6.0 function Take-Permissions { @@ -86,13 +88,17 @@ Write-Host "Windows MIDI Services Developer Prep Script" -ForegroundColor DarkCy Write-Host "=========================================================================" -ForegroundColor DarkGray Write-Host "This script is for developers and power users who need to run development" -ForegroundColor DarkCyan Write-Host "builds of Windows MIDI Services on a Windows PC which has the public" -ForegroundColor DarkCyan -Write-Host "release already installed. This must be run in administrator mode." -ForegroundColor DarkCyan +Write-Host "release already installed." -ForegroundColor DarkCyan Write-Host -Write-Host "Running this script will change registry permissions to enable the" -ForegroundColor DarkCyan -Write-Host "installer to install developer bits, and will also de-register the in-box" -ForegroundColor DarkCyan -Write-Host "'Midisrv' Windows MIDI Service." -ForegroundColor DarkCyan +Write-Host "Running this script will change registry permissions to take ownership of " -ForegroundColor DarkCyan +Write-Host "the component registry entries from Trusted Installer and grant them to you" -ForegroundColor DarkCyan +Write-Host "to enable the Developer Preview installer to install developer bits. This" -ForegroundColor DarkCyan +Write-Host "will also de-register the in-box 'Midisrv' Windows MIDI Service." -ForegroundColor DarkCyan Write-Host -Write-Host "These actions are not easily reversible without reinstalling Windows." -ForegroundColor Cyan +Write-Host "This script must be run from an elevated command prompt using the " -ForegroundColor LightkCyan +Write-Host "'Run as Administrator' feature or (if enabled) 'sudo'. " -ForegroundColor LightCyan +Write-Host +Write-Host "These actions are not easily reversible without reinstalling Windows." -ForegroundColor DarkCyan Write-Host $confirmation = Read-Host "Do you want to continue? (y/n)" From 09f429d8710b3d7ce50549e6916a0e8362f1d916 Mon Sep 17 00:00:00 2001 From: Pete Brown Date: Thu, 28 Nov 2024 13:04:27 -0500 Subject: [PATCH 06/10] Network MIDI work --- src/app-sdk/app-sdk-tools-and-tests.sln | 19 + src/app-sdk/coalesce/pch.h | 2 +- src/app-sdk/midimdnsinfo/color.hpp | 881 ++++++++++++++++++ src/app-sdk/midimdnsinfo/main.cpp | 41 + src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj | 204 ++++ .../midimdnsinfo/midimdnsinfo.vcxproj.filters | 39 + src/app-sdk/midimdnsinfo/packages.config | 6 + src/app-sdk/midimdnsinfo/pch.cpp | 10 + src/app-sdk/midimdnsinfo/pch.h | 74 ++ .../WindowsMidiServicesSdkRedist.wxs | 10 +- .../Microsoft.Windows.Devices.Midi2.vcxproj | 1 + ...soft.Windows.Devices.Midi2.vcxproj.filters | 3 + src/app-sdk/winrt/MidiAdvertisedHost.idl | 26 + .../winrt/MidiNetworkEndpointManager.cpp | 64 ++ .../winrt/MidiNetworkEndpointManager.h | 36 +- .../winrt/MidiNetworkEndpointManager.idl | 5 + 16 files changed, 1410 insertions(+), 11 deletions(-) create mode 100644 src/app-sdk/midimdnsinfo/color.hpp create mode 100644 src/app-sdk/midimdnsinfo/main.cpp create mode 100644 src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj create mode 100644 src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj.filters create mode 100644 src/app-sdk/midimdnsinfo/packages.config create mode 100644 src/app-sdk/midimdnsinfo/pch.cpp create mode 100644 src/app-sdk/midimdnsinfo/pch.h create mode 100644 src/app-sdk/winrt/MidiAdvertisedHost.idl diff --git a/src/app-sdk/app-sdk-tools-and-tests.sln b/src/app-sdk/app-sdk-tools-and-tests.sln index 89715e3b8..02f1e8431 100644 --- a/src/app-sdk/app-sdk-tools-and-tests.sln +++ b/src/app-sdk/app-sdk-tools-and-tests.sln @@ -19,6 +19,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "midiusbinfo", "midiusbinfo\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SdkInitialization.unittests", "tests\SdkInitialization.unittests\SdkInitialization.unittests.vcxproj", "{9803D8E6-5CA5-420C-A02B-5E3327355041}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "midimdnsinfo", "midimdnsinfo\midimdnsinfo.vcxproj", "{C787073C-50F0-5CA0-D53C-12107196F2F0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -127,6 +129,22 @@ Global {9803D8E6-5CA5-420C-A02B-5E3327355041}.Release|ARM64EC.Build.0 = Release|x64 {9803D8E6-5CA5-420C-A02B-5E3327355041}.Release|x64.ActiveCfg = Release|x64 {9803D8E6-5CA5-420C-A02B-5E3327355041}.Release|x64.Build.0 = Release|x64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Debug|Any CPU.ActiveCfg = Debug|x64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Debug|Any CPU.Build.0 = Debug|x64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Debug|ARM64.Build.0 = Debug|ARM64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Debug|ARM64EC.Build.0 = Debug|ARM64EC + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Debug|x64.ActiveCfg = Debug|x64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Debug|x64.Build.0 = Debug|x64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|Any CPU.ActiveCfg = Release|x64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|Any CPU.Build.0 = Release|x64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|ARM64.ActiveCfg = Release|ARM64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|ARM64.Build.0 = Release|ARM64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|ARM64EC.Build.0 = Release|ARM64EC + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|x64.ActiveCfg = Release|x64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -138,6 +156,7 @@ Global {4DABE157-7DD5-422A-8C77-B83EAC9987D0} = {900D72D2-91F0-4E6C-B694-192FD48393D2} {0F688DE9-BE99-4A86-BE79-C5BE32BC471D} = {C8B31D71-0226-4D2D-AC78-53D5C84F472F} {9803D8E6-5CA5-420C-A02B-5E3327355041} = {900D72D2-91F0-4E6C-B694-192FD48393D2} + {C787073C-50F0-5CA0-D53C-12107196F2F0} = {C8B31D71-0226-4D2D-AC78-53D5C84F472F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AE1DF8B9-9FAB-4E20-8AC6-FF316882222F} diff --git a/src/app-sdk/coalesce/pch.h b/src/app-sdk/coalesce/pch.h index f1153d7a7..1861a96c8 100644 --- a/src/app-sdk/coalesce/pch.h +++ b/src/app-sdk/coalesce/pch.h @@ -19,7 +19,7 @@ namespace foundation = winrt::Windows::Foundation; namespace collections = winrt::Windows::Foundation::Collections; - +namespace enumeration = winrt::Windows::Devices::Enumeration; #include #include diff --git a/src/app-sdk/midimdnsinfo/color.hpp b/src/app-sdk/midimdnsinfo/color.hpp new file mode 100644 index 000000000..cb080b6e5 --- /dev/null +++ b/src/app-sdk/midimdnsinfo/color.hpp @@ -0,0 +1,881 @@ +// source: https://github.com/aafulei/color-console/blob/master/include/color.hpp + + +#ifndef COLOR_HPP +#define COLOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace hue +{ + constexpr int DEFAULT_COLOR = 7; + constexpr int BAD_COLOR = -256; + + const std::map CODES = { + {"black", 0}, {"k", 0}, + {"blue", 1}, {"b", 1}, + {"green", 2}, {"g", 2}, + {"aqua", 3}, {"a", 3}, + {"red", 4}, {"r", 4}, + {"purple", 5}, {"p", 5}, + {"yellow", 6}, {"y", 6}, + {"white", 7}, {"w", 7}, + {"grey", 8}, {"e", 8}, + {"light blue", 9}, {"lb", 9}, + {"light green", 10}, {"lg", 10}, + {"light aqua", 11}, {"la", 11}, + {"light red", 12}, {"lr", 12}, + {"light purple", 13}, {"lp", 13}, + {"light yellow", 14}, {"ly", 14}, + {"bright white", 15}, {"bw", 15} + }; + + const std::map NAMES = { + { 0, "black"}, + { 1, "blue"}, + { 2, "green"}, + { 3, "aqua"}, + { 4, "red"}, + { 5, "purple"}, + { 6, "yellow"}, + { 7, "white"}, + { 8, "grey"}, + { 9, "light blue"}, + {10, "light green"}, + {11, "light aqua"}, + {12, "light red"}, + {13, "light purple"}, + {14, "light yellow"}, + {15, "bright white"} + }; + + inline bool is_good(int c) + { + return 0 <= c && c < 256; + } + + inline int itoc(int c) + { + return is_good(c) ? c : BAD_COLOR; + } + + inline int itoc(int a, int b) + { + return itoc(a + b * 16); + } + + // std::string to color + int stoc(std::string a) + { + // convert s to lowercase, and format variants like "light_blue" + std::transform(a.begin(), a.end(), a.begin(), [](char c) + { + if ('A' <= c && c <= 'Z') + c = c - 'A' + 'a'; + else if (c == '_' || c == '-') + c = ' '; + return c; + }); + + // operator[] on std::map is non-const, use std::map::at instead + return (CODES.find(a) != CODES.end()) ? CODES.at(a) : BAD_COLOR; + } + + int stoc(std::string a, std::string b) + { + return itoc(stoc(a), stoc(b)); + } + + std::string ctos(int c) + { + return (0 <= c && c < 256) ? + "(text) " + NAMES.at(c % 16) + " + " + + "(background) " + NAMES.at(c / 16) : + "BAD COLOR"; + } + + int get() + { + CONSOLE_SCREEN_BUFFER_INFO i; + return GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &i) ? + i.wAttributes : BAD_COLOR; + } + + int get_text() + { + return (get() != BAD_COLOR) ? get() % 16 : BAD_COLOR; + } + + int get_background() + { + return (get() != BAD_COLOR) ? get() / 16 : BAD_COLOR; + } + + void set(int c) + { + if (is_good(c)) + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); + } + + void set(int a, int b) + { + set(a + b * 16); + } + + void set(std::string a, std::string b) + { + set(stoc(a) + stoc(b) * 16); + } + + void set_text(std::string a) + { + set(stoc(a), get_background()); + } + + void set_background(std::string b) + { + set(get_text(), stoc(b)); + } + + void reset() + { + set(DEFAULT_COLOR); + } + + int invert(int c) + { + if (is_good(c)) { + int a = c % 16; + int b = c / 16; + return b + a * 16; + } + else + return BAD_COLOR; + } + + std::ostream& reset(std::ostream& os) { reset(); return os; } + std::ostream& black(std::ostream& os) { set_text("k"); return os; } + std::ostream& blue(std::ostream& os) { set_text("b"); return os; } + std::ostream& green(std::ostream& os) { set_text("g"); return os; } + std::ostream& aqua(std::ostream& os) { set_text("a"); return os; } + std::ostream& red(std::ostream& os) { set_text("r"); return os; } + std::ostream& purple(std::ostream& os) { set_text("p"); return os; } + std::ostream& yellow(std::ostream& os) { set_text("y"); return os; } + std::ostream& white(std::ostream& os) { set_text("w"); return os; } + std::ostream& grey(std::ostream& os) { set_text("e"); return os; } + std::ostream& light_blue(std::ostream& os) { set_text("lb"); return os; } + std::ostream& light_green(std::ostream& os) { set_text("lg"); return os; } + std::ostream& light_aqua(std::ostream& os) { set_text("la"); return os; } + std::ostream& light_red(std::ostream& os) { set_text("lr"); return os; } + std::ostream& light_purple(std::ostream& os) { set_text("lp"); return os; } + std::ostream& light_yellow(std::ostream& os) { set_text("ly"); return os; } + std::ostream& bright_white(std::ostream& os) { set_text("bw"); return os; } + std::ostream& on_black(std::ostream& os) { set_background("k"); return os; } + std::ostream& on_blue(std::ostream& os) { set_background("b"); return os; } + std::ostream& on_green(std::ostream& os) { set_background("g"); return os; } + std::ostream& on_aqua(std::ostream& os) { set_background("a"); return os; } + std::ostream& on_red(std::ostream& os) { set_background("r"); return os; } + std::ostream& on_purple(std::ostream& os) { set_background("p"); return os; } + std::ostream& on_yellow(std::ostream& os) { set_background("y"); return os; } + std::ostream& on_white(std::ostream& os) { set_background("w"); return os; } + std::ostream& on_grey(std::ostream& os) { set_background("e"); return os; } + std::ostream& on_light_blue(std::ostream& os) { set_background("lb"); return os; } + std::ostream& on_light_green(std::ostream& os) { set_background("lg"); return os; } + std::ostream& on_light_aqua(std::ostream& os) { set_background("la"); return os; } + std::ostream& on_light_red(std::ostream& os) { set_background("lr"); return os; } + std::ostream& on_light_purple(std::ostream& os) { set_background("lp"); return os; } + std::ostream& on_light_yellow(std::ostream& os) { set_background("ly"); return os; } + std::ostream& on_bright_white(std::ostream& os) { set_background("bw"); return os; } + std::ostream& black_on_black(std::ostream& os) { set("k", "k"); return os; } + std::ostream& black_on_blue(std::ostream& os) { set("k", "b"); return os; } + std::ostream& black_on_green(std::ostream& os) { set("k", "g"); return os; } + std::ostream& black_on_aqua(std::ostream& os) { set("k", "a"); return os; } + std::ostream& black_on_red(std::ostream& os) { set("k", "r"); return os; } + std::ostream& black_on_purple(std::ostream& os) { set("k", "p"); return os; } + std::ostream& black_on_yellow(std::ostream& os) { set("k", "y"); return os; } + std::ostream& black_on_white(std::ostream& os) { set("k", "w"); return os; } + std::ostream& black_on_grey(std::ostream& os) { set("k", "e"); return os; } + std::ostream& black_on_light_blue(std::ostream& os) { set("k", "lb"); return os; } + std::ostream& black_on_light_green(std::ostream& os) { set("k", "lg"); return os; } + std::ostream& black_on_light_aqua(std::ostream& os) { set("k", "la"); return os; } + std::ostream& black_on_light_red(std::ostream& os) { set("k", "lr"); return os; } + std::ostream& black_on_light_purple(std::ostream& os) { set("k", "lp"); return os; } + std::ostream& black_on_light_yellow(std::ostream& os) { set("k", "ly"); return os; } + std::ostream& black_on_bright_white(std::ostream& os) { set("k", "bw"); return os; } + std::ostream& blue_on_black(std::ostream& os) { set("b", "k"); return os; } + std::ostream& blue_on_blue(std::ostream& os) { set("b", "b"); return os; } + std::ostream& blue_on_green(std::ostream& os) { set("b", "g"); return os; } + std::ostream& blue_on_aqua(std::ostream& os) { set("b", "a"); return os; } + std::ostream& blue_on_red(std::ostream& os) { set("b", "r"); return os; } + std::ostream& blue_on_purple(std::ostream& os) { set("b", "p"); return os; } + std::ostream& blue_on_yellow(std::ostream& os) { set("b", "y"); return os; } + std::ostream& blue_on_white(std::ostream& os) { set("b", "w"); return os; } + std::ostream& blue_on_grey(std::ostream& os) { set("b", "e"); return os; } + std::ostream& blue_on_light_blue(std::ostream& os) { set("b", "lb"); return os; } + std::ostream& blue_on_light_green(std::ostream& os) { set("b", "lg"); return os; } + std::ostream& blue_on_light_aqua(std::ostream& os) { set("b", "la"); return os; } + std::ostream& blue_on_light_red(std::ostream& os) { set("b", "lr"); return os; } + std::ostream& blue_on_light_purple(std::ostream& os) { set("b", "lp"); return os; } + std::ostream& blue_on_light_yellow(std::ostream& os) { set("b", "ly"); return os; } + std::ostream& blue_on_bright_white(std::ostream& os) { set("b", "bw"); return os; } + std::ostream& green_on_black(std::ostream& os) { set("g", "k"); return os; } + std::ostream& green_on_blue(std::ostream& os) { set("g", "b"); return os; } + std::ostream& green_on_green(std::ostream& os) { set("g", "g"); return os; } + std::ostream& green_on_aqua(std::ostream& os) { set("g", "a"); return os; } + std::ostream& green_on_red(std::ostream& os) { set("g", "r"); return os; } + std::ostream& green_on_purple(std::ostream& os) { set("g", "p"); return os; } + std::ostream& green_on_yellow(std::ostream& os) { set("g", "y"); return os; } + std::ostream& green_on_white(std::ostream& os) { set("g", "w"); return os; } + std::ostream& green_on_grey(std::ostream& os) { set("g", "e"); return os; } + std::ostream& green_on_light_blue(std::ostream& os) { set("g", "lb"); return os; } + std::ostream& green_on_light_green(std::ostream& os) { set("g", "lg"); return os; } + std::ostream& green_on_light_aqua(std::ostream& os) { set("g", "la"); return os; } + std::ostream& green_on_light_red(std::ostream& os) { set("g", "lr"); return os; } + std::ostream& green_on_light_purple(std::ostream& os) { set("g", "lp"); return os; } + std::ostream& green_on_light_yellow(std::ostream& os) { set("g", "ly"); return os; } + std::ostream& green_on_bright_white(std::ostream& os) { set("g", "bw"); return os; } + std::ostream& aqua_on_black(std::ostream& os) { set("a", "k"); return os; } + std::ostream& aqua_on_blue(std::ostream& os) { set("a", "b"); return os; } + std::ostream& aqua_on_green(std::ostream& os) { set("a", "g"); return os; } + std::ostream& aqua_on_aqua(std::ostream& os) { set("a", "a"); return os; } + std::ostream& aqua_on_red(std::ostream& os) { set("a", "r"); return os; } + std::ostream& aqua_on_purple(std::ostream& os) { set("a", "p"); return os; } + std::ostream& aqua_on_yellow(std::ostream& os) { set("a", "y"); return os; } + std::ostream& aqua_on_white(std::ostream& os) { set("a", "w"); return os; } + std::ostream& aqua_on_grey(std::ostream& os) { set("a", "e"); return os; } + std::ostream& aqua_on_light_blue(std::ostream& os) { set("a", "lb"); return os; } + std::ostream& aqua_on_light_green(std::ostream& os) { set("a", "lg"); return os; } + std::ostream& aqua_on_light_aqua(std::ostream& os) { set("a", "la"); return os; } + std::ostream& aqua_on_light_red(std::ostream& os) { set("a", "lr"); return os; } + std::ostream& aqua_on_light_purple(std::ostream& os) { set("a", "lp"); return os; } + std::ostream& aqua_on_light_yellow(std::ostream& os) { set("a", "ly"); return os; } + std::ostream& aqua_on_bright_white(std::ostream& os) { set("a", "bw"); return os; } + std::ostream& red_on_black(std::ostream& os) { set("r", "k"); return os; } + std::ostream& red_on_blue(std::ostream& os) { set("r", "b"); return os; } + std::ostream& red_on_green(std::ostream& os) { set("r", "g"); return os; } + std::ostream& red_on_aqua(std::ostream& os) { set("r", "a"); return os; } + std::ostream& red_on_red(std::ostream& os) { set("r", "r"); return os; } + std::ostream& red_on_purple(std::ostream& os) { set("r", "p"); return os; } + std::ostream& red_on_yellow(std::ostream& os) { set("r", "y"); return os; } + std::ostream& red_on_white(std::ostream& os) { set("r", "w"); return os; } + std::ostream& red_on_grey(std::ostream& os) { set("r", "e"); return os; } + std::ostream& red_on_light_blue(std::ostream& os) { set("r", "lb"); return os; } + std::ostream& red_on_light_green(std::ostream& os) { set("r", "lg"); return os; } + std::ostream& red_on_light_aqua(std::ostream& os) { set("r", "la"); return os; } + std::ostream& red_on_light_red(std::ostream& os) { set("r", "lr"); return os; } + std::ostream& red_on_light_purple(std::ostream& os) { set("r", "lp"); return os; } + std::ostream& red_on_light_yellow(std::ostream& os) { set("r", "ly"); return os; } + std::ostream& red_on_bright_white(std::ostream& os) { set("r", "bw"); return os; } + std::ostream& purple_on_black(std::ostream& os) { set("p", "k"); return os; } + std::ostream& purple_on_blue(std::ostream& os) { set("p", "b"); return os; } + std::ostream& purple_on_green(std::ostream& os) { set("p", "g"); return os; } + std::ostream& purple_on_aqua(std::ostream& os) { set("p", "a"); return os; } + std::ostream& purple_on_red(std::ostream& os) { set("p", "r"); return os; } + std::ostream& purple_on_purple(std::ostream& os) { set("p", "p"); return os; } + std::ostream& purple_on_yellow(std::ostream& os) { set("p", "y"); return os; } + std::ostream& purple_on_white(std::ostream& os) { set("p", "w"); return os; } + std::ostream& purple_on_grey(std::ostream& os) { set("p", "e"); return os; } + std::ostream& purple_on_light_blue(std::ostream& os) { set("p", "lb"); return os; } + std::ostream& purple_on_light_green(std::ostream& os) { set("p", "lg"); return os; } + std::ostream& purple_on_light_aqua(std::ostream& os) { set("p", "la"); return os; } + std::ostream& purple_on_light_red(std::ostream& os) { set("p", "lr"); return os; } + std::ostream& purple_on_light_purple(std::ostream& os) { set("p", "lp"); return os; } + std::ostream& purple_on_light_yellow(std::ostream& os) { set("p", "ly"); return os; } + std::ostream& purple_on_bright_white(std::ostream& os) { set("p", "bw"); return os; } + std::ostream& yellow_on_black(std::ostream& os) { set("y", "k"); return os; } + std::ostream& yellow_on_blue(std::ostream& os) { set("y", "b"); return os; } + std::ostream& yellow_on_green(std::ostream& os) { set("y", "g"); return os; } + std::ostream& yellow_on_aqua(std::ostream& os) { set("y", "a"); return os; } + std::ostream& yellow_on_red(std::ostream& os) { set("y", "r"); return os; } + std::ostream& yellow_on_purple(std::ostream& os) { set("y", "p"); return os; } + std::ostream& yellow_on_yellow(std::ostream& os) { set("y", "y"); return os; } + std::ostream& yellow_on_white(std::ostream& os) { set("y", "w"); return os; } + std::ostream& yellow_on_grey(std::ostream& os) { set("y", "e"); return os; } + std::ostream& yellow_on_light_blue(std::ostream& os) { set("y", "lb"); return os; } + std::ostream& yellow_on_light_green(std::ostream& os) { set("y", "lg"); return os; } + std::ostream& yellow_on_light_aqua(std::ostream& os) { set("y", "la"); return os; } + std::ostream& yellow_on_light_red(std::ostream& os) { set("y", "lr"); return os; } + std::ostream& yellow_on_light_purple(std::ostream& os) { set("y", "lp"); return os; } + std::ostream& yellow_on_light_yellow(std::ostream& os) { set("y", "ly"); return os; } + std::ostream& yellow_on_bright_white(std::ostream& os) { set("y", "bw"); return os; } + std::ostream& white_on_black(std::ostream& os) { set("w", "k"); return os; } + std::ostream& white_on_blue(std::ostream& os) { set("w", "b"); return os; } + std::ostream& white_on_green(std::ostream& os) { set("w", "g"); return os; } + std::ostream& white_on_aqua(std::ostream& os) { set("w", "a"); return os; } + std::ostream& white_on_red(std::ostream& os) { set("w", "r"); return os; } + std::ostream& white_on_purple(std::ostream& os) { set("w", "p"); return os; } + std::ostream& white_on_yellow(std::ostream& os) { set("w", "y"); return os; } + std::ostream& white_on_white(std::ostream& os) { set("w", "w"); return os; } + std::ostream& white_on_grey(std::ostream& os) { set("w", "e"); return os; } + std::ostream& white_on_light_blue(std::ostream& os) { set("w", "lb"); return os; } + std::ostream& white_on_light_green(std::ostream& os) { set("w", "lg"); return os; } + std::ostream& white_on_light_aqua(std::ostream& os) { set("w", "la"); return os; } + std::ostream& white_on_light_red(std::ostream& os) { set("w", "lr"); return os; } + std::ostream& white_on_light_purple(std::ostream& os) { set("w", "lp"); return os; } + std::ostream& white_on_light_yellow(std::ostream& os) { set("w", "ly"); return os; } + std::ostream& white_on_bright_white(std::ostream& os) { set("w", "bw"); return os; } + std::ostream& grey_on_black(std::ostream& os) { set("e", "k"); return os; } + std::ostream& grey_on_blue(std::ostream& os) { set("e", "b"); return os; } + std::ostream& grey_on_green(std::ostream& os) { set("e", "g"); return os; } + std::ostream& grey_on_aqua(std::ostream& os) { set("e", "a"); return os; } + std::ostream& grey_on_red(std::ostream& os) { set("e", "r"); return os; } + std::ostream& grey_on_purple(std::ostream& os) { set("e", "p"); return os; } + std::ostream& grey_on_yellow(std::ostream& os) { set("e", "y"); return os; } + std::ostream& grey_on_white(std::ostream& os) { set("e", "w"); return os; } + std::ostream& grey_on_grey(std::ostream& os) { set("e", "e"); return os; } + std::ostream& grey_on_light_blue(std::ostream& os) { set("e", "lb"); return os; } + std::ostream& grey_on_light_green(std::ostream& os) { set("e", "lg"); return os; } + std::ostream& grey_on_light_aqua(std::ostream& os) { set("e", "la"); return os; } + std::ostream& grey_on_light_red(std::ostream& os) { set("e", "lr"); return os; } + std::ostream& grey_on_light_purple(std::ostream& os) { set("e", "lp"); return os; } + std::ostream& grey_on_light_yellow(std::ostream& os) { set("e", "ly"); return os; } + std::ostream& grey_on_bright_white(std::ostream& os) { set("e", "bw"); return os; } + std::ostream& light_blue_on_black(std::ostream& os) { set("lb", "k"); return os; } + std::ostream& light_blue_on_blue(std::ostream& os) { set("lb", "b"); return os; } + std::ostream& light_blue_on_green(std::ostream& os) { set("lb", "g"); return os; } + std::ostream& light_blue_on_aqua(std::ostream& os) { set("lb", "a"); return os; } + std::ostream& light_blue_on_red(std::ostream& os) { set("lb", "r"); return os; } + std::ostream& light_blue_on_purple(std::ostream& os) { set("lb", "p"); return os; } + std::ostream& light_blue_on_yellow(std::ostream& os) { set("lb", "y"); return os; } + std::ostream& light_blue_on_white(std::ostream& os) { set("lb", "w"); return os; } + std::ostream& light_blue_on_grey(std::ostream& os) { set("lb", "e"); return os; } + std::ostream& light_blue_on_light_blue(std::ostream& os) { set("lb", "lb"); return os; } + std::ostream& light_blue_on_light_green(std::ostream& os) { set("lb", "lg"); return os; } + std::ostream& light_blue_on_light_aqua(std::ostream& os) { set("lb", "la"); return os; } + std::ostream& light_blue_on_light_red(std::ostream& os) { set("lb", "lr"); return os; } + std::ostream& light_blue_on_light_purple(std::ostream& os) { set("lb", "lp"); return os; } + std::ostream& light_blue_on_light_yellow(std::ostream& os) { set("lb", "ly"); return os; } + std::ostream& light_blue_on_bright_white(std::ostream& os) { set("lb", "bw"); return os; } + std::ostream& light_green_on_black(std::ostream& os) { set("lg", "k"); return os; } + std::ostream& light_green_on_blue(std::ostream& os) { set("lg", "b"); return os; } + std::ostream& light_green_on_green(std::ostream& os) { set("lg", "g"); return os; } + std::ostream& light_green_on_aqua(std::ostream& os) { set("lg", "a"); return os; } + std::ostream& light_green_on_red(std::ostream& os) { set("lg", "r"); return os; } + std::ostream& light_green_on_purple(std::ostream& os) { set("lg", "p"); return os; } + std::ostream& light_green_on_yellow(std::ostream& os) { set("lg", "y"); return os; } + std::ostream& light_green_on_white(std::ostream& os) { set("lg", "w"); return os; } + std::ostream& light_green_on_grey(std::ostream& os) { set("lg", "e"); return os; } + std::ostream& light_green_on_light_blue(std::ostream& os) { set("lg", "lb"); return os; } + std::ostream& light_green_on_light_green(std::ostream& os) { set("lg", "lg"); return os; } + std::ostream& light_green_on_light_aqua(std::ostream& os) { set("lg", "la"); return os; } + std::ostream& light_green_on_light_red(std::ostream& os) { set("lg", "lr"); return os; } + std::ostream& light_green_on_light_purple(std::ostream& os) { set("lg", "lp"); return os; } + std::ostream& light_green_on_light_yellow(std::ostream& os) { set("lg", "ly"); return os; } + std::ostream& light_green_on_bright_white(std::ostream& os) { set("lg", "bw"); return os; } + std::ostream& light_aqua_on_black(std::ostream& os) { set("la", "k"); return os; } + std::ostream& light_aqua_on_blue(std::ostream& os) { set("la", "b"); return os; } + std::ostream& light_aqua_on_green(std::ostream& os) { set("la", "g"); return os; } + std::ostream& light_aqua_on_aqua(std::ostream& os) { set("la", "a"); return os; } + std::ostream& light_aqua_on_red(std::ostream& os) { set("la", "r"); return os; } + std::ostream& light_aqua_on_purple(std::ostream& os) { set("la", "p"); return os; } + std::ostream& light_aqua_on_yellow(std::ostream& os) { set("la", "y"); return os; } + std::ostream& light_aqua_on_white(std::ostream& os) { set("la", "w"); return os; } + std::ostream& light_aqua_on_grey(std::ostream& os) { set("la", "e"); return os; } + std::ostream& light_aqua_on_light_blue(std::ostream& os) { set("la", "lb"); return os; } + std::ostream& light_aqua_on_light_green(std::ostream& os) { set("la", "lg"); return os; } + std::ostream& light_aqua_on_light_aqua(std::ostream& os) { set("la", "la"); return os; } + std::ostream& light_aqua_on_light_red(std::ostream& os) { set("la", "lr"); return os; } + std::ostream& light_aqua_on_light_purple(std::ostream& os) { set("la", "lp"); return os; } + std::ostream& light_aqua_on_light_yellow(std::ostream& os) { set("la", "ly"); return os; } + std::ostream& light_aqua_on_bright_white(std::ostream& os) { set("la", "bw"); return os; } + std::ostream& light_red_on_black(std::ostream& os) { set("lr", "k"); return os; } + std::ostream& light_red_on_blue(std::ostream& os) { set("lr", "b"); return os; } + std::ostream& light_red_on_green(std::ostream& os) { set("lr", "g"); return os; } + std::ostream& light_red_on_aqua(std::ostream& os) { set("lr", "a"); return os; } + std::ostream& light_red_on_red(std::ostream& os) { set("lr", "r"); return os; } + std::ostream& light_red_on_purple(std::ostream& os) { set("lr", "p"); return os; } + std::ostream& light_red_on_yellow(std::ostream& os) { set("lr", "y"); return os; } + std::ostream& light_red_on_white(std::ostream& os) { set("lr", "w"); return os; } + std::ostream& light_red_on_grey(std::ostream& os) { set("lr", "e"); return os; } + std::ostream& light_red_on_light_blue(std::ostream& os) { set("lr", "lb"); return os; } + std::ostream& light_red_on_light_green(std::ostream& os) { set("lr", "lg"); return os; } + std::ostream& light_red_on_light_aqua(std::ostream& os) { set("lr", "la"); return os; } + std::ostream& light_red_on_light_red(std::ostream& os) { set("lr", "lr"); return os; } + std::ostream& light_red_on_light_purple(std::ostream& os) { set("lr", "lp"); return os; } + std::ostream& light_red_on_light_yellow(std::ostream& os) { set("lr", "ly"); return os; } + std::ostream& light_red_on_bright_white(std::ostream& os) { set("lr", "bw"); return os; } + std::ostream& light_purple_on_black(std::ostream& os) { set("lp", "k"); return os; } + std::ostream& light_purple_on_blue(std::ostream& os) { set("lp", "b"); return os; } + std::ostream& light_purple_on_green(std::ostream& os) { set("lp", "g"); return os; } + std::ostream& light_purple_on_aqua(std::ostream& os) { set("lp", "a"); return os; } + std::ostream& light_purple_on_red(std::ostream& os) { set("lp", "r"); return os; } + std::ostream& light_purple_on_purple(std::ostream& os) { set("lp", "p"); return os; } + std::ostream& light_purple_on_yellow(std::ostream& os) { set("lp", "y"); return os; } + std::ostream& light_purple_on_white(std::ostream& os) { set("lp", "w"); return os; } + std::ostream& light_purple_on_grey(std::ostream& os) { set("lp", "e"); return os; } + std::ostream& light_purple_on_light_blue(std::ostream& os) { set("lp", "lb"); return os; } + std::ostream& light_purple_on_light_green(std::ostream& os) { set("lp", "lg"); return os; } + std::ostream& light_purple_on_light_aqua(std::ostream& os) { set("lp", "la"); return os; } + std::ostream& light_purple_on_light_red(std::ostream& os) { set("lp", "lr"); return os; } + std::ostream& light_purple_on_light_purple(std::ostream& os) { set("lp", "lp"); return os; } + std::ostream& light_purple_on_light_yellow(std::ostream& os) { set("lp", "ly"); return os; } + std::ostream& light_purple_on_bright_white(std::ostream& os) { set("lp", "bw"); return os; } + std::ostream& light_yellow_on_black(std::ostream& os) { set("ly", "k"); return os; } + std::ostream& light_yellow_on_blue(std::ostream& os) { set("ly", "b"); return os; } + std::ostream& light_yellow_on_green(std::ostream& os) { set("ly", "g"); return os; } + std::ostream& light_yellow_on_aqua(std::ostream& os) { set("ly", "a"); return os; } + std::ostream& light_yellow_on_red(std::ostream& os) { set("ly", "r"); return os; } + std::ostream& light_yellow_on_purple(std::ostream& os) { set("ly", "p"); return os; } + std::ostream& light_yellow_on_yellow(std::ostream& os) { set("ly", "y"); return os; } + std::ostream& light_yellow_on_white(std::ostream& os) { set("ly", "w"); return os; } + std::ostream& light_yellow_on_grey(std::ostream& os) { set("ly", "e"); return os; } + std::ostream& light_yellow_on_light_blue(std::ostream& os) { set("ly", "lb"); return os; } + std::ostream& light_yellow_on_light_green(std::ostream& os) { set("ly", "lg"); return os; } + std::ostream& light_yellow_on_light_aqua(std::ostream& os) { set("ly", "la"); return os; } + std::ostream& light_yellow_on_light_red(std::ostream& os) { set("ly", "lr"); return os; } + std::ostream& light_yellow_on_light_purple(std::ostream& os) { set("ly", "lp"); return os; } + std::ostream& light_yellow_on_light_yellow(std::ostream& os) { set("ly", "ly"); return os; } + std::ostream& light_yellow_on_bright_white(std::ostream& os) { set("ly", "bw"); return os; } + std::ostream& bright_white_on_black(std::ostream& os) { set("bw", "k"); return os; } + std::ostream& bright_white_on_blue(std::ostream& os) { set("bw", "b"); return os; } + std::ostream& bright_white_on_green(std::ostream& os) { set("bw", "g"); return os; } + std::ostream& bright_white_on_aqua(std::ostream& os) { set("bw", "a"); return os; } + std::ostream& bright_white_on_red(std::ostream& os) { set("bw", "r"); return os; } + std::ostream& bright_white_on_purple(std::ostream& os) { set("bw", "p"); return os; } + std::ostream& bright_white_on_yellow(std::ostream& os) { set("bw", "y"); return os; } + std::ostream& bright_white_on_white(std::ostream& os) { set("bw", "w"); return os; } + std::ostream& bright_white_on_grey(std::ostream& os) { set("bw", "e"); return os; } + std::ostream& bright_white_on_light_blue(std::ostream& os) { set("bw", "lb"); return os; } + std::ostream& bright_white_on_light_green(std::ostream& os) { set("bw", "lg"); return os; } + std::ostream& bright_white_on_light_aqua(std::ostream& os) { set("bw", "la"); return os; } + std::ostream& bright_white_on_light_red(std::ostream& os) { set("bw", "lr"); return os; } + std::ostream& bright_white_on_light_purple(std::ostream& os) { set("bw", "lp"); return os; } + std::ostream& bright_white_on_light_yellow(std::ostream& os) { set("bw", "ly"); return os; } + std::ostream& bright_white_on_bright_white(std::ostream& os) { set("bw", "bw"); return os; } +} + + +namespace dye +{ + template + using bar = typename std::conditional::value, std::string, T>::type; + + template class colorful; + template class item; + + template + class colorful : private std::list> + { + public: + using std::list>::list; + + colorful& operator+=(const colorful& rhs) + { + this->insert(this->end(), rhs.begin(), rhs.end()); + return *this; + } + + colorful& operator+=(colorful&& rhs) + { + this->splice(this->end(), std::move(rhs)); + return *this; + } + + colorful& operator+=(T t) + { + this->push_back(std::move(t)); + return *this; + } + + void push_front(T t) + { + this->std::list>::push_front(item(std::move(t))); + } + + void push_back(T t) + { + this->std::list>::push_back(item(std::move(t))); + } + + colorful& invert() + { + for (auto& elem : *this) + elem.invert(); + return *this; + } + + template + friend std::ostream& operator<<(std::ostream&, const colorful&); + + template + friend colorful invert(colorful col); + }; + + template + colorful operator+(colorful lhs, colorful rhs) + { + colorful res(std::move(lhs)); + return res += rhs; + } + + template + colorful operator+(colorful lhs, std::string rhs) + { + colorful res(std::move(lhs)); + res.push_back(std::move(rhs)); + return res; + } + + template + colorful operator+(const std::string& lhs, colorful rhs) + { + colorful res(std::move(rhs)); + res.push_front(std::move(lhs)); + return res; + } + + template + std::ostream& operator<<(std::ostream& os, const colorful& colorful) + { + for (const auto& elem : colorful) + os << elem; + return os; + } + + template + colorful invert(colorful col) + { + colorful res(std::move(col)); + for (auto& elem : res) + elem.invert(); + return res; + } + + template + class item + { + T thing; + int color; + + public: + item(T t) : thing(std::move(t)), color(hue::get()) {} + item(T t, int a) : thing(std::move(t)), color(hue::itoc(a)) {} + item(T t, int a, int b) : thing(std::move(t)), color(hue::itoc(a, b)) {} + item(T t, std::string a) : thing(std::move(t)), color(hue::stoc(a)) {} + item(T t, std::string a, std::string b) : thing(std::move(t)), color(hue::stoc(a, b)) {} + + item& invert() + { + color = hue::invert(color); + return *this; + } + + template + friend class colorful; + + template + friend std::ostream& operator<<(std::ostream&, const item&); + }; + + template + std::ostream& operator<<(std::ostream& os, const item& it) + { + hue::set(it.color); + os << it.thing; + hue::reset(); + return os; + } + + template using R = colorful>; + template using S = item>; + + template R colorize(T t, std::string a) { return R { S(t, a) }; } + template R vanilla(T t) { return R { S(t) }; } + template R black(T t) { return R { S(t, "k") }; } + template R blue(T t) { return R { S(t, "b") }; } + template R green(T t) { return R { S(t, "g") }; } + template R aqua(T t) { return R { S(t, "a") }; } + template R red(T t) { return R { S(t, "r") }; } + template R purple(T t) { return R { S(t, "p") }; } + template R yellow(T t) { return R { S(t, "y") }; } + template R white(T t) { return R { S(t, "w") }; } + template R grey(T t) { return R { S(t, "e") }; } + template R light_blue(T t) { return R { S(t, "lb") }; } + template R light_green(T t) { return R { S(t, "lg") }; } + template R light_aqua(T t) { return R { S(t, "la") }; } + template R light_red(T t) { return R { S(t, "lr") }; } + template R light_purple(T t) { return R { S(t, "lp") }; } + template R light_yellow(T t) { return R { S(t, "ly") }; } + template R bright_white(T t) { return R { S(t, "bw") }; } + template R on_black(T t) { return R { S(t, "k", "k") }; } + template R on_blue(T t) { return R { S(t, "k", "b") }; } + template R on_green(T t) { return R { S(t, "k", "g") }; } + template R on_aqua(T t) { return R { S(t, "k", "a") }; } + template R on_red(T t) { return R { S(t, "k", "r") }; } + template R on_purple(T t) { return R { S(t, "k", "p") }; } + template R on_yellow(T t) { return R { S(t, "k", "y") }; } + template R on_white(T t) { return R { S(t, "k", "w") }; } + template R on_grey(T t) { return R { S(t, "k", "e") }; } + template R on_light_blue(T t) { return R { S(t, "k", "lb") }; } + template R on_light_green(T t) { return R { S(t, "k", "lg") }; } + template R on_light_aqua(T t) { return R { S(t, "k", "la") }; } + template R on_light_red(T t) { return R { S(t, "k", "lr") }; } + template R on_light_purple(T t) { return R { S(t, "k", "lp") }; } + template R on_light_yellow(T t) { return R { S(t, "k", "ly") }; } + template R on_bright_white(T t) { return R { S(t, "k", "bw") }; } + template R black_on_black(T t) { return R { S(t, "k", "k") }; } + template R black_on_blue(T t) { return R { S(t, "k", "b") }; } + template R black_on_green(T t) { return R { S(t, "k", "g") }; } + template R black_on_aqua(T t) { return R { S(t, "k", "a") }; } + template R black_on_red(T t) { return R { S(t, "k", "r") }; } + template R black_on_purple(T t) { return R { S(t, "k", "p") }; } + template R black_on_yellow(T t) { return R { S(t, "k", "y") }; } + template R black_on_white(T t) { return R { S(t, "k", "w") }; } + template R black_on_grey(T t) { return R { S(t, "k", "e") }; } + template R black_on_light_blue(T t) { return R { S(t, "k", "lb") }; } + template R black_on_light_green(T t) { return R { S(t, "k", "lg") }; } + template R black_on_light_aqua(T t) { return R { S(t, "k", "la") }; } + template R black_on_light_red(T t) { return R { S(t, "k", "lr") }; } + template R black_on_light_purple(T t) { return R { S(t, "k", "lp") }; } + template R black_on_light_yellow(T t) { return R { S(t, "k", "ly") }; } + template R black_on_bright_white(T t) { return R { S(t, "k", "bw") }; } + template R blue_on_black(T t) { return R { S(t, "b", "k") }; } + template R blue_on_blue(T t) { return R { S(t, "b", "b") }; } + template R blue_on_green(T t) { return R { S(t, "b", "g") }; } + template R blue_on_aqua(T t) { return R { S(t, "b", "a") }; } + template R blue_on_red(T t) { return R { S(t, "b", "r") }; } + template R blue_on_purple(T t) { return R { S(t, "b", "p") }; } + template R blue_on_yellow(T t) { return R { S(t, "b", "y") }; } + template R blue_on_white(T t) { return R { S(t, "b", "w") }; } + template R blue_on_grey(T t) { return R { S(t, "b", "e") }; } + template R blue_on_light_blue(T t) { return R { S(t, "b", "lb") }; } + template R blue_on_light_green(T t) { return R { S(t, "b", "lg") }; } + template R blue_on_light_aqua(T t) { return R { S(t, "b", "la") }; } + template R blue_on_light_red(T t) { return R { S(t, "b", "lr") }; } + template R blue_on_light_purple(T t) { return R { S(t, "b", "lp") }; } + template R blue_on_light_yellow(T t) { return R { S(t, "b", "ly") }; } + template R blue_on_bright_white(T t) { return R { S(t, "b", "bw") }; } + template R green_on_black(T t) { return R { S(t, "g", "k") }; } + template R green_on_blue(T t) { return R { S(t, "g", "b") }; } + template R green_on_green(T t) { return R { S(t, "g", "g") }; } + template R green_on_aqua(T t) { return R { S(t, "g", "a") }; } + template R green_on_red(T t) { return R { S(t, "g", "r") }; } + template R green_on_purple(T t) { return R { S(t, "g", "p") }; } + template R green_on_yellow(T t) { return R { S(t, "g", "y") }; } + template R green_on_white(T t) { return R { S(t, "g", "w") }; } + template R green_on_grey(T t) { return R { S(t, "g", "e") }; } + template R green_on_light_blue(T t) { return R { S(t, "g", "lb") }; } + template R green_on_light_green(T t) { return R { S(t, "g", "lg") }; } + template R green_on_light_aqua(T t) { return R { S(t, "g", "la") }; } + template R green_on_light_red(T t) { return R { S(t, "g", "lr") }; } + template R green_on_light_purple(T t) { return R { S(t, "g", "lp") }; } + template R green_on_light_yellow(T t) { return R { S(t, "g", "ly") }; } + template R green_on_bright_white(T t) { return R { S(t, "g", "bw") }; } + template R aqua_on_black(T t) { return R { S(t, "a", "k") }; } + template R aqua_on_blue(T t) { return R { S(t, "a", "b") }; } + template R aqua_on_green(T t) { return R { S(t, "a", "g") }; } + template R aqua_on_aqua(T t) { return R { S(t, "a", "a") }; } + template R aqua_on_red(T t) { return R { S(t, "a", "r") }; } + template R aqua_on_purple(T t) { return R { S(t, "a", "p") }; } + template R aqua_on_yellow(T t) { return R { S(t, "a", "y") }; } + template R aqua_on_white(T t) { return R { S(t, "a", "w") }; } + template R aqua_on_grey(T t) { return R { S(t, "a", "e") }; } + template R aqua_on_light_blue(T t) { return R { S(t, "a", "lb") }; } + template R aqua_on_light_green(T t) { return R { S(t, "a", "lg") }; } + template R aqua_on_light_aqua(T t) { return R { S(t, "a", "la") }; } + template R aqua_on_light_red(T t) { return R { S(t, "a", "lr") }; } + template R aqua_on_light_purple(T t) { return R { S(t, "a", "lp") }; } + template R aqua_on_light_yellow(T t) { return R { S(t, "a", "ly") }; } + template R aqua_on_bright_white(T t) { return R { S(t, "a", "bw") }; } + template R red_on_black(T t) { return R { S(t, "r", "k") }; } + template R red_on_blue(T t) { return R { S(t, "r", "b") }; } + template R red_on_green(T t) { return R { S(t, "r", "g") }; } + template R red_on_aqua(T t) { return R { S(t, "r", "a") }; } + template R red_on_red(T t) { return R { S(t, "r", "r") }; } + template R red_on_purple(T t) { return R { S(t, "r", "p") }; } + template R red_on_yellow(T t) { return R { S(t, "r", "y") }; } + template R red_on_white(T t) { return R { S(t, "r", "w") }; } + template R red_on_grey(T t) { return R { S(t, "r", "e") }; } + template R red_on_light_blue(T t) { return R { S(t, "r", "lb") }; } + template R red_on_light_green(T t) { return R { S(t, "r", "lg") }; } + template R red_on_light_aqua(T t) { return R { S(t, "r", "la") }; } + template R red_on_light_red(T t) { return R { S(t, "r", "lr") }; } + template R red_on_light_purple(T t) { return R { S(t, "r", "lp") }; } + template R red_on_light_yellow(T t) { return R { S(t, "r", "ly") }; } + template R red_on_bright_white(T t) { return R { S(t, "r", "bw") }; } + template R purple_on_black(T t) { return R { S(t, "p", "k") }; } + template R purple_on_blue(T t) { return R { S(t, "p", "b") }; } + template R purple_on_green(T t) { return R { S(t, "p", "g") }; } + template R purple_on_aqua(T t) { return R { S(t, "p", "a") }; } + template R purple_on_red(T t) { return R { S(t, "p", "r") }; } + template R purple_on_purple(T t) { return R { S(t, "p", "p") }; } + template R purple_on_yellow(T t) { return R { S(t, "p", "y") }; } + template R purple_on_white(T t) { return R { S(t, "p", "w") }; } + template R purple_on_grey(T t) { return R { S(t, "p", "e") }; } + template R purple_on_light_blue(T t) { return R { S(t, "p", "lb") }; } + template R purple_on_light_green(T t) { return R { S(t, "p", "lg") }; } + template R purple_on_light_aqua(T t) { return R { S(t, "p", "la") }; } + template R purple_on_light_red(T t) { return R { S(t, "p", "lr") }; } + template R purple_on_light_purple(T t) { return R { S(t, "p", "lp") }; } + template R purple_on_light_yellow(T t) { return R { S(t, "p", "ly") }; } + template R purple_on_bright_white(T t) { return R { S(t, "p", "bw") }; } + template R yellow_on_black(T t) { return R { S(t, "y", "k") }; } + template R yellow_on_blue(T t) { return R { S(t, "y", "b") }; } + template R yellow_on_green(T t) { return R { S(t, "y", "g") }; } + template R yellow_on_aqua(T t) { return R { S(t, "y", "a") }; } + template R yellow_on_red(T t) { return R { S(t, "y", "r") }; } + template R yellow_on_purple(T t) { return R { S(t, "y", "p") }; } + template R yellow_on_yellow(T t) { return R { S(t, "y", "y") }; } + template R yellow_on_white(T t) { return R { S(t, "y", "w") }; } + template R yellow_on_grey(T t) { return R { S(t, "y", "e") }; } + template R yellow_on_light_blue(T t) { return R { S(t, "y", "lb") }; } + template R yellow_on_light_green(T t) { return R { S(t, "y", "lg") }; } + template R yellow_on_light_aqua(T t) { return R { S(t, "y", "la") }; } + template R yellow_on_light_red(T t) { return R { S(t, "y", "lr") }; } + template R yellow_on_light_purple(T t) { return R { S(t, "y", "lp") }; } + template R yellow_on_light_yellow(T t) { return R { S(t, "y", "ly") }; } + template R yellow_on_bright_white(T t) { return R { S(t, "y", "bw") }; } + template R white_on_black(T t) { return R { S(t, "w", "k") }; } + template R white_on_blue(T t) { return R { S(t, "w", "b") }; } + template R white_on_green(T t) { return R { S(t, "w", "g") }; } + template R white_on_aqua(T t) { return R { S(t, "w", "a") }; } + template R white_on_red(T t) { return R { S(t, "w", "r") }; } + template R white_on_purple(T t) { return R { S(t, "w", "p") }; } + template R white_on_yellow(T t) { return R { S(t, "w", "y") }; } + template R white_on_white(T t) { return R { S(t, "w", "w") }; } + template R white_on_grey(T t) { return R { S(t, "w", "e") }; } + template R white_on_light_blue(T t) { return R { S(t, "w", "lb") }; } + template R white_on_light_green(T t) { return R { S(t, "w", "lg") }; } + template R white_on_light_aqua(T t) { return R { S(t, "w", "la") }; } + template R white_on_light_red(T t) { return R { S(t, "w", "lr") }; } + template R white_on_light_purple(T t) { return R { S(t, "w", "lp") }; } + template R white_on_light_yellow(T t) { return R { S(t, "w", "ly") }; } + template R white_on_bright_white(T t) { return R { S(t, "w", "bw") }; } + template R grey_on_black(T t) { return R { S(t, "e", "k") }; } + template R grey_on_blue(T t) { return R { S(t, "e", "b") }; } + template R grey_on_green(T t) { return R { S(t, "e", "g") }; } + template R grey_on_aqua(T t) { return R { S(t, "e", "a") }; } + template R grey_on_red(T t) { return R { S(t, "e", "r") }; } + template R grey_on_purple(T t) { return R { S(t, "e", "p") }; } + template R grey_on_yellow(T t) { return R { S(t, "e", "y") }; } + template R grey_on_white(T t) { return R { S(t, "e", "w") }; } + template R grey_on_grey(T t) { return R { S(t, "e", "e") }; } + template R grey_on_light_blue(T t) { return R { S(t, "e", "lb") }; } + template R grey_on_light_green(T t) { return R { S(t, "e", "lg") }; } + template R grey_on_light_aqua(T t) { return R { S(t, "e", "la") }; } + template R grey_on_light_red(T t) { return R { S(t, "e", "lr") }; } + template R grey_on_light_purple(T t) { return R { S(t, "e", "lp") }; } + template R grey_on_light_yellow(T t) { return R { S(t, "e", "ly") }; } + template R grey_on_bright_white(T t) { return R { S(t, "e", "bw") }; } + template R light_blue_on_black(T t) { return R { S(t, "lb", "k") }; } + template R light_blue_on_blue(T t) { return R { S(t, "lb", "b") }; } + template R light_blue_on_green(T t) { return R { S(t, "lb", "g") }; } + template R light_blue_on_aqua(T t) { return R { S(t, "lb", "a") }; } + template R light_blue_on_red(T t) { return R { S(t, "lb", "r") }; } + template R light_blue_on_purple(T t) { return R { S(t, "lb", "p") }; } + template R light_blue_on_yellow(T t) { return R { S(t, "lb", "y") }; } + template R light_blue_on_white(T t) { return R { S(t, "lb", "w") }; } + template R light_blue_on_grey(T t) { return R { S(t, "lb", "e") }; } + template R light_blue_on_light_blue(T t) { return R { S(t, "lb", "lb") }; } + template R light_blue_on_light_green(T t) { return R { S(t, "lb", "lg") }; } + template R light_blue_on_light_aqua(T t) { return R { S(t, "lb", "la") }; } + template R light_blue_on_light_red(T t) { return R { S(t, "lb", "lr") }; } + template R light_blue_on_light_purple(T t) { return R { S(t, "lb", "lp") }; } + template R light_blue_on_light_yellow(T t) { return R { S(t, "lb", "ly") }; } + template R light_blue_on_bright_white(T t) { return R { S(t, "lb", "bw") }; } + template R light_green_on_black(T t) { return R { S(t, "lg", "k") }; } + template R light_green_on_blue(T t) { return R { S(t, "lg", "b") }; } + template R light_green_on_green(T t) { return R { S(t, "lg", "g") }; } + template R light_green_on_aqua(T t) { return R { S(t, "lg", "a") }; } + template R light_green_on_red(T t) { return R { S(t, "lg", "r") }; } + template R light_green_on_purple(T t) { return R { S(t, "lg", "p") }; } + template R light_green_on_yellow(T t) { return R { S(t, "lg", "y") }; } + template R light_green_on_white(T t) { return R { S(t, "lg", "w") }; } + template R light_green_on_grey(T t) { return R { S(t, "lg", "e") }; } + template R light_green_on_light_blue(T t) { return R { S(t, "lg", "lb") }; } + template R light_green_on_light_green(T t) { return R { S(t, "lg", "lg") }; } + template R light_green_on_light_aqua(T t) { return R { S(t, "lg", "la") }; } + template R light_green_on_light_red(T t) { return R { S(t, "lg", "lr") }; } + template R light_green_on_light_purple(T t) { return R { S(t, "lg", "lp") }; } + template R light_green_on_light_yellow(T t) { return R { S(t, "lg", "ly") }; } + template R light_green_on_bright_white(T t) { return R { S(t, "lg", "bw") }; } + template R light_aqua_on_black(T t) { return R { S(t, "la", "k") }; } + template R light_aqua_on_blue(T t) { return R { S(t, "la", "b") }; } + template R light_aqua_on_green(T t) { return R { S(t, "la", "g") }; } + template R light_aqua_on_aqua(T t) { return R { S(t, "la", "a") }; } + template R light_aqua_on_red(T t) { return R { S(t, "la", "r") }; } + template R light_aqua_on_purple(T t) { return R { S(t, "la", "p") }; } + template R light_aqua_on_yellow(T t) { return R { S(t, "la", "y") }; } + template R light_aqua_on_white(T t) { return R { S(t, "la", "w") }; } + template R light_aqua_on_grey(T t) { return R { S(t, "la", "e") }; } + template R light_aqua_on_light_blue(T t) { return R { S(t, "la", "lb") }; } + template R light_aqua_on_light_green(T t) { return R { S(t, "la", "lg") }; } + template R light_aqua_on_light_aqua(T t) { return R { S(t, "la", "la") }; } + template R light_aqua_on_light_red(T t) { return R { S(t, "la", "lr") }; } + template R light_aqua_on_light_purple(T t) { return R { S(t, "la", "lp") }; } + template R light_aqua_on_light_yellow(T t) { return R { S(t, "la", "ly") }; } + template R light_aqua_on_bright_white(T t) { return R { S(t, "la", "bw") }; } + template R light_red_on_black(T t) { return R { S(t, "lr", "k") }; } + template R light_red_on_blue(T t) { return R { S(t, "lr", "b") }; } + template R light_red_on_green(T t) { return R { S(t, "lr", "g") }; } + template R light_red_on_aqua(T t) { return R { S(t, "lr", "a") }; } + template R light_red_on_red(T t) { return R { S(t, "lr", "r") }; } + template R light_red_on_purple(T t) { return R { S(t, "lr", "p") }; } + template R light_red_on_yellow(T t) { return R { S(t, "lr", "y") }; } + template R light_red_on_white(T t) { return R { S(t, "lr", "w") }; } + template R light_red_on_grey(T t) { return R { S(t, "lr", "e") }; } + template R light_red_on_light_blue(T t) { return R { S(t, "lr", "lb") }; } + template R light_red_on_light_green(T t) { return R { S(t, "lr", "lg") }; } + template R light_red_on_light_aqua(T t) { return R { S(t, "lr", "la") }; } + template R light_red_on_light_red(T t) { return R { S(t, "lr", "lr") }; } + template R light_red_on_light_purple(T t) { return R { S(t, "lr", "lp") }; } + template R light_red_on_light_yellow(T t) { return R { S(t, "lr", "ly") }; } + template R light_red_on_bright_white(T t) { return R { S(t, "lr", "bw") }; } + template R light_purple_on_black(T t) { return R { S(t, "lp", "k") }; } + template R light_purple_on_blue(T t) { return R { S(t, "lp", "b") }; } + template R light_purple_on_green(T t) { return R { S(t, "lp", "g") }; } + template R light_purple_on_aqua(T t) { return R { S(t, "lp", "a") }; } + template R light_purple_on_red(T t) { return R { S(t, "lp", "r") }; } + template R light_purple_on_purple(T t) { return R { S(t, "lp", "p") }; } + template R light_purple_on_yellow(T t) { return R { S(t, "lp", "y") }; } + template R light_purple_on_white(T t) { return R { S(t, "lp", "w") }; } + template R light_purple_on_grey(T t) { return R { S(t, "lp", "e") }; } + template R light_purple_on_light_blue(T t) { return R { S(t, "lp", "lb") }; } + template R light_purple_on_light_green(T t) { return R { S(t, "lp", "lg") }; } + template R light_purple_on_light_aqua(T t) { return R { S(t, "lp", "la") }; } + template R light_purple_on_light_red(T t) { return R { S(t, "lp", "lr") }; } + template R light_purple_on_light_purple(T t) { return R { S(t, "lp", "lp") }; } + template R light_purple_on_light_yellow(T t) { return R { S(t, "lp", "ly") }; } + template R light_purple_on_bright_white(T t) { return R { S(t, "lp", "bw") }; } + template R light_yellow_on_black(T t) { return R { S(t, "ly", "k") }; } + template R light_yellow_on_blue(T t) { return R { S(t, "ly", "b") }; } + template R light_yellow_on_green(T t) { return R { S(t, "ly", "g") }; } + template R light_yellow_on_aqua(T t) { return R { S(t, "ly", "a") }; } + template R light_yellow_on_red(T t) { return R { S(t, "ly", "r") }; } + template R light_yellow_on_purple(T t) { return R { S(t, "ly", "p") }; } + template R light_yellow_on_yellow(T t) { return R { S(t, "ly", "y") }; } + template R light_yellow_on_white(T t) { return R { S(t, "ly", "w") }; } + template R light_yellow_on_grey(T t) { return R { S(t, "ly", "e") }; } + template R light_yellow_on_light_blue(T t) { return R { S(t, "ly", "lb") }; } + template R light_yellow_on_light_green(T t) { return R { S(t, "ly", "lg") }; } + template R light_yellow_on_light_aqua(T t) { return R { S(t, "ly", "la") }; } + template R light_yellow_on_light_red(T t) { return R { S(t, "ly", "lr") }; } + template R light_yellow_on_light_purple(T t) { return R { S(t, "ly", "lp") }; } + template R light_yellow_on_light_yellow(T t) { return R { S(t, "ly", "ly") }; } + template R light_yellow_on_bright_white(T t) { return R { S(t, "ly", "bw") }; } + template R bright_white_on_black(T t) { return R { S(t, "bw", "k") }; } + template R bright_white_on_blue(T t) { return R { S(t, "bw", "b") }; } + template R bright_white_on_green(T t) { return R { S(t, "bw", "g") }; } + template R bright_white_on_aqua(T t) { return R { S(t, "bw", "a") }; } + template R bright_white_on_red(T t) { return R { S(t, "bw", "r") }; } + template R bright_white_on_purple(T t) { return R { S(t, "bw", "p") }; } + template R bright_white_on_yellow(T t) { return R { S(t, "bw", "y") }; } + template R bright_white_on_white(T t) { return R { S(t, "bw", "w") }; } + template R bright_white_on_grey(T t) { return R { S(t, "bw", "e") }; } + template R bright_white_on_light_blue(T t) { return R { S(t, "bw", "lb") }; } + template R bright_white_on_light_green(T t) { return R { S(t, "bw", "lg") }; } + template R bright_white_on_light_aqua(T t) { return R { S(t, "bw", "la") }; } + template R bright_white_on_light_red(T t) { return R { S(t, "bw", "lr") }; } + template R bright_white_on_light_purple(T t) { return R { S(t, "bw", "lp") }; } + template R bright_white_on_light_yellow(T t) { return R { S(t, "bw", "ly") }; } + template R bright_white_on_bright_white(T t) { return R { S(t, "bw", "bw") }; } +} + +#endif \ No newline at end of file diff --git a/src/app-sdk/midimdnsinfo/main.cpp b/src/app-sdk/midimdnsinfo/main.cpp new file mode 100644 index 000000000..b245ec09f --- /dev/null +++ b/src/app-sdk/midimdnsinfo/main.cpp @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License +// ============================================================================ +// This is part of the Windows MIDI Services App SDK and should be used +// in your Windows application via an official binary distribution. +// Further information: https://aka.ms/midi +// ============================================================================ + + +#pragma once + +#include "pch.h" + +#include "color.hpp" + +void WriteBrightLabel(std::string label) +{ + auto fullLabel = label + ":"; + std::cout << std::left << std::setw(25) << std::setfill(' ') << dye::white(fullLabel); +} + +void WriteLabel(std::string label) +{ + auto fullLabel = label + ":"; + std::cout << std::left << std::setw(25) << std::setfill(' ') << dye::grey(fullLabel); +} + +int __cdecl main() +{ + winrt::init_apartment(); + + std::cout << dye::grey("===================================================================") << std::endl; + std::cout << dye::aqua(" Enumerating MIDI mdns advertisements currently visible to this PC") << std::endl; + std::cout << dye::grey("===================================================================") << std::endl; + + + std::cout << std::endl; + + return 0; +} + diff --git a/src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj b/src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj new file mode 100644 index 000000000..f4837f8a3 --- /dev/null +++ b/src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj @@ -0,0 +1,204 @@ + + + + + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 + true + true + true + true + 15.0 + {C787073C-50F0-5CA0-D53C-12107196F2F0} + Win32Proj + midiusbinfo + 10.0 + 10.0.20348.0 + midimdnsinfo + + + + + + Debug + ARM64 + + + Debug + ARM64EC + + + Release + ARM64 + + + Debug + x64 + + + Release + ARM64EC + + + Release + x64 + + + + Application + v143 + v142 + v141 + v140 + Unicode + + + true + true + + + false + true + false + + + + + + + + + + + + $(SolutionDir)vsfiles\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ + $(SolutionDir)vsfiles\out\$(ProjectName)\$(Platform)\$(Configuration)\ + $(IncludePath) + ..\..\api\VSFiles\intermediate\midiks\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midiksenum\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midikscommon\$(Platform)\$(Configuration);$(LibraryPath) + $(ExternalIncludePath);$(SolutionDir)..\api\inc;$(SolutionDir)..\api\vsfiles\intermediate\IDL\$(Platform)\$(Configuration) + + + $(SolutionDir)vsfiles\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ + $(SolutionDir)vsfiles\out\$(ProjectName)\$(Platform)\$(Configuration)\ + $(IncludePath) + ..\..\api\VSFiles\intermediate\midiks\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midiksenum\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midikscommon\$(Platform)\$(Configuration);$(LibraryPath) + $(ExternalIncludePath);$(SolutionDir)..\api\inc;$(SolutionDir)..\api\vsfiles\intermediate\IDL\$(Platform)\$(Configuration) + + + $(SolutionDir)vsfiles\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ + $(SolutionDir)vsfiles\out\$(ProjectName)\$(Platform)\$(Configuration)\ + $(IncludePath) + ..\..\api\VSFiles\intermediate\midiks\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midiksenum\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midikscommon\$(Platform)\$(Configuration);$(LibraryPath) + $(ExternalIncludePath);$(SolutionDir)..\api\inc;$(SolutionDir)..\api\vsfiles\intermediate\IDL\$(Platform)\$(Configuration) + + + $(SolutionDir)vsfiles\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ + $(SolutionDir)vsfiles\out\$(ProjectName)\$(Platform)\$(Configuration)\ + $(IncludePath) + ..\..\api\VSFiles\intermediate\midiks\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midiksenum\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midikscommon\$(Platform)\$(Configuration);$(LibraryPath) + $(ExternalIncludePath);$(SolutionDir)..\api\inc;$(SolutionDir)..\api\vsfiles\intermediate\IDL\$(Platform)\$(Configuration) + + + $(SolutionDir)vsfiles\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ + $(SolutionDir)vsfiles\out\$(ProjectName)\$(Platform)\$(Configuration)\ + $(IncludePath) + ..\..\api\VSFiles\intermediate\midiks\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midiksenum\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midikscommon\$(Platform)\$(Configuration);$(LibraryPath) + $(ExternalIncludePath);$(SolutionDir)..\api\inc;$(SolutionDir)..\api\vsfiles\intermediate\IDL\$(Platform)\$(Configuration) + + + $(SolutionDir)vsfiles\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ + $(SolutionDir)vsfiles\out\$(ProjectName)\$(Platform)\$(Configuration)\ + $(IncludePath) + ..\..\api\VSFiles\intermediate\midiks\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midiksenum\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midikscommon\$(Platform)\$(Configuration);$(LibraryPath) + $(ExternalIncludePath);$(SolutionDir)..\api\inc;$(SolutionDir)..\api\vsfiles\intermediate\IDL\$(Platform)\$(Configuration) + + + + Use + pch.h + $(IntDir)pch.pch + _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) + Level4 + %(AdditionalOptions) /permissive- /bigobj + + + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + stdcpp20 + stdcpp20 + stdcpp20 + %(AdditionalIncludeDirectories);..\..\api\VSFiles\intermediate\idl\$(Platform)\$(Configuration);..\..\api\inc;$(SolutionDir)..\..\build\staging\version\;$(GeneratedFilesDir) + %(AdditionalIncludeDirectories);..\..\api\VSFiles\intermediate\idl\$(Platform)\$(Configuration);..\..\api\inc;$(SolutionDir)..\..\build\staging\version\;$(GeneratedFilesDir) + %(AdditionalIncludeDirectories);..\..\api\VSFiles\intermediate\idl\$(Platform)\$(Configuration);..\..\api\inc;$(SolutionDir)..\..\build\staging\version\;$(GeneratedFilesDir) + + + Console + false + %(AdditionalDependencies);onecoreuap.lib;ksuser.lib;avrt.lib;midiks.lib;midikscommon.lib;midiksenum.lib + %(AdditionalDependencies);onecoreuap.lib;ksuser.lib;avrt.lib;midiks.lib;midikscommon.lib;midiksenum.lib + %(AdditionalDependencies);onecoreuap.lib;ksuser.lib;avrt.lib + + + + + WIN32;%(PreprocessorDefinitions) + stdcpp20 + + + ntdll.lib;%(AdditionalDependencies) + + + + + MaxSpeed + true + true + NDEBUG;%(PreprocessorDefinitions) + stdcpp20 + stdcpp20 + stdcpp20 + %(AdditionalIncludeDirectories);..\..\api\VSFiles\intermediate\idl\$(Platform)\$(Configuration);..\..\api\inc;$(SolutionDir)..\..\build\staging\version\;$(GeneratedFilesDir) + %(AdditionalIncludeDirectories);..\..\api\VSFiles\intermediate\idl\$(Platform)\$(Configuration);..\..\api\inc;$(SolutionDir)..\..\build\staging\version\;$(GeneratedFilesDir) + %(AdditionalIncludeDirectories);..\..\api\VSFiles\intermediate\idl\$(Platform)\$(Configuration);..\..\api\inc;$(SolutionDir)..\..\build\staging\version\;$(GeneratedFilesDir) + + + Console + true + true + false + %(AdditionalDependencies);onecoreuap.lib;ksuser.lib;avrt.lib;midiks.lib;midikscommon.lib;midiksenum.lib + %(AdditionalDependencies);onecoreuap.lib;ksuser.lib;avrt.lib;midiks.lib;midikscommon.lib;midiksenum.lib + %(AdditionalDependencies);onecoreuap.lib;ksuser.lib;avrt.lib + + + + + + + + + + Create + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + \ No newline at end of file diff --git a/src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj.filters b/src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj.filters new file mode 100644 index 000000000..d58691aee --- /dev/null +++ b/src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj.filters @@ -0,0 +1,39 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + + + + + + + \ No newline at end of file diff --git a/src/app-sdk/midimdnsinfo/packages.config b/src/app-sdk/midimdnsinfo/packages.config new file mode 100644 index 000000000..e478c2039 --- /dev/null +++ b/src/app-sdk/midimdnsinfo/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/app-sdk/midimdnsinfo/pch.cpp b/src/app-sdk/midimdnsinfo/pch.cpp new file mode 100644 index 000000000..b437ca7e5 --- /dev/null +++ b/src/app-sdk/midimdnsinfo/pch.cpp @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License +// ============================================================================ +// This is part of the Windows MIDI Services App SDK and should be used +// in your Windows application via an official binary distribution. +// Further information: https://aka.ms/midi +// ============================================================================ + + +#include "pch.h" diff --git a/src/app-sdk/midimdnsinfo/pch.h b/src/app-sdk/midimdnsinfo/pch.h new file mode 100644 index 000000000..a637da3d6 --- /dev/null +++ b/src/app-sdk/midimdnsinfo/pch.h @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License +// ============================================================================ +// This is part of the Windows MIDI Services App SDK and should be used +// in your Windows application via an official binary distribution. +// Further information: https://aka.ms/midi +// ============================================================================ + + +#pragma once + +#include +//#include + +//#pragma warning (disable: 4005) +//#include +//#pragma warning (pop) + + +#include +#include +#include + + +#include +#include +#include +#include + +using namespace winrt::Windows::Devices::Enumeration; + +namespace foundation = winrt::Windows::Foundation; +namespace collections = winrt::Windows::Foundation::Collections; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +//#include "SWDevice.h" +#include +//#include "Devpkey.h" +#include + + +#include "wstring_util.h" + +#include + +namespace internal = ::WindowsMidiServicesInternal; + + diff --git a/src/app-sdk/sdk-runtime-installer/sdk-package/WindowsMidiServicesSdkRedist.wxs b/src/app-sdk/sdk-runtime-installer/sdk-package/WindowsMidiServicesSdkRedist.wxs index 63e093da0..a7e2a5cb2 100644 --- a/src/app-sdk/sdk-runtime-installer/sdk-package/WindowsMidiServicesSdkRedist.wxs +++ b/src/app-sdk/sdk-runtime-installer/sdk-package/WindowsMidiServicesSdkRedist.wxs @@ -19,8 +19,6 @@ - - @@ -44,27 +42,27 @@ + Value="[TOOLSROOT_INSTALLFOLDER]" Permanent="no"/> + Value="[TOOLSROOT_INSTALLFOLDER]" Permanent="no"/> diff --git a/src/app-sdk/winrt/Microsoft.Windows.Devices.Midi2.vcxproj b/src/app-sdk/winrt/Microsoft.Windows.Devices.Midi2.vcxproj index 5e0d70e56..583625e0d 100644 --- a/src/app-sdk/winrt/Microsoft.Windows.Devices.Midi2.vcxproj +++ b/src/app-sdk/winrt/Microsoft.Windows.Devices.Midi2.vcxproj @@ -711,6 +711,7 @@ + diff --git a/src/app-sdk/winrt/Microsoft.Windows.Devices.Midi2.vcxproj.filters b/src/app-sdk/winrt/Microsoft.Windows.Devices.Midi2.vcxproj.filters index d60de4cbf..873201704 100644 --- a/src/app-sdk/winrt/Microsoft.Windows.Devices.Midi2.vcxproj.filters +++ b/src/app-sdk/winrt/Microsoft.Windows.Devices.Midi2.vcxproj.filters @@ -472,6 +472,9 @@ SDK\Endpoints\Network + + SDK\Endpoints\Network + diff --git a/src/app-sdk/winrt/MidiAdvertisedHost.idl b/src/app-sdk/winrt/MidiAdvertisedHost.idl new file mode 100644 index 000000000..e3268a84a --- /dev/null +++ b/src/app-sdk/winrt/MidiAdvertisedHost.idl @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License +// ============================================================================ +// This is part of the Windows MIDI Services App SDK and should be used +// in your Windows application via an official binary distribution. +// Further information: https://aka.ms/midi +// ============================================================================ + +namespace Microsoft.Windows.Devices.Midi2.Endpoints.Network +{ + [experimental] + struct MidiAdvertisedHost + { + // from SRV record + String ServiceInstanceName; + String ServiceType; + String HostName; + UInt16 Port; + + // from TXT record + String UmpEndpointName; + String ProductInstanceId; + + // TODO: A/AAAA IP records + }; +} \ No newline at end of file diff --git a/src/app-sdk/winrt/MidiNetworkEndpointManager.cpp b/src/app-sdk/winrt/MidiNetworkEndpointManager.cpp index 0a5623144..7517e3fb9 100644 --- a/src/app-sdk/winrt/MidiNetworkEndpointManager.cpp +++ b/src/app-sdk/winrt/MidiNetworkEndpointManager.cpp @@ -52,4 +52,68 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Network::impleme UNREFERENCED_PARAMETER(removalConfig); throw hresult_not_implemented(); } + + + + + + collections::IVector MidiNetworkEndpointManager::GetAdvertisedHosts() + { + //var askFor = new String[]{ "System.Devices.Dnssd.HostName", + // "System.Devices.Dnssd.ServiceName", + // "System.Devices.Dnssd.InstanceName", + // "System.Devices.IpAddress", + // "System.Devices.Dnssd.PortNumber", + // "System.Devices.Dnssd.TextAttributes", + //}; + + + auto results = enumeration::DeviceInformation::FindAllAsync( + MidiNetworkUdpDnsSdQueryString(), + MidiNetworkUdpDnsSdQueryAdditionalProperties()).get(); + + if (results && results.Size() > 0) + { + for (auto const& result : results) + { + if (result.Properties().HasKey(L"System.Devices.Dnssd.ServiceName")) + { + + } + + if (result.Properties().HasKey(L"System.Devices.Dnssd.InstanceName")) + { + + } + + if (result.Properties().HasKey(L"System.Devices.IpAddress")) + { + + } + + if (result.Properties().HasKey(L"System.Devices.Dnssd.PortNumber")) + { + + } + + if (result.Properties().HasKey(L"System.Devices.Dnssd.TextAttributes")) + { + + } + } + + } + + //var askFor = new String[]{ "System.Devices.Dnssd.HostName", + // "System.Devices.Dnssd.ServiceName", + // "System.Devices.Dnssd.InstanceName", + // "System.Devices.IpAddress", + // "System.Devices.Dnssd.PortNumber", + // "System.Devices.Dnssd.TextAttributes", + //}; + //dw = DeviceInformation.CreateWatcher(queryString, askFor, DeviceInformationKind.AssociationEndpointService); + + throw hresult_not_implemented(); + + } } diff --git a/src/app-sdk/winrt/MidiNetworkEndpointManager.h b/src/app-sdk/winrt/MidiNetworkEndpointManager.h index e35c908cc..b27a57317 100644 --- a/src/app-sdk/winrt/MidiNetworkEndpointManager.h +++ b/src/app-sdk/winrt/MidiNetworkEndpointManager.h @@ -16,12 +16,40 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Network::impleme { //MidiNetworkEndpointManager() = default; + // TODO: may want to move the enumeration functions to another class + + static winrt::hstring MidiNetworkUdpDnsServiceType() { return L"_midi2_udp.local"; } + + static winrt::hstring MidiNetworkUdpDnsSdQueryString() + { + return + L"System.Devices.AepService.ProtocolId:={4526e8c1-8aac-4153-9b16-55e86ada0e54} AND " \ + L"System.Devices.Dnssd.ServiceName: = \"" + MidiNetworkEndpointManager::MidiNetworkUdpDnsServiceType() + L"\" AND " \ + L"System.Devices.Dnssd.Domain: = \"local\""; + } + + static collections::IVector MidiNetworkUdpDnsSdQueryAdditionalProperties() + { + auto props = winrt::single_threaded_vector(); + + props.Append(L"System.Devices.Dnssd.ServiceName"); + props.Append(L"System.Devices.Dnssd.InstanceName"); + props.Append(L"System.Devices.IpAddress"); + props.Append(L"System.Devices.Dnssd.PortNumber"); + props.Append(L"System.Devices.Dnssd.TextAttributes"); + + return props; + } + static bool IsTransportAvailable(); static winrt::guid TransportId(); - static winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Network::MidiNetworkHostEndpointCreationResult CreateNetworkHost(winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Network::MidiNetworkHostEndpointCreationConfig const& creationConfig); - static winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Network::MidiNetworkHostEndpointRemovalResult RemoveNetworkHost(winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Network::MidiNetworkHostEndpointRemovalConfig const& removalConfig); - static winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Network::MidiNetworkClientEndpointCreationResult CreateNetworkClient(winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Network::MidiNetworkClientEndpointCreationConfig const& creationConfig); - static winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Network::MidiNetworkClientEndpointRemovalResult RemoveNetworkClient(winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Network::MidiNetworkClientEndpointRemovalConfig const& removalConfig); + static midi2::Endpoints::Network::MidiNetworkHostEndpointCreationResult CreateNetworkHost(midi2::Endpoints::Network::MidiNetworkHostEndpointCreationConfig const& creationConfig); + static midi2::Endpoints::Network::MidiNetworkHostEndpointRemovalResult RemoveNetworkHost(midi2::Endpoints::Network::MidiNetworkHostEndpointRemovalConfig const& removalConfig); + static midi2::Endpoints::Network::MidiNetworkClientEndpointCreationResult CreateNetworkClient(midi2::Endpoints::Network::MidiNetworkClientEndpointCreationConfig const& creationConfig); + static midi2::Endpoints::Network::MidiNetworkClientEndpointRemovalResult RemoveNetworkClient(midi2::Endpoints::Network::MidiNetworkClientEndpointRemovalConfig const& removalConfig); + + static collections::IVector GetAdvertisedHosts(); + }; } namespace winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Network::factory_implementation diff --git a/src/app-sdk/winrt/MidiNetworkEndpointManager.idl b/src/app-sdk/winrt/MidiNetworkEndpointManager.idl index b932a045e..82e9a6683 100644 --- a/src/app-sdk/winrt/MidiNetworkEndpointManager.idl +++ b/src/app-sdk/winrt/MidiNetworkEndpointManager.idl @@ -18,6 +18,7 @@ import "MidiNetworkClientEndpointCreationConfig.idl"; import "MidiNetworkClientEndpointRemovalResult.idl"; import "MidiNetworkClientEndpointRemovalConfig.idl"; +import "MidiAdvertisedHost.idl"; namespace Microsoft.Windows.Devices.Midi2.Endpoints.Network { @@ -40,6 +41,10 @@ namespace Microsoft.Windows.Devices.Midi2.Endpoints.Network static MidiNetworkClientEndpointRemovalResult RemoveNetworkClient( MidiNetworkClientEndpointRemovalConfig removalConfig); + // list the hosts currently visible to this PC + static Windows.Foundation.Collections.IVector GetAdvertisedHosts(); + static String MidiNetworkUdpDnsServiceType{ get; }; + static String MidiNetworkUdpDnsSdQueryString{ get; }; } } \ No newline at end of file From f2d04f7e3fe00a5e6b244215ec222ecae1730f44 Mon Sep 17 00:00:00 2001 From: Pete Brown Date: Thu, 28 Nov 2024 13:24:28 -0500 Subject: [PATCH 07/10] Update dev prep scripts --- src/dev-tools/reg-helpers/dev-prep.cmd | 10 ++++++++++ .../reg-helpers/midi-pre-install-reg-steps.ps1 | 3 --- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/dev-tools/reg-helpers/dev-prep.cmd b/src/dev-tools/reg-helpers/dev-prep.cmd index 88a128067..978b7887a 100644 --- a/src/dev-tools/reg-helpers/dev-prep.cmd +++ b/src/dev-tools/reg-helpers/dev-prep.cmd @@ -1 +1,11 @@ +@echo off +echo[ +echo ================================================================================== +echo To run this script, you must have the ability to run local scripts turned on. You +echo can find this in Settings - System - For Developers - Powershell +echo[ +echo You also need to run this from an elevated command prompt. Do not just double +echo click this cmd file. +echo ================================================================================== +echo[ pwsh .\midi-pre-install-reg-steps.ps1 \ No newline at end of file diff --git a/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 b/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 index 3a474c741..f625b27db 100644 --- a/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 +++ b/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 @@ -95,9 +95,6 @@ Write-Host "the component registry entries from Trusted Installer and grant them Write-Host "to enable the Developer Preview installer to install developer bits. This" -ForegroundColor DarkCyan Write-Host "will also de-register the in-box 'Midisrv' Windows MIDI Service." -ForegroundColor DarkCyan Write-Host -Write-Host "This script must be run from an elevated command prompt using the " -ForegroundColor LightkCyan -Write-Host "'Run as Administrator' feature or (if enabled) 'sudo'. " -ForegroundColor LightCyan -Write-Host Write-Host "These actions are not easily reversible without reinstalling Windows." -ForegroundColor DarkCyan Write-Host From a642d69524b0562748ac91a60a78467493590920 Mon Sep 17 00:00:00 2001 From: Pete Brown Date: Thu, 28 Nov 2024 18:13:28 -0500 Subject: [PATCH 08/10] Add emulation info to mididiag --- src/app-sdk/mididiag/main.cpp | 72 ++++++++++++++++++++-- src/app-sdk/mididiag/mididiag_field_defs.h | 4 +- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/src/app-sdk/mididiag/main.cpp b/src/app-sdk/mididiag/main.cpp index 7c9711a32..37f23ebdf 100644 --- a/src/app-sdk/mididiag/main.cpp +++ b/src/app-sdk/mididiag/main.cpp @@ -957,6 +957,21 @@ std::wstring GetProcessorArchitectureString(WORD const arch) } +#define ENV_PROCESSOR_ARCHITECTURE L"PROCESSOR_ARCHITECTURE" +#define ENV_PROCESSOR_IDENTIFIER L"PROCESSOR_IDENTIFIER" +#define ENV_PROCESSOR_LEVEL L"PROCESSOR_LEVEL" +#define ENV_PROCESSOR_REVISION L"PROCESSOR_REVISION" + + +void OutputProcessorEnvVariables() +{ + OutputStringField(ENV_PROCESSOR_ARCHITECTURE, std::wstring{ _wgetenv(ENV_PROCESSOR_ARCHITECTURE)}); + OutputStringField(ENV_PROCESSOR_IDENTIFIER, std::wstring{ _wgetenv(ENV_PROCESSOR_IDENTIFIER) }); + OutputStringField(ENV_PROCESSOR_LEVEL, std::wstring{ _wgetenv(ENV_PROCESSOR_LEVEL) }); + OutputStringField(ENV_PROCESSOR_REVISION, std::wstring{ _wgetenv(ENV_PROCESSOR_REVISION) }); +} + + void OutputSystemInfo(_In_ SYSTEM_INFO const& sysinfo) { // that sysinfo.dwNumberOfProcessors can return some strange results. @@ -969,6 +984,51 @@ void OutputSystemInfo(_In_ SYSTEM_INFO const& sysinfo) OutputHexNumericField(MIDIDIAG_FIELD_LABEL_SYSTEM_INFO_PROCESSOR_REVISION, sysinfo.wProcessorRevision); } +void OutputProcessAndNativeMachine() +{ + USHORT processMachine; + USHORT nativeMachine; + + HANDLE hProcess = ::GetCurrentProcess(); + + if (hProcess) + { + auto worked = ::IsWow64Process2(hProcess, &processMachine, &nativeMachine); + + if (worked) + { + // if not running emulated, IsWow64Process2 returns machine unknown for the process. + if ((processMachine == IMAGE_FILE_MACHINE_UNKNOWN || processMachine == IMAGE_FILE_MACHINE_ARM64) && nativeMachine == IMAGE_FILE_MACHINE_ARM64) + { + OutputStringField(MIDIDIAG_FIELD_LABEL_SYSTEM_INFO_PROCESSOR_EMULATION, std::wstring{ L"Native Arm64 process on Arm64 PC (Note Emulated)" }); + } + else if ((processMachine == IMAGE_FILE_MACHINE_UNKNOWN || processMachine == IMAGE_FILE_MACHINE_AMD64) && nativeMachine == IMAGE_FILE_MACHINE_AMD64) + { + OutputStringField(MIDIDIAG_FIELD_LABEL_SYSTEM_INFO_PROCESSOR_EMULATION, std::wstring{ L"Native Intel/AMD x64 on x64 PC (Not Emulated)" }); + } + else if (processMachine == IMAGE_FILE_MACHINE_AMD64 && nativeMachine == IMAGE_FILE_MACHINE_ARM64) + { + OutputStringField(MIDIDIAG_FIELD_LABEL_SYSTEM_INFO_PROCESSOR_EMULATION, std::wstring{ L"Intel/AMD x64 process on Arm64 PC (Emulated)" }); + } + else if (processMachine == IMAGE_FILE_MACHINE_ARM64 && nativeMachine == IMAGE_FILE_MACHINE_AMD64) + { + // not supported today, but here in case it is some day + OutputStringField(MIDIDIAG_FIELD_LABEL_SYSTEM_INFO_PROCESSOR_EMULATION, std::wstring{ L"Arm64 process on Intel/AMD x64 PC (Emulated)" }); + } + else + { + OutputError(L"Unidentified process and/or machine architecture"); + } + } + else + { + OutputError(L"Unable to query process and machine architecture."); + } + + } +} + + bool DoSectionSystemInfo(_In_ bool verbose) { UNREFERENCED_PARAMETER(verbose); @@ -978,19 +1038,19 @@ bool DoSectionSystemInfo(_In_ bool verbose) // if running under emulation on Arm64, this is going to return the emulated sys info - OutputSectionHeader(MIDIDIAG_SECTION_LABEL_APPARENT_SYSTEM_INFO); + OutputSectionHeader(MIDIDIAG_SECTION_LABEL_PROCESSOR_ENV); + OutputProcessorEnvVariables(); - SYSTEM_INFO sysinfo; - ::GetNativeSystemInfo(&sysinfo); - OutputSystemInfo(sysinfo); - - // if running under emulation on Arm64, this is going to return the Arm info OutputSectionHeader(MIDIDIAG_SECTION_LABEL_NATIVE_SYSTEM_INFO); SYSTEM_INFO sysinfoNative; ::GetNativeSystemInfo(&sysinfoNative); OutputSystemInfo(sysinfoNative); + OutputItemSeparator(); + OutputProcessAndNativeMachine(); + OutputItemSeparator(); + TIMECAPS timecaps; auto tcresult = ::timeGetDevCaps(&timecaps, sizeof(timecaps)); diff --git a/src/app-sdk/mididiag/mididiag_field_defs.h b/src/app-sdk/mididiag/mididiag_field_defs.h index 8b42a4c31..e2ab9e289 100644 --- a/src/app-sdk/mididiag/mididiag_field_defs.h +++ b/src/app-sdk/mididiag/mididiag_field_defs.h @@ -110,11 +110,13 @@ #define MIDIDIAG_SECTION_LABEL_OS L"os" #define MIDIDIAG_FIELD_LABEL_OS_VERSION L"os_version" -#define MIDIDIAG_SECTION_LABEL_APPARENT_SYSTEM_INFO L"apparent_system_info" +#define MIDIDIAG_SECTION_LABEL_PROCESSOR_ENV L"processor_env" #define MIDIDIAG_SECTION_LABEL_NATIVE_SYSTEM_INFO L"native_system_info" #define MIDIDIAG_FIELD_LABEL_SYSTEM_INFO_PROCESSOR_ARCH L"processor_architecture" #define MIDIDIAG_FIELD_LABEL_SYSTEM_INFO_PROCESSOR_LEVEL L"processor_level" #define MIDIDIAG_FIELD_LABEL_SYSTEM_INFO_PROCESSOR_REVISION L"processor_revision" +#define MIDIDIAG_FIELD_LABEL_SYSTEM_INFO_PROCESSOR_EMULATION L"running_emulated" + #define MIDIDIAG_FIELD_LABEL_SYSTEM_INFO_TIMECAPS_ERROR L"timecaps_error" #define MIDIDIAG_FIELD_LABEL_SYSTEM_INFO_TIMECAPS_MIN_PERIOD L"timecaps_min_period" From 6de9dacf9386314e52cfe2a77d83580deba9edab Mon Sep 17 00:00:00 2001 From: Pete Brown Date: Mon, 2 Dec 2024 12:14:07 -0500 Subject: [PATCH 09/10] Add 64/32 bit check to reg scripts --- src/dev-tools/reg-helpers/midi-list-reg.ps1 | 7 +++++++ .../reg-helpers/midi-pre-install-reg-steps.ps1 | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/dev-tools/reg-helpers/midi-list-reg.ps1 b/src/dev-tools/reg-helpers/midi-list-reg.ps1 index ddc6fbad6..b10cd13d1 100644 --- a/src/dev-tools/reg-helpers/midi-list-reg.ps1 +++ b/src/dev-tools/reg-helpers/midi-list-reg.ps1 @@ -27,6 +27,13 @@ Write-Host "you will need to run the dev-prep script before running the installer." -ForegroundColor DarkCyan Write-Host + if (!([Environment]::Is64BitProcess)) +{ + Write-Host + Write-Host "This appears to be a 32-bit host. This script must be run from a 64-bit elevated shell." -ForegroundColor Red + Write-Host + Exit +} # display info about the MIDI Service that is installed diff --git a/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 b/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 index f625b27db..11498cd76 100644 --- a/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 +++ b/src/dev-tools/reg-helpers/midi-pre-install-reg-steps.ps1 @@ -98,6 +98,16 @@ Write-Host Write-Host "These actions are not easily reversible without reinstalling Windows." -ForegroundColor DarkCyan Write-Host +if (!([Environment]::Is64BitProcess)) +{ + Write-Host + Write-Host "This appears to be a 32-bit host. This script must be run from a 64-bit elevated shell." -ForegroundColor Red + Write-Host + Exit +} + + + $confirmation = Read-Host "Do you want to continue? (y/n)" if ($confirmation -eq 'y' -or $confirmation -eq 'Y') { From bcc9482ff0700e8cec6db7d82daa6175d7a9da7f Mon Sep 17 00:00:00 2001 From: Pete Brown Date: Mon, 2 Dec 2024 12:14:25 -0500 Subject: [PATCH 10/10] Working on network midi --- build/nuke_build/Build.cs | 16 ++---- build/staging/version/BundleInfo.wxi | 2 +- .../version/WindowsMidiServicesVersion.cs | 6 +-- .../version/WindowsMidiServicesVersion.h | 6 +-- .../basics/client-basics-cpp.vcxproj | 2 +- samples/cpp-winrt/basics/packages.config | 2 +- .../loopback-endpoints-cpp.vcxproj | 2 +- .../loopback-endpoints/packages.config | 2 +- samples/cpp-winrt/send-speed/packages.config | 2 +- .../send-speed/send-speed-cpp.vcxproj | 2 +- .../static-enum-endpoints/packages.config | 2 +- .../static-enum-endpoints-cpp.vcxproj | 2 +- .../cpp-winrt/watch-endpoints/packages.config | 2 +- .../watch-endpoints-cpp.vcxproj | 2 +- src/app-sdk/app-sdk-tools-and-tests.sln | 4 +- src/app-sdk/mididiag/main.cpp | 4 +- src/app-sdk/mididiag/mididiag.vcxproj | 2 +- src/app-sdk/mididiag/packages.config | 2 +- src/app-sdk/midimdnsinfo/main.cpp | 4 ++ src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj | 37 +++++--------- src/app-sdk/midimdnsinfo/packages.config | 2 +- src/app-sdk/midiusbinfo/midiusbinfo.vcxproj | 2 +- src/app-sdk/midiusbinfo/packages.config | 2 +- .../WindowsMidiServicesSdkRedist.wxs | 16 +++++- .../winrt/MidiNetworkEndpointManager.cpp | 51 ++++++++----------- .../EnumMdnsAdvertisementsCommand.cs | 27 ++++++++++ src/user-tools/midi-console/Midi/Program.cs | 10 ++++ .../Midi/Resources/Strings.Designer.cs | 9 ++++ .../midi-console/Midi/Resources/Strings.resx | 3 ++ 29 files changed, 132 insertions(+), 93 deletions(-) create mode 100644 src/user-tools/midi-console/Midi/Commands/Enumerate/EnumMdnsAdvertisementsCommand.cs diff --git a/build/nuke_build/Build.cs b/build/nuke_build/Build.cs index 5be548828..abbaa78ce 100644 --- a/build/nuke_build/Build.cs +++ b/build/nuke_build/Build.cs @@ -514,6 +514,7 @@ class Build : NukeBuild { Path.Combine(solutionDir, "mididiag"), Path.Combine(solutionDir, "midiusbinfo"), + Path.Combine(solutionDir, "midimdnsinfo"), }; foreach (var projectFolder in toolsDirectories) @@ -547,15 +548,6 @@ class Build : NukeBuild } - - - - - - - - - MSBuildTasks.MSBuild(_ => _ .SetTargetPath(AppSdkSolutionFolder / "app-sdk-tools-and-tests.sln") .SetMaxCpuCount(14) @@ -581,12 +573,10 @@ class Build : NukeBuild stagingPlatform = "Arm64"; } - // MIDI diagnostics app + // MIDI utilities FileSystemTasks.CopyFileToDirectory(sdkOutputRootFolder / "mididiag" / stagingPlatform / Configuration.Release / $"mididiag.exe", AppSdkStagingFolder / stagingPlatform, FileExistsPolicy.Overwrite, true); - //FileSystemTasks.CopyFileToDirectory(sdkOutputRootFolder / "mididiag" / stagingPlatform / Configuration.Release / $"mididiag.exe.manifest", AppSdkStagingFolder / stagingPlatform, FileExistsPolicy.Overwrite, true); - - // MIDI USB info utility FileSystemTasks.CopyFileToDirectory(sdkOutputRootFolder / "midiusbinfo" / stagingPlatform / Configuration.Release / $"midiusbinfo.exe", AppSdkStagingFolder / stagingPlatform, FileExistsPolicy.Overwrite, true); + FileSystemTasks.CopyFileToDirectory(sdkOutputRootFolder / "midimdnsinfo" / stagingPlatform / Configuration.Release / $"midimdnsinfo.exe", AppSdkStagingFolder / stagingPlatform, FileExistsPolicy.Overwrite, true); } }); diff --git a/build/staging/version/BundleInfo.wxi b/build/staging/version/BundleInfo.wxi index 240a54ee5..c0084699d 100644 --- a/build/staging/version/BundleInfo.wxi +++ b/build/staging/version/BundleInfo.wxi @@ -1,4 +1,4 @@ - + diff --git a/build/staging/version/WindowsMidiServicesVersion.cs b/build/staging/version/WindowsMidiServicesVersion.cs index 6b655b3d3..55b25d45d 100644 --- a/build/staging/version/WindowsMidiServicesVersion.cs +++ b/build/staging/version/WindowsMidiServicesVersion.cs @@ -6,12 +6,12 @@ public static class MidiBuildInformation { public const string Source = "GitHub Preview"; public const string Name = "Developer Preview 8"; - public const string BuildFullVersion = "1.0.2-preview-8.241127-1315"; + public const string BuildFullVersion = "1.0.2-preview-8.241128-2138"; public const string VersionMajor = "1"; public const string VersionMinor = "0"; public const string VersionRevision = "2"; - public const string VersionDateNumber = "241127"; - public const string VersionTimeNumber = "1315"; + public const string VersionDateNumber = "241128"; + public const string VersionTimeNumber = "2138"; } } diff --git a/build/staging/version/WindowsMidiServicesVersion.h b/build/staging/version/WindowsMidiServicesVersion.h index 3cc3c22b8..55eb24342 100644 --- a/build/staging/version/WindowsMidiServicesVersion.h +++ b/build/staging/version/WindowsMidiServicesVersion.h @@ -5,12 +5,12 @@ #define WINDOWS_MIDI_SERVICES_BUILD_SOURCE L"GitHub Preview" #define WINDOWS_MIDI_SERVICES_BUILD_VERSION_NAME L"Developer Preview 8" -#define WINDOWS_MIDI_SERVICES_BUILD_VERSION_FULL L"1.0.2-preview-8.241127-1315" +#define WINDOWS_MIDI_SERVICES_BUILD_VERSION_FULL L"1.0.2-preview-8.241128-2138" #define WINDOWS_MIDI_SERVICES_BUILD_VERSION_MAJOR L"1" #define WINDOWS_MIDI_SERVICES_BUILD_VERSION_MINOR L"0" #define WINDOWS_MIDI_SERVICES_BUILD_VERSION_REVISION L"2" -#define WINDOWS_MIDI_SERVICES_BUILD_VERSION_DATE_NUMBER L"241127" -#define WINDOWS_MIDI_SERVICES_BUILD_VERSION_TIME_NUMBER L"1315" +#define WINDOWS_MIDI_SERVICES_BUILD_VERSION_DATE_NUMBER L"241128" +#define WINDOWS_MIDI_SERVICES_BUILD_VERSION_TIME_NUMBER L"2138" #endif diff --git a/samples/cpp-winrt/basics/client-basics-cpp.vcxproj b/samples/cpp-winrt/basics/client-basics-cpp.vcxproj index d8af6da7f..3ba3bf0c8 100644 --- a/samples/cpp-winrt/basics/client-basics-cpp.vcxproj +++ b/samples/cpp-winrt/basics/client-basics-cpp.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241128-2138 true true false diff --git a/samples/cpp-winrt/basics/packages.config b/samples/cpp-winrt/basics/packages.config index 9ca35a8fd..3ab704bb9 100644 --- a/samples/cpp-winrt/basics/packages.config +++ b/samples/cpp-winrt/basics/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/samples/cpp-winrt/loopback-endpoints/loopback-endpoints-cpp.vcxproj b/samples/cpp-winrt/loopback-endpoints/loopback-endpoints-cpp.vcxproj index 8d2ce5104..f6a96c439 100644 --- a/samples/cpp-winrt/loopback-endpoints/loopback-endpoints-cpp.vcxproj +++ b/samples/cpp-winrt/loopback-endpoints/loopback-endpoints-cpp.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241128-2138 true true true diff --git a/samples/cpp-winrt/loopback-endpoints/packages.config b/samples/cpp-winrt/loopback-endpoints/packages.config index 9ca35a8fd..3ab704bb9 100644 --- a/samples/cpp-winrt/loopback-endpoints/packages.config +++ b/samples/cpp-winrt/loopback-endpoints/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/samples/cpp-winrt/send-speed/packages.config b/samples/cpp-winrt/send-speed/packages.config index 9ca35a8fd..3ab704bb9 100644 --- a/samples/cpp-winrt/send-speed/packages.config +++ b/samples/cpp-winrt/send-speed/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/samples/cpp-winrt/send-speed/send-speed-cpp.vcxproj b/samples/cpp-winrt/send-speed/send-speed-cpp.vcxproj index 4f63dfad0..f5f6a41b5 100644 --- a/samples/cpp-winrt/send-speed/send-speed-cpp.vcxproj +++ b/samples/cpp-winrt/send-speed/send-speed-cpp.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241128-2138 true true true diff --git a/samples/cpp-winrt/static-enum-endpoints/packages.config b/samples/cpp-winrt/static-enum-endpoints/packages.config index 9ca35a8fd..3ab704bb9 100644 --- a/samples/cpp-winrt/static-enum-endpoints/packages.config +++ b/samples/cpp-winrt/static-enum-endpoints/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/samples/cpp-winrt/static-enum-endpoints/static-enum-endpoints-cpp.vcxproj b/samples/cpp-winrt/static-enum-endpoints/static-enum-endpoints-cpp.vcxproj index e41cc22a0..04d584c43 100644 --- a/samples/cpp-winrt/static-enum-endpoints/static-enum-endpoints-cpp.vcxproj +++ b/samples/cpp-winrt/static-enum-endpoints/static-enum-endpoints-cpp.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241128-2138 true true true diff --git a/samples/cpp-winrt/watch-endpoints/packages.config b/samples/cpp-winrt/watch-endpoints/packages.config index 9ca35a8fd..3ab704bb9 100644 --- a/samples/cpp-winrt/watch-endpoints/packages.config +++ b/samples/cpp-winrt/watch-endpoints/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/samples/cpp-winrt/watch-endpoints/watch-endpoints-cpp.vcxproj b/samples/cpp-winrt/watch-endpoints/watch-endpoints-cpp.vcxproj index 728d33c50..5f4114e89 100644 --- a/samples/cpp-winrt/watch-endpoints/watch-endpoints-cpp.vcxproj +++ b/samples/cpp-winrt/watch-endpoints/watch-endpoints-cpp.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241128-2138 true true true diff --git a/src/app-sdk/app-sdk-tools-and-tests.sln b/src/app-sdk/app-sdk-tools-and-tests.sln index 02f1e8431..ee92035f1 100644 --- a/src/app-sdk/app-sdk-tools-and-tests.sln +++ b/src/app-sdk/app-sdk-tools-and-tests.sln @@ -141,8 +141,8 @@ Global {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|Any CPU.Build.0 = Release|x64 {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|ARM64.ActiveCfg = Release|ARM64 {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|ARM64.Build.0 = Release|ARM64 - {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|ARM64EC.ActiveCfg = Release|ARM64EC - {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|ARM64EC.Build.0 = Release|ARM64EC + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|ARM64EC.ActiveCfg = Release|ARM64 + {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|ARM64EC.Build.0 = Release|ARM64 {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|x64.ActiveCfg = Release|x64 {C787073C-50F0-5CA0-D53C-12107196F2F0}.Release|x64.Build.0 = Release|x64 EndGlobalSection diff --git a/src/app-sdk/mididiag/main.cpp b/src/app-sdk/mididiag/main.cpp index 37f23ebdf..4e4b031b6 100644 --- a/src/app-sdk/mididiag/main.cpp +++ b/src/app-sdk/mididiag/main.cpp @@ -986,8 +986,8 @@ void OutputSystemInfo(_In_ SYSTEM_INFO const& sysinfo) void OutputProcessAndNativeMachine() { - USHORT processMachine; - USHORT nativeMachine; + USHORT processMachine{ 0 }; + USHORT nativeMachine{ 0 }; HANDLE hProcess = ::GetCurrentProcess(); diff --git a/src/app-sdk/mididiag/mididiag.vcxproj b/src/app-sdk/mididiag/mididiag.vcxproj index bea533c1a..ab7d0521d 100644 --- a/src/app-sdk/mididiag/mididiag.vcxproj +++ b/src/app-sdk/mididiag/mididiag.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241128-2138 true true true diff --git a/src/app-sdk/mididiag/packages.config b/src/app-sdk/mididiag/packages.config index e478c2039..f15524917 100644 --- a/src/app-sdk/mididiag/packages.config +++ b/src/app-sdk/mididiag/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/app-sdk/midimdnsinfo/main.cpp b/src/app-sdk/midimdnsinfo/main.cpp index b245ec09f..b5139d8f3 100644 --- a/src/app-sdk/midimdnsinfo/main.cpp +++ b/src/app-sdk/midimdnsinfo/main.cpp @@ -34,6 +34,10 @@ int __cdecl main() std::cout << dye::grey("===================================================================") << std::endl; + + + + std::cout << std::endl; return 0; diff --git a/src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj b/src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj index f4837f8a3..6fdd86e51 100644 --- a/src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj +++ b/src/app-sdk/midimdnsinfo/midimdnsinfo.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241128-2138 true true true @@ -10,7 +10,7 @@ 15.0 {C787073C-50F0-5CA0-D53C-12107196F2F0} Win32Proj - midiusbinfo + midimdnsinfo 10.0 10.0.20348.0 midimdnsinfo @@ -73,42 +73,42 @@ $(SolutionDir)vsfiles\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ $(SolutionDir)vsfiles\out\$(ProjectName)\$(Platform)\$(Configuration)\ $(IncludePath) - ..\..\api\VSFiles\intermediate\midiks\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midiksenum\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midikscommon\$(Platform)\$(Configuration);$(LibraryPath) + $(LibraryPath) $(ExternalIncludePath);$(SolutionDir)..\api\inc;$(SolutionDir)..\api\vsfiles\intermediate\IDL\$(Platform)\$(Configuration) $(SolutionDir)vsfiles\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ $(SolutionDir)vsfiles\out\$(ProjectName)\$(Platform)\$(Configuration)\ $(IncludePath) - ..\..\api\VSFiles\intermediate\midiks\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midiksenum\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midikscommon\$(Platform)\$(Configuration);$(LibraryPath) + $(LibraryPath) $(ExternalIncludePath);$(SolutionDir)..\api\inc;$(SolutionDir)..\api\vsfiles\intermediate\IDL\$(Platform)\$(Configuration) $(SolutionDir)vsfiles\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ $(SolutionDir)vsfiles\out\$(ProjectName)\$(Platform)\$(Configuration)\ $(IncludePath) - ..\..\api\VSFiles\intermediate\midiks\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midiksenum\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midikscommon\$(Platform)\$(Configuration);$(LibraryPath) + $(LibraryPath) $(ExternalIncludePath);$(SolutionDir)..\api\inc;$(SolutionDir)..\api\vsfiles\intermediate\IDL\$(Platform)\$(Configuration) $(SolutionDir)vsfiles\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ $(SolutionDir)vsfiles\out\$(ProjectName)\$(Platform)\$(Configuration)\ $(IncludePath) - ..\..\api\VSFiles\intermediate\midiks\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midiksenum\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midikscommon\$(Platform)\$(Configuration);$(LibraryPath) + $(LibraryPath) $(ExternalIncludePath);$(SolutionDir)..\api\inc;$(SolutionDir)..\api\vsfiles\intermediate\IDL\$(Platform)\$(Configuration) $(SolutionDir)vsfiles\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ $(SolutionDir)vsfiles\out\$(ProjectName)\$(Platform)\$(Configuration)\ $(IncludePath) - ..\..\api\VSFiles\intermediate\midiks\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midiksenum\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midikscommon\$(Platform)\$(Configuration);$(LibraryPath) + $(LibraryPath) $(ExternalIncludePath);$(SolutionDir)..\api\inc;$(SolutionDir)..\api\vsfiles\intermediate\IDL\$(Platform)\$(Configuration) $(SolutionDir)vsfiles\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ $(SolutionDir)vsfiles\out\$(ProjectName)\$(Platform)\$(Configuration)\ $(IncludePath) - ..\..\api\VSFiles\intermediate\midiks\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midiksenum\$(Platform)\$(Configuration);..\..\api\VSFiles\intermediate\midikscommon\$(Platform)\$(Configuration);$(LibraryPath) + $(LibraryPath) $(ExternalIncludePath);$(SolutionDir)..\api\inc;$(SolutionDir)..\api\vsfiles\intermediate\IDL\$(Platform)\$(Configuration) @@ -135,18 +135,9 @@ Console false - %(AdditionalDependencies);onecoreuap.lib;ksuser.lib;avrt.lib;midiks.lib;midikscommon.lib;midiksenum.lib - %(AdditionalDependencies);onecoreuap.lib;ksuser.lib;avrt.lib;midiks.lib;midikscommon.lib;midiksenum.lib - %(AdditionalDependencies);onecoreuap.lib;ksuser.lib;avrt.lib - - - - - WIN32;%(PreprocessorDefinitions) - stdcpp20 - - - ntdll.lib;%(AdditionalDependencies) + %(AdditionalDependencies);onecoreuap.lib; + %(AdditionalDependencies);onecoreuap.lib; + %(AdditionalDependencies);onecoreuap.lib; @@ -167,9 +158,9 @@ true true false - %(AdditionalDependencies);onecoreuap.lib;ksuser.lib;avrt.lib;midiks.lib;midikscommon.lib;midiksenum.lib - %(AdditionalDependencies);onecoreuap.lib;ksuser.lib;avrt.lib;midiks.lib;midikscommon.lib;midiksenum.lib - %(AdditionalDependencies);onecoreuap.lib;ksuser.lib;avrt.lib + %(AdditionalDependencies);onecoreuap.lib; + %(AdditionalDependencies);onecoreuap.lib; + %(AdditionalDependencies);onecoreuap.lib; diff --git a/src/app-sdk/midimdnsinfo/packages.config b/src/app-sdk/midimdnsinfo/packages.config index e478c2039..f15524917 100644 --- a/src/app-sdk/midimdnsinfo/packages.config +++ b/src/app-sdk/midimdnsinfo/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/app-sdk/midiusbinfo/midiusbinfo.vcxproj b/src/app-sdk/midiusbinfo/midiusbinfo.vcxproj index 58e4c440b..1b792fbb4 100644 --- a/src/app-sdk/midiusbinfo/midiusbinfo.vcxproj +++ b/src/app-sdk/midiusbinfo/midiusbinfo.vcxproj @@ -2,7 +2,7 @@ - Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241127-1315 + Microsoft.Windows.Devices.Midi2.1.0.2-preview-8.241128-2138 true true true diff --git a/src/app-sdk/midiusbinfo/packages.config b/src/app-sdk/midiusbinfo/packages.config index e478c2039..f15524917 100644 --- a/src/app-sdk/midiusbinfo/packages.config +++ b/src/app-sdk/midiusbinfo/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/app-sdk/sdk-runtime-installer/sdk-package/WindowsMidiServicesSdkRedist.wxs b/src/app-sdk/sdk-runtime-installer/sdk-package/WindowsMidiServicesSdkRedist.wxs index a7e2a5cb2..d80253914 100644 --- a/src/app-sdk/sdk-runtime-installer/sdk-package/WindowsMidiServicesSdkRedist.wxs +++ b/src/app-sdk/sdk-runtime-installer/sdk-package/WindowsMidiServicesSdkRedist.wxs @@ -65,7 +65,20 @@ Value="[TOOLSROOT_INSTALLFOLDER]" Permanent="no"/> - + + + + + + + + + + diff --git a/src/app-sdk/winrt/MidiNetworkEndpointManager.cpp b/src/app-sdk/winrt/MidiNetworkEndpointManager.cpp index 7517e3fb9..b173d1c9c 100644 --- a/src/app-sdk/winrt/MidiNetworkEndpointManager.cpp +++ b/src/app-sdk/winrt/MidiNetworkEndpointManager.cpp @@ -59,61 +59,52 @@ namespace winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Network::impleme collections::IVector MidiNetworkEndpointManager::GetAdvertisedHosts() { - //var askFor = new String[]{ "System.Devices.Dnssd.HostName", - // "System.Devices.Dnssd.ServiceName", - // "System.Devices.Dnssd.InstanceName", - // "System.Devices.IpAddress", - // "System.Devices.Dnssd.PortNumber", - // "System.Devices.Dnssd.TextAttributes", - //}; + auto results = winrt::single_threaded_vector(); - - auto results = enumeration::DeviceInformation::FindAllAsync( + auto entries = enumeration::DeviceInformation::FindAllAsync( MidiNetworkUdpDnsSdQueryString(), MidiNetworkUdpDnsSdQueryAdditionalProperties()).get(); - if (results && results.Size() > 0) + if (entries && entries.Size() > 0) { - for (auto const& result : results) + + for (auto const& entry : entries) { - if (result.Properties().HasKey(L"System.Devices.Dnssd.ServiceName")) - { + MidiAdvertisedHost host; + if (entry.Properties().HasKey(L"System.Devices.Dnssd.ServiceName")) + { + host.ServiceType = L"Test Service Name"; } - if (result.Properties().HasKey(L"System.Devices.Dnssd.InstanceName")) + if (entry.Properties().HasKey(L"System.Devices.Dnssd.InstanceName")) { - + host.ServiceInstanceName = L"Test Instance Name"; } - if (result.Properties().HasKey(L"System.Devices.IpAddress")) + if (entry.Properties().HasKey(L"System.Devices.IpAddress")) { - + //host.Address = L""; } - if (result.Properties().HasKey(L"System.Devices.Dnssd.PortNumber")) + if (entry.Properties().HasKey(L"System.Devices.Dnssd.PortNumber")) { - + //host.Port = L""; } - if (result.Properties().HasKey(L"System.Devices.Dnssd.TextAttributes")) + if (entry.Properties().HasKey(L"System.Devices.Dnssd.TextAttributes")) { + // TODO: Parse out the text entries } + + results.Append(host); } } - //var askFor = new String[]{ "System.Devices.Dnssd.HostName", - // "System.Devices.Dnssd.ServiceName", - // "System.Devices.Dnssd.InstanceName", - // "System.Devices.IpAddress", - // "System.Devices.Dnssd.PortNumber", - // "System.Devices.Dnssd.TextAttributes", - //}; - //dw = DeviceInformation.CreateWatcher(queryString, askFor, DeviceInformationKind.AssociationEndpointService); - - throw hresult_not_implemented(); + // empty collection if nothing found + return results; } } diff --git a/src/user-tools/midi-console/Midi/Commands/Enumerate/EnumMdnsAdvertisementsCommand.cs b/src/user-tools/midi-console/Midi/Commands/Enumerate/EnumMdnsAdvertisementsCommand.cs new file mode 100644 index 000000000..6d2e4d707 --- /dev/null +++ b/src/user-tools/midi-console/Midi/Commands/Enumerate/EnumMdnsAdvertisementsCommand.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License +// ============================================================================ +// This is part of Windows MIDI Services and should be used +// in your Windows application via an official binary distribution. +// Further information: https://aka.ms/midi +// ============================================================================ + +using Microsoft.Windows.Devices.Midi2.Endpoints.Network; + +namespace Microsoft.Midi.ConsoleApp +{ + internal class EnumMdnsAdvertisementsCommand : Command + { + public sealed class Settings : CommandSettings + { + } + + public override int Execute(CommandContext context, Settings settings) + { + + + + return 0; + } + } +} diff --git a/src/user-tools/midi-console/Midi/Program.cs b/src/user-tools/midi-console/Midi/Program.cs index f36b0ba55..3db903567 100644 --- a/src/user-tools/midi-console/Midi/Program.cs +++ b/src/user-tools/midi-console/Midi/Program.cs @@ -69,6 +69,16 @@ .WithAlias("transports") .WithDescription(Strings.CommandEnumerateTransportPluginsDescription) .WithExample("enumerate", "transport-plugins") + .WithExample("enumerate", "transports") + ; + + enumerate.AddCommand("mdns-advertisements") + .WithAlias("mdns") + .WithAlias("network-midi") + .WithDescription(Strings.CommandEnumerateMdnsAdvertisementsDescription) + .WithExample("enumerate", "mdns-advertisements") + .WithExample("enumerate", "mdns") + .WithExample("enumerate", "network-midi") ; diff --git a/src/user-tools/midi-console/Midi/Resources/Strings.Designer.cs b/src/user-tools/midi-console/Midi/Resources/Strings.Designer.cs index da2ff39f0..4655927bb 100644 --- a/src/user-tools/midi-console/Midi/Resources/Strings.Designer.cs +++ b/src/user-tools/midi-console/Midi/Resources/Strings.Designer.cs @@ -177,6 +177,15 @@ internal static string CommandEnumerateLegacyEndpointsDescription { } } + /// + /// Looks up a localized string similar to List discovered MDNS advertisements for Network MIDI 2.0 (UDP) services on the network.. + /// + internal static string CommandEnumerateMdnsAdvertisementsDescription { + get { + return ResourceManager.GetString("CommandEnumerateMdnsAdvertisementsDescription", resourceCulture); + } + } + /// /// Looks up a localized string similar to List all MIDI transport plugins installed on this PC.. /// diff --git a/src/user-tools/midi-console/Midi/Resources/Strings.resx b/src/user-tools/midi-console/Midi/Resources/Strings.resx index 65e02fab3..7ad25aff1 100644 --- a/src/user-tools/midi-console/Midi/Resources/Strings.resx +++ b/src/user-tools/midi-console/Midi/Resources/Strings.resx @@ -875,4 +875,7 @@ Timestamp Failed to start up the SDK initializer (COM object may not be available or registered) + + List discovered MDNS advertisements for Network MIDI 2.0 (UDP) services on the network. + \ No newline at end of file