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/pathscanner.h"
32 #include "pbd/xml++.h"
34 #include "midi++/port.h"
35 #include "midi++/manager.h"
37 #include "ardour/filesystem_paths.h"
38 #include "ardour/session.h"
39 #include "ardour/route.h"
40 #include "ardour/midi_ui.h"
41 #include "ardour/rc_configuration.h"
43 #include "generic_midi_control_protocol.h"
44 #include "midicontrollable.h"
45 #include "midifunction.h"
46 #include "midiaction.h"
48 using namespace ARDOUR;
54 #define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
56 GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
57 : ControlProtocol (s, _("Generic MIDI"))
62 _input_port = MIDI::Manager::instance()->midi_input_port ();
63 _output_port = MIDI::Manager::instance()->midi_output_port ();
66 _feedback_interval = 10000; // microseconds
67 last_feedback_time = 0;
72 /* these signals are emitted by the MidiControlUI's event loop thread
73 * and we may as well handle them right there in the same the same
77 Controllable::StartLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::start_learning, this, _1));
78 Controllable::StopLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::stop_learning, this, _1));
79 Controllable::CreateBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::create_binding, this, _1, _2, _3));
80 Controllable::DeleteBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1));
82 Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
84 /* XXXX SOMETHING GOES WRONG HERE (april 2012) - STILL DEBUGGING */
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));
92 /* this one is cross-thread */
94 Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
99 GenericMidiControlProtocol::~GenericMidiControlProtocol ()
105 static const char * const midimap_env_variable_name = "ARDOUR_MIDIMAPS_PATH";
106 static const char* const midi_map_dir_name = "midi_maps";
107 static const char* const midi_map_suffix = ".map";
110 system_midi_map_search_path ()
112 bool midimap_path_defined = false;
113 std::string spath_env (Glib::getenv (midimap_env_variable_name, midimap_path_defined));
115 if (midimap_path_defined) {
119 SearchPath spath (ardour_data_search_path());
120 spath.add_subdirectory_to_paths(midi_map_dir_name);
122 // just return the first directory in the search path that exists
123 for (SearchPath::const_iterator i = spath.begin(); i != spath.end(); ++i) {
124 if (Glib::file_test (*i, Glib::FILE_TEST_EXISTS)) {
128 return std::string();
132 user_midi_map_directory ()
134 return Glib::build_filename (user_config_directory(), midi_map_dir_name);
138 midi_map_filter (const string &str, void */*arg*/)
140 return (str.length() > strlen(midi_map_suffix) &&
141 str.find (midi_map_suffix) == (str.length() - strlen (midi_map_suffix)));
145 GenericMidiControlProtocol::reload_maps ()
147 vector<string *> *midi_maps;
149 SearchPath spath (system_midi_map_search_path());
150 spath += user_midi_map_directory ();
152 midi_maps = scanner (spath.to_string(), midi_map_filter, 0, false, true);
155 cerr << "No MIDI maps found using " << spath.to_string() << endl;
159 for (vector<string*>::iterator i = midi_maps->begin(); i != midi_maps->end(); ++i) {
160 string fullpath = *(*i);
164 if (!tree.read (fullpath.c_str())) {
170 XMLProperty* prop = tree.root()->property ("name");
176 mi.name = prop->value ();
179 map_info.push_back (mi);
186 GenericMidiControlProtocol::drop_all ()
188 Glib::Threads::Mutex::Lock lm (pending_lock);
189 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
191 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
194 controllables.clear ();
196 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
199 pending_controllables.clear ();
201 for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
206 for (MIDIActions::iterator i = actions.begin(); i != actions.end(); ++i) {
213 GenericMidiControlProtocol::drop_bindings ()
215 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
217 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
218 if (!(*i)->learned()) {
220 i = controllables.erase (i);
226 for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
231 _current_binding = "";
237 GenericMidiControlProtocol::set_active (bool /*yn*/)
239 /* start/stop delivery/outbound thread */
244 GenericMidiControlProtocol::set_feedback_interval (microseconds_t ms)
246 _feedback_interval = ms;
250 GenericMidiControlProtocol::send_feedback ()
252 /* This is executed in RT "process" context", so no blocking calls
259 microseconds_t now = get_microseconds ();
261 if (last_feedback_time != 0) {
262 if ((now - last_feedback_time) < _feedback_interval) {
269 last_feedback_time = now;
273 GenericMidiControlProtocol::_send_feedback ()
275 /* This is executed in RT "process" context", so no blocking calls
278 const int32_t bufsize = 16 * 1024; /* XXX too big */
279 MIDI::byte buf[bufsize];
280 int32_t bsize = bufsize;
282 /* XXX: due to bugs in some ALSA / JACK MIDI bridges, we have to do separate
283 writes for each controllable here; if we send more than one MIDI message
284 in a single jack_midi_event_write then some bridges will only pass the
288 Glib::Threads::Mutex::Lock lm (controllables_lock, Glib::Threads::TRY_LOCK);
293 for (MIDIControllables::iterator r = controllables.begin(); r != controllables.end(); ++r) {
294 MIDI::byte* end = (*r)->write_feedback (buf, bsize);
296 _output_port->write (buf, (int32_t) (end - buf), 0);
302 GenericMidiControlProtocol::start_learning (Controllable* c)
308 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
310 MIDIControllables::iterator tmp;
311 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
314 if ((*i)->get_controllable() == c) {
316 controllables.erase (i);
322 Glib::Threads::Mutex::Lock lm (pending_lock);
324 MIDIPendingControllables::iterator ptmp;
325 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
328 if (((*i)->first)->get_controllable() == c) {
329 (*i)->second.disconnect();
332 pending_controllables.erase (i);
338 MIDIControllable* mc = 0;
340 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
341 if ((*i)->get_controllable() && ((*i)->get_controllable()->id() == c->id())) {
348 mc = new MIDIControllable (this, *_input_port, *c, false);
352 Glib::Threads::Mutex::Lock lm (pending_lock);
354 MIDIPendingControllable* element = new MIDIPendingControllable;
356 c->LearningFinished.connect_same_thread (element->second, boost::bind (&GenericMidiControlProtocol::learning_stopped, this, mc));
358 pending_controllables.push_back (element);
361 mc->learn_about_external_control ();
366 GenericMidiControlProtocol::learning_stopped (MIDIControllable* mc)
368 Glib::Threads::Mutex::Lock lm (pending_lock);
369 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
371 MIDIPendingControllables::iterator tmp;
373 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
377 if ( (*i)->first == mc) {
378 (*i)->second.disconnect();
380 pending_controllables.erase(i);
386 controllables.push_back (mc);
390 GenericMidiControlProtocol::stop_learning (Controllable* c)
392 Glib::Threads::Mutex::Lock lm (pending_lock);
393 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
394 MIDIControllable* dptr = 0;
396 /* learning timed out, and we've been told to consider this attempt to learn to be cancelled. find the
397 relevant MIDIControllable and remove it from the pending list.
400 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
401 if (((*i)->first)->get_controllable() == c) {
402 (*i)->first->stop_learning ();
404 (*i)->second.disconnect();
407 pending_controllables.erase (i);
416 GenericMidiControlProtocol::delete_binding (PBD::Controllable* control)
419 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
421 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
422 MIDIControllable* existingBinding = (*iter);
424 if (control == (existingBinding->get_controllable())) {
425 delete existingBinding;
426 iter = controllables.erase (iter);
436 GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, int control_number)
438 if (control != NULL) {
439 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
441 MIDI::channel_t channel = (pos & 0xf);
442 MIDI::byte value = control_number;
444 // Create a MIDIControllable
445 MIDIControllable* mc = new MIDIControllable (this, *_input_port, *control, false);
447 // Remove any old binding for this midi channel/type/value pair
448 // Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
449 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
450 MIDIControllable* existingBinding = (*iter);
452 if ((existingBinding->get_control_channel() & 0xf ) == channel &&
453 existingBinding->get_control_additional() == value &&
454 (existingBinding->get_control_type() & 0xf0 ) == MIDI::controller) {
456 delete existingBinding;
457 iter = controllables.erase (iter);
464 // Update the MIDI Controllable based on the the pos param
465 // Here is where a table lookup for user mappings could go; for now we'll just wing it...
466 mc->bind_midi(channel, MIDI::controller, value);
468 controllables.push_back (mc);
473 GenericMidiControlProtocol::get_state ()
475 XMLNode* node = new XMLNode ("Protocol");
478 node->add_property (X_("name"), _name);
479 node->add_property (X_("feedback"), do_feedback ? "1" : "0");
480 snprintf (buf, sizeof (buf), "%" PRIu64, _feedback_interval);
481 node->add_property (X_("feedback_interval"), buf);
483 if (!_current_binding.empty()) {
484 node->add_property ("binding", _current_binding);
487 XMLNode* children = new XMLNode (X_("Controls"));
489 node->add_child_nocopy (*children);
491 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
492 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
494 /* we don't care about bindings that come from a bindings map, because
495 they will all be reset/recreated when we load the relevant bindings
499 if ((*i)->get_controllable() && (*i)->learned()) {
500 children->add_child_nocopy ((*i)->get_state());
508 GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
511 XMLNodeConstIterator niter;
512 const XMLProperty* prop;
514 if ((prop = node.property ("feedback")) != 0) {
515 do_feedback = (bool) atoi (prop->value().c_str());
520 if ((prop = node.property ("feedback_interval")) != 0) {
521 if (sscanf (prop->value().c_str(), "%" PRIu64, &_feedback_interval) != 1) {
522 _feedback_interval = 10000;
525 _feedback_interval = 10000;
528 boost::shared_ptr<Controllable> c;
531 Glib::Threads::Mutex::Lock lm (pending_lock);
532 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
535 pending_controllables.clear ();
539 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
540 controllables.clear ();
541 nlist = node.children(); // "Controls"
547 nlist = nlist.front()->children(); // "MIDIControllable" ...
553 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
557 if ((prop = (*niter)->property ("id")) != 0) {
559 ID id = prop->value ();
560 Controllable* c = Controllable::by_id (id);
563 MIDIControllable* mc = new MIDIControllable (this, *_input_port, *c, false);
565 if (mc->set_state (**niter, version) == 0) {
566 controllables.push_back (mc);
570 warning << string_compose (
571 _("Generic MIDI control: controllable %1 not found in session (ignored)"),
578 if ((prop = node.property ("binding")) != 0) {
579 for (list<MapInfo>::iterator x = map_info.begin(); x != map_info.end(); ++x) {
580 if (prop->value() == (*x).name) {
581 load_bindings ((*x).path);
591 GenericMidiControlProtocol::set_feedback (bool yn)
594 last_feedback_time = 0;
599 GenericMidiControlProtocol::get_feedback () const
605 GenericMidiControlProtocol::load_bindings (const string& xmlpath)
609 if (!state_tree.read (xmlpath.c_str())) {
610 error << string_compose(_("Could not understand MIDI bindings file %1"), xmlpath) << endmsg;
614 XMLNode* root = state_tree.root();
616 if (root->name() != X_("ArdourMIDIBindings")) {
617 error << string_compose (_("MIDI Bindings file %1 is not really a MIDI bindings file"), xmlpath) << endmsg;
621 const XMLProperty* prop;
623 if ((prop = root->property ("version")) == 0) {
630 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
631 Stateful::loading_state_version = (major * 1000) + minor;
634 const XMLNodeList& children (root->children());
635 XMLNodeConstIterator citer;
636 XMLNodeConstIterator gciter;
638 MIDIControllable* mc;
642 for (citer = children.begin(); citer != children.end(); ++citer) {
644 if ((*citer)->name() == "DeviceInfo") {
645 const XMLProperty* prop;
647 if ((prop = (*citer)->property ("bank-size")) != 0) {
648 _bank_size = atoi (prop->value());
652 if ((prop = (*citer)->property ("motorised")) != 0 || ((prop = (*citer)->property ("motorized")) != 0)) {
653 _motorised = string_is_affirmative (prop->value ());
658 if ((prop = (*citer)->property ("threshold")) != 0) {
659 _threshold = atoi (prop->value ());
666 if ((*citer)->name() == "Binding") {
667 const XMLNode* child = *citer;
669 if (child->property ("uri")) {
672 if ((mc = create_binding (*child)) != 0) {
673 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
674 controllables.push_back (mc);
677 } else if (child->property ("function")) {
682 if ((mf = create_function (*child)) != 0) {
683 functions.push_back (mf);
686 } else if (child->property ("action")) {
689 if ((ma = create_action (*child)) != 0) {
690 actions.push_back (ma);
696 if ((prop = root->property ("name")) != 0) {
697 _current_binding = prop->value ();
700 reset_controllables ();
706 GenericMidiControlProtocol::create_binding (const XMLNode& node)
708 const XMLProperty* prop;
710 MIDI::channel_t channel;
716 if ((prop = node.property (X_("ctl"))) != 0) {
717 ev = MIDI::controller;
718 } else if ((prop = node.property (X_("note"))) != 0) {
720 } else if ((prop = node.property (X_("pgm"))) != 0) {
722 } else if ((prop = node.property (X_("pb"))) != 0) {
723 ev = MIDI::pitchbend;
728 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
732 detail = (MIDI::byte) intval;
734 if ((prop = node.property (X_("channel"))) == 0) {
738 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
741 channel = (MIDI::channel_t) intval;
742 /* adjust channel to zero-based counting */
747 if ((prop = node.property (X_("momentary"))) != 0) {
748 momentary = string_is_affirmative (prop->value());
753 prop = node.property (X_("uri"));
756 MIDIControllable* mc = new MIDIControllable (this, *_input_port, momentary);
758 if (mc->init (uri)) {
763 mc->bind_midi (channel, ev, detail);
769 GenericMidiControlProtocol::reset_controllables ()
771 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
773 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ) {
774 MIDIControllable* existingBinding = (*iter);
775 MIDIControllables::iterator next = iter;
778 if (!existingBinding->learned()) {
779 ControllableDescriptor& desc (existingBinding->descriptor());
782 desc.set_bank_offset (_current_bank * _bank_size);
785 /* its entirely possible that the session doesn't have
786 * the specified controllable (e.g. it has too few
787 * tracks). if we find this to be the case, we just leave
788 * the binding around, unbound, and it will do "late
789 * binding" (or "lazy binding") if/when any data arrives.
792 existingBinding->lookup_controllable ();
799 boost::shared_ptr<Controllable>
800 GenericMidiControlProtocol::lookup_controllable (const ControllableDescriptor& desc) const
802 return session->controllable_by_descriptor (desc);
806 GenericMidiControlProtocol::create_function (const XMLNode& node)
808 const XMLProperty* prop;
810 MIDI::byte detail = 0;
811 MIDI::channel_t channel = 0;
814 MIDI::byte* data = 0;
815 uint32_t data_size = 0;
818 if ((prop = node.property (X_("ctl"))) != 0) {
819 ev = MIDI::controller;
820 } else if ((prop = node.property (X_("note"))) != 0) {
822 } else if ((prop = node.property (X_("pgm"))) != 0) {
824 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
826 if (prop->name() == X_("sysex")) {
837 stringstream ss (prop->value());
849 data = new MIDI::byte[cnt];
853 stringstream ss (prop->value());
858 data[cnt++] = (MIDI::byte) val;
863 warning << "Binding ignored - unknown type" << endmsg;
867 if (data_size == 0) {
868 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
872 detail = (MIDI::byte) intval;
874 if ((prop = node.property (X_("channel"))) == 0) {
878 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
881 channel = (MIDI::channel_t) intval;
882 /* adjust channel to zero-based counting */
888 if ((prop = node.property (X_("arg"))) != 0 || (prop = node.property (X_("argument"))) != 0 || (prop = node.property (X_("arguments"))) != 0) {
889 argument = prop->value ();
892 prop = node.property (X_("function"));
894 MIDIFunction* mf = new MIDIFunction (*_input_port);
896 if (mf->setup (*this, prop->value(), argument, data, data_size)) {
901 mf->bind_midi (channel, ev, detail);
907 GenericMidiControlProtocol::create_action (const XMLNode& node)
909 const XMLProperty* prop;
911 MIDI::byte detail = 0;
912 MIDI::channel_t channel = 0;
915 MIDI::byte* data = 0;
916 uint32_t data_size = 0;
918 if ((prop = node.property (X_("ctl"))) != 0) {
919 ev = MIDI::controller;
920 } else if ((prop = node.property (X_("note"))) != 0) {
922 } else if ((prop = node.property (X_("pgm"))) != 0) {
924 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
926 if (prop->name() == X_("sysex")) {
937 stringstream ss (prop->value());
949 data = new MIDI::byte[cnt];
953 stringstream ss (prop->value());
958 data[cnt++] = (MIDI::byte) val;
963 warning << "Binding ignored - unknown type" << endmsg;
967 if (data_size == 0) {
968 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
972 detail = (MIDI::byte) intval;
974 if ((prop = node.property (X_("channel"))) == 0) {
978 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
981 channel = (MIDI::channel_t) intval;
982 /* adjust channel to zero-based counting */
988 prop = node.property (X_("action"));
990 MIDIAction* ma = new MIDIAction (*_input_port);
992 if (ma->init (*this, prop->value(), data, data_size)) {
997 ma->bind_midi (channel, ev, detail);
1003 GenericMidiControlProtocol::set_current_bank (uint32_t b)
1006 reset_controllables ();
1010 GenericMidiControlProtocol::next_bank ()
1013 reset_controllables ();
1017 GenericMidiControlProtocol::prev_bank()
1019 if (_current_bank) {
1021 reset_controllables ();
1026 GenericMidiControlProtocol::set_motorised (bool m)
1032 GenericMidiControlProtocol::set_threshold (int t)