move MidiPortManager from AudioEngine to Session
[ardour.git] / libs / surfaces / generic_midi / generic_midi_control_protocol.cc
1 /*
2     Copyright (C) 2006 Paul Davis
3  
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.
8
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.
13
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.
17
18 */
19
20 #include <stdint.h>
21
22 #include <sstream>
23 #include <algorithm>
24
25 #include <glibmm/fileutils.h>
26 #include <glibmm/miscutils.h>
27
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"
33
34 #include "midi++/port.h"
35
36 #include "ardour/audioengine.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"
42 #include "ardour/midiport_manager.h"
43
44 #include "generic_midi_control_protocol.h"
45 #include "midicontrollable.h"
46 #include "midifunction.h"
47 #include "midiaction.h"
48
49 using namespace ARDOUR;
50 using namespace PBD;
51 using namespace std;
52
53 #include "i18n.h"
54
55 #define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
56
57 GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
58         : ControlProtocol (s, _("Generic MIDI"))
59         , _motorised (false)
60         , _threshold (10)
61         , gui (0)
62 {
63         _input_port = s.midi_input_port ();
64         _output_port = s.midi_output_port ();
65
66         do_feedback = false;
67         _feedback_interval = 10000; // microseconds
68         last_feedback_time = 0;
69
70         _current_bank = 0;
71         _bank_size = 0;
72
73         /* these signals are emitted by the MidiControlUI's event loop thread
74          * and we may as well handle them right there in the same the same
75          * thread
76          */
77
78         Controllable::StartLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::start_learning, this, _1));
79         Controllable::StopLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::stop_learning, this, _1));
80         Controllable::CreateBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::create_binding, this, _1, _2, _3));
81         Controllable::DeleteBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1));
82
83         Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
84 #if 0
85         /* XXXX SOMETHING GOES WRONG HERE (april 2012) - STILL DEBUGGING */
86         /* this signal is emitted by the process() callback, and if
87          * send_feedback() is going to do anything, it should do it in the
88          * context of the process() callback itself.
89          */
90
91         Session::SendFeedback.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this));
92 #endif
93         /* this one is cross-thread */
94
95         Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
96
97         reload_maps ();
98 }
99
100 GenericMidiControlProtocol::~GenericMidiControlProtocol ()
101 {
102         drop_all ();
103         tear_down_gui ();
104 }
105
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";
109
110 SearchPath
111 system_midi_map_search_path ()
112 {
113         bool midimap_path_defined = false;
114         std::string spath_env (Glib::getenv (midimap_env_variable_name, midimap_path_defined));
115
116         if (midimap_path_defined) {
117                 return spath_env;
118         }
119
120         SearchPath spath (ardour_data_search_path());
121         spath.add_subdirectory_to_paths(midi_map_dir_name);
122         return spath;
123 }
124
125 static std::string
126 user_midi_map_directory ()
127 {
128         return Glib::build_filename (user_config_directory(), midi_map_dir_name);
129 }
130
131 static bool
132 midi_map_filter (const string &str, void */*arg*/)
133 {
134         return (str.length() > strlen(midi_map_suffix) &&
135                 str.find (midi_map_suffix) == (str.length() - strlen (midi_map_suffix)));
136 }
137
138 void
139 GenericMidiControlProtocol::reload_maps ()
140 {
141         vector<string *> *midi_maps;
142         PathScanner scanner;
143         SearchPath spath (system_midi_map_search_path());
144         spath += user_midi_map_directory ();
145
146         midi_maps = scanner (spath.to_string(), midi_map_filter, 0, false, true);
147
148         if (!midi_maps) {
149                 cerr << "No MIDI maps found using " << spath.to_string() << endl;
150                 return;
151         }
152
153         for (vector<string*>::iterator i = midi_maps->begin(); i != midi_maps->end(); ++i) {
154                 string fullpath = *(*i);
155
156                 XMLTree tree;
157
158                 if (!tree.read (fullpath.c_str())) {
159                         continue;
160                 }
161
162                 MapInfo mi;
163
164                 XMLProperty* prop = tree.root()->property ("name");
165
166                 if (!prop) {
167                         continue;
168                 }
169
170                 mi.name = prop->value ();
171                 mi.path = fullpath;
172                 
173                 map_info.push_back (mi);
174         }
175
176         delete midi_maps;
177 }
178         
179 void
180 GenericMidiControlProtocol::drop_all ()
181 {
182         Glib::Threads::Mutex::Lock lm (pending_lock);
183         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
184
185         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
186                 delete *i;
187         }
188         controllables.clear ();
189
190         for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
191                 delete *i;
192         }
193         pending_controllables.clear ();
194
195         for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
196                 delete *i;
197         }
198         functions.clear ();
199
200         for (MIDIActions::iterator i = actions.begin(); i != actions.end(); ++i) {
201                 delete *i;
202         }
203         actions.clear ();
204 }
205
206 void
207 GenericMidiControlProtocol::drop_bindings ()
208 {
209         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
210
211         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
212                 if (!(*i)->learned()) {
213                         delete *i;
214                         i = controllables.erase (i);
215                 } else {
216                         ++i;
217                 }
218         }
219
220         for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
221                 delete *i;
222         }
223         functions.clear ();
224
225         _current_binding = "";
226         _bank_size = 0;
227         _current_bank = 0;
228 }
229
230 int
231 GenericMidiControlProtocol::set_active (bool /*yn*/)
232 {
233         /* start/stop delivery/outbound thread */
234         return 0;
235 }
236
237 void
238 GenericMidiControlProtocol::set_feedback_interval (microseconds_t ms)
239 {
240         _feedback_interval = ms;
241 }
242
243 void 
244 GenericMidiControlProtocol::send_feedback ()
245 {
246         /* This is executed in RT "process" context", so no blocking calls
247          */
248
249         if (!do_feedback) {
250                 return;
251         }
252
253         microseconds_t now = get_microseconds ();
254
255         if (last_feedback_time != 0) {
256                 if ((now - last_feedback_time) < _feedback_interval) {
257                         return;
258                 }
259         }
260
261         _send_feedback ();
262         
263         last_feedback_time = now;
264 }
265
266 void 
267 GenericMidiControlProtocol::_send_feedback ()
268 {
269         /* This is executed in RT "process" context", so no blocking calls
270          */
271
272         const int32_t bufsize = 16 * 1024; /* XXX too big */
273         MIDI::byte buf[bufsize];
274         int32_t bsize = bufsize;
275
276         /* XXX: due to bugs in some ALSA / JACK MIDI bridges, we have to do separate
277            writes for each controllable here; if we send more than one MIDI message
278            in a single jack_midi_event_write then some bridges will only pass the
279            first on to ALSA.
280         */
281
282         Glib::Threads::Mutex::Lock lm (controllables_lock, Glib::Threads::TRY_LOCK);
283         if (!lm.locked ()) {
284                 return;
285         }
286         
287         for (MIDIControllables::iterator r = controllables.begin(); r != controllables.end(); ++r) {
288                 MIDI::byte* end = (*r)->write_feedback (buf, bsize);
289                 if (end != buf) {
290                         _output_port->write (buf, (int32_t) (end - buf), 0);
291                 }
292         }
293 }
294
295 bool
296 GenericMidiControlProtocol::start_learning (Controllable* c)
297 {
298         if (c == 0) {
299                 return false;
300         }
301
302         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
303
304         MIDIControllables::iterator tmp;
305         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
306                 tmp = i;
307                 ++tmp;
308                 if ((*i)->get_controllable() == c) {
309                         delete (*i);
310                         controllables.erase (i);
311                 }
312                 i = tmp;
313         }
314
315         {
316                 Glib::Threads::Mutex::Lock lm (pending_lock);
317                 
318                 MIDIPendingControllables::iterator ptmp;
319                 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
320                         ptmp = i;
321                         ++ptmp;
322                         if (((*i)->first)->get_controllable() == c) {
323                                 (*i)->second.disconnect();
324                                 delete (*i)->first;
325                                 delete *i;
326                                 pending_controllables.erase (i);
327                         }
328                         i = ptmp;
329                 }
330         }
331
332         MIDIControllable* mc = 0;
333
334         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
335                 if ((*i)->get_controllable() && ((*i)->get_controllable()->id() == c->id())) {
336                         mc = *i;
337                         break;
338                 }
339         }
340
341         if (!mc) {
342                 mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
343         }
344         
345         {
346                 Glib::Threads::Mutex::Lock lm (pending_lock);
347
348                 MIDIPendingControllable* element = new MIDIPendingControllable;
349                 element->first = mc;
350                 c->LearningFinished.connect_same_thread (element->second, boost::bind (&GenericMidiControlProtocol::learning_stopped, this, mc));
351
352                 pending_controllables.push_back (element);
353         }
354
355         mc->learn_about_external_control ();
356         return true;
357 }
358
359 void
360 GenericMidiControlProtocol::learning_stopped (MIDIControllable* mc)
361 {
362         Glib::Threads::Mutex::Lock lm (pending_lock);
363         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
364         
365         MIDIPendingControllables::iterator tmp;
366
367         for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
368                 tmp = i;
369                 ++tmp;
370
371                 if ( (*i)->first == mc) {
372                         (*i)->second.disconnect();
373                         delete *i;
374                         pending_controllables.erase(i);
375                 }
376
377                 i = tmp;
378         }
379
380         controllables.push_back (mc);
381 }
382
383 void
384 GenericMidiControlProtocol::stop_learning (Controllable* c)
385 {
386         Glib::Threads::Mutex::Lock lm (pending_lock);
387         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
388         MIDIControllable* dptr = 0;
389
390         /* learning timed out, and we've been told to consider this attempt to learn to be cancelled. find the
391            relevant MIDIControllable and remove it from the pending list.
392         */
393
394         for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
395                 if (((*i)->first)->get_controllable() == c) {
396                         (*i)->first->stop_learning ();
397                         dptr = (*i)->first;
398                         (*i)->second.disconnect();
399
400                         delete *i;
401                         pending_controllables.erase (i);
402                         break;
403                 }
404         }
405         
406         delete dptr;
407 }
408
409 void
410 GenericMidiControlProtocol::delete_binding (PBD::Controllable* control)
411 {
412         if (control != 0) {
413                 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
414                 
415                 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
416                         MIDIControllable* existingBinding = (*iter);
417                         
418                         if (control == (existingBinding->get_controllable())) {
419                                 delete existingBinding;
420                                 iter = controllables.erase (iter);
421                         } else {
422                                 ++iter;
423                         }
424                         
425                 }
426         }
427 }
428
429 void
430 GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, int control_number)
431 {
432         if (control != NULL) {
433                 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
434                 
435                 MIDI::channel_t channel = (pos & 0xf);
436                 MIDI::byte value = control_number;
437                 
438                 // Create a MIDIControllable
439                 MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *control, false);
440
441                 // Remove any old binding for this midi channel/type/value pair
442                 // Note:  can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
443                 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
444                         MIDIControllable* existingBinding = (*iter);
445                         
446                         if ((existingBinding->get_control_channel() & 0xf ) == channel &&
447                             existingBinding->get_control_additional() == value &&
448                             (existingBinding->get_control_type() & 0xf0 ) == MIDI::controller) {
449                                 
450                                 delete existingBinding;
451                                 iter = controllables.erase (iter);
452                         } else {
453                                 ++iter;
454                         }
455                         
456                 }
457                 
458                 // Update the MIDI Controllable based on the the pos param
459                 // Here is where a table lookup for user mappings could go; for now we'll just wing it...
460                 mc->bind_midi(channel, MIDI::controller, value);
461
462                 controllables.push_back (mc);
463         }
464 }
465
466 XMLNode&
467 GenericMidiControlProtocol::get_state () 
468 {
469         XMLNode* node = new XMLNode ("Protocol"); 
470         char buf[32];
471
472         node->add_property (X_("name"), _name);
473         node->add_property (X_("feedback"), do_feedback ? "1" : "0");
474         snprintf (buf, sizeof (buf), "%" PRIu64, _feedback_interval);
475         node->add_property (X_("feedback_interval"), buf);
476         snprintf (buf, sizeof (buf), "%d", _threshold);
477         node->add_property (X_("threshold"), buf);
478
479         if (!_current_binding.empty()) {
480                 node->add_property ("binding", _current_binding);
481         }
482
483         XMLNode* children = new XMLNode (X_("Controls"));
484
485         node->add_child_nocopy (*children);
486
487         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
488         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
489
490                 /* we don't care about bindings that come from a bindings map, because
491                    they will all be reset/recreated when we load the relevant bindings
492                    file.
493                 */
494
495                 if ((*i)->get_controllable() && (*i)->learned()) {
496                         children->add_child_nocopy ((*i)->get_state());
497                 }
498         }
499
500         return *node;
501 }
502
503 int
504 GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
505 {
506         XMLNodeList nlist;
507         XMLNodeConstIterator niter;
508         const XMLProperty* prop;
509
510         if ((prop = node.property ("feedback")) != 0) {
511                 do_feedback = (bool) atoi (prop->value().c_str());
512         } else {
513                 do_feedback = false;
514         }
515
516         if ((prop = node.property ("feedback_interval")) != 0) {
517                 if (sscanf (prop->value().c_str(), "%" PRIu64, &_feedback_interval) != 1) {
518                         _feedback_interval = 10000;
519                 }
520         } else {
521                 _feedback_interval = 10000;
522         }
523
524         if ((prop = node.property ("threshold")) != 0) {
525                 if (sscanf (prop->value().c_str(), "%d", &_threshold) != 1) {
526                         _threshold = 10;
527                 }
528         } else {
529                 _threshold = 10;
530         }
531
532         boost::shared_ptr<Controllable> c;
533         
534         {
535                 Glib::Threads::Mutex::Lock lm (pending_lock);
536                 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
537                         delete *i;
538                 }
539                 pending_controllables.clear ();
540         }
541
542         /* Load up specific bindings from the
543          * <Controls><MidiControllable>...</MidiControllable><Controls> section
544          */
545
546         {
547                 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
548                 controllables.clear ();
549                 nlist = node.children(); // "Controls"
550
551                 if (!nlist.empty()) {
552                         nlist = nlist.front()->children(); // "MIDIControllable" ...
553
554                         if (!nlist.empty()) {
555                                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
556                                         
557                                         if ((prop = (*niter)->property ("id")) != 0) {
558                                                 
559                                                 ID id = prop->value ();
560                                                 Controllable* c = Controllable::by_id (id);
561                                                 
562                                                 if (c) {
563                                                         MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
564                                                         
565                                                         if (mc->set_state (**niter, version) == 0) {
566                                                                 controllables.push_back (mc);
567                                                         }
568                                                         
569                                                 } else {
570                                                         warning << string_compose (
571                                                                 _("Generic MIDI control: controllable %1 not found in session (ignored)"),
572                                                                 id) << endmsg;
573                                                 }
574                                         }
575                                 }
576                         }
577                 }
578         }
579
580         if ((prop = node.property ("binding")) != 0) {
581                 for (list<MapInfo>::iterator x = map_info.begin(); x != map_info.end(); ++x) {
582                         if (prop->value() == (*x).name) {
583                                 load_bindings ((*x).path);
584                                 break;
585                         }
586                 }
587         }
588
589         return 0;
590 }
591
592 int
593 GenericMidiControlProtocol::set_feedback (bool yn)
594 {
595         do_feedback = yn;
596         last_feedback_time = 0;
597         return 0;
598 }
599
600 bool
601 GenericMidiControlProtocol::get_feedback () const
602 {
603         return do_feedback;
604 }
605
606 int
607 GenericMidiControlProtocol::load_bindings (const string& xmlpath)
608 {
609         XMLTree state_tree;
610
611         if (!state_tree.read (xmlpath.c_str())) {
612                 error << string_compose(_("Could not understand MIDI bindings file %1"), xmlpath) << endmsg;
613                 return -1;
614         }
615
616         XMLNode* root = state_tree.root();
617
618         if (root->name() != X_("ArdourMIDIBindings")) {
619                 error << string_compose (_("MIDI Bindings file %1 is not really a MIDI bindings file"), xmlpath) << endmsg;
620                 return -1;
621         }
622
623         const XMLProperty* prop;
624
625         if ((prop = root->property ("version")) == 0) {
626                 return -1;
627         } else {
628                 int major;
629                 int minor;
630                 int micro;
631
632                 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, &micro);
633                 Stateful::loading_state_version = (major * 1000) + minor;
634         }
635         
636         const XMLNodeList& children (root->children());
637         XMLNodeConstIterator citer;
638         XMLNodeConstIterator gciter;
639
640         MIDIControllable* mc;
641
642         drop_all ();
643
644         for (citer = children.begin(); citer != children.end(); ++citer) {
645                 
646                 if ((*citer)->name() == "DeviceInfo") {
647                         const XMLProperty* prop;
648
649                         if ((prop = (*citer)->property ("bank-size")) != 0) {
650                                 _bank_size = atoi (prop->value());
651                                 _current_bank = 0;
652                         }
653
654                         if ((prop = (*citer)->property ("motorised")) != 0 || ((prop = (*citer)->property ("motorized")) != 0)) {
655                                 _motorised = string_is_affirmative (prop->value ());
656                         } else {
657                                 _motorised = false;
658                         }
659
660                         if ((prop = (*citer)->property ("threshold")) != 0) {
661                                 _threshold = atoi (prop->value ());
662                         } else {
663                                 _threshold = 10;
664                         }
665
666                 }
667
668                 if ((*citer)->name() == "Binding") {
669                         const XMLNode* child = *citer;
670
671                         if (child->property ("uri")) {
672                                 /* controllable */
673                                 
674                                 if ((mc = create_binding (*child)) != 0) {
675                                         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
676                                         controllables.push_back (mc);
677                                 }
678
679                         } else if (child->property ("function")) {
680
681                                 /* function */
682                                 MIDIFunction* mf;
683
684                                 if ((mf = create_function (*child)) != 0) {
685                                         functions.push_back (mf);
686                                 }
687
688                         } else if (child->property ("action")) {
689                                 MIDIAction* ma;
690
691                                 if ((ma = create_action (*child)) != 0) {
692                                         actions.push_back (ma);
693                                 }
694                         }
695                 }
696         }
697         
698         if ((prop = root->property ("name")) != 0) {
699                 _current_binding = prop->value ();
700         }
701
702         reset_controllables ();
703
704         return 0;
705 }
706
707 MIDIControllable*
708 GenericMidiControlProtocol::create_binding (const XMLNode& node)
709 {
710         const XMLProperty* prop;
711         MIDI::byte detail;
712         MIDI::channel_t channel;
713         string uri;
714         MIDI::eventType ev;
715         int intval;
716         bool momentary;
717
718         if ((prop = node.property (X_("ctl"))) != 0) {
719                 ev = MIDI::controller;
720         } else if ((prop = node.property (X_("note"))) != 0) {
721                 ev = MIDI::on;
722         } else if ((prop = node.property (X_("pgm"))) != 0) {
723                 ev = MIDI::program;
724         } else if ((prop = node.property (X_("pb"))) != 0) {
725                 ev = MIDI::pitchbend;
726         } else {
727                 return 0;
728         }
729         
730         if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
731                 return 0;
732         }
733         
734         detail = (MIDI::byte) intval;
735
736         if ((prop = node.property (X_("channel"))) == 0) {
737                 return 0;
738         }
739         
740         if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
741                 return 0;
742         }
743         channel = (MIDI::channel_t) intval;
744         /* adjust channel to zero-based counting */
745         if (channel > 0) {
746                 channel -= 1;
747         }
748
749         if ((prop = node.property (X_("momentary"))) != 0) {
750                 momentary = string_is_affirmative (prop->value());
751         } else {
752                 momentary = false;
753         }
754         
755         prop = node.property (X_("uri"));
756         uri = prop->value();
757
758         MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), momentary);
759
760         if (mc->init (uri)) {
761                 delete mc;
762                 return 0;
763         }
764
765         mc->bind_midi (channel, ev, detail);
766
767         return mc;
768 }
769
770 void
771 GenericMidiControlProtocol::reset_controllables ()
772 {
773         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
774
775         for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ) {
776                 MIDIControllable* existingBinding = (*iter);
777                 MIDIControllables::iterator next = iter;
778                 ++next;
779
780                 if (!existingBinding->learned()) {
781                         ControllableDescriptor& desc (existingBinding->descriptor());
782
783                         if (desc.banked()) {
784                                 desc.set_bank_offset (_current_bank * _bank_size);
785                         }
786
787                         /* its entirely possible that the session doesn't have
788                          * the specified controllable (e.g. it has too few
789                          * tracks). if we find this to be the case, we just leave
790                          * the binding around, unbound, and it will do "late
791                          * binding" (or "lazy binding") if/when any data arrives.
792                          */
793
794                         existingBinding->lookup_controllable ();
795                 }
796
797                 iter = next;
798         }
799 }
800
801 boost::shared_ptr<Controllable>
802 GenericMidiControlProtocol::lookup_controllable (const ControllableDescriptor& desc) const
803 {
804         return session->controllable_by_descriptor (desc);
805 }
806
807 MIDIFunction*
808 GenericMidiControlProtocol::create_function (const XMLNode& node)
809 {
810         const XMLProperty* prop;
811         int intval;
812         MIDI::byte detail = 0;
813         MIDI::channel_t channel = 0;
814         string uri;
815         MIDI::eventType ev;
816         MIDI::byte* data = 0;
817         uint32_t data_size = 0;
818         string argument;
819
820         if ((prop = node.property (X_("ctl"))) != 0) {
821                 ev = MIDI::controller;
822         } else if ((prop = node.property (X_("note"))) != 0) {
823                 ev = MIDI::on;
824         } else if ((prop = node.property (X_("pgm"))) != 0) {
825                 ev = MIDI::program;
826         } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
827
828                 if (prop->name() == X_("sysex")) {
829                         ev = MIDI::sysex;
830                 } else {
831                         ev = MIDI::any;
832                 }
833
834                 int val;
835                 uint32_t cnt;
836
837                 {
838                         cnt = 0;
839                         stringstream ss (prop->value());
840                         ss << hex;
841                         
842                         while (ss >> val) {
843                                 cnt++;
844                         }
845                 }
846
847                 if (cnt == 0) {
848                         return 0;
849                 }
850
851                 data = new MIDI::byte[cnt];
852                 data_size = cnt;
853                 
854                 {
855                         stringstream ss (prop->value());
856                         ss << hex;
857                         cnt = 0;
858                         
859                         while (ss >> val) {
860                                 data[cnt++] = (MIDI::byte) val;
861                         }
862                 }
863
864         } else {
865                 warning << "Binding ignored - unknown type" << endmsg;
866                 return 0;
867         }
868
869         if (data_size == 0) {
870                 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
871                         return 0;
872                 }
873                 
874                 detail = (MIDI::byte) intval;
875
876                 if ((prop = node.property (X_("channel"))) == 0) {
877                         return 0;
878                 }
879         
880                 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
881                         return 0;
882                 }
883                 channel = (MIDI::channel_t) intval;
884                 /* adjust channel to zero-based counting */
885                 if (channel > 0) {
886                         channel -= 1;
887                 }
888         }
889
890         if ((prop = node.property (X_("arg"))) != 0 || (prop = node.property (X_("argument"))) != 0 || (prop = node.property (X_("arguments"))) != 0) {
891                 argument = prop->value ();
892         }
893
894         prop = node.property (X_("function"));
895         
896         MIDIFunction* mf = new MIDIFunction (*_input_port->parser());
897         
898         if (mf->setup (*this, prop->value(), argument, data, data_size)) {
899                 delete mf;
900                 return 0;
901         }
902
903         mf->bind_midi (channel, ev, detail);
904
905         return mf;
906 }
907
908 MIDIAction*
909 GenericMidiControlProtocol::create_action (const XMLNode& node)
910 {
911         const XMLProperty* prop;
912         int intval;
913         MIDI::byte detail = 0;
914         MIDI::channel_t channel = 0;
915         string uri;
916         MIDI::eventType ev;
917         MIDI::byte* data = 0;
918         uint32_t data_size = 0;
919
920         if ((prop = node.property (X_("ctl"))) != 0) {
921                 ev = MIDI::controller;
922         } else if ((prop = node.property (X_("note"))) != 0) {
923                 ev = MIDI::on;
924         } else if ((prop = node.property (X_("pgm"))) != 0) {
925                 ev = MIDI::program;
926         } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
927
928                 if (prop->name() == X_("sysex")) {
929                         ev = MIDI::sysex;
930                 } else {
931                         ev = MIDI::any;
932                 }
933
934                 int val;
935                 uint32_t cnt;
936
937                 {
938                         cnt = 0;
939                         stringstream ss (prop->value());
940                         ss << hex;
941                         
942                         while (ss >> val) {
943                                 cnt++;
944                         }
945                 }
946
947                 if (cnt == 0) {
948                         return 0;
949                 }
950
951                 data = new MIDI::byte[cnt];
952                 data_size = cnt;
953                 
954                 {
955                         stringstream ss (prop->value());
956                         ss << hex;
957                         cnt = 0;
958                         
959                         while (ss >> val) {
960                                 data[cnt++] = (MIDI::byte) val;
961                         }
962                 }
963
964         } else {
965                 warning << "Binding ignored - unknown type" << endmsg;
966                 return 0;
967         }
968
969         if (data_size == 0) {
970                 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
971                         return 0;
972                 }
973                 
974                 detail = (MIDI::byte) intval;
975
976                 if ((prop = node.property (X_("channel"))) == 0) {
977                         return 0;
978                 }
979         
980                 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
981                         return 0;
982                 }
983                 channel = (MIDI::channel_t) intval;
984                 /* adjust channel to zero-based counting */
985                 if (channel > 0) {
986                         channel -= 1;
987                 }
988         }
989
990         prop = node.property (X_("action"));
991         
992         MIDIAction* ma = new MIDIAction (*_input_port->parser());
993         
994         if (ma->init (*this, prop->value(), data, data_size)) {
995                 delete ma;
996                 return 0;
997         }
998
999         ma->bind_midi (channel, ev, detail);
1000
1001         return ma;
1002 }
1003
1004 void
1005 GenericMidiControlProtocol::set_current_bank (uint32_t b)
1006 {
1007         _current_bank = b;
1008         reset_controllables ();
1009 }
1010
1011 void
1012 GenericMidiControlProtocol::next_bank ()
1013 {
1014         _current_bank++;
1015         reset_controllables ();
1016 }
1017
1018 void
1019 GenericMidiControlProtocol::prev_bank()
1020 {
1021         if (_current_bank) {
1022                 _current_bank--;
1023                 reset_controllables ();
1024         }
1025 }
1026
1027 void
1028 GenericMidiControlProtocol::set_motorised (bool m)
1029 {
1030         _motorised = m;
1031 }
1032
1033 void
1034 GenericMidiControlProtocol::set_threshold (int t)
1035 {
1036         _threshold = t;
1037 }