@@ -15,22 +15,24 @@ static constexpr auto midi_api(libremidi::API api)
1515 return (api == libremidi::API ::UNSPECIFIED ) ? libremidi::midi1::default_api () : api;
1616}
1717midi_protocol::midi_protocol (
18- ossia::net::network_context_ptr ctx, std::string device_name ,
18+ ossia::net::network_context_ptr ctx, midi_protocol_configuration config ,
1919 libremidi::input_configuration& conf, libremidi::input_api_configuration api)
2020 : protocol_base{flags{}}
2121 , m_context{ctx}
22+ , m_config{std::move (config)}
2223{
23- conf.on_message = [this ](const libremidi::message& m) { midi_callback (m ); };
24+ conf.on_message = [this ](libremidi::message&& m) { midi_callback (std::move (m) ); };
2425
2526 conf.ignore_timing = false ;
2627 m_input = std::make_unique<libremidi::midi_in>(conf, api);
2728}
2829
2930midi_protocol::midi_protocol (
30- ossia::net::network_context_ptr ctx, std::string device_name ,
31+ ossia::net::network_context_ptr ctx, midi_protocol_configuration config ,
3132 libremidi::output_configuration& conf, libremidi::output_api_configuration api)
3233 : protocol_base{flags{}}
3334 , m_context{ctx}
35+ , m_config{std::move (config)}
3436{
3537 m_output = std::make_unique<libremidi::midi_out>(conf, api);
3638}
@@ -162,16 +164,34 @@ bool midi_protocol::pull(parameter_base& address)
162164
163165 case address_info::Type::NoteOff_N: {
164166 const midi_channel& chan = m_channels[adrinfo.channel - 1 ];
165- int32_t val{chan.note_off_N [adrinfo.note ]};
166- address.set_value (val);
167+ if (m_config.velocity_zero_is_note_off )
168+ {
169+ int32_t val{chan.note_on_N [adrinfo.note ]};
170+ address.set_value (0 );
171+ }
172+ else
173+ {
174+ int32_t val{chan.note_off_N [adrinfo.note ]};
175+ address.set_value (val);
176+ }
167177 return true ;
168178 }
169179
170180 case address_info::Type::NoteOff: {
171181 const midi_channel& chan = m_channels[adrinfo.channel - 1 ];
172- std::vector<ossia::value> val{
173- int32_t {chan.note_off .first }, int32_t {chan.note_off .second }};
174- address.set_value (ossia::value{std::move (val)});
182+
183+ if (m_config.velocity_zero_is_note_off )
184+ {
185+ std::vector<ossia::value> val{
186+ int32_t {chan.note_on .first }, int32_t {0 }};
187+ address.set_value (ossia::value{std::move (val)});
188+ }
189+ else
190+ {
191+ std::vector<ossia::value> val{
192+ int32_t {chan.note_off .first }, int32_t {chan.note_off .second }};
193+ address.set_value (ossia::value{std::move (val)});
194+ }
175195 return true ;
176196 }
177197
@@ -233,15 +253,23 @@ bool midi_protocol::push(const parameter_base& address, const ossia::value& v)
233253 }
234254
235255 case address_info::Type::NoteOff_N: {
236- m_output->send_message (libremidi::channel_events::note_off (
237- adrinfo.channel , adrinfo.note , to_int (v)));
256+ if (m_config.velocity_zero_is_note_off )
257+ m_output->send_message (libremidi::channel_events::note_on (
258+ adrinfo.channel , adrinfo.note , 0 ));
259+ else
260+ m_output->send_message (libremidi::channel_events::note_off (
261+ adrinfo.channel , adrinfo.note , to_int (v)));
238262 return true ;
239263 }
240264
241265 case address_info::Type::NoteOff: {
242266 auto & val = v.get <std::vector<ossia::value>>();
243- m_output->send_message (libremidi::channel_events::note_off (
244- adrinfo.channel , to_int (val[0 ]), to_int (val[1 ])));
267+ if (m_config.velocity_zero_is_note_off )
268+ m_output->send_message (libremidi::channel_events::note_on (
269+ adrinfo.channel , to_int (val[0 ]), 0 ));
270+ else
271+ m_output->send_message (libremidi::channel_events::note_off (
272+ adrinfo.channel , to_int (val[0 ]), to_int (val[1 ])));
245273 return true ;
246274 }
247275
@@ -328,7 +356,10 @@ bool midi_protocol::observe(parameter_base& address, bool enable)
328356 }
329357 case address_info::Type::NoteOff: {
330358 midi_channel& chan = m_channels[adrinfo.channel - 1 ];
331- chan.callback_note_off = enable;
359+ if (m_config.velocity_zero_is_note_off )
360+ chan.callback_note_on = enable;
361+ else
362+ chan.callback_note_off = enable;
332363 return true ;
333364 }
334365 case address_info::Type::CC : {
@@ -348,7 +379,10 @@ bool midi_protocol::observe(parameter_base& address, bool enable)
348379 }
349380 case address_info::Type::NoteOff_N: {
350381 midi_channel& chan = m_channels[adrinfo.channel - 1 ];
351- chan.callback_note_off_N [adrinfo.note ] = enable;
382+ if (m_config.velocity_zero_is_note_off )
383+ chan.callback_note_on_N [adrinfo.note ] = enable;
384+ else
385+ chan.callback_note_off_N [adrinfo.note ] = enable;
352386 return true ;
353387 }
354388 case address_info::Type::CC_N : {
@@ -546,7 +580,7 @@ void midi_protocol::value_callback(
546580 m_dev->on_message (param);
547581}
548582
549- void midi_protocol::midi_callback (const libremidi::message& mess)
583+ void midi_protocol::midi_callback (libremidi::message& & mess)
550584{
551585 if (m_logger.inbound_logger )
552586 {
@@ -559,6 +593,16 @@ void midi_protocol::midi_callback(const libremidi::message& mess)
559593 m_logger.inbound_logger ->info (" MIDI in: {0}" , mess.bytes [0 ]);
560594 }
561595
596+ if (this ->m_config .velocity_zero_is_note_off ) {
597+ if (mess.get_message_type () == libremidi::message_type::NOTE_ON ) {
598+ const auto status = mess.bytes [0 ];
599+ const auto note = mess.bytes [1 ];
600+ const auto vel = mess.bytes [2 ];
601+ if (vel == 0 )
602+ mess.bytes [0 ] = (status & 0x0F ) | 0x80 ;
603+ }
604+ }
605+
562606 if (m_learning)
563607 {
564608 on_learn (mess);
0 commit comments