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