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)->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 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
549 if ((prop = (*niter)->property ("id")) != 0) {
551 ID id = prop->value ();
552 Controllable* c = Controllable::by_id (id);
555 MIDIControllable* mc = new MIDIControllable (this, *_input_port, *c, false);
557 if (mc->set_state (**niter, version) == 0) {
558 controllables.push_back (mc);
562 warning << string_compose (
563 _("Generic MIDI control: controllable %1 not found in session (ignored)"),
571 if ((prop = node.property ("binding")) != 0) {
572 for (list<MapInfo>::iterator x = map_info.begin(); x != map_info.end(); ++x) {
573 if (prop->value() == (*x).name) {
574 load_bindings ((*x).path);
584 GenericMidiControlProtocol::set_feedback (bool yn)
587 last_feedback_time = 0;
592 GenericMidiControlProtocol::get_feedback () const
598 GenericMidiControlProtocol::load_bindings (const string& xmlpath)
602 if (!state_tree.read (xmlpath.c_str())) {
603 error << string_compose(_("Could not understand MIDI bindings file %1"), xmlpath) << endmsg;
607 XMLNode* root = state_tree.root();
609 if (root->name() != X_("ArdourMIDIBindings")) {
610 error << string_compose (_("MIDI Bindings file %1 is not really a MIDI bindings file"), xmlpath) << endmsg;
614 const XMLProperty* prop;
616 if ((prop = root->property ("version")) == 0) {
623 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
624 Stateful::loading_state_version = (major * 1000) + minor;
627 const XMLNodeList& children (root->children());
628 XMLNodeConstIterator citer;
629 XMLNodeConstIterator gciter;
631 MIDIControllable* mc;
635 for (citer = children.begin(); citer != children.end(); ++citer) {
637 if ((*citer)->name() == "DeviceInfo") {
638 const XMLProperty* prop;
640 if ((prop = (*citer)->property ("bank-size")) != 0) {
641 _bank_size = atoi (prop->value());
645 if ((prop = (*citer)->property ("motorised")) != 0 || ((prop = (*citer)->property ("motorized")) != 0)) {
646 _motorised = string_is_affirmative (prop->value ());
651 if ((prop = (*citer)->property ("threshold")) != 0) {
652 _threshold = atoi (prop->value ());
659 if ((*citer)->name() == "Binding") {
660 const XMLNode* child = *citer;
662 if (child->property ("uri")) {
665 if ((mc = create_binding (*child)) != 0) {
666 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
667 controllables.push_back (mc);
670 } else if (child->property ("function")) {
675 if ((mf = create_function (*child)) != 0) {
676 functions.push_back (mf);
679 } else if (child->property ("action")) {
682 if ((ma = create_action (*child)) != 0) {
683 actions.push_back (ma);
689 if ((prop = root->property ("name")) != 0) {
690 _current_binding = prop->value ();
693 reset_controllables ();
699 GenericMidiControlProtocol::create_binding (const XMLNode& node)
701 const XMLProperty* prop;
703 MIDI::channel_t channel;
709 if ((prop = node.property (X_("ctl"))) != 0) {
710 ev = MIDI::controller;
711 } else if ((prop = node.property (X_("note"))) != 0) {
713 } else if ((prop = node.property (X_("pgm"))) != 0) {
715 } else if ((prop = node.property (X_("pb"))) != 0) {
716 ev = MIDI::pitchbend;
721 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
725 detail = (MIDI::byte) intval;
727 if ((prop = node.property (X_("channel"))) == 0) {
731 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
734 channel = (MIDI::channel_t) intval;
735 /* adjust channel to zero-based counting */
740 if ((prop = node.property (X_("momentary"))) != 0) {
741 momentary = string_is_affirmative (prop->value());
746 prop = node.property (X_("uri"));
749 MIDIControllable* mc = new MIDIControllable (this, *_input_port, momentary);
751 if (mc->init (uri)) {
756 mc->bind_midi (channel, ev, detail);
762 GenericMidiControlProtocol::reset_controllables ()
764 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
766 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ) {
767 MIDIControllable* existingBinding = (*iter);
768 MIDIControllables::iterator next = iter;
771 if (!existingBinding->learned()) {
772 ControllableDescriptor& desc (existingBinding->descriptor());
775 desc.set_bank_offset (_current_bank * _bank_size);
778 /* its entirely possible that the session doesn't have
779 * the specified controllable (e.g. it has too few
780 * tracks). if we find this to be the case, we just leave
781 * the binding around, unbound, and it will do "late
782 * binding" (or "lazy binding") if/when any data arrives.
785 existingBinding->lookup_controllable ();
792 boost::shared_ptr<Controllable>
793 GenericMidiControlProtocol::lookup_controllable (const ControllableDescriptor& desc) const
795 return session->controllable_by_descriptor (desc);
799 GenericMidiControlProtocol::create_function (const XMLNode& node)
801 const XMLProperty* prop;
803 MIDI::byte detail = 0;
804 MIDI::channel_t channel = 0;
807 MIDI::byte* data = 0;
808 uint32_t data_size = 0;
811 if ((prop = node.property (X_("ctl"))) != 0) {
812 ev = MIDI::controller;
813 } else if ((prop = node.property (X_("note"))) != 0) {
815 } else if ((prop = node.property (X_("pgm"))) != 0) {
817 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
819 if (prop->name() == X_("sysex")) {
830 stringstream ss (prop->value());
842 data = new MIDI::byte[cnt];
846 stringstream ss (prop->value());
851 data[cnt++] = (MIDI::byte) val;
856 warning << "Binding ignored - unknown type" << endmsg;
860 if (data_size == 0) {
861 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
865 detail = (MIDI::byte) intval;
867 if ((prop = node.property (X_("channel"))) == 0) {
871 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
874 channel = (MIDI::channel_t) intval;
875 /* adjust channel to zero-based counting */
881 if ((prop = node.property (X_("arg"))) != 0 || (prop = node.property (X_("argument"))) != 0 || (prop = node.property (X_("arguments"))) != 0) {
882 argument = prop->value ();
885 prop = node.property (X_("function"));
887 MIDIFunction* mf = new MIDIFunction (*_input_port);
889 if (mf->setup (*this, prop->value(), argument, data, data_size)) {
894 mf->bind_midi (channel, ev, detail);
900 GenericMidiControlProtocol::create_action (const XMLNode& node)
902 const XMLProperty* prop;
904 MIDI::byte detail = 0;
905 MIDI::channel_t channel = 0;
908 MIDI::byte* data = 0;
909 uint32_t data_size = 0;
911 if ((prop = node.property (X_("ctl"))) != 0) {
912 ev = MIDI::controller;
913 } else if ((prop = node.property (X_("note"))) != 0) {
915 } else if ((prop = node.property (X_("pgm"))) != 0) {
917 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
919 if (prop->name() == X_("sysex")) {
930 stringstream ss (prop->value());
942 data = new MIDI::byte[cnt];
946 stringstream ss (prop->value());
951 data[cnt++] = (MIDI::byte) val;
956 warning << "Binding ignored - unknown type" << endmsg;
960 if (data_size == 0) {
961 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
965 detail = (MIDI::byte) intval;
967 if ((prop = node.property (X_("channel"))) == 0) {
971 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
974 channel = (MIDI::channel_t) intval;
975 /* adjust channel to zero-based counting */
981 prop = node.property (X_("action"));
983 MIDIAction* ma = new MIDIAction (*_input_port);
985 if (ma->init (*this, prop->value(), data, data_size)) {
990 ma->bind_midi (channel, ev, detail);
996 GenericMidiControlProtocol::set_current_bank (uint32_t b)
999 reset_controllables ();
1003 GenericMidiControlProtocol::next_bank ()
1006 reset_controllables ();
1010 GenericMidiControlProtocol::prev_bank()
1012 if (_current_bank) {
1014 reset_controllables ();
1019 GenericMidiControlProtocol::set_motorised (bool m)
1025 GenericMidiControlProtocol::set_threshold (int t)