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 nlist = nlist.front()->children ();
549 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
551 if ((prop = (*niter)->property ("id")) != 0) {
553 ID id = prop->value ();
554 Controllable* c = Controllable::by_id (id);
557 MIDIControllable* mc = new MIDIControllable (this, *_input_port, *c, false);
559 if (mc->set_state (**niter, version) == 0) {
560 controllables.push_back (mc);
564 warning << string_compose (
565 _("Generic MIDI control: controllable %1 not found in session (ignored)"),
573 if ((prop = node.property ("binding")) != 0) {
574 for (list<MapInfo>::iterator x = map_info.begin(); x != map_info.end(); ++x) {
575 if (prop->value() == (*x).name) {
576 load_bindings ((*x).path);
586 GenericMidiControlProtocol::set_feedback (bool yn)
589 last_feedback_time = 0;
594 GenericMidiControlProtocol::get_feedback () const
600 GenericMidiControlProtocol::load_bindings (const string& xmlpath)
604 if (!state_tree.read (xmlpath.c_str())) {
605 error << string_compose(_("Could not understand MIDI bindings file %1"), xmlpath) << endmsg;
609 XMLNode* root = state_tree.root();
611 if (root->name() != X_("ArdourMIDIBindings")) {
612 error << string_compose (_("MIDI Bindings file %1 is not really a MIDI bindings file"), xmlpath) << endmsg;
616 const XMLProperty* prop;
618 if ((prop = root->property ("version")) == 0) {
625 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
626 Stateful::loading_state_version = (major * 1000) + minor;
629 const XMLNodeList& children (root->children());
630 XMLNodeConstIterator citer;
631 XMLNodeConstIterator gciter;
633 MIDIControllable* mc;
637 for (citer = children.begin(); citer != children.end(); ++citer) {
639 if ((*citer)->name() == "DeviceInfo") {
640 const XMLProperty* prop;
642 if ((prop = (*citer)->property ("bank-size")) != 0) {
643 _bank_size = atoi (prop->value());
647 if ((prop = (*citer)->property ("motorised")) != 0 || ((prop = (*citer)->property ("motorized")) != 0)) {
648 _motorised = string_is_affirmative (prop->value ());
653 if ((prop = (*citer)->property ("threshold")) != 0) {
654 _threshold = atoi (prop->value ());
661 if ((*citer)->name() == "Binding") {
662 const XMLNode* child = *citer;
664 if (child->property ("uri")) {
667 if ((mc = create_binding (*child)) != 0) {
668 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
669 controllables.push_back (mc);
672 } else if (child->property ("function")) {
677 if ((mf = create_function (*child)) != 0) {
678 functions.push_back (mf);
681 } else if (child->property ("action")) {
684 if ((ma = create_action (*child)) != 0) {
685 actions.push_back (ma);
691 if ((prop = root->property ("name")) != 0) {
692 _current_binding = prop->value ();
695 reset_controllables ();
701 GenericMidiControlProtocol::create_binding (const XMLNode& node)
703 const XMLProperty* prop;
705 MIDI::channel_t channel;
711 if ((prop = node.property (X_("ctl"))) != 0) {
712 ev = MIDI::controller;
713 } else if ((prop = node.property (X_("note"))) != 0) {
715 } else if ((prop = node.property (X_("pgm"))) != 0) {
717 } else if ((prop = node.property (X_("pb"))) != 0) {
718 ev = MIDI::pitchbend;
723 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
727 detail = (MIDI::byte) intval;
729 if ((prop = node.property (X_("channel"))) == 0) {
733 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
736 channel = (MIDI::channel_t) intval;
737 /* adjust channel to zero-based counting */
742 if ((prop = node.property (X_("momentary"))) != 0) {
743 momentary = string_is_affirmative (prop->value());
748 prop = node.property (X_("uri"));
751 MIDIControllable* mc = new MIDIControllable (this, *_input_port, momentary);
753 if (mc->init (uri)) {
758 mc->bind_midi (channel, ev, detail);
764 GenericMidiControlProtocol::reset_controllables ()
766 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
768 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ) {
769 MIDIControllable* existingBinding = (*iter);
770 MIDIControllables::iterator next = iter;
773 if (!existingBinding->learned()) {
774 ControllableDescriptor& desc (existingBinding->descriptor());
777 desc.set_bank_offset (_current_bank * _bank_size);
780 /* its entirely possible that the session doesn't have
781 * the specified controllable (e.g. it has too few
782 * tracks). if we find this to be the case, we just leave
783 * the binding around, unbound, and it will do "late
784 * binding" (or "lazy binding") if/when any data arrives.
787 existingBinding->lookup_controllable ();
794 boost::shared_ptr<Controllable>
795 GenericMidiControlProtocol::lookup_controllable (const ControllableDescriptor& desc) const
797 return session->controllable_by_descriptor (desc);
801 GenericMidiControlProtocol::create_function (const XMLNode& node)
803 const XMLProperty* prop;
805 MIDI::byte detail = 0;
806 MIDI::channel_t channel = 0;
809 MIDI::byte* data = 0;
810 uint32_t data_size = 0;
813 if ((prop = node.property (X_("ctl"))) != 0) {
814 ev = MIDI::controller;
815 } else if ((prop = node.property (X_("note"))) != 0) {
817 } else if ((prop = node.property (X_("pgm"))) != 0) {
819 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
821 if (prop->name() == X_("sysex")) {
832 stringstream ss (prop->value());
844 data = new MIDI::byte[cnt];
848 stringstream ss (prop->value());
853 data[cnt++] = (MIDI::byte) val;
858 warning << "Binding ignored - unknown type" << endmsg;
862 if (data_size == 0) {
863 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
867 detail = (MIDI::byte) intval;
869 if ((prop = node.property (X_("channel"))) == 0) {
873 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
876 channel = (MIDI::channel_t) intval;
877 /* adjust channel to zero-based counting */
883 if ((prop = node.property (X_("arg"))) != 0 || (prop = node.property (X_("argument"))) != 0 || (prop = node.property (X_("arguments"))) != 0) {
884 argument = prop->value ();
887 prop = node.property (X_("function"));
889 MIDIFunction* mf = new MIDIFunction (*_input_port);
891 if (mf->setup (*this, prop->value(), argument, data, data_size)) {
896 mf->bind_midi (channel, ev, detail);
902 GenericMidiControlProtocol::create_action (const XMLNode& node)
904 const XMLProperty* prop;
906 MIDI::byte detail = 0;
907 MIDI::channel_t channel = 0;
910 MIDI::byte* data = 0;
911 uint32_t data_size = 0;
913 if ((prop = node.property (X_("ctl"))) != 0) {
914 ev = MIDI::controller;
915 } else if ((prop = node.property (X_("note"))) != 0) {
917 } else if ((prop = node.property (X_("pgm"))) != 0) {
919 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
921 if (prop->name() == X_("sysex")) {
932 stringstream ss (prop->value());
944 data = new MIDI::byte[cnt];
948 stringstream ss (prop->value());
953 data[cnt++] = (MIDI::byte) val;
958 warning << "Binding ignored - unknown type" << endmsg;
962 if (data_size == 0) {
963 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
967 detail = (MIDI::byte) intval;
969 if ((prop = node.property (X_("channel"))) == 0) {
973 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
976 channel = (MIDI::channel_t) intval;
977 /* adjust channel to zero-based counting */
983 prop = node.property (X_("action"));
985 MIDIAction* ma = new MIDIAction (*_input_port);
987 if (ma->init (*this, prop->value(), data, data_size)) {
992 ma->bind_midi (channel, ev, detail);
998 GenericMidiControlProtocol::set_current_bank (uint32_t b)
1001 reset_controllables ();
1005 GenericMidiControlProtocol::next_bank ()
1008 reset_controllables ();
1012 GenericMidiControlProtocol::prev_bank()
1014 if (_current_bank) {
1016 reset_controllables ();
1021 GenericMidiControlProtocol::set_motorised (bool m)
1027 GenericMidiControlProtocol::set_threshold (int t)