ActionManager::get_all_actions() no longer includes <Actions> in the paths it returns...
[ardour.git] / libs / surfaces / us2400 / surface.cc
1 /*
2     Copyright (C) 2012 Paul Davis
3         Copyright (C) 2017 Ben Loftis
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #include <sstream>
22 #include <iomanip>
23 #include <iostream>
24 #include <cstdio>
25 #include <cmath>
26
27 #include <glibmm/convert.h>
28
29 #include "pbd/stacktrace.h"
30
31 #include "midi++/port.h"
32
33 #include "ardour/audioengine.h"
34 #include "ardour/automation_control.h"
35 #include "ardour/debug.h"
36 #include "ardour/route.h"
37 #include "ardour/panner.h"
38 #include "ardour/panner_shell.h"
39 #include "ardour/profile.h"
40 #include "ardour/rc_configuration.h"
41 #include "ardour/session.h"
42 #include "ardour/utils.h"
43
44 #include <gtkmm2ext/gui_thread.h>
45
46 #include "control_group.h"
47 #include "surface_port.h"
48 #include "surface.h"
49 #include "strip.h"
50 #include "us2400_control_protocol.h"
51 #include "jog_wheel.h"
52
53 #include "strip.h"
54 #include "button.h"
55 #include "led.h"
56 #include "pot.h"
57 #include "fader.h"
58 #include "jog.h"
59 #include "meter.h"
60
61 #include "pbd/i18n.h"
62
63 #ifdef PLATFORM_WINDOWS
64 #define random() rand()
65 #endif
66
67 using namespace std;
68 using namespace PBD;
69 using ARDOUR::Stripable;
70 using ARDOUR::Panner;
71 using ARDOUR::Profile;
72 using ARDOUR::AutomationControl;
73 using namespace ArdourSurface;
74 using namespace US2400;
75
76 #define ui_context() US2400Protocol::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
77
78 // The MCU sysex header.4th byte Will be overwritten
79 // when we get an incoming sysex that identifies
80 // the device type
81 static MidiByteArray mackie_sysex_hdr  (5, MIDI::sysex, 0x0, 0x0, 0x66, 0x14);
82
83 // The MCU extender sysex header.4th byte Will be overwritten
84 // when we get an incoming sysex that identifies
85 // the device type
86 static MidiByteArray mackie_sysex_hdr_xt  (5, MIDI::sysex, 0x0, 0x0, 0x66, 0x15);
87
88 static MidiByteArray empty_midi_byte_array;
89
90 Surface::Surface (US2400Protocol& mcp, const std::string& device_name, uint32_t number, surface_type_t stype)
91         : _mcp (mcp)
92         , _stype (stype)
93         , _number (number)
94         , _name (device_name)
95         , _active (false)
96         , _connected (false)
97         , _jog_wheel (0)
98         , _master_fader (0)
99         , _last_master_gain_written (-0.0f)
100         , _joystick_active (false)
101         , connection_state (0)
102         , input_source (0)
103 {
104         DEBUG_TRACE (DEBUG::US2400, "Surface::Surface init\n");
105
106         try {
107                 _port = new SurfacePort (*this);
108         } catch (...) {
109                 throw failed_constructor ();
110         }
111
112         /* only the first Surface object has global controls */
113         /* lets use master_position instead */
114         uint32_t mp = _mcp.device_info().master_position();
115         if (_number == mp) {
116                 DEBUG_TRACE (DEBUG::US2400, "Surface matches MasterPosition. Might have global controls.\n");
117                 if (_mcp.device_info().has_global_controls()) {
118                         init_controls ();
119                         DEBUG_TRACE (DEBUG::US2400, "init_controls done\n");
120                 }
121
122                 if (_mcp.device_info().has_master_fader()) {
123                         setup_master ();
124                         DEBUG_TRACE (DEBUG::US2400, "setup_master done\n");
125                 }
126         }
127
128         uint32_t n = _mcp.device_info().strip_cnt();
129
130         if (n) {
131                 init_strips (n);
132                 DEBUG_TRACE (DEBUG::US2400, "init_strips done\n");
133         }
134
135         connect_to_signals ();
136
137         DEBUG_TRACE (DEBUG::US2400, "Surface::Surface done\n");
138 }
139
140 Surface::~Surface ()
141 {
142         DEBUG_TRACE (DEBUG::US2400, "Surface::~Surface init\n");
143
144         if (input_source) {
145                 g_source_destroy (input_source);
146                 input_source = 0;
147         }
148
149         // delete groups (strips)
150         for (Groups::iterator it = groups.begin(); it != groups.end(); ++it) {
151                 delete it->second;
152         }
153
154         // delete controls (global buttons, master fader etc)
155         for (Controls::iterator it = controls.begin(); it != controls.end(); ++it) {
156                 delete *it;
157         }
158
159         delete _jog_wheel;
160         delete _port;
161         // the ports take time to release and we may be rebuilding right away
162         // in the case of changing devices.
163         g_usleep (10000);
164         DEBUG_TRACE (DEBUG::US2400, "Surface::~Surface done\n");
165 }
166
167 bool
168 Surface::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn)
169 {
170         if (!_port) {
171                 return false;
172         }
173
174         string ni = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (_port->input_name());
175         string no = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (_port->output_name());
176
177         if (ni == name1 || ni == name2) {
178                 if (yn) {
179                         connection_state |= InputConnected;
180                 } else {
181                         connection_state &= ~InputConnected;
182                 }
183         } else if (no == name1 || no == name2) {
184                 if (yn) {
185                         connection_state |= OutputConnected;
186                 } else {
187                         connection_state &= ~OutputConnected;
188                 }
189         } else {
190                 /* not our ports */
191                 return false;
192         }
193
194         if ((connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) {
195
196                 /* this will send a device query message, which should
197                    result in a response that will kick off device type
198                    discovery and activation of the surface(s).
199
200                    The intended order of events is:
201
202                    - each surface sends a device query message
203                    - devices respond with either MCP or LCP response (sysex in both
204                    cases)
205                    - sysex message causes Surface::turn_it_on() which tells the
206                    MCP object that the surface is ready, and sets up strip
207                    displays and binds faders and buttons for that surface
208
209                    In the case of LCP, where this is a handshake process that could
210                    fail, the response process to the initial sysex after a device query
211                    will mark the surface inactive, which won't shut anything down
212                    but will stop any writes to the device.
213
214                    Note: there are no known cases of the handshake process failing.
215
216                    We actually can't initiate this in this callback, so we have
217                    to queue it with the MCP event loop.
218                 */
219
220                 /* XXX this is a horrible hack. Without a short sleep here,
221                    something prevents the device wakeup messages from being
222                    sent and/or the responses from being received.
223                 */
224
225                 g_usleep (100000);
226                 connected ();
227
228         } else {
229                 DEBUG_TRACE (DEBUG::US2400, string_compose ("Surface %1 disconnected (input or output or both)\n", _name));
230                 _active = false;
231         }
232
233         return true; /* connection status changed */
234 }
235
236 XMLNode&
237 Surface::get_state()
238 {
239         XMLNode* node = new XMLNode (X_("Surface"));
240         node->set_property (X_("name"), _name);
241         node->add_child_nocopy (_port->get_state());
242         return *node;
243 }
244
245 int
246 Surface::set_state (const XMLNode& node, int version)
247 {
248         /* Look for a node named after the device we're part of */
249
250         XMLNodeList const& children = node.children();
251         XMLNode* mynode = 0;
252
253         for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
254                 std::string name;
255                 if ((*c)->get_property (X_("name"), name) && name == _name) {
256                         mynode = *c;
257                         break;
258                 }
259         }
260
261         if (!mynode) {
262                 return 0;
263         }
264
265         XMLNode* portnode = mynode->child (X_("Port"));
266         if (portnode) {
267                 if (_port->set_state (*portnode, version)) {
268                         return -1;
269                 }
270         }
271
272         return 0;
273 }
274
275 const MidiByteArray&
276 Surface::sysex_hdr() const
277 {
278         switch  (_stype) {
279         case st_mcu: return mackie_sysex_hdr;
280         case st_ext: return mackie_sysex_hdr_xt;
281         default: return mackie_sysex_hdr_xt;
282         }
283         cout << "SurfacePort::sysex_hdr _port_type not known" << endl;
284         return mackie_sysex_hdr;
285 }
286
287 static GlobalControlDefinition mackie_global_controls[] = {
288         { "external", Pot::External, Pot::factory, "none" },
289         { "fader_touch", Led::FaderTouch, Led::factory, "master" },
290         { "timecode", Led::Timecode, Led::factory, "none" },
291         { "beats", Led::Beats, Led::factory, "none" },
292         { "solo", Led::RudeSolo, Led::factory, "none" },
293         { "relay_click", Led::RelayClick, Led::factory, "none" },
294         { "", 0, Led::factory, "" }
295 };
296
297 void
298 Surface::init_controls()
299 {
300         Group* group;
301
302         DEBUG_TRACE (DEBUG::US2400, "Surface::init_controls: creating groups\n");
303         groups["assignment"] = new Group  ("assignment");
304         groups["automation"] = new Group  ("automation");
305         groups["bank"] = new Group  ("bank");
306         groups["cursor"] = new Group  ("cursor");
307         groups["display"] = new Group  ("display");
308         groups["function select"] = new Group  ("function select");
309         groups["global view"] = new Group ("global view");
310         groups["master"] = new Group ("master");
311         groups["modifiers"] = new Group  ("modifiers");
312         groups["none"] = new Group  ("none");
313         groups["transport"] = new Group  ("transport");
314         groups["user"] = new Group  ("user");
315         groups["utilities"] = new Group  ("utilities");
316
317         DEBUG_TRACE (DEBUG::US2400, "Surface::init_controls: creating jog wheel\n");
318         if (_mcp.device_info().has_jog_wheel()) {
319                 _jog_wheel = new US2400::JogWheel (_mcp);
320         }
321
322         DEBUG_TRACE (DEBUG::US2400, "Surface::init_controls: creating global controls\n");
323         for (uint32_t n = 0; mackie_global_controls[n].name[0]; ++n) {
324                 group = groups[mackie_global_controls[n].group_name];
325                 Control* control = mackie_global_controls[n].factory (*this, mackie_global_controls[n].id, mackie_global_controls[n].name, *group);
326                 controls_by_device_independent_id[mackie_global_controls[n].id] = control;
327         }
328
329         /* add global buttons */
330         DEBUG_TRACE (DEBUG::US2400, "Surface::init_controls: adding global buttons\n");
331         const map<Button::ID,GlobalButtonInfo>& global_buttons (_mcp.device_info().global_buttons());
332
333         for (map<Button::ID,GlobalButtonInfo>::const_iterator b = global_buttons.begin(); b != global_buttons.end(); ++b){
334                 group = groups[b->second.group];
335                 controls_by_device_independent_id[b->first] = Button::factory (*this, b->first, b->second.id, b->second.label, *group);
336         }
337 }
338
339 void
340 Surface::init_strips (uint32_t n)
341 {
342         const map<Button::ID,StripButtonInfo>& strip_buttons (_mcp.device_info().strip_buttons());
343
344         //surface 4  has no strips
345         if ((_stype != st_mcu) && (_stype != st_ext))
346                 return;
347         
348         for (uint32_t i = 0; i < n; ++i) {
349
350                 char name[32];
351
352                 snprintf (name, sizeof (name), "strip_%d", (8* _number) + i);
353
354                 Strip* strip = new Strip (*this, name, i, strip_buttons);
355
356                 strip->set_global_index (_number*n + i);
357
358                 groups[name] = strip;
359                 strips.push_back (strip);
360         }
361 }
362
363 void
364 Surface::master_monitor_may_have_changed ()
365 {
366         if (_number == _mcp.device_info().master_position()) {
367                 setup_master ();
368         }
369 }
370
371 void
372 Surface::setup_master ()
373 {
374         boost::shared_ptr<Stripable> m;
375
376         if ((m = _mcp.get_session().monitor_out()) == 0) {
377                 m = _mcp.get_session().master_out();
378         }
379
380         if (!m) {
381                 if (_master_fader) {
382                         _master_fader->reset_control ();
383                 }
384                 master_connection.disconnect ();
385                 return;
386         }
387
388         if (!_master_fader) {
389                 Groups::iterator group_it;
390                 Group* master_group;
391                 group_it = groups.find("master");
392
393                 if (group_it == groups.end()) {
394                         groups["master"] = master_group = new Group ("master");
395                 } else {
396                         master_group = group_it->second;
397                 }
398
399                 _master_fader = dynamic_cast<Fader*> (Fader::factory (*this, _mcp.device_info().strip_cnt(), "master", *master_group));
400
401                 DeviceInfo device_info = _mcp.device_info();
402                 GlobalButtonInfo master_button = device_info.get_global_button(Button::MasterFaderTouch);
403                 Button* bb = dynamic_cast<Button*> (Button::factory (
404                                                     *this,
405                                                     Button::MasterFaderTouch,
406                                                     master_button.id,
407                                                     master_button.label,
408                                                     *(group_it->second)
409                                                     ));
410
411                 DEBUG_TRACE (DEBUG::US2400, string_compose ("surface %1 Master Fader new button BID %2 id %3\n",
412                                                                    number(), Button::MasterFaderTouch, bb->id()));
413         } else {
414                 master_connection.disconnect ();
415         }
416
417         _master_fader->set_control (m->gain_control());
418         m->gain_control()->Changed.connect (master_connection, MISSING_INVALIDATOR, boost::bind (&Surface::master_gain_changed, this), ui_context());
419         _last_master_gain_written = FLT_MAX; /* some essentially impossible value */
420         _port->write (_master_fader->set_position (0.0));
421         master_gain_changed ();
422 }
423
424 void
425 Surface::master_gain_changed ()
426 {
427         if (!_master_fader) {
428                 return;
429         }
430
431         boost::shared_ptr<AutomationControl> ac = _master_fader->control();
432         if (!ac) {
433                 return;
434         }
435
436         float normalized_position = ac->internal_to_interface (ac->get_value());
437         if (normalized_position == _last_master_gain_written) {
438                 return;
439         }
440
441         DEBUG_TRACE (DEBUG::US2400, "Surface::master_gain_changed: updating surface master fader\n");
442
443         _port->write (_master_fader->set_position (normalized_position));
444         _last_master_gain_written = normalized_position;
445 }
446
447 float
448 Surface::scaled_delta (float delta, float current_speed)
449 {
450         /* XXX needs work before use */
451         const float sign = delta < 0.0 ? -1.0 : 1.0;
452
453         return ((sign * std::pow (delta + 1.0, 2.0)) + current_speed) / 100.0;
454 }
455
456 void
457 Surface::blank_jog_ring ()
458 {
459 }
460
461 float
462 Surface::scrub_scaling_factor () const
463 {
464         return 100.0;
465 }
466
467 void
468 Surface::connect_to_signals ()
469 {
470         if (!_connected) {
471
472
473                 DEBUG_TRACE (DEBUG::US2400, string_compose ("Surface %1 connecting to signals on port %2\n",
474                                                                    number(), _port->input_port().name()));
475
476                 MIDI::Parser* p = _port->input_port().parser();
477
478                 /* Incoming sysex */
479                 p->sysex.connect_same_thread (*this, boost::bind (&Surface::handle_midi_sysex, this, _1, _2, _3));
480                 /* V-Pot messages are Controller */
481                 p->controller.connect_same_thread (*this, boost::bind (&Surface::handle_midi_controller_message, this, _1, _2));
482                 /* Button messages are NoteOn */
483                 p->note_on.connect_same_thread (*this, boost::bind (&Surface::handle_midi_note_on_message, this, _1, _2));
484                 /* Button messages are NoteOn but libmidi++ sends note-on w/velocity = 0 as note-off so catch them too */
485                 p->note_off.connect_same_thread (*this, boost::bind (&Surface::handle_midi_note_on_message, this, _1, _2));
486                 /* Fader messages are Pitchbend */
487                 uint32_t i;
488                 for (i = 0; i < _mcp.device_info().strip_cnt(); i++) {
489                         p->channel_pitchbend[i].connect_same_thread (*this, boost::bind (&Surface::handle_midi_pitchbend_message, this, _1, _2, i));
490                 }
491                 // Master fader
492                 p->channel_pitchbend[_mcp.device_info().strip_cnt()].connect_same_thread (*this, boost::bind (&Surface::handle_midi_pitchbend_message, this, _1, _2, _mcp.device_info().strip_cnt()));
493
494                 _connected = true;
495         }
496 }
497
498 void
499 Surface::handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t pb, uint32_t fader_id)
500 {
501         /* Pitchbend messages are fader position messages. Nothing in the data we get
502          * from the MIDI::Parser conveys the fader ID, which was given by the
503          * channel ID in the status byte.
504          *
505          * Instead, we have used bind() to supply the fader-within-strip ID
506          * when we connected to the per-channel pitchbend events.
507          */
508
509         DEBUG_TRACE (DEBUG::US2400, string_compose ("Surface::handle_midi_pitchbend_message on port %3, fader = %1 value = %2 (%4)\n",
510                                                            fader_id, pb, _number, pb/16384.0));
511
512         turn_it_on ();
513
514         Fader* fader = faders[fader_id];
515
516         if (fader) {
517                 Strip* strip = dynamic_cast<Strip*> (&fader->group());
518                 float pos = pb / 16384.0;
519                 if (strip) {
520                         strip->handle_fader (*fader, pos);
521                 } else {
522                         DEBUG_TRACE (DEBUG::US2400, "Handling master fader\n");
523                         /* master fader */
524                         fader->set_value (pos); // alter master gain
525                         _port->write (fader->set_position (pos)); // write back value (required for servo)
526                 }
527         } else {
528                 DEBUG_TRACE (DEBUG::US2400, "fader not found\n");
529         }
530 }
531
532 void
533 Surface::handle_midi_note_on_message (MIDI::Parser &, MIDI::EventTwoBytes* ev)
534 {
535         DEBUG_TRACE (DEBUG::US2400, string_compose ("Surface::handle_midi_note_on_message %1 = %2\n", (int) ev->note_number, (int) ev->velocity));
536
537         turn_it_on ();
538
539         /* fader touch sense is given by "buttons" 0xe..0xe7 and 0xe8 for the
540          * master.
541          */
542
543         if (ev->note_number >= 0xE0 && ev->note_number <= 0xE8) {
544                 Fader* fader = faders[ev->note_number];
545
546                 DEBUG_TRACE (DEBUG::US2400, string_compose ("Surface: fader touch message, fader = %1\n", fader));
547
548                 if (fader) {
549
550                         Strip* strip = dynamic_cast<Strip*> (&fader->group());
551
552                         if (ev->velocity > 64) {
553                                 strip->handle_fader_touch (*fader, true);
554                         } else {
555                                 strip->handle_fader_touch (*fader, false);
556                         }
557                 }
558                 return;
559         }
560
561         Button* button = buttons[ev->note_number];
562
563         if (button) {
564
565                 if (ev->velocity > 64) {
566                         button->pressed ();
567                 }
568
569                 Strip* strip = dynamic_cast<Strip*> (&button->group());
570
571                 if (mcp().main_modifier_state() == US2400Protocol::MODIFIER_OPTION) {
572
573                         /* special case: CLR Solo looks like a strip's solo button, but with MODIFIER_OPTION it becomes global CLR SOLO */
574                         DEBUG_TRACE (DEBUG::US2400, string_compose ("HERE option global button %1\n", button->id()));
575                         _mcp.handle_button_event (*this, *button, ev->velocity > 64 ? press : release);
576
577                 } else if (strip) {
578                         DEBUG_TRACE (DEBUG::US2400, string_compose ("strip %1 button %2 pressed ? %3\n",
579                                                                            strip->index(), button->name(), (ev->velocity > 64)));
580                         strip->handle_button (*button, ev->velocity > 64 ? press : release);
581                 } else {
582                         /* global button */
583                         DEBUG_TRACE (DEBUG::US2400, string_compose ("global button %1\n", button->id()));
584                         _mcp.handle_button_event (*this, *button, ev->velocity > 64 ? press : release);
585                 }
586
587                 if (ev->velocity <= 64) {
588                         button->released ();
589                 }
590
591         } else {
592                 DEBUG_TRACE (DEBUG::US2400, string_compose ("no button found for %1\n", (int) ev->note_number));
593         }
594
595         /* button release should reset timer AFTER handler(s) have run */
596 }
597
598 void
599 Surface::handle_midi_controller_message (MIDI::Parser &, MIDI::EventTwoBytes* ev)
600 {
601         DEBUG_TRACE (DEBUG::US2400, string_compose ("SurfacePort::handle_midi_controller %1 = %2\n", (int) ev->controller_number, (int) ev->value));
602
603         turn_it_on ();
604
605         /* The joystick is not touch sensitive.
606          * ignore the joystick until the user clicks the "null" button.
607          * The joystick sends spurious controller messages,
608          * and since they are absolute values (joy position) this can send undesired changes. 
609          */
610         if (_stype == st_joy && ev->controller_number == 0x01) {
611                 _joystick_active = true;
612
613         /* Unfortunately the device does not appear to respond to the NULL button's LED,
614          * to indicate that the joystick is active.
615          */
616 #if 0 // this approach doesn't seem to work
617                 MidiByteArray joy_active (3, 0xB0, 0x01, 0x01);
618                 _port->write (joy_active);
619 #endif
620         }
621
622 #ifdef MIXBUS32C  //in 32C, we can use the joystick for the last 2 mixbus send level & pans
623
624         if (_stype == st_joy && _joystick_active) {
625                 if (ev->controller_number == 0x03) {
626                         float value = (float)ev->value / 127.0;
627                         float db_value = 20.0 * value;
628                         float inv_db = 20.0 - db_value; 
629                         boost::shared_ptr<Stripable> r = mcp().subview_stripable();
630                         if (r && r->is_input_strip()) {
631                                 boost::shared_ptr<AutomationControl> pc = r->send_level_controllable (10);
632                                 if (pc) {
633                                         pc->set_value (-db_value , PBD::Controllable::NoGroup);
634                                 }
635                                 pc = r->send_level_controllable (11);
636                                 if (pc) {
637                                         pc->set_value (-inv_db, PBD::Controllable::NoGroup);
638                                 }
639                         }
640                 }
641                 if (ev->controller_number == 0x02) {
642                         float value = (float)ev->value / 127.0;
643                         boost::shared_ptr<Stripable> r = mcp().subview_stripable();
644                         if (r && r->is_input_strip()) {
645                                 boost::shared_ptr<AutomationControl> pc = r->send_pan_azi_controllable (10);
646                                 if (pc) {
647                                         float v = pc->interface_to_internal(value);
648                                         pc->set_value (v, PBD::Controllable::NoGroup);
649                                 }
650                                 pc = r->send_pan_azi_controllable (11);
651                                 if (pc) {
652                                         float v = pc->interface_to_internal(value);
653                                         pc->set_value (v, PBD::Controllable::NoGroup);
654                                 }
655                         }
656                 }
657                 return;
658         }
659 #endif
660
661         Pot* pot = pots[ev->controller_number];
662
663         // bit 6 gives the sign
664         float sign = (ev->value & 0x40) == 0 ? 1.0 : -1.0;
665         // bits 0..5 give the velocity. we interpret this as "ticks
666         // moved before this message was sent"
667         float ticks = (ev->value & 0x3f);
668         if (ticks == 0) {
669                 /* euphonix and perhaps other devices send zero
670                    when they mean 1, we think.
671                 */
672                 ticks = 1;
673         }
674
675         float delta = 0;
676         if (mcp().main_modifier_state() == US2400Protocol::MODIFIER_SHIFT) {
677                 delta = sign * (ticks / (float) 0xff);
678         } else {
679                 delta = sign * (ticks / (float) 0x3f);
680         }
681
682         if (!pot) {
683                 if (ev->controller_number == Jog::ID && _jog_wheel) {
684
685                         DEBUG_TRACE (DEBUG::US2400, string_compose ("Jog wheel moved %1\n", ticks));
686                         _jog_wheel->jog_event (delta);
687                         return;
688                 }
689                 // add external (pedal?) control here
690
691                 return;
692         }
693
694         Strip* strip = dynamic_cast<Strip*> (&pot->group());
695         if (strip) {
696                 strip->handle_pot (*pot, delta);
697         }
698 }
699
700 void
701 Surface::handle_midi_sysex (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count)
702 {
703         MidiByteArray bytes (count, raw_bytes);
704
705         /* always save the device type ID so that our outgoing sysex messages
706          * are correct
707          */
708
709         if (_stype == st_mcu) {
710                 mackie_sysex_hdr[4] = bytes[4];
711         } else {
712                 mackie_sysex_hdr_xt[4] = bytes[4];
713         }
714
715         switch (bytes[5]) {
716         case 0x01:
717                 if (!_active) {
718                         DEBUG_TRACE (DEBUG::US2400, string_compose ("surface #%1,  handle_midi_sysex: %2\n", _number, bytes));
719                         DEBUG_TRACE (DEBUG::US2400, string_compose ("Mackie Control Device ready, current status = %1\n", _active));
720                         turn_it_on ();
721                 }
722                 break;
723
724         case 0x06:
725                 if (!_active) {
726                         DEBUG_TRACE (DEBUG::US2400, string_compose ("surface #%1,  handle_midi_sysex: %2\n", _number, bytes));
727                 }
728                 /* Behringer X-Touch Compact: Device Ready
729                 */
730                 DEBUG_TRACE (DEBUG::US2400, string_compose ("Behringer X-Touch Compact ready, current status = %1\n", _active));
731                 turn_it_on ();
732                 break;
733
734         case 0x03: /* LCP Connection Confirmation */
735                 DEBUG_TRACE (DEBUG::US2400, string_compose ("surface #%1,  handle_midi_sysex: %2\n", _number, bytes));
736                 DEBUG_TRACE (DEBUG::US2400, "Logic Control Device confirms connection, ardour replies\n");
737 //              if (bytes[4] == 0x10 || bytes[4] == 0x11) {
738 //                      write_sysex (host_connection_confirmation (bytes));                     turn_it_on ();
739                         turn_it_on ();
740 //              }
741                 break;
742
743 //      case 0x04: /* LCP: Confirmation Denied */
744 //              DEBUG_TRACE (DEBUG::US2400, string_compose ("surface #%1,  handle_midi_sysex: %2\n", _number, bytes));
745 //              DEBUG_TRACE (DEBUG::US2400, "Logic Control Device denies connection\n");
746 //              _active = false;
747 //              break;
748
749         default:
750                 DEBUG_TRACE (DEBUG::US2400, string_compose ("surface #%1,  handle_midi_sysex: %2\n", _number, bytes));
751 //              DEBUG_TRACE (DEBUG::US2400, string_compose ("unknown device ID byte %1", (int) bytes[5]));
752                 error << "MCP: unknown sysex: " << bytes << endmsg;
753         }
754 }
755
756 static MidiByteArray
757 calculate_challenge_response (MidiByteArray::iterator begin, MidiByteArray::iterator end)
758 {
759         MidiByteArray l;
760         back_insert_iterator<MidiByteArray> back  (l);
761         copy (begin, end, back);
762
763         MidiByteArray retval;
764
765         // this is how to calculate the response to the challenge.
766         // from the Logic docs.
767         retval <<  (0x7f &  (l[0] +  (l[1] ^ 0xa) - l[3]));
768         retval <<  (0x7f &  ((l[2] >> l[3]) ^  (l[0] + l[3])));
769         retval <<  (0x7f &  ((l[3] -  (l[2] << 2)) ^  (l[0] | l[1])));
770         retval <<  (0x7f &  (l[1] - l[2] +  (0xf0 ^  (l[3] << 4))));
771
772         return retval;
773 }
774
775 MidiByteArray
776 Surface::host_connection_query (MidiByteArray & bytes)
777 {
778         MidiByteArray response;
779
780         if (bytes[4] != 0x10 && bytes[4] != 0x11) {
781                 /* not a Logic Control device - no response required */
782                 return response;
783         }
784
785         // handle host connection query
786         DEBUG_TRACE (DEBUG::US2400, string_compose ("host connection query: %1\n", bytes));
787
788         if  (bytes.size() != 18) {
789                 cerr << "expecting 18 bytes, read " << bytes << " from " << _port->input_port().name() << endl;
790                 return response;
791         }
792
793         // build and send host connection reply
794         response << 0x02;
795         copy (bytes.begin() + 6, bytes.begin() + 6 + 7, back_inserter (response));
796         response << calculate_challenge_response (bytes.begin() + 6 + 7, bytes.begin() + 6 + 7 + 4);
797         return response;
798 }
799
800 MidiByteArray
801 Surface::host_connection_confirmation (const MidiByteArray & bytes)
802 {
803         DEBUG_TRACE (DEBUG::US2400, string_compose ("host_connection_confirmation: %1\n", bytes));
804
805         // decode host connection confirmation
806         if  (bytes.size() != 14) {
807                 ostringstream os;
808                 os << "expecting 14 bytes, read " << bytes << " from " << _port->input_port().name();
809                 throw MackieControlException (os.str());
810         }
811
812         // send version request
813         return MidiByteArray (2, 0x13, 0x00);
814 }
815
816 void
817 Surface::turn_it_on ()
818 {
819         if (_active) {
820                 return;
821         }
822
823         _active = true;
824
825         _mcp.device_ready ();  //this gets redundantly called with each new surface connection; but this is desirable to get the banks set up correctly
826
827         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
828                 (*s)->notify_all ();
829         }
830
831 }
832
833 void
834 Surface::write_sysex (const MidiByteArray & mba)
835 {
836         if (mba.empty()) {
837                 return;
838         }
839
840         MidiByteArray buf;
841         buf << sysex_hdr() << mba << MIDI::eox;
842         _port->write (buf);
843 }
844
845 void
846 Surface::write_sysex (MIDI::byte msg)
847 {
848         MidiByteArray buf;
849         buf << sysex_hdr() << msg << MIDI::eox;
850         _port->write (buf);
851 }
852
853 uint32_t
854 Surface::n_strips (bool with_locked_strips) const
855 {
856         if (with_locked_strips) {
857                 return strips.size();
858         }
859
860         uint32_t n = 0;
861
862         for (Strips::const_iterator it = strips.begin(); it != strips.end(); ++it) {
863                 if (!(*it)->locked()) {
864                         ++n;
865                 }
866         }
867         return n;
868 }
869
870 Strip*
871 Surface::nth_strip (uint32_t n) const
872 {
873         if (n > n_strips()) {
874                 return 0;
875         }
876         return strips[n];
877 }
878
879 void
880 Surface::zero_all ()
881 {
882         if (_mcp.device_info().has_master_fader () && _master_fader) {
883                 _port->write (_master_fader->zero ());
884         }
885
886         // zero all strips
887         for (Strips::iterator it = strips.begin(); it != strips.end(); ++it) {
888                 (*it)->zero();
889         }
890
891         zero_controls ();
892 }
893
894 void
895 Surface::zero_controls ()
896 {
897         if (!_mcp.device_info().has_global_controls()) {
898                 return;
899         }
900
901         // turn off global buttons and leds
902
903         for (Controls::iterator it = controls.begin(); it != controls.end(); ++it) {
904                 Control & control = **it;
905                 if (!control.group().is_strip()) {
906                         _port->write (control.zero());
907                 }
908         }
909
910         // and the led ring for the master strip
911         blank_jog_ring ();
912
913         _last_master_gain_written = 0.0f;
914 }
915
916 void
917 Surface::periodic (uint64_t now_usecs)
918 {
919         if (_active) {
920                 master_gain_changed();
921                 for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
922                         (*s)->periodic (now_usecs);
923                 }
924         }
925 }
926
927 void
928 Surface::redisplay (ARDOUR::microseconds_t now, bool force)
929 {
930         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
931                 (*s)->redisplay (now, force);
932         }
933 }
934
935 void
936 Surface::write (const MidiByteArray& data)
937 {
938         if (_active) {
939                 _port->write (data);
940         } else {
941                 DEBUG_TRACE (DEBUG::US2400, "surface not active, write ignored\n");
942         }
943 }
944
945 void
946 Surface::update_strip_selection ()
947 {
948         Strips::iterator s = strips.begin();
949         for ( ; s != strips.end(); ++s) {
950                 (*s)->update_selection_state();
951         }
952 }
953
954 void
955 Surface::map_stripables (const vector<boost::shared_ptr<Stripable> >& stripables)
956 {
957         vector<boost::shared_ptr<Stripable> >::const_iterator r;
958         Strips::iterator s = strips.begin();
959
960         DEBUG_TRACE (DEBUG::US2400, string_compose ("Mapping %1 stripables to %2 strips\n", stripables.size(), strips.size()));
961
962         for (r = stripables.begin(); r != stripables.end() && s != strips.end(); ++s) {
963
964                 /* don't try to assign stripables to a locked strip. it won't
965                    use it anyway, but if we do, then we get out of sync
966                    with the proposed mapping.
967                 */
968
969                 if (!(*s)->locked()) {
970                         DEBUG_TRACE (DEBUG::US2400, string_compose ("Mapping stripable \"%1\" to strip %2\n", (*r)->name(), (*s)->global_index()));
971                         (*s)->set_stripable (*r);
972                         ++r;
973                 }
974         }
975
976         for (; s != strips.end(); ++s) {
977                 DEBUG_TRACE (DEBUG::US2400, string_compose ("strip %1 being set to null stripable\n", (*s)->global_index()));
978                 (*s)->reset_stripable ();
979         }
980 }
981
982 void
983 Surface::subview_mode_changed ()
984 {
985         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
986                 (*s)->subview_mode_changed ();
987         }
988         
989         //channel selection likely changed.  disable the joystick so it doesn't send spurious messages
990         if (_stype == st_joy) {
991                 _joystick_active = false;
992         }
993 }
994
995 void
996 Surface::say_hello ()
997 {
998         /* wakeup for Mackie Control */
999         MidiByteArray wakeup (7, MIDI::sysex, 0x00, 0x00, 0x66, 0x14, 0x00, MIDI::eox);
1000         _port->write (wakeup);
1001         wakeup[4] = 0x15; /* wakup Mackie XT */
1002         _port->write (wakeup);
1003         wakeup[4] = 0x10; /* wakeup Logic Control */
1004         _port->write (wakeup);
1005         wakeup[4] = 0x11; /* wakeup Logic Control XT */
1006         _port->write (wakeup);
1007 }
1008
1009 void
1010 Surface::next_jog_mode ()
1011 {
1012 }
1013
1014 void
1015 Surface::set_jog_mode (JogWheel::Mode)
1016 {
1017 }
1018
1019 bool
1020 Surface::stripable_is_locked_to_strip (boost::shared_ptr<Stripable> stripable) const
1021 {
1022         for (Strips::const_iterator s = strips.begin(); s != strips.end(); ++s) {
1023                 if ((*s)->stripable() == stripable && (*s)->locked()) {
1024                         return true;
1025                 }
1026         }
1027         return false;
1028 }
1029
1030 bool
1031 Surface::stripable_is_mapped (boost::shared_ptr<Stripable> stripable) const
1032 {
1033         for (Strips::const_iterator s = strips.begin(); s != strips.end(); ++s) {
1034                 if ((*s)->stripable() == stripable) {
1035                         return true;
1036                 }
1037         }
1038
1039         return false;
1040 }
1041
1042 void
1043 Surface::notify_metering_state_changed()
1044 {
1045         for (Strips::const_iterator s = strips.begin(); s != strips.end(); ++s) {
1046                 (*s)->notify_metering_state_changed ();
1047         }
1048 }
1049
1050 void
1051 Surface::reset ()
1052 {
1053         if (_port) {
1054                 /* reset msg for Mackie Control */
1055                 MidiByteArray msg;
1056                 msg << sysex_hdr();
1057                 msg << 0x08;
1058                 msg << 0x00;
1059                 msg << MIDI::eox;
1060                 _port->write (msg);
1061         }
1062 }
1063
1064 void
1065 Surface::toggle_backlight ()
1066 {
1067 return;  //avoid sending anything that might be misconstrued
1068 }
1069
1070 void
1071 Surface::recalibrate_faders ()
1072 {
1073 return;  //avoid sending anything that might be misconstrued
1074 }
1075
1076 void
1077 Surface::set_touch_sensitivity (int sensitivity)
1078 {
1079         /* NOTE: assumed called from GUI code, hence sleep() */
1080
1081         /* sensitivity already clamped by caller */
1082
1083         if (_port) {
1084                 MidiByteArray msg;
1085
1086                 msg << sysex_hdr ();
1087                 msg << 0x0e;
1088                 msg << 0xff; /* overwritten for each fader below */
1089                 msg << (sensitivity & 0x7f);
1090                 msg << MIDI::eox;
1091
1092                 for (int fader = 0; fader < 9; ++fader) {
1093                         msg[6] = fader;
1094                         _port->write (msg);
1095                 }
1096         }
1097 }
1098
1099 void
1100 Surface::hui_heartbeat ()
1101 {
1102         if (!_port) {
1103                 return;
1104         }
1105
1106         MidiByteArray msg (3, MIDI::on, 0x0, 0x0);
1107         _port->write (msg);
1108 }
1109
1110 void
1111 Surface::connected ()
1112 {
1113         DEBUG_TRACE (DEBUG::US2400, string_compose ("Surface %1 now connected, trying to ping device...\n", _name));
1114
1115         say_hello ();
1116 }
1117
1118