@@ -19,6 +19,56 @@ class midi_in_impl final
1919 {
2020 } configuration;
2121
22+ #if LIBREMIDI_WINMIDI_HAS_COM_EXTENSIONS
23+ struct raw_callback_type final : IMidiEndpointConnectionMessagesReceivedCallback
24+ {
25+ explicit raw_callback_type (midi_in_impl& self)
26+ : self{self}
27+ {
28+
29+ }
30+
31+ midi_in_impl& self;
32+ HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void ** ppvObject) override
33+ {
34+ if (!ppvObject)
35+ return E_POINTER;
36+
37+ if (riid == __uuidof (IUnknown) ||
38+ riid == __uuidof (IMidiEndpointConnectionMessagesReceivedCallback))
39+ {
40+ *ppvObject = static_cast <IMidiEndpointConnectionMessagesReceivedCallback*>(this );
41+ AddRef ();
42+ return S_OK;
43+ }
44+
45+ *ppvObject = nullptr ;
46+ return E_NOINTERFACE;
47+ }
48+
49+ ULONG STDMETHODCALLTYPE AddRef () override
50+ {
51+ return 1 ;
52+ }
53+
54+ ULONG STDMETHODCALLTYPE Release () override
55+ {
56+ return 1 ;
57+ }
58+
59+ HRESULT STDMETHODCALLTYPE MessagesReceived (
60+ GUID sessionId,
61+ GUID connectionId,
62+ UINT64 timestamp,
63+ UINT32 wordCount,
64+ UINT32 *messages) override {
65+ HRESULT res{};
66+ self.process_message (sessionId, connectionId, timestamp, wordCount, messages);
67+ return res;
68+ }
69+ } raw_callback{*this };
70+ #endif
71+
2272 explicit midi_in_impl (
2373 libremidi::ump_input_configuration&& conf, winmidi::input_configuration&& apiconf)
2474 : configuration{std::move (conf), std::move (apiconf)}
@@ -55,12 +105,20 @@ class midi_in_impl final
55105 // TODO use a MidiGroupEndpointListener for the filtering
56106 m_endpoint = m_session.CreateEndpointConnection (ep.EndpointDeviceId ());
57107
108+ #if !LIBREMIDI_WINMIDI_HAS_COM_EXTENSIONS
58109 m_revoke_token = m_endpoint.MessageReceived (
59110 [this ](
60111 const winrt::Microsoft::Windows::Devices::Midi2::IMidiMessageReceivedEventSource&,
61112 const winrt::Microsoft::Windows::Devices::Midi2::MidiMessageReceivedEventArgs& args) {
62113 process_message (args);
63114 });
115+ #else
116+ m_raw_endpoint = m_endpoint.as <IMidiEndpointConnectionRaw>();
117+
118+ m_raw_endpoint->SetMessagesReceivedCallback (
119+ &raw_callback
120+ );
121+ #endif
64122
65123 m_endpoint.Open ();
66124
@@ -96,9 +154,43 @@ class midi_in_impl final
96154 {ump_space, ump_space + b.Size ()}, m_processing.timestamp <timestamp_info>(to_ns, 0 ));
97155 }
98156
157+ #if LIBREMIDI_WINMIDI_HAS_COM_EXTENSIONS
158+ void process_message (
159+ const GUID& /* sessionId */ ,
160+ const GUID& /* connectionId */ ,
161+ UINT64 timestamp,
162+ UINT32 wordCount,
163+ UINT32 *ump)
164+ {
165+ static constexpr timestamp_backend_info timestamp_info{
166+ .has_absolute_timestamps = true ,
167+ .absolute_is_monotonic = false ,
168+ .has_samples = false ,
169+ };
170+
171+ if (wordCount == 0 )
172+ return ;
173+
174+ if (m_group_filter >= 0 )
175+ {
176+ int group = cmidi2_ump_get_group (ump);
177+ if (group != m_group_filter)
178+ return ;
179+ }
180+
181+ auto to_ns = [t = timestamp] { return t; };
182+ m_processing.on_bytes (
183+ {ump, ump + wordCount}, m_processing.timestamp <timestamp_info>(to_ns, 0 ));
184+ }
185+ #endif
186+
99187 stdx::error close_port () override
100188 {
189+ #if !LIBREMIDI_WINMIDI_HAS_COM_EXTENSIONS
101190 m_endpoint.MessageReceived (m_revoke_token);
191+ #else
192+ m_raw_endpoint->RemoveMessagesReceivedCallback ();
193+ #endif
102194 m_session.DisconnectEndpointConnection (m_endpoint.ConnectionId ());
103195 return stdx::error{};
104196 }
@@ -109,6 +201,9 @@ class midi_in_impl final
109201 MidiSession m_session;
110202 winrt::event_token m_revoke_token{};
111203 winrt::Microsoft::Windows::Devices::Midi2::MidiEndpointConnection m_endpoint{nullptr };
204+ #if LIBREMIDI_WINMIDI_HAS_COM_EXTENSIONS
205+ winrt::impl::com_ref<IMidiEndpointConnectionRaw> m_raw_endpoint{};
206+ #endif
112207 midi2::input_state_machine m_processing{this ->configuration };
113208 int m_group_filter = -1 ;
114209};
0 commit comments