diff --git a/build/electron-projection/MIDI Project electron projection notes.txt b/build/electron-projection/MIDI Project electron projection notes.txt
index 86312828..6be9f291 100644
--- a/build/electron-projection/MIDI Project electron projection notes.txt
+++ b/build/electron-projection/MIDI Project electron projection notes.txt
@@ -34,7 +34,9 @@ copy Windows.winmd from the unionmetadata to same folder
copy C:\Program Files\Microsoft Visual Studio\2022\Preview\Common7\IDE\VC\vcpackages platform.winmd to same folder
-Comment out SendMessageStruct body and reference
+Comment out SendSingleMessageStruct body and reference
+Comment out SendMultipleMessagesStructList
+Comment out SendMultipleMessagesStructArray
Open binding.sln in VS and recompile in BOTH debug and release
diff --git a/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiChannelEndpointListener.md b/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiChannelEndpointListener.md
index 762aa3da..1e600be3 100644
--- a/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiChannelEndpointListener.md
+++ b/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiChannelEndpointListener.md
@@ -27,6 +27,39 @@ In addition to the properties and methods in `IMidiEndpointMessageProcessingPlug
| ---- | ---- |
| `MidiChannelEndpointListener()` | Construct a new instance of this type |
+## Example
+
+```cpp
+// set up your message receive handler and create your connection
+// before setting up the individual message listeners. The event
+// handler has the same signature as the main message received
+// event on the connection.
+
+midi2::MidiChannelEndpointListener channelsListener;
+
+// listening to channels generally only makes sense if you also
+// specify the group you are listening to.
+channelsListener.IncludeGroup(midi2::MidiGroup(5));
+
+// add the channels you are listening to. Any messages which do
+// not have channels will not be raised through the event here.
+channelsListener.IncludeChannels().Append(midi2::MidiChannel(3));
+channelsListener.IncludeChannels().Append(midi2::MidiChannel(7));
+
+// set this if you don't want the main message received event on the
+// connection to fire for any messages this plugin handles.
+channelsListener.PreventFiringMainMessageReceivedEvent(true);
+
+auto channelMessagesReceivedEventToken = channelsListener.MessageReceived(MyMessageReceivedHandler);
+
+myConnection.AddMessageProcessingPlugin(channelsListener);
+
+// open after setting up the plugin so you don't miss any messages
+myConnection.Open();
+
+// ...
+```
+
## IDL
[MidiChannelEndpointListener IDL](https://github.com/microsoft/MIDI/blob/main/src/api/Client/Midi2Client/MidiChannelEndpointListener.idl)
diff --git a/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiGroupEndpointListener.md b/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiGroupEndpointListener.md
index 903a41fd..00ba1e6f 100644
--- a/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiGroupEndpointListener.md
+++ b/docs/developer-docs/Windows.Devices.Midi2/processing-plugins/MidiGroupEndpointListener.md
@@ -28,6 +28,31 @@ In addition to the properties and methods in `IMidiEndpointMessageProcessingPlug
| ---- | ---- |
| `MidiGroupEndpointListener()` | Construct a new instance of this type |
+
+```cpp
+// set up your message receive handler and create your connection
+// before setting up the individual message listeners. The event
+// handler has the same signature as the main message received
+// event on the connection.
+
+midi2::MidiGroupEndpointListener groupsListener;
+groupsListener.IncludeGroups().Append(midi2::MidiGroup(5));
+groupsListener.IncludeGroups().Append(midi2::MidiGroup(6));
+
+// set this if you don't want the main message received event on the
+// connection to fire for any messages this plugin handles.
+groupsListener.PreventFiringMainMessageReceivedEvent(true);
+
+auto groupsMessagesReceivedEventToken = groupsListener.MessageReceived(MyMessageReceivedHandler);
+
+myConnection.AddMessageProcessingPlugin(groupsListener);
+
+// open after setting up the plugin so you don't miss any messages
+myConnection.Open();
+
+// ...
+```
+
## IDL
[MidiGroupEndpointListener IDL](https://github.com/microsoft/MIDI/blob/main/src/api/Client/Midi2Client/MidiGroupEndpointListener.idl)
diff --git a/src/prototypes/ble-midi1-proto/PropertySheet.props b/src/prototypes/ble-midi1-proto/PropertySheet.props
new file mode 100644
index 00000000..b0c62269
--- /dev/null
+++ b/src/prototypes/ble-midi1-proto/PropertySheet.props
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/prototypes/ble-midi1-proto/ble-midi1-proto.sln b/src/prototypes/ble-midi1-proto/ble-midi1-proto.sln
new file mode 100644
index 00000000..9ba3c530
--- /dev/null
+++ b/src/prototypes/ble-midi1-proto/ble-midi1-proto.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.10.34607.79
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ble-midi1-proto", "ble-midi1-proto.vcxproj", "{4AF9289B-9B4F-4774-895E-535A72A8C285}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4AF9289B-9B4F-4774-895E-535A72A8C285}.Debug|x64.ActiveCfg = Debug|x64
+ {4AF9289B-9B4F-4774-895E-535A72A8C285}.Debug|x64.Build.0 = Debug|x64
+ {4AF9289B-9B4F-4774-895E-535A72A8C285}.Debug|x86.ActiveCfg = Debug|Win32
+ {4AF9289B-9B4F-4774-895E-535A72A8C285}.Debug|x86.Build.0 = Debug|Win32
+ {4AF9289B-9B4F-4774-895E-535A72A8C285}.Release|x64.ActiveCfg = Release|x64
+ {4AF9289B-9B4F-4774-895E-535A72A8C285}.Release|x64.Build.0 = Release|x64
+ {4AF9289B-9B4F-4774-895E-535A72A8C285}.Release|x86.ActiveCfg = Release|Win32
+ {4AF9289B-9B4F-4774-895E-535A72A8C285}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {D14FD0F4-65C4-4919-8373-EF6004DDB3E7}
+ EndGlobalSection
+EndGlobal
diff --git a/src/prototypes/ble-midi1-proto/ble-midi1-proto.vcxproj b/src/prototypes/ble-midi1-proto/ble-midi1-proto.vcxproj
new file mode 100644
index 00000000..d0c8e495
--- /dev/null
+++ b/src/prototypes/ble-midi1-proto/ble-midi1-proto.vcxproj
@@ -0,0 +1,129 @@
+
+
+
+
+ true
+ true
+ true
+ true
+ 15.0
+ {4af9289b-9b4f-4774-895e-535a72a8c285}
+ Win32Proj
+ ble_midi1_proto
+ 10.0.22621.0
+ 10.0.17134.0
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ Application
+ v143
+ v142
+ v141
+ v140
+ Unicode
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)
+ Level4
+ %(AdditionalOptions) /permissive- /bigobj
+
+
+
+
+ Disabled
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+ Console
+ false
+
+
+
+
+ WIN32;%(PreprocessorDefinitions)
+
+
+
+
+ MaxSpeed
+ true
+ true
+ NDEBUG;%(PreprocessorDefinitions)
+ stdcpp20
+ stdcpp20
+
+
+ Console
+ true
+ true
+ false
+
+
+
+
+
+
+
+
+ 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/prototypes/ble-midi1-proto/main.cpp b/src/prototypes/ble-midi1-proto/main.cpp
new file mode 100644
index 00000000..1636b377
--- /dev/null
+++ b/src/prototypes/ble-midi1-proto/main.cpp
@@ -0,0 +1,424 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License
+// ============================================================================
+// This is part of the Windows MIDI Services App API and should be used
+// in your Windows application via an official binary distribution.
+// Further information: https://github.com/microsoft/MIDI/
+// ============================================================================
+
+// NOTE: This is prototype code for working through some BLE approaches before
+// implementing it in the Windows service. Eventually, this code will go stale,
+// but we'll keep it around. This is not production code.
+
+#include "pch.h"
+
+using namespace winrt;
+using namespace Windows::Foundation;
+
+// some refs
+// https://learn.microsoft.com/en-us/windows/uwp/devices-sensors/gatt-client
+
+
+
+#define MIDI_BLE_SERVICE L"{03B80E5A-EDE8-4B33-A751-6CE34EC4C700}"
+#define MIDI_BLE_DATA_IO_CHARACTERISTIC L"{7772E5DB-3868-4112-A1A9-F2669D106BF3}"
+
+winrt::guid MIDI_BLE_SERVICE_UUID(MIDI_BLE_SERVICE);
+winrt::guid MIDI_BLE_DATA_IO_CHARACTERISTIC_UUID(MIDI_BLE_DATA_IO_CHARACTERISTIC);
+
+// Notes:
+// Write (encryption recommended, write without response is required)
+// Read (encryption recommended, respond with no payload)
+// Notify (encryption recommended)
+// Max connection interval is 15ms. Lower is better.
+
+
+enumeration::DeviceWatcher m_Watcher{ nullptr };
+bool m_enumerationCompleted{ false };
+
+winrt::impl::consume_Windows_Devices_Enumeration_IDeviceWatcher::Added_revoker m_DeviceAdded;
+winrt::impl::consume_Windows_Devices_Enumeration_IDeviceWatcher::Removed_revoker m_DeviceRemoved;
+winrt::impl::consume_Windows_Devices_Enumeration_IDeviceWatcher::Updated_revoker m_DeviceUpdated;
+winrt::impl::consume_Windows_Devices_Enumeration_IDeviceWatcher::Stopped_revoker m_DeviceStopped;
+winrt::impl::consume_Windows_Devices_Enumeration_IDeviceWatcher::EnumerationCompleted_revoker m_DeviceEnumerationCompleted;
+
+
+void OnDeviceAdded(enumeration::DeviceWatcher, enumeration::DeviceInformation info)
+{
+ std::cout << "Added: " << winrt::to_string(info.Id()) << std::endl;
+ std::cout << "Name: " << winrt::to_string(info.Name()) << std::endl;
+
+
+ // get the BLE device from this
+
+ auto bleDevice = bt::BluetoothLEDevice::FromIdAsync(info.Id()).get();
+
+ if (bleDevice != nullptr)
+ {
+ std::cout << "BLE Name: " << winrt::to_string(bleDevice.Name()) << std::endl;
+
+ if (bleDevice.ConnectionStatus() == bt::BluetoothConnectionStatus::Connected)
+ {
+ std::cout << "Current status: Connected " << std::endl;
+ }
+ else
+ {
+ std::cout << "Current status: Disconnected " << std::endl;
+ }
+
+
+
+ auto gattServicesResult = bleDevice.GetGattServicesAsync().get();
+
+ if (gattServicesResult.Status() == gatt::GattCommunicationStatus::Success)
+ {
+ for (auto service : gattServicesResult.Services())
+ {
+ auto serviceUuid = service.Uuid();
+
+ if (serviceUuid == MIDI_BLE_SERVICE_UUID)
+ {
+ std::cout << "MIDI Service Found: " << winrt::to_string(winrt::to_hstring(serviceUuid)) << std::endl;
+
+ auto characteristics = service.GetAllCharacteristics();
+
+ for (auto characteristic : characteristics)
+ {
+ auto uuid = characteristic.Uuid();
+ //auto descriptorResult = characteristic.GetDescriptorsForUuidAsync(uuid).get();
+
+ //for (auto desc : descriptorResult.Descriptors())
+ //{
+ // desc.
+ //}
+
+ if (uuid == MIDI_BLE_DATA_IO_CHARACTERISTIC_UUID)
+ {
+ std::cout << "MIDI Data IO Characteristic Found: " << winrt::to_string(winrt::to_hstring(uuid)) << std::endl;
+
+ auto properties = characteristic.CharacteristicProperties();
+
+ if ((properties & gatt::GattCharacteristicProperties::Read) == gatt::GattCharacteristicProperties::Read)
+ {
+ // includes input port
+ std::cout << "- Supports READ (input port)" << std::endl;
+ }
+
+ if ((properties & gatt::GattCharacteristicProperties::Write) == gatt::GattCharacteristicProperties::Write)
+ {
+ // includes output port
+ std::cout << "- Supports WRITE (output port)" << std::endl;
+ }
+
+ if ((properties & gatt::GattCharacteristicProperties::Notify) == gatt::GattCharacteristicProperties::Notify)
+ {
+ std::cout << "- Supports NOTIFY" << std::endl;
+ }
+
+ }
+
+
+ }
+
+ // no need to continue looking
+ break;
+ }
+ }
+ }
+ else
+ {
+ std::cout << "Unable to communicate with device to get gatt services" << std::endl;
+ }
+
+ std::cout << "------------------------" << std::endl;
+
+ }
+
+}
+
+void OnDeviceRemoved(enumeration::DeviceWatcher, enumeration::DeviceInformationUpdate upd)
+{
+ std::cout << "Removed: " << winrt::to_string(upd.Id()) << std::endl;
+}
+
+void OnDeviceUpdated(enumeration::DeviceWatcher, enumeration::DeviceInformationUpdate upd)
+{
+ std::cout << "-----------" << std::endl;
+
+ std::cout << "Updated: " << winrt::to_string(upd.Id()).c_str() << std::endl;
+
+ auto bleDevice = bt::BluetoothLEDevice::FromIdAsync(upd.Id()).get();
+
+ if (bleDevice != nullptr)
+ {
+ std::cout << "Name: " << winrt::to_string(bleDevice.Name()) << " : ";
+
+ if (bleDevice.ConnectionStatus() == bt::BluetoothConnectionStatus::Connected)
+ {
+ std::cout << "Connected " << std::endl;
+ }
+ else
+ {
+ std::cout << "Disconnected " << std::endl;
+ }
+ }
+
+ // spit out the updated properties
+ for (auto prop : upd.Properties())
+ {
+ std::cout << winrt::to_string(prop.Key()) << std::endl;
+ }
+
+ std::cout << "-----------" << std::endl;
+}
+
+void OnDeviceStopped(enumeration::DeviceWatcher, foundation::IInspectable)
+{
+
+}
+
+void OnEnumerationCompleted(enumeration::DeviceWatcher, foundation::IInspectable)
+{
+ m_enumerationCompleted = true;
+
+}
+
+void TestEnumeration()
+{
+ // enumerate ble MIDI devices
+
+ winrt::hstring deviceSelector = bt::BluetoothLEDevice::GetDeviceSelector();
+
+
+ auto requestedProperties = winrt::single_threaded_vector(
+ {
+ L"System.DeviceInterface.Bluetooth.DeviceAddress",
+ L"System.DeviceInterface.Bluetooth.Flags",
+ L"System.DeviceInterface.Bluetooth.LastConnectedTime",
+ L"System.DeviceInterface.Bluetooth.Manufacturer",
+ L"System.DeviceInterface.Bluetooth.ModelNumber",
+ L"System.DeviceInterface.Bluetooth.ProductId",
+ L"System.DeviceInterface.Bluetooth.ProductVersion",
+ L"System.DeviceInterface.Bluetooth.ServiceGuid",
+ L"System.DeviceInterface.Bluetooth.VendorId",
+ L"System.DeviceInterface.Bluetooth.VendorIdSource",
+ L"System.Devices.Connected",
+ L"System.Devices.DeviceCapabilities",
+ L"System.Devices.DeviceCharacteristics"
+ }
+ );
+
+
+ m_Watcher = enumeration::DeviceInformation::CreateWatcher(deviceSelector, requestedProperties);
+
+ auto deviceAddedHandler = foundation::TypedEventHandler(OnDeviceAdded);
+ auto deviceRemovedHandler = foundation::TypedEventHandler(OnDeviceRemoved);
+ auto deviceUpdatedHandler = foundation::TypedEventHandler(OnDeviceUpdated);
+ auto deviceStoppedHandler = foundation::TypedEventHandler(OnDeviceStopped);
+ auto deviceEnumerationCompletedHandler = foundation::TypedEventHandler(OnEnumerationCompleted);
+
+ m_DeviceAdded = m_Watcher.Added(winrt::auto_revoke, deviceAddedHandler);
+ m_DeviceRemoved = m_Watcher.Removed(winrt::auto_revoke, deviceRemovedHandler);
+ m_DeviceUpdated = m_Watcher.Updated(winrt::auto_revoke, deviceUpdatedHandler);
+ m_DeviceStopped = m_Watcher.Stopped(winrt::auto_revoke, deviceStoppedHandler);
+ m_DeviceEnumerationCompleted = m_Watcher.EnumerationCompleted(winrt::auto_revoke, deviceEnumerationCompletedHandler);
+
+ // this blocks
+ m_Watcher.Start();
+
+}
+
+
+IAsyncAction TestReceivingData()
+{
+ std::cout << "Test Receiving Data ---------------------------------------------------------" << std::endl;
+
+ winrt::hstring id = L"BluetoothLE#BluetoothLE3c:6a:a7:f0:4e:b0-48:b6:20:1a:71:9d";
+
+ try
+ {
+ gatt::GattSession session{ nullptr };
+
+ std::cout << "Creating session" << std::endl;
+
+ auto bleId = bt::BluetoothDeviceId::FromId(id);
+
+ session = co_await gatt::GattSession::FromDeviceIdAsync(bleId);
+
+ std::cout << "Session created" << std::endl;
+
+ session.MaintainConnection(true);
+
+ auto bleDevice = bt::BluetoothLEDevice::FromIdAsync(id).get();
+
+ if (bleDevice != nullptr)
+ {
+ std::cout << "Using device " << winrt::to_string(bleDevice.Name()) << std::endl;
+
+ auto service = bleDevice.GetGattService(MIDI_BLE_SERVICE_UUID);
+
+ if (service != nullptr)
+ {
+ std::cout << "Found service" << std::endl;;
+
+ auto openStatus = co_await service.OpenAsync(gatt::GattSharingMode::SharedReadAndWrite);
+
+ if (openStatus == gatt::GattOpenStatus::Success)
+ {
+ std::cout << "Service opened" << std::endl;
+ }
+ else
+ {
+ std::cout << "Unable to open service" << std::endl;
+ co_return;
+ }
+
+ std::cout << "Getting MIDI Data IO characteristic" << std::endl;
+
+ auto characteristicsResult = co_await service.GetCharacteristicsForUuidAsync(MIDI_BLE_DATA_IO_CHARACTERISTIC_UUID);
+
+ if (characteristicsResult.Status() == gatt::GattCommunicationStatus::Success)
+ {
+ if (characteristicsResult.Characteristics().Size() == 0)
+ {
+ // this is unexpected
+ std::cout << "Returned no characteristics for the required UUID" << std::endl;
+ }
+ else if (characteristicsResult.Characteristics().Size() > 1)
+ {
+ // TODO: Need to find out under which cases this happens
+ std::cout << "Returned more than one characteristic for the same UUID" << std::endl;
+ }
+ else
+ {
+ std::cout << "Returned just the one characteristic for the UUID" << std::endl;
+
+ auto characteristic = characteristicsResult.Characteristics().GetAt(0);
+
+ co_await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
+ gatt::GattClientCharacteristicConfigurationDescriptorValue::Notify);
+
+
+ auto valueChangedHandler = [&](gatt::GattCharacteristic const& sender, gatt::GattValueChangedEventArgs const& args)
+ {
+ //std::cout << "Value changed" << std::endl;
+
+ // we get an IBuffer here
+
+ //std::cout << "Data size is " << args.CharacteristicValue().Length() << " bytes" << std::endl;
+
+ std::cout << "> ";
+
+ for (int i = 0; i < args.CharacteristicValue().Length(); i++)
+ {
+ // read next byte
+ auto b = *(args.CharacteristicValue().data() + i);
+
+ std::cout << "0x" << std::hex << (unsigned)b << " ";
+ }
+
+ std::cout << std::endl;
+ };
+
+ // wire up ValueChanged so we actually get data
+ characteristic.ValueChanged(valueChangedHandler);
+
+ while (true)
+ {
+ ::Sleep(100);
+ }
+
+ session.Close();
+
+ }
+ }
+
+
+ service.Close();
+ }
+ }
+
+ std::cout << "Done" << std::endl;
+
+
+ // wait for incoming data indefinitely
+
+ //auto characteristic = characteristicsResult.Characteristics().GetAt(0);
+
+ //auto readResult = characteristic.ReadValueAsync().get();
+
+ //if (readResult.Status() == gatt::GattCommunicationStatus::Success)
+ //{
+ // // we get an IBuffer here
+
+ // for (int i = 0; i < readResult.Value().Length(); i++)
+ // {
+ // // read next byte
+ // auto b = *(readResult.Value().data() + i);
+
+ // std::cout << std::hex << b << " ";
+ // }
+
+ // std::cout << std::endl;
+
+ //}
+ //session.Close();
+
+
+
+
+
+
+
+
+ }
+ catch (winrt::hresult_error err)
+ {
+ // Important: using .get() means we don't actually get to handle these exceptions.
+
+ if (err.code() == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION))
+ {
+ std::cout << "Cannot access the BLE device because it's being used by another process" << std::endl;
+ }
+ else
+ {
+ std::cout << "HRESULT exception 0x" << std::hex << err.code() << std::endl;
+ }
+
+ co_return;
+ }
+ catch (...)
+ {
+ std::cout << "Exception" << std::endl;
+
+ co_return;
+ }
+
+}
+
+
+
+int main()
+{
+ init_apartment();
+
+ //TestEnumeration();
+
+ std::thread enumerationThread(TestEnumeration);
+
+ enumerationThread.detach();
+
+
+ while (!m_enumerationCompleted)
+ {
+ Sleep(1000);
+ }
+
+ TestReceivingData().get();
+
+ //system("pause > nul");
+ system("pause");
+
+
+}
+
diff --git a/src/prototypes/ble-midi1-proto/packages.config b/src/prototypes/ble-midi1-proto/packages.config
new file mode 100644
index 00000000..cbf6205e
--- /dev/null
+++ b/src/prototypes/ble-midi1-proto/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/prototypes/ble-midi1-proto/pch.cpp b/src/prototypes/ble-midi1-proto/pch.cpp
new file mode 100644
index 00000000..bcb5590b
--- /dev/null
+++ b/src/prototypes/ble-midi1-proto/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h"
diff --git a/src/prototypes/ble-midi1-proto/pch.h b/src/prototypes/ble-midi1-proto/pch.h
new file mode 100644
index 00000000..7854996e
--- /dev/null
+++ b/src/prototypes/ble-midi1-proto/pch.h
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License
+// ============================================================================
+// This is part of the Windows MIDI Services App API and should be used
+// in your Windows application via an official binary distribution.
+// Further information: https://github.com/microsoft/MIDI/
+// ============================================================================
+
+
+#pragma once
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+namespace json = ::winrt::Windows::Data::Json;
+namespace enumeration = ::winrt::Windows::Devices::Enumeration;
+namespace foundation = ::winrt::Windows::Foundation;
+namespace collections = ::winrt::Windows::Foundation::Collections;
+namespace bt = ::winrt::Windows::Devices::Bluetooth;
+namespace gatt = ::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile;
+namespace streams = ::winrt::Windows::Storage::Streams;
+
+#include
\ No newline at end of file