@@ -102,28 +102,88 @@ class midi_in_impl final
102102
103103 m_group_filter = port.port - 1 ;
104104
105- // TODO use a MidiGroupEndpointListener for the filtering
106- m_endpoint = m_session.CreateEndpointConnection (ep.EndpointDeviceId ());
105+ try
106+ {
107+ // TODO use a MidiGroupEndpointListener for the filtering
108+ m_endpoint = m_session.CreateEndpointConnection (ep.EndpointDeviceId ());
109+ if (!m_endpoint)
110+ return std::errc::device_or_resource_busy;
111+
112+ #if !LIBREMIDI_WINMIDI_HAS_COM_EXTENSIONS
113+ m_revoke_token = m_endpoint.MessageReceived (
114+ [this ](
115+ const winrt::Microsoft::Windows::Devices::Midi2::IMidiMessageReceivedEventSource&,
116+ const winrt::Microsoft::Windows::Devices::Midi2::MidiMessageReceivedEventArgs& args) {
117+ process_message (args);
118+ });
119+ #else
120+ m_endpoint.as (libremidi::IID_IMidiEndpointConnectionRaw, m_raw_endpoint.put_void ());
121+
122+ m_raw_endpoint->SetMessagesReceivedCallback (
123+ &raw_callback
124+ );
125+ #endif
126+
127+ m_endpoint.Open ();
128+
129+ return stdx::error{};
130+ }
131+ catch (...)
132+ {
133+ return std::errc::io_error;
134+ }
135+ }
136+
137+ #if LIBREMIDI_WINMIDI_HAS_VIRTUAL_DEVICE
138+ stdx::error open_virtual_port (std::string_view port_name) override
139+ {
140+ // Create endpoint information for the virtual device
141+ using namespace winrt ::Microsoft::Windows::Devices::Midi2;
142+ using namespace winrt ::Microsoft::Windows::Devices::Midi2::Endpoints::Virtual;
143+
144+ auto conf = setup_virtualdevice_config (configuration.client_name , port_name, port_name, MidiFunctionBlockDirection::BlockInput);
145+
146+ m_virtual = MidiVirtualDeviceManager::CreateVirtualDevice (conf);
147+ if (m_virtual == nullptr )
148+ return std::errc::device_or_resource_busy;
149+
150+ try
151+ {
152+ // Create a connection to the device-side endpoint
153+ m_endpoint = m_session.CreateEndpointConnection (m_virtual.DeviceEndpointDeviceId ());
154+ if (!m_endpoint)
155+ return std::errc::device_or_resource_busy;
156+
157+ // Add the virtual device as a message processing plugin to receive messages
158+ m_endpoint.AddMessageProcessingPlugin (m_virtual);
107159
108160#if !LIBREMIDI_WINMIDI_HAS_COM_EXTENSIONS
109- m_revoke_token = m_endpoint.MessageReceived (
110- [this ](
111- const winrt::Microsoft::Windows::Devices::Midi2::IMidiMessageReceivedEventSource&,
112- const winrt::Microsoft::Windows::Devices::Midi2::MidiMessageReceivedEventArgs& args) {
113- process_message (args);
114- });
161+ // Register message received event handler
162+ m_revoke_token = m_endpoint.MessageReceived (
163+ [this ](
164+ const winrt::Microsoft::Windows::Devices::Midi2::IMidiMessageReceivedEventSource&,
165+ const winrt::Microsoft::Windows::Devices::Midi2::MidiMessageReceivedEventArgs& args) {
166+ process_message (args);
167+ });
115168#else
116- m_endpoint.as (libremidi::IID_IMidiEndpointConnectionRaw, m_raw_endpoint.put_void ());
117-
118- m_raw_endpoint->SetMessagesReceivedCallback (
119- &raw_callback
120- );
169+ // Use COM interface for raw callback
170+ m_endpoint.as (libremidi::IID_IMidiEndpointConnectionRaw, m_raw_endpoint.put_void ());
171+ if (m_raw_endpoint)
172+ {
173+ m_raw_endpoint->SetMessagesReceivedCallback (&raw_callback);
174+ }
121175#endif
122176
123- m_endpoint.Open ();
177+ m_endpoint.Open ();
124178
125- return stdx::error{};
179+ return stdx::error{};
180+ }
181+ catch (...)
182+ {
183+ return std::errc::io_error;
184+ }
126185 }
186+ #endif
127187
128188 void process_message (
129189 const winrt::Microsoft::Windows::Devices::Midi2::MidiMessageReceivedEventArgs& msg)
@@ -198,6 +258,12 @@ class midi_in_impl final
198258 }
199259#endif
200260 m_session.DisconnectEndpointConnection (m_endpoint.ConnectionId ());
261+
262+ if (m_virtual)
263+ {
264+ m_virtual.Cleanup ();
265+ m_virtual = nullptr ;
266+ }
201267 return stdx::error{};
202268 }
203269
@@ -209,6 +275,9 @@ class midi_in_impl final
209275 winrt::Microsoft::Windows::Devices::Midi2::MidiEndpointConnection m_endpoint{nullptr };
210276#if LIBREMIDI_WINMIDI_HAS_COM_EXTENSIONS
211277 winrt::impl::com_ref<IMidiEndpointConnectionRaw> m_raw_endpoint{};
278+ #endif
279+ #if LIBREMIDI_WINMIDI_HAS_VIRTUAL_DEVICE
280+ winrt::Microsoft::Windows::Devices::Midi2::Endpoints::Virtual::MidiVirtualDevice m_virtual{nullptr };
212281#endif
213282 midi2::input_state_machine m_processing{this ->configuration };
214283 int m_group_filter = -1 ;
0 commit comments