@@ -83,10 +83,6 @@ class midi_out_impl final
8383 if (!m_endpoint)
8484 return std::errc::device_or_resource_busy;
8585
86- #if LIBREMIDI_WINMIDI_HAS_COM_EXTENSIONS
87- m_endpoint.as (libremidi::IID_IMidiEndpointConnectionRaw, m_raw_endpoint.put_void ());
88- #endif
89-
9086 m_endpoint.Open ();
9187
9288 return stdx::error{};
@@ -104,70 +100,96 @@ class midi_out_impl final
104100 return std::errc::not_connected;
105101
106102 m_session.DisconnectEndpointConnection (m_endpoint.ConnectionId ());
103+ #if LIBREMIDI_WINMIDI_HAS_VIRTUAL_DEVICE
107104 if (m_virtual)
108105 {
109106 m_virtual.Cleanup ();
110107 m_virtual = nullptr ;
111108 }
109+ #endif
112110 return stdx::error{};
113111 }
114112
115- stdx::error send_ump (const uint32_t * message, size_t size) override
113+ std::errc write_raw (const uint32_t * ump, int64_t bytes)
116114 {
117- auto write_func = [this ](const uint32_t * ump, int64_t bytes) -> std::errc {
118-
119- #if !LIBREMIDI_WINMIDI_HAS_COM_EXTENSIONS
120- MidiSendMessageResults ret{};
121- switch (bytes / 4 )
122- {
123- case 1 :
124- ret = m_endpoint.SendSingleMessagePacket (MidiMessage32 (0 , ump[0 ]));
125- break ;
126- case 2 :
127- ret = m_endpoint.SendSingleMessagePacket (MidiMessage64 (0 , ump[0 ], ump[1 ]));
128- break ;
129- case 3 :
130- ret = m_endpoint.SendSingleMessagePacket (MidiMessage96 (0 , ump[0 ], ump[1 ], ump[2 ]));
131- break ;
132- case 4 :
133- ret = m_endpoint.SendSingleMessagePacket (
134- MidiMessage128 (0 , ump[0 ], ump[1 ], ump[2 ], ump[3 ]));
135- break ;
136- default :
137- return std::errc::bad_message;
138- }
139- if (ret != MidiSendMessageResults::Succeeded)
115+ #if LIBREMIDI_WINMIDI_HAS_COM_EXTENSIONS
116+ HRESULT ret{};
117+ switch (bytes / 4 )
118+ {
119+ case 1 :
120+ assert (m_raw_endpoint->ValidateBufferHasOnlyCompleteUmps (1 , (UINT32*)ump));
121+ ret = m_raw_endpoint->SendMidiMessagesRaw (0 , 1 , (UINT32*)ump);
122+ break ;
123+ case 2 :
124+ assert (m_raw_endpoint->ValidateBufferHasOnlyCompleteUmps (2 , (UINT32*)ump));
125+ ret = m_raw_endpoint->SendMidiMessagesRaw (0 , 2 , (UINT32*)ump);
126+ break ;
127+ case 3 :
128+ assert (m_raw_endpoint->ValidateBufferHasOnlyCompleteUmps (3 , (UINT32*)ump));
129+ ret = m_raw_endpoint->SendMidiMessagesRaw (0 , 3 , (UINT32*)ump);
130+ break ;
131+ case 4 :
132+ assert (m_raw_endpoint->ValidateBufferHasOnlyCompleteUmps (4 , (UINT32*)ump));
133+ ret = m_raw_endpoint->SendMidiMessagesRaw (0 , 4 , (UINT32*)ump);
134+ break ;
135+ default :
140136 return std::errc::bad_message;
137+ }
138+ if (ret < 0 )
139+ return std::errc::io_error;
140+ return std::errc{};
141141 #else
142- HRESULT ret{};
143- switch (bytes / 4 )
144- {
145- case 1 :
146- assert (m_raw_endpoint->ValidateBufferHasOnlyCompleteUmps (1 , (UINT32*)ump));
147- ret = m_raw_endpoint->SendMidiMessagesRaw (0 , 1 , (UINT32*)ump);
148- break ;
149- case 2 :
150- assert (m_raw_endpoint->ValidateBufferHasOnlyCompleteUmps (2 , (UINT32*)ump));
151- ret = m_raw_endpoint->SendMidiMessagesRaw (0 , 2 , (UINT32*)ump);
152- break ;
153- case 3 :
154- assert (m_raw_endpoint->ValidateBufferHasOnlyCompleteUmps (3 , (UINT32*)ump));
155- ret = m_raw_endpoint->SendMidiMessagesRaw (0 , 3 , (UINT32*)ump);
156- break ;
157- case 4 :
158- assert (m_raw_endpoint->ValidateBufferHasOnlyCompleteUmps (4 , (UINT32*)ump));
159- ret = m_raw_endpoint->SendMidiMessagesRaw (0 , 4 , (UINT32*)ump);
160- break ;
161- default :
162- return std::errc::bad_message;
163- }
142+ return write (ump, bytes);
164143 #endif
165- if (ret < 0 )
166- return std::errc::io_error;
167- return std::errc{0 };
168- };
144+ }
145+
146+ std::errc write (const uint32_t * ump, int64_t bytes)
147+ {
148+ MidiSendMessageResults ret{};
149+ switch (bytes / 4 )
150+ {
151+ case 1 :
152+ ret = m_endpoint.SendSingleMessagePacket (MidiMessage32 (0 , ump[0 ]));
153+ break ;
154+ case 2 :
155+ ret = m_endpoint.SendSingleMessagePacket (MidiMessage64 (0 , ump[0 ], ump[1 ]));
156+ break ;
157+ case 3 :
158+ ret = m_endpoint.SendSingleMessagePacket (MidiMessage96 (0 , ump[0 ], ump[1 ], ump[2 ]));
159+ break ;
160+ case 4 :
161+ ret = m_endpoint.SendSingleMessagePacket (
162+ MidiMessage128 (0 , ump[0 ], ump[1 ], ump[2 ], ump[3 ]));
163+ break ;
164+ default :
165+ return std::errc::bad_message;
166+ }
167+ if (ret != MidiSendMessageResults::Succeeded)
168+ return std::errc::io_error;
169+ return std::errc{};
170+ }
171+
172+ stdx::error send_ump (const uint32_t * message, size_t size) override
173+ {
174+ #if LIBREMIDI_WINMIDI_HAS_VIRTUAL_DEVICE
175+ if (m_virtual)
176+ {
177+ // Virtual port does not support raw API per
178+ // https://github.com/celtera/libremidi/issues/194#issuecomment-4156127901
169179
170- return segment_ump_stream (message, size, write_func, []() { });
180+ return segment_ump_stream (message, size,
181+ [this ](const uint32_t * ump, int64_t bytes) -> std::errc {
182+ return write (ump, bytes);
183+ }, []() { });
184+ }
185+ else
186+ #endif
187+ {
188+ return segment_ump_stream (message, size,
189+ [this ](const uint32_t * ump, int64_t bytes) -> std::errc {
190+ return write_raw (ump, bytes);
191+ }, []() { });
192+ }
171193 }
172194
173195private:
0 commit comments