From 561c8eea0cfa45f0b54461b149b4c330e0bbaa3b Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Wed, 6 Dec 2017 16:32:53 +0100 Subject: Prototype to allow embedding sysex in midi-map --- .../generic_midi/generic_midi_control_protocol.cc | 44 +++++++++++++++++++++- .../generic_midi/generic_midi_control_protocol.h | 2 + 2 files changed, 45 insertions(+), 1 deletion(-) (limited to 'libs') diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc index 4d394e5082..d973ba77b6 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -42,6 +42,7 @@ #include "ardour/session.h" #include "ardour/midi_ui.h" #include "ardour/rc_configuration.h" +#include "ardour/raw_midi_parser.h" #include "ardour/midiport_manager.h" #include "ardour/debug.h" @@ -241,6 +242,8 @@ GenericMidiControlProtocol::drop_all () delete *i; } actions.clear (); + + _sysex_init = ""; } void @@ -266,6 +269,7 @@ GenericMidiControlProtocol::drop_bindings () _current_binding = ""; _bank_size = 0; _current_bank = 0; + _sysex_init = ""; } int @@ -720,7 +724,7 @@ GenericMidiControlProtocol::load_bindings (const string& xmlpath) DEBUG_TRACE (DEBUG::GenericMidi, "Load bindings: Reading midi map\n"); XMLTree state_tree; - if (!state_tree.read (xmlpath.c_str())) { + if (!state_tree.read (xmlpath)) { error << string_compose(_("Could not understand MIDI bindings file %1"), xmlpath) << endmsg; return -1; } @@ -792,12 +796,25 @@ GenericMidiControlProtocol::load_bindings (const string& xmlpath) } } } + + if ((*citer)->name() == "Sysex") { + for (XMLNodeList::const_iterator n = (*citer)->children ().begin (); n != (*citer)->children ().end (); ++n) { + if (!(*n)->is_content ()) { continue; } + _sysex_init = (*n)->content (); + break; + } + } + } if ((prop = root->property ("name")) != 0) { _current_binding = prop->value (); } + if ((connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) { + + send_sysex_init (); + } reset_controllables (); return 0; @@ -1221,6 +1238,31 @@ void GenericMidiControlProtocol::connected () { cerr << "Now connected\n"; + send_sysex_init (); +} + +void +GenericMidiControlProtocol::send_sysex_init () +{ + if (_sysex_init.empty ()) { + return; + } + + boost::shared_ptr p = boost::dynamic_pointer_cast (_output_port); + assert (p); + + gsize size = 0; + guchar* buf = g_base64_decode (_sysex_init.c_str(), &size); + + RawMidiParser mp; + for (size_t i = 0; i < size; ++i) { + if (mp.process_byte (buf[i])) { + p->write (mp.midi_buffer (), mp.buffer_size (), 0); + /* delay for physical MIDI rate; 320usec / byte */ + g_usleep (400 * mp.buffer_size ()); + } + } + g_free (buf); } boost::shared_ptr diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h index 6585c7ea24..8a2670bfd7 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h @@ -162,6 +162,7 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { void reset_controllables (); void drop_all (); + void send_sysex_init (); enum ConnectionState { InputConnected = 0x1, @@ -174,6 +175,7 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { void connected(); std::string _current_binding; + std::string _sysex_init; uint32_t _bank_size; uint32_t _current_bank; /** true if this surface is motorised. If it is, we assume -- cgit v1.2.3