2 Copyright (C) 2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <glibmm/fileutils.h>
26 #include <glibmm/miscutils.h>
28 #include "pbd/controllable_descriptor.h"
29 #include "pbd/error.h"
30 #include "pbd/failed_constructor.h"
31 #include "pbd/file_utils.h"
32 #include "pbd/xml++.h"
33 #include "pbd/compose.h"
35 #include "midi++/port.h"
37 #include "ardour/audioengine.h"
38 #include "ardour/filesystem_paths.h"
39 #include "ardour/session.h"
40 #include "ardour/route.h"
41 #include "ardour/midi_ui.h"
42 #include "ardour/rc_configuration.h"
43 #include "ardour/midiport_manager.h"
44 #include "ardour/debug.h"
46 #include "generic_midi_control_protocol.h"
47 #include "midicontrollable.h"
48 #include "midifunction.h"
49 #include "midiaction.h"
51 using namespace ARDOUR;
57 #define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
59 GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
60 : ControlProtocol (s, _("Generic MIDI"))
65 _input_port = s.midi_input_port ();
66 _output_port = s.midi_output_port ();
69 _feedback_interval = 10000; // microseconds
70 last_feedback_time = 0;
75 /* these signals are emitted by the MidiControlUI's event loop thread
76 * and we may as well handle them right there in the same the same
80 Controllable::StartLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::start_learning, this, _1));
81 Controllable::StopLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::stop_learning, this, _1));
82 Controllable::CreateBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::create_binding, this, _1, _2, _3));
83 Controllable::DeleteBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1));
85 /* this signal is emitted by the process() callback, and if
86 * send_feedback() is going to do anything, it should do it in the
87 * context of the process() callback itself.
90 Session::SendFeedback.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this));
91 //Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
93 /* this one is cross-thread */
95 Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
100 GenericMidiControlProtocol::~GenericMidiControlProtocol ()
106 static const char * const midimap_env_variable_name = "ARDOUR_MIDIMAPS_PATH";
107 static const char* const midi_map_dir_name = "midi_maps";
108 static const char* const midi_map_suffix = ".map";
111 system_midi_map_search_path ()
113 bool midimap_path_defined = false;
114 std::string spath_env (Glib::getenv (midimap_env_variable_name, midimap_path_defined));
116 if (midimap_path_defined) {
120 Searchpath spath (ardour_data_search_path());
121 spath.add_subdirectory_to_paths(midi_map_dir_name);
126 user_midi_map_directory ()
128 return Glib::build_filename (user_config_directory(), midi_map_dir_name);
132 midi_map_filter (const string &str, void* /*arg*/)
134 return (str.length() > strlen(midi_map_suffix) &&
135 str.find (midi_map_suffix) == (str.length() - strlen (midi_map_suffix)));
139 GenericMidiControlProtocol::reload_maps ()
141 vector<string> midi_maps;
142 Searchpath spath (system_midi_map_search_path());
143 spath += user_midi_map_directory ();
145 find_files_matching_filter (midi_maps, spath, midi_map_filter, 0, false, true);
147 if (midi_maps.empty()) {
148 cerr << "No MIDI maps found using " << spath.to_string() << endl;
152 for (vector<string>::iterator i = midi_maps.begin(); i != midi_maps.end(); ++i) {
153 string fullpath = *i;
157 if (!tree.read (fullpath.c_str())) {
163 XMLProperty* prop = tree.root()->property ("name");
169 mi.name = prop->value ();
172 map_info.push_back (mi);
177 GenericMidiControlProtocol::drop_all ()
179 DEBUG_TRACE (DEBUG::GenericMidi, "Drop all bindings\n");
180 Glib::Threads::Mutex::Lock lm (pending_lock);
181 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
183 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
186 controllables.clear ();
188 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
191 pending_controllables.clear ();
193 for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
198 for (MIDIActions::iterator i = actions.begin(); i != actions.end(); ++i) {
205 GenericMidiControlProtocol::drop_bindings ()
207 DEBUG_TRACE (DEBUG::GenericMidi, "Drop bindings, leave learned\n");
208 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
210 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
211 if (!(*i)->learned()) {
213 i = controllables.erase (i);
219 for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
224 _current_binding = "";
230 GenericMidiControlProtocol::set_active (bool /*yn*/)
232 /* start/stop delivery/outbound thread */
237 GenericMidiControlProtocol::set_feedback_interval (microseconds_t ms)
239 _feedback_interval = ms;
243 GenericMidiControlProtocol::send_feedback ()
245 /* This is executed in RT "process" context", so no blocking calls
252 microseconds_t now = get_microseconds ();
254 if (last_feedback_time != 0) {
255 if ((now - last_feedback_time) < _feedback_interval) {
262 last_feedback_time = now;
266 GenericMidiControlProtocol::_send_feedback ()
268 /* This is executed in RT "process" context", so no blocking calls
271 const int32_t bufsize = 16 * 1024; /* XXX too big */
272 MIDI::byte buf[bufsize];
273 int32_t bsize = bufsize;
275 /* XXX: due to bugs in some ALSA / JACK MIDI bridges, we have to do separate
276 writes for each controllable here; if we send more than one MIDI message
277 in a single jack_midi_event_write then some bridges will only pass the
281 Glib::Threads::Mutex::Lock lm (controllables_lock, Glib::Threads::TRY_LOCK);
286 for (MIDIControllables::iterator r = controllables.begin(); r != controllables.end(); ++r) {
287 MIDI::byte* end = (*r)->write_feedback (buf, bsize);
289 _output_port->write (buf, (int32_t) (end - buf), 0);
295 GenericMidiControlProtocol::start_learning (Controllable* c)
301 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
303 MIDIControllables::iterator tmp;
304 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
307 if ((*i)->get_controllable() == c) {
309 controllables.erase (i);
315 Glib::Threads::Mutex::Lock lm (pending_lock);
317 MIDIPendingControllables::iterator ptmp;
318 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
321 if (((*i)->first)->get_controllable() == c) {
322 (*i)->second.disconnect();
325 pending_controllables.erase (i);
331 MIDIControllable* mc = 0;
333 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
334 if ((*i)->get_controllable() && ((*i)->get_controllable()->id() == c->id())) {
341 mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
345 Glib::Threads::Mutex::Lock lm (pending_lock);
347 MIDIPendingControllable* element = new MIDIPendingControllable;
349 c->LearningFinished.connect_same_thread (element->second, boost::bind (&GenericMidiControlProtocol::learning_stopped, this, mc));
351 pending_controllables.push_back (element);
354 mc->learn_about_external_control ();
359 GenericMidiControlProtocol::learning_stopped (MIDIControllable* mc)
361 Glib::Threads::Mutex::Lock lm (pending_lock);
362 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
364 MIDIPendingControllables::iterator tmp;
366 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
370 if ( (*i)->first == mc) {
371 (*i)->second.disconnect();
373 pending_controllables.erase(i);
379 controllables.push_back (mc);
383 GenericMidiControlProtocol::stop_learning (Controllable* c)
385 Glib::Threads::Mutex::Lock lm (pending_lock);
386 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
387 MIDIControllable* dptr = 0;
389 /* learning timed out, and we've been told to consider this attempt to learn to be cancelled. find the
390 relevant MIDIControllable and remove it from the pending list.
393 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
394 if (((*i)->first)->get_controllable() == c) {
395 (*i)->first->stop_learning ();
397 (*i)->second.disconnect();
400 pending_controllables.erase (i);
409 GenericMidiControlProtocol::delete_binding (PBD::Controllable* control)
412 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
414 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
415 MIDIControllable* existingBinding = (*iter);
417 if (control == (existingBinding->get_controllable())) {
418 delete existingBinding;
419 iter = controllables.erase (iter);
429 GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, int control_number)
431 if (control != NULL) {
432 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
434 MIDI::channel_t channel = (pos & 0xf);
435 MIDI::byte value = control_number;
437 // Create a MIDIControllable
438 MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *control, false);
440 // Remove any old binding for this midi channel/type/value pair
441 // Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
442 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
443 MIDIControllable* existingBinding = (*iter);
445 if ((existingBinding->get_control_channel() & 0xf ) == channel &&
446 existingBinding->get_control_additional() == value &&
447 (existingBinding->get_control_type() & 0xf0 ) == MIDI::controller) {
449 delete existingBinding;
450 iter = controllables.erase (iter);
457 // Update the MIDI Controllable based on the the pos param
458 // Here is where a table lookup for user mappings could go; for now we'll just wing it...
459 mc->bind_midi(channel, MIDI::controller, value);
460 DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Create binding: Channel: %1 Controller: %2 Value: %3 \n", channel, MIDI::controller, value));
461 controllables.push_back (mc);
466 GenericMidiControlProtocol::get_state ()
468 XMLNode& node (ControlProtocol::get_state());
471 snprintf (buf, sizeof (buf), "%" PRIu64, _feedback_interval);
472 node.add_property (X_("feedback_interval"), buf);
473 snprintf (buf, sizeof (buf), "%d", _threshold);
474 node.add_property (X_("threshold"), buf);
476 if (!_current_binding.empty()) {
477 node.add_property ("binding", _current_binding);
480 XMLNode* children = new XMLNode (X_("Controls"));
482 node.add_child_nocopy (*children);
484 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
485 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
487 /* we don't care about bindings that come from a bindings map, because
488 they will all be reset/recreated when we load the relevant bindings
492 if ((*i)->get_controllable() && (*i)->learned()) {
493 children->add_child_nocopy ((*i)->get_state());
501 GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
504 XMLNodeConstIterator niter;
505 const XMLProperty* prop;
507 if (ControlProtocol::set_state (node, version)) {
511 if ((prop = node.property ("feedback_interval")) != 0) {
512 if (sscanf (prop->value().c_str(), "%" PRIu64, &_feedback_interval) != 1) {
513 _feedback_interval = 10000;
516 _feedback_interval = 10000;
519 if ((prop = node.property ("threshold")) != 0) {
520 if (sscanf (prop->value().c_str(), "%d", &_threshold) != 1) {
527 boost::shared_ptr<Controllable> c;
530 Glib::Threads::Mutex::Lock lm (pending_lock);
531 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
534 pending_controllables.clear ();
537 /* Load up specific bindings from the
538 * <Controls><MidiControllable>...</MidiControllable><Controls> section
542 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
543 controllables.clear ();
544 nlist = node.children(); // "Controls"
546 if (!nlist.empty()) {
547 nlist = nlist.front()->children(); // "MIDIControllable" ...
549 if (!nlist.empty()) {
550 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
552 if ((prop = (*niter)->property ("id")) != 0) {
554 ID id = prop->value ();
555 Controllable* c = Controllable::by_id (id);
558 MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
560 if (mc->set_state (**niter, version) == 0) {
561 controllables.push_back (mc);
565 warning << string_compose (
566 _("Generic MIDI control: controllable %1 not found in session (ignored)"),
575 if ((prop = node.property ("binding")) != 0) {
576 for (list<MapInfo>::iterator x = map_info.begin(); x != map_info.end(); ++x) {
577 if (prop->value() == (*x).name) {
578 load_bindings ((*x).path);
588 GenericMidiControlProtocol::set_feedback (bool yn)
591 last_feedback_time = 0;
596 GenericMidiControlProtocol::get_feedback () const
602 GenericMidiControlProtocol::load_bindings (const string& xmlpath)
604 DEBUG_TRACE (DEBUG::GenericMidi, "Load bindings: Reading midi map\n");
607 if (!state_tree.read (xmlpath.c_str())) {
608 error << string_compose(_("Could not understand MIDI bindings file %1"), xmlpath) << endmsg;
612 XMLNode* root = state_tree.root();
614 if (root->name() != X_("ArdourMIDIBindings")) {
615 error << string_compose (_("MIDI Bindings file %1 is not really a MIDI bindings file"), xmlpath) << endmsg;
619 const XMLProperty* prop;
621 if ((prop = root->property ("version")) == 0) {
628 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
629 Stateful::loading_state_version = (major * 1000) + minor;
632 const XMLNodeList& children (root->children());
633 XMLNodeConstIterator citer;
634 XMLNodeConstIterator gciter;
636 MIDIControllable* mc;
640 DEBUG_TRACE (DEBUG::GenericMidi, "Loading bindings\n");
641 for (citer = children.begin(); citer != children.end(); ++citer) {
643 if ((*citer)->name() == "DeviceInfo") {
644 const XMLProperty* prop;
646 if ((prop = (*citer)->property ("bank-size")) != 0) {
647 _bank_size = atoi (prop->value());
651 if ((prop = (*citer)->property ("motorised")) != 0 || ((prop = (*citer)->property ("motorized")) != 0)) {
652 _motorised = string_is_affirmative (prop->value ());
657 if ((prop = (*citer)->property ("threshold")) != 0) {
658 _threshold = atoi (prop->value ());
665 if ((*citer)->name() == "Binding") {
666 const XMLNode* child = *citer;
668 if (child->property ("uri")) {
671 if ((mc = create_binding (*child)) != 0) {
672 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
673 controllables.push_back (mc);
676 } else if (child->property ("function")) {
681 if ((mf = create_function (*child)) != 0) {
682 functions.push_back (mf);
685 } else if (child->property ("action")) {
688 if ((ma = create_action (*child)) != 0) {
689 actions.push_back (ma);
695 if ((prop = root->property ("name")) != 0) {
696 _current_binding = prop->value ();
699 reset_controllables ();
705 GenericMidiControlProtocol::create_binding (const XMLNode& node)
707 const XMLProperty* prop;
709 MIDI::channel_t channel;
715 if ((prop = node.property (X_("ctl"))) != 0) {
716 ev = MIDI::controller;
717 } else if ((prop = node.property (X_("note"))) != 0) {
719 } else if ((prop = node.property (X_("pgm"))) != 0) {
721 } else if ((prop = node.property (X_("pb"))) != 0) {
722 ev = MIDI::pitchbend;
727 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
731 detail = (MIDI::byte) intval;
733 if ((prop = node.property (X_("channel"))) == 0) {
737 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
740 channel = (MIDI::channel_t) intval;
741 /* adjust channel to zero-based counting */
746 if ((prop = node.property (X_("momentary"))) != 0) {
747 momentary = string_is_affirmative (prop->value());
752 prop = node.property (X_("uri"));
755 MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), momentary);
757 if (mc->init (uri)) {
762 mc->bind_midi (channel, ev, detail);
768 GenericMidiControlProtocol::reset_controllables ()
770 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
772 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ) {
773 MIDIControllable* existingBinding = (*iter);
774 MIDIControllables::iterator next = iter;
777 if (!existingBinding->learned()) {
778 ControllableDescriptor& desc (existingBinding->descriptor());
781 desc.set_bank_offset (_current_bank * _bank_size);
784 /* its entirely possible that the session doesn't have
785 * the specified controllable (e.g. it has too few
786 * tracks). if we find this to be the case, we just leave
787 * the binding around, unbound, and it will do "late
788 * binding" (or "lazy binding") if/when any data arrives.
791 existingBinding->lookup_controllable ();
798 boost::shared_ptr<Controllable>
799 GenericMidiControlProtocol::lookup_controllable (const ControllableDescriptor& desc) const
801 return session->controllable_by_descriptor (desc);
805 GenericMidiControlProtocol::create_function (const XMLNode& node)
807 const XMLProperty* prop;
809 MIDI::byte detail = 0;
810 MIDI::channel_t channel = 0;
813 MIDI::byte* data = 0;
814 uint32_t data_size = 0;
817 if ((prop = node.property (X_("ctl"))) != 0) {
818 ev = MIDI::controller;
819 } else if ((prop = node.property (X_("note"))) != 0) {
821 } else if ((prop = node.property (X_("pgm"))) != 0) {
823 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
825 if (prop->name() == X_("sysex")) {
836 stringstream ss (prop->value());
848 data = new MIDI::byte[cnt];
852 stringstream ss (prop->value());
857 data[cnt++] = (MIDI::byte) val;
862 warning << "Binding ignored - unknown type" << endmsg;
866 if (data_size == 0) {
867 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
871 detail = (MIDI::byte) intval;
873 if ((prop = node.property (X_("channel"))) == 0) {
877 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
880 channel = (MIDI::channel_t) intval;
881 /* adjust channel to zero-based counting */
887 if ((prop = node.property (X_("arg"))) != 0 || (prop = node.property (X_("argument"))) != 0 || (prop = node.property (X_("arguments"))) != 0) {
888 argument = prop->value ();
891 prop = node.property (X_("function"));
893 MIDIFunction* mf = new MIDIFunction (*_input_port->parser());
895 if (mf->setup (*this, prop->value(), argument, data, data_size)) {
900 mf->bind_midi (channel, ev, detail);
906 GenericMidiControlProtocol::create_action (const XMLNode& node)
908 const XMLProperty* prop;
910 MIDI::byte detail = 0;
911 MIDI::channel_t channel = 0;
914 MIDI::byte* data = 0;
915 uint32_t data_size = 0;
917 if ((prop = node.property (X_("ctl"))) != 0) {
918 ev = MIDI::controller;
919 } else if ((prop = node.property (X_("note"))) != 0) {
921 } else if ((prop = node.property (X_("pgm"))) != 0) {
923 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
925 if (prop->name() == X_("sysex")) {
936 stringstream ss (prop->value());
948 data = new MIDI::byte[cnt];
952 stringstream ss (prop->value());
957 data[cnt++] = (MIDI::byte) val;
962 warning << "Binding ignored - unknown type" << endmsg;
966 if (data_size == 0) {
967 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
971 detail = (MIDI::byte) intval;
973 if ((prop = node.property (X_("channel"))) == 0) {
977 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
980 channel = (MIDI::channel_t) intval;
981 /* adjust channel to zero-based counting */
987 prop = node.property (X_("action"));
989 MIDIAction* ma = new MIDIAction (*_input_port->parser());
991 if (ma->init (*this, prop->value(), data, data_size)) {
996 ma->bind_midi (channel, ev, detail);
1002 GenericMidiControlProtocol::set_current_bank (uint32_t b)
1005 reset_controllables ();
1009 GenericMidiControlProtocol::next_bank ()
1012 reset_controllables ();
1016 GenericMidiControlProtocol::prev_bank()
1018 if (_current_bank) {
1020 reset_controllables ();
1025 GenericMidiControlProtocol::set_motorised (bool m)
1031 GenericMidiControlProtocol::set_threshold (int t)