mackie: cleanup subview mode a little
[ardour.git] / libs / surfaces / mackie / surface.cc
1 /*
2     Copyright (C) 2012 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 <sstream>
21 #include <iomanip>
22 #include <iostream>
23 #include <cstdio>
24 #include <cmath>
25
26 #include <glibmm/convert.h>
27
28 #include "midi++/port.h"
29
30 #include "ardour/audioengine.h"
31 #include "ardour/automation_control.h"
32 #include "ardour/debug.h"
33 #include "ardour/route.h"
34 #include "ardour/panner.h"
35 #include "ardour/panner_shell.h"
36 #include "ardour/profile.h"
37 #include "ardour/rc_configuration.h"
38 #include "ardour/session.h"
39 #include "ardour/utils.h"
40
41 #include <gtkmm2ext/gui_thread.h>
42
43 #include "control_group.h"
44 #include "surface_port.h"
45 #include "surface.h"
46 #include "strip.h"
47 #include "mackie_control_protocol.h"
48 #include "jog_wheel.h"
49
50 #include "strip.h"
51 #include "button.h"
52 #include "led.h"
53 #include "pot.h"
54 #include "fader.h"
55 #include "jog.h"
56 #include "meter.h"
57
58 #include "i18n.h"
59
60 #ifdef PLATFORM_WINDOWS
61 #define random() rand()
62 #endif
63
64 using namespace std;
65 using namespace PBD;
66 using ARDOUR::Route;
67 using ARDOUR::Panner;
68 using ARDOUR::Profile;
69 using ARDOUR::AutomationControl;
70 using namespace ArdourSurface;
71 using namespace Mackie;
72
73 #define ui_context() MackieControlProtocol::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
74
75 // The MCU sysex header.4th byte Will be overwritten
76 // when we get an incoming sysex that identifies
77 // the device type
78 static MidiByteArray mackie_sysex_hdr  (5, MIDI::sysex, 0x0, 0x0, 0x66, 0x14);
79
80 // The MCU extender sysex header.4th byte Will be overwritten
81 // when we get an incoming sysex that identifies
82 // the device type
83 static MidiByteArray mackie_sysex_hdr_xt  (5, MIDI::sysex, 0x0, 0x0, 0x66, 0x15);
84
85 static MidiByteArray empty_midi_byte_array;
86
87 Surface::Surface (MackieControlProtocol& mcp, const std::string& device_name, uint32_t number, surface_type_t stype)
88         : _mcp (mcp)
89         , _stype (stype)
90         , _number (number)
91         , _name (device_name)
92         , _active (false)
93         , _connected (false)
94         , _jog_wheel (0)
95         , _master_fader (0)
96         , _last_master_gain_written (-0.0f)
97         , connection_state (0)
98         , input_source (0)
99 {
100         DEBUG_TRACE (DEBUG::MackieControl, "Surface::Surface init\n");
101
102         try {
103                 _port = new SurfacePort (*this);
104         } catch (...) {
105                 throw failed_constructor ();
106         }
107
108         /* only the first Surface object has global controls */
109         /* lets use master_position instead */
110         uint32_t mp = _mcp.device_info().master_position();
111         if (_number == mp) {
112                 DEBUG_TRACE (DEBUG::MackieControl, "Surface matches MasterPosition. Might have global controls.\n");
113                 if (_mcp.device_info().has_global_controls()) {
114                         init_controls ();
115                         DEBUG_TRACE (DEBUG::MackieControl, "init_controls done\n");
116                 }
117
118                 if (_mcp.device_info().has_master_fader()) {
119                         setup_master ();
120                         DEBUG_TRACE (DEBUG::MackieControl, "setup_master done\n");
121                 }
122         }
123
124         uint32_t n = _mcp.device_info().strip_cnt();
125
126         if (n) {
127                 init_strips (n);
128                 DEBUG_TRACE (DEBUG::MackieControl, "init_strips done\n");
129         }
130
131         if (_mcp.device_info().uses_ipmidi()) {
132                 /* ipMIDI port already exists, we can just assume that we're
133                  * connected.
134                  *
135                  * If the user still hasn't connected the ipMIDI surface and/or
136                  * turned it on, then they have to press "Discover Mackie
137                  * Devices" in the GUI at the right time.
138                  */
139
140                 connection_state |= (InputConnected|OutputConnected);
141                 connected ();
142         }
143
144         connect_to_signals ();
145
146         DEBUG_TRACE (DEBUG::MackieControl, "Surface::Surface done\n");
147 }
148
149 Surface::~Surface ()
150 {
151         DEBUG_TRACE (DEBUG::MackieControl, "Surface::~Surface init\n");
152
153         if (input_source) {
154                 g_source_destroy (input_source);
155                 input_source = 0;
156         }
157
158         // delete groups (strips)
159         for (Groups::iterator it = groups.begin(); it != groups.end(); ++it) {
160                 delete it->second;
161         }
162
163         // delete controls (global buttons, master fader etc)
164         for (Controls::iterator it = controls.begin(); it != controls.end(); ++it) {
165                 delete *it;
166         }
167
168         delete _jog_wheel;
169         delete _port;
170         // the ports take time to release and we may be rebuilding right away
171         // in the case of changing devices.
172         g_usleep (10000);
173         DEBUG_TRACE (DEBUG::MackieControl, "Surface::~Surface done\n");
174 }
175
176 bool
177 Surface::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn)
178 {
179         if (!_port) {
180                 return false;
181         }
182
183         string ni = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (_port->input_name());
184         string no = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (_port->output_name());
185
186         if (ni == name1 || ni == name2) {
187                 if (yn) {
188                         connection_state |= InputConnected;
189                 } else {
190                         connection_state &= ~InputConnected;
191                 }
192         } else if (no == name1 || no == name2) {
193                 if (yn) {
194                         connection_state |= OutputConnected;
195                 } else {
196                         connection_state &= ~OutputConnected;
197                 }
198         } else {
199                 /* not our ports */
200                 return false;
201         }
202
203         if ((connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) {
204
205                 /* this will send a device query message, which should
206                    result in a response that will kick off device type
207                    discovery and activation of the surface(s).
208
209                    The intended order of events is:
210
211                    - each surface sends a device query message
212                    - devices respond with either MCP or LCP response (sysex in both
213                    cases)
214                    - sysex message causes Surface::turn_it_on() which tells the
215                    MCP object that the surface is ready, and sets up strip
216                    displays and binds faders and buttons for that surface
217
218                    In the case of LCP, where this is a handshake process that could
219                    fail, the response process to the initial sysex after a device query
220                    will mark the surface inactive, which won't shut anything down
221                    but will stop any writes to the device.
222
223                    Note: there are no known cases of the handshake process failing.
224
225                    We actually can't initiate this in this callback, so we have
226                    to queue it with the MCP event loop.
227                 */
228
229                 /* XXX this is a horrible hack. Without a short sleep here,
230                    something prevents the device wakeup messages from being
231                    sent and/or the responses from being received.
232                 */
233
234                 g_usleep (100000);
235                 connected ();
236
237         } else {
238                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 disconnected (input or output or both)\n", _name));
239                 _active = false;
240         }
241
242         return true; /* connection status changed */
243 }
244
245 XMLNode&
246 Surface::get_state()
247 {
248         XMLNode* node = new XMLNode (X_("Surface"));
249         node->add_property (X_("name"), _name);
250         node->add_child_nocopy (_port->get_state());
251         return *node;
252 }
253
254 int
255 Surface::set_state (const XMLNode& node, int version)
256 {
257         /* Look for a node named after the device we're part of */
258
259         XMLNodeList const& children = node.children();
260         XMLNode* mynode = 0;
261
262         for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
263                 XMLProperty const* prop = (*c)->property (X_("name"));
264                 if (prop) {
265                         if (prop->value() == _name) {
266                                 mynode = *c;
267                                 break;
268                         }
269                 }
270         }
271
272         if (!mynode) {
273                 return 0;
274         }
275
276         XMLNode* portnode = mynode->child (X_("Port"));
277         if (portnode) {
278                 if (_port->set_state (*portnode, version)) {
279                         return -1;
280                 }
281         }
282
283         return 0;
284 }
285
286 const MidiByteArray&
287 Surface::sysex_hdr() const
288 {
289         switch  (_stype) {
290         case mcu: return mackie_sysex_hdr;
291         case ext: return mackie_sysex_hdr_xt;
292         }
293         cout << "SurfacePort::sysex_hdr _port_type not known" << endl;
294         return mackie_sysex_hdr;
295 }
296
297 static GlobalControlDefinition mackie_global_controls[] = {
298         { "external", Pot::External, Pot::factory, "none" },
299         { "fader_touch", Led::FaderTouch, Led::factory, "master" },
300         { "timecode", Led::Timecode, Led::factory, "none" },
301         { "beats", Led::Beats, Led::factory, "none" },
302         { "solo", Led::RudeSolo, Led::factory, "none" },
303         { "relay_click", Led::RelayClick, Led::factory, "none" },
304         { "", 0, Led::factory, "" }
305 };
306
307 void
308 Surface::init_controls()
309 {
310         Group* group;
311
312         DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: creating groups\n");
313         groups["assignment"] = new Group  ("assignment");
314         groups["automation"] = new Group  ("automation");
315         groups["bank"] = new Group  ("bank");
316         groups["cursor"] = new Group  ("cursor");
317         groups["display"] = new Group  ("display");
318         groups["function select"] = new Group  ("function select");
319         groups["global view"] = new Group ("global view");
320         groups["master"] = new Group ("master");
321         groups["modifiers"] = new Group  ("modifiers");
322         groups["none"] = new Group  ("none");
323         groups["transport"] = new Group  ("transport");
324         groups["user"] = new Group  ("user");
325         groups["utilities"] = new Group  ("utilities");
326
327         DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: creating jog wheel\n");
328         if (_mcp.device_info().has_jog_wheel()) {
329                 _jog_wheel = new Mackie::JogWheel (_mcp);
330         }
331
332         DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: creating global controls\n");
333         for (uint32_t n = 0; mackie_global_controls[n].name[0]; ++n) {
334                 group = groups[mackie_global_controls[n].group_name];
335                 Control* control = mackie_global_controls[n].factory (*this, mackie_global_controls[n].id, mackie_global_controls[n].name, *group);
336                 controls_by_device_independent_id[mackie_global_controls[n].id] = control;
337         }
338
339         /* add global buttons */
340         DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: adding global buttons\n");
341         const map<Button::ID,GlobalButtonInfo>& global_buttons (_mcp.device_info().global_buttons());
342
343         for (map<Button::ID,GlobalButtonInfo>::const_iterator b = global_buttons.begin(); b != global_buttons.end(); ++b){
344                 group = groups[b->second.group];
345                 controls_by_device_independent_id[b->first] = Button::factory (*this, b->first, b->second.id, b->second.label, *group);
346         }
347 }
348
349 void
350 Surface::init_strips (uint32_t n)
351 {
352         const map<Button::ID,StripButtonInfo>& strip_buttons (_mcp.device_info().strip_buttons());
353
354         for (uint32_t i = 0; i < n; ++i) {
355
356                 char name[32];
357
358                 snprintf (name, sizeof (name), "strip_%d", (8* _number) + i);
359
360                 Strip* strip = new Strip (*this, name, i, strip_buttons);
361
362                 groups[name] = strip;
363                 strips.push_back (strip);
364         }
365 }
366
367 void
368 Surface::master_monitor_may_have_changed ()
369 {
370         setup_master ();
371 }
372
373 void
374 Surface::setup_master ()
375 {
376         boost::shared_ptr<Route> m;
377
378         if ((m = _mcp.get_session().monitor_out()) == 0) {
379                 m = _mcp.get_session().master_out();
380         }
381
382         if (!m) {
383                 _master_fader->set_control (boost::shared_ptr<AutomationControl>());
384                 master_connection.disconnect ();
385                 return;
386         }
387
388         if (!_master_fader) {
389                 _master_fader = dynamic_cast<Fader*> (Fader::factory (*this, _mcp.device_info().strip_cnt(), "master", *groups["master"]));
390
391                 Groups::iterator group_it;
392                 group_it = groups.find("master");
393
394                 DeviceInfo device_info = _mcp.device_info();
395                 GlobalButtonInfo master_button = device_info.get_global_button(Button::MasterFaderTouch);
396                 Button* bb = dynamic_cast<Button*> (Button::factory (
397                                                             *this,
398                                                             Button::MasterFaderTouch,
399                                                             master_button.id,
400                                                             master_button.label,
401                                                             *(group_it->second)
402                                                             ));
403
404                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 Master Fader new button BID %2 id %3\n",
405                                                                    number(), Button::MasterFaderTouch, bb->id()));
406         } else {
407                 master_connection.disconnect ();
408         }
409
410         _master_fader->set_control (m->gain_control());
411         m->gain_control()->Changed.connect (master_connection, MISSING_INVALIDATOR, boost::bind (&Surface::master_gain_changed, this), ui_context());
412         _last_master_gain_written = FLT_MAX; /* some essentially impossible value */
413         master_gain_changed ();
414 }
415
416 void
417 Surface::master_gain_changed ()
418 {
419         if (!_master_fader) {
420                 return;
421         }
422
423         boost::shared_ptr<AutomationControl> ac = _master_fader->control();
424         if (!ac) {
425                 return;
426         }
427
428         float normalized_position = ac->internal_to_interface (ac->get_value());
429         if (normalized_position == _last_master_gain_written) {
430                 return;
431         }
432
433         DEBUG_TRACE (DEBUG::MackieControl, "Surface::master_gain_changed: updating surface master fader\n");
434
435         _port->write (_master_fader->set_position (normalized_position));
436         _last_master_gain_written = normalized_position;
437 }
438
439 float
440 Surface::scaled_delta (float delta, float current_speed)
441 {
442         /* XXX needs work before use */
443         const float sign = delta < 0.0 ? -1.0 : 1.0;
444
445         return ((sign * std::pow (delta + 1.0, 2.0)) + current_speed) / 100.0;
446 }
447
448 void
449 Surface::display_bank_start (uint32_t current_bank)
450 {
451         if  (current_bank == 0) {
452                 // send Ar. to 2-char display on the master
453                 show_two_char_display ("Ar", "..");
454         } else {
455                 // write the current first remote_id to the 2-char display
456                 show_two_char_display (current_bank);
457         }
458 }
459
460 void
461 Surface::blank_jog_ring ()
462 {
463         Control* control = controls_by_device_independent_id[Jog::ID];
464
465         if (control) {
466                 Pot* pot = dynamic_cast<Pot*> (control);
467                 if (pot) {
468                         _port->write (pot->set (0.0, false, Pot::spread));
469                 }
470         }
471 }
472
473 float
474 Surface::scrub_scaling_factor () const
475 {
476         return 100.0;
477 }
478
479 void
480 Surface::connect_to_signals ()
481 {
482         if (!_connected) {
483
484
485                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 connecting to signals on port %2\n",
486                                                                    number(), _port->input_port().name()));
487
488                 MIDI::Parser* p = _port->input_port().parser();
489
490                 /* Incoming sysex */
491                 p->sysex.connect_same_thread (*this, boost::bind (&Surface::handle_midi_sysex, this, _1, _2, _3));
492                 /* V-Pot messages are Controller */
493                 p->controller.connect_same_thread (*this, boost::bind (&Surface::handle_midi_controller_message, this, _1, _2));
494                 /* Button messages are NoteOn */
495                 p->note_on.connect_same_thread (*this, boost::bind (&Surface::handle_midi_note_on_message, this, _1, _2));
496                 /* Button messages are NoteOn but libmidi++ sends note-on w/velocity = 0 as note-off so catch them too */
497                 p->note_off.connect_same_thread (*this, boost::bind (&Surface::handle_midi_note_on_message, this, _1, _2));
498                 /* Fader messages are Pitchbend */
499                 uint32_t i;
500                 for (i = 0; i < _mcp.device_info().strip_cnt(); i++) {
501                         p->channel_pitchbend[i].connect_same_thread (*this, boost::bind (&Surface::handle_midi_pitchbend_message, this, _1, _2, i));
502                 }
503                 // Master fader
504                 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()));
505
506                 _connected = true;
507         }
508 }
509
510 void
511 Surface::handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t pb, uint32_t fader_id)
512 {
513         /* Pitchbend messages are fader position messages. Nothing in the data we get
514          * from the MIDI::Parser conveys the fader ID, which was given by the
515          * channel ID in the status byte.
516          *
517          * Instead, we have used bind() to supply the fader-within-strip ID
518          * when we connected to the per-channel pitchbend events.
519          */
520
521         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface::handle_midi_pitchbend_message on port %3, fader = %1 value = %2 (%4)\n",
522                                                            fader_id, pb, _number, pb/16384.0));
523
524         if (_mcp.device_info().no_handshake()) {
525                 turn_it_on ();
526         }
527
528         if (_mcp.main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
529                 /* user is doing a reset to unity gain but device sends a PB
530                  * message in the middle of the touch on/off messages. Ignore
531                  * it.
532                  */
533                 return;
534         }
535
536         Fader* fader = faders[fader_id];
537
538         if (fader) {
539                 Strip* strip = dynamic_cast<Strip*> (&fader->group());
540                 float pos = pb / 16384.0;
541                 if (strip) {
542                         strip->handle_fader (*fader, pos);
543                 } else {
544                         DEBUG_TRACE (DEBUG::MackieControl, "Handling master fader\n");
545                         /* master fader */
546                         fader->set_value (pos); // alter master gain
547                         _port->write (fader->set_position (pos)); // write back value (required for servo)
548                 }
549         } else {
550                 DEBUG_TRACE (DEBUG::MackieControl, "fader not found\n");
551         }
552 }
553
554 void
555 Surface::handle_midi_note_on_message (MIDI::Parser &, MIDI::EventTwoBytes* ev)
556 {
557         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface::handle_midi_note_on_message %1 = %2\n", (int) ev->note_number, (int) ev->velocity));
558
559         if (_mcp.device_info().no_handshake()) {
560                 turn_it_on ();
561         }
562
563         if (_mcp.device_info().device_type() == DeviceInfo::HUI && ev->note_number == 0 && ev->velocity == 127) {
564                 turn_it_on ();
565         }
566
567         /* fader touch sense is given by "buttons" 0xe..0xe7 and 0xe8 for the
568          * master.
569          */
570
571         if (ev->note_number >= 0xE0 && ev->note_number <= 0xE8) {
572                 Fader* fader = faders[ev->note_number];
573
574                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface: fader touch message, fader = %1\n", fader));
575
576                 if (fader) {
577
578                         Strip* strip = dynamic_cast<Strip*> (&fader->group());
579
580                         if (ev->velocity > 64) {
581                                 strip->handle_fader_touch (*fader, true);
582                         } else {
583                                 strip->handle_fader_touch (*fader, false);
584                         }
585                 }
586                 return;
587         }
588
589         Button* button = buttons[ev->note_number];
590
591         if (button) {
592
593                 if (ev->velocity > 64) {
594                         button->pressed ();
595                 }
596
597                 Strip* strip = dynamic_cast<Strip*> (&button->group());
598
599                 if (strip) {
600                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 button %2 pressed ? %3\n",
601                                                                            strip->index(), button->name(), (ev->velocity > 64)));
602                         strip->handle_button (*button, ev->velocity > 64 ? press : release);
603                 } else {
604                         /* global button */
605                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("global button %1\n", button->id()));
606                         _mcp.handle_button_event (*this, *button, ev->velocity > 64 ? press : release);
607                 }
608
609                 if (ev->velocity <= 64) {
610                         button->released ();
611                 }
612
613         } else {
614                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("no button found for %1\n", (int) ev->note_number));
615         }
616
617         /* button release should reset timer AFTER handler(s) have run */
618 }
619
620 void
621 Surface::handle_midi_controller_message (MIDI::Parser &, MIDI::EventTwoBytes* ev)
622 {
623         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("SurfacePort::handle_midi_controller %1 = %2\n", (int) ev->controller_number, (int) ev->value));
624
625         if (_mcp.device_info().no_handshake()) {
626                 turn_it_on ();
627         }
628
629         Pot* pot = pots[ev->controller_number];
630
631         // bit 6 gives the sign
632         float sign = (ev->value & 0x40) == 0 ? 1.0 : -1.0;
633         // bits 0..5 give the velocity. we interpret this as "ticks
634         // moved before this message was sent"
635         float ticks = (ev->value & 0x3f);
636         if (ticks == 0) {
637                 /* euphonix and perhaps other devices send zero
638                    when they mean 1, we think.
639                 */
640                 ticks = 1;
641         }
642
643         float delta = 0;
644         if (mcp().main_modifier_state() == MackieControlProtocol::MODIFIER_CONTROL) {
645                 delta = sign * (ticks / (float) 0xff);
646         } else {
647                 delta = sign * (ticks / (float) 0x3f);
648         }
649
650         if (!pot) {
651                 if (ev->controller_number == Jog::ID && _jog_wheel) {
652
653                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Jog wheel moved %1\n", ticks));
654                         _jog_wheel->jog_event (delta);
655                         return;
656                 }
657                 // add external (pedal?) control here
658
659                 return;
660         }
661
662         Strip* strip = dynamic_cast<Strip*> (&pot->group());
663         if (strip) {
664                 strip->handle_pot (*pot, delta);
665         }
666 }
667
668 void
669 Surface::handle_midi_sysex (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count)
670 {
671         MidiByteArray bytes (count, raw_bytes);
672
673         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("handle_midi_sysex: %1\n", bytes));
674
675         if (_mcp.device_info().no_handshake()) {
676                 turn_it_on ();
677         }
678
679         /* always save the device type ID so that our outgoing sysex messages
680          * are correct
681          */
682
683         if (_stype == mcu) {
684                 mackie_sysex_hdr[4] = bytes[4];
685         } else {
686                 mackie_sysex_hdr_xt[4] = bytes[4];
687         }
688
689         switch (bytes[5]) {
690         case 0x01:
691                 /* MCP: Device Ready
692                    LCP: Connection Challenge
693                 */
694                 if (bytes[4] == 0x10 || bytes[4] == 0x11) {
695                         DEBUG_TRACE (DEBUG::MackieControl, "Logic Control Device connection challenge\n");
696                         write_sysex (host_connection_query (bytes));
697                 } else {
698                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Mackie Control Device ready, current status = %1\n", _active));
699                         turn_it_on ();
700                 }
701                 break;
702
703         case 0x03: /* LCP Connection Confirmation */
704                 DEBUG_TRACE (DEBUG::MackieControl, "Logic Control Device confirms connection, ardour replies\n");
705                 if (bytes[4] == 0x10 || bytes[4] == 0x11) {
706                         write_sysex (host_connection_confirmation (bytes));
707                         turn_it_on ();
708                 }
709                 break;
710
711         case 0x04: /* LCP: Confirmation Denied */
712                 DEBUG_TRACE (DEBUG::MackieControl, "Logic Control Device denies connection\n");
713                 _active = false;
714                 break;
715         default:
716                 error << "MCP: unknown sysex: " << bytes << endmsg;
717         }
718 }
719
720 static MidiByteArray
721 calculate_challenge_response (MidiByteArray::iterator begin, MidiByteArray::iterator end)
722 {
723         MidiByteArray l;
724         back_insert_iterator<MidiByteArray> back  (l);
725         copy (begin, end, back);
726
727         MidiByteArray retval;
728
729         // this is how to calculate the response to the challenge.
730         // from the Logic docs.
731         retval <<  (0x7f &  (l[0] +  (l[1] ^ 0xa) - l[3]));
732         retval <<  (0x7f &  ( (l[2] >> l[3]) ^  (l[0] + l[3])));
733         retval <<  (0x7f &  ((l[3] -  (l[2] << 2)) ^  (l[0] | l[1])));
734         retval <<  (0x7f &  (l[1] - l[2] +  (0xf0 ^  (l[3] << 4))));
735
736         return retval;
737 }
738
739 MidiByteArray
740 Surface::host_connection_query (MidiByteArray & bytes)
741 {
742         MidiByteArray response;
743
744         if (bytes[4] != 0x10 && bytes[4] != 0x11) {
745                 /* not a Logic Control device - no response required */
746                 return response;
747         }
748
749         // handle host connection query
750         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("host connection query: %1\n", bytes));
751
752         if  (bytes.size() != 18) {
753                 cerr << "expecting 18 bytes, read " << bytes << " from " << _port->input_port().name() << endl;
754                 return response;
755         }
756
757         // build and send host connection reply
758         response << 0x02;
759         copy (bytes.begin() + 6, bytes.begin() + 6 + 7, back_inserter (response));
760         response << calculate_challenge_response (bytes.begin() + 6 + 7, bytes.begin() + 6 + 7 + 4);
761         return response;
762 }
763
764 MidiByteArray
765 Surface::host_connection_confirmation (const MidiByteArray & bytes)
766 {
767         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("host_connection_confirmation: %1\n", bytes));
768
769         // decode host connection confirmation
770         if  (bytes.size() != 14) {
771                 ostringstream os;
772                 os << "expecting 14 bytes, read " << bytes << " from " << _port->input_port().name();
773                 throw MackieControlException (os.str());
774         }
775
776         // send version request
777         return MidiByteArray (2, 0x13, 0x00);
778 }
779
780 void
781 Surface::turn_it_on ()
782 {
783         if (_active) {
784                 return;
785         }
786
787         _active = true;
788
789         _mcp.device_ready ();
790
791         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
792                 (*s)->notify_all ();
793         }
794
795         update_view_mode_display ();
796
797         if (_mcp.device_info ().has_global_controls ()) {
798                 _mcp.update_global_button (Button::Read, _mcp.metering_active ());
799         }
800 }
801
802 void
803 Surface::write_sysex (const MidiByteArray & mba)
804 {
805         if (mba.empty()) {
806                 return;
807         }
808
809         MidiByteArray buf;
810         buf << sysex_hdr() << mba << MIDI::eox;
811         _port->write (buf);
812 }
813
814 void
815 Surface::write_sysex (MIDI::byte msg)
816 {
817         MidiByteArray buf;
818         buf << sysex_hdr() << msg << MIDI::eox;
819         _port->write (buf);
820 }
821
822 uint32_t
823 Surface::n_strips (bool with_locked_strips) const
824 {
825         if (with_locked_strips) {
826                 return strips.size();
827         }
828
829         uint32_t n = 0;
830
831         for (Strips::const_iterator it = strips.begin(); it != strips.end(); ++it) {
832                 if (!(*it)->locked()) {
833                         ++n;
834                 }
835         }
836         return n;
837 }
838
839 Strip*
840 Surface::nth_strip (uint32_t n) const
841 {
842         if (n > n_strips()) {
843                 return 0;
844         }
845         return strips[n];
846 }
847
848 void
849 Surface::zero_all ()
850 {
851         if (_mcp.device_info().has_timecode_display ()) {
852                 display_timecode (string (10, '0'), string (10, ' '));
853         }
854
855         if (_mcp.device_info().has_two_character_display()) {
856                 show_two_char_display (string (2, '0'), string (2, ' '));
857         }
858
859         if (_mcp.device_info().has_master_fader () && _master_fader) {
860                 _port->write (_master_fader->zero ());
861         }
862
863         // zero all strips
864         for (Strips::iterator it = strips.begin(); it != strips.end(); ++it) {
865                 (*it)->zero();
866         }
867
868         zero_controls ();
869 }
870
871 void
872 Surface::zero_controls ()
873 {
874         if (!_mcp.device_info().has_global_controls()) {
875                 return;
876         }
877
878         // turn off global buttons and leds
879
880         for (Controls::iterator it = controls.begin(); it != controls.end(); ++it) {
881                 Control & control = **it;
882                 if (!control.group().is_strip()) {
883                         _port->write (control.zero());
884                 }
885         }
886
887         // and the led ring for the master strip
888         blank_jog_ring ();
889
890         _last_master_gain_written = 0.0f;
891 }
892
893 void
894 Surface::periodic (uint64_t now_usecs)
895 {
896         master_gain_changed();
897         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
898                 (*s)->periodic (now_usecs);
899         }
900 }
901
902 void
903 Surface::redisplay (ARDOUR::microseconds_t now)
904 {
905         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
906                 (*s)->redisplay (now);
907         }
908 }
909
910 void
911 Surface::write (const MidiByteArray& data)
912 {
913         if (_active) {
914                 _port->write (data);
915         } else {
916                 DEBUG_TRACE (DEBUG::MackieControl, "surface not active, write ignored\n");
917         }
918 }
919
920 void
921 Surface::map_routes (const vector<boost::shared_ptr<Route> >& routes)
922 {
923         vector<boost::shared_ptr<Route> >::const_iterator r;
924         Strips::iterator s = strips.begin();
925
926         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Mapping %1 routes\n", routes.size()));
927
928         for (r = routes.begin(); r != routes.end() && s != strips.end(); ++s) {
929
930                 /* don't try to assign routes to a locked strip. it won't
931                    use it anyway, but if we do, then we get out of sync
932                    with the proposed mapping.
933                 */
934
935                 if (!(*s)->locked()) {
936                         (*s)->set_route (*r);
937                         ++r;
938                 }
939         }
940
941         for (; s != strips.end(); ++s) {
942                 (*s)->set_route (boost::shared_ptr<Route>());
943         }
944
945
946 }
947
948 static char
949 translate_seven_segment (char achar)
950 {
951         achar = toupper (achar);
952
953         if  (achar >= 0x40 && achar <= 0x60) {
954                 return achar - 0x40;
955         } else if  (achar >= 0x21 && achar <= 0x3f) {
956                 return achar;
957         } else {
958                 return 0x00;
959         }
960 }
961
962 void
963 Surface::show_two_char_display (const std::string & msg, const std::string & dots)
964 {
965         if (_stype != mcu || !_mcp.device_info().has_two_character_display() || msg.length() != 2 || dots.length() != 2) {
966                 return;
967         }
968
969         MidiByteArray right (3, 0xb0, 0x4b, 0x00);
970         MidiByteArray left (3, 0xb0, 0x4a, 0x00);
971
972         right[2] = translate_seven_segment (msg[0]) +  (dots[0] == '.' ? 0x40 : 0x00);
973         left[2] = translate_seven_segment (msg[1]) +  (dots[1] == '.' ? 0x40 : 0x00);
974
975         _port->write (right);
976         _port->write (left);
977 }
978
979 void
980 Surface::show_two_char_display (unsigned int value, const std::string & /*dots*/)
981 {
982         ostringstream os;
983         os << setfill('0') << setw(2) << value % 100;
984         show_two_char_display (os.str());
985 }
986
987 void
988 Surface::display_timecode (const std::string & timecode, const std::string & last_timecode)
989 {
990         if (!_active || !_mcp.device_info().has_timecode_display()) {
991                 return;
992         }
993         // if there's no change, send nothing, not even sysex header
994         if  (timecode == last_timecode) return;
995
996         // length sanity checking
997         string local_timecode = timecode;
998
999         // truncate to 10 characters
1000         if  (local_timecode.length() > 10) {
1001                 local_timecode = local_timecode.substr (0, 10);
1002         }
1003
1004         // pad to 10 characters
1005         while  (local_timecode.length() < 10) {
1006                 local_timecode += " ";
1007         }
1008
1009         // translate characters.
1010         // Only the characters that actually changed are sent.
1011         int position = 0x3f;
1012         int i;
1013         for (i = local_timecode.length () - 1; i >= 0; i--) {
1014                 position++;
1015                 if (local_timecode[i] == last_timecode[i]) {
1016                         continue;
1017                 }
1018                 MidiByteArray retval (2, 0xb0, position);
1019                 retval << translate_seven_segment (local_timecode[i]);
1020                 _port->write (retval);
1021         }
1022 }
1023
1024 void
1025 Surface::update_flip_mode_display ()
1026 {
1027         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
1028                 (*s)->potmode_changed (true);
1029         }
1030 }
1031
1032 void
1033 Surface::update_potmode ()
1034 {
1035         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
1036                 (*s)->potmode_changed (false);
1037         }
1038 }
1039
1040 void
1041 Surface::subview_mode_changed ()
1042 {
1043         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
1044                 (*s)->subview_mode_changed ();
1045         }
1046
1047         if (_mcp.subview_mode() == MackieControlProtocol::None) {
1048                 update_view_mode_display ();
1049         }
1050 }
1051
1052 void
1053 Surface::update_view_mode_display ()
1054 {
1055         string text;
1056         int id = -1;
1057
1058         if (!_active) {
1059                 return;
1060         }
1061
1062         switch (_mcp.view_mode()) {
1063         case MackieControlProtocol::Mixer:
1064                 show_two_char_display ("Mx");
1065                 id = Button::View;
1066                 text = _("Mixer View");
1067                 break;
1068         case MackieControlProtocol::AudioTracks:
1069                 show_two_char_display ("AT");
1070                 id = Button::AudioTracks;
1071                 text = _("Audio Tracks");
1072                 break;
1073         case MackieControlProtocol::MidiTracks:
1074                 show_two_char_display ("MT");
1075                 id = Button::MidiTracks;
1076                 text = _("MIDI Tracks");
1077                 break;
1078         case MackieControlProtocol::Plugins:
1079                 show_two_char_display ("PL");
1080                 id = Button::Plugin;
1081                 text = _("Plugins");
1082                 break;
1083         case MackieControlProtocol::Busses:
1084                 show_two_char_display ("BS");
1085                 id = Button::Busses;
1086                 if (Profile->get_mixbus()) {
1087                         text = _("Mixbusses");
1088                 } else {
1089                         text = _("Busses");
1090                 }
1091                 break;
1092         case MackieControlProtocol::Auxes:
1093                 show_two_char_display ("Au");
1094                 id = Button::Aux;
1095                 text = _("Auxes");
1096                 break;
1097         case MackieControlProtocol::Selected:
1098                 show_two_char_display ("SE");
1099                 id = Button::User;
1100                 text = _("Selected Routes");
1101                 break;
1102         default:
1103                 break;
1104         }
1105
1106         vector<int> view_mode_buttons;
1107         view_mode_buttons.push_back (Button::View);
1108         view_mode_buttons.push_back (Button::Busses);
1109         view_mode_buttons.push_back (Button::Plugin);
1110         view_mode_buttons.push_back (Button::AudioTracks);
1111         view_mode_buttons.push_back (Button::MidiTracks);
1112         view_mode_buttons.push_back (Button::Aux);
1113         view_mode_buttons.push_back (Button::User);
1114
1115         if (id >= 0) {
1116
1117                 for (vector<int>::iterator i = view_mode_buttons.begin(); i != view_mode_buttons.end(); ++i) {
1118                         map<int,Control*>::iterator x = controls_by_device_independent_id.find (id);
1119
1120                         if (x != controls_by_device_independent_id.end()) {
1121                                 Button* button = dynamic_cast<Button*> (x->second);
1122                                 if (button) {
1123                                         bool onoff;
1124                                         onoff = (*i) == id;
1125
1126                                         _port->write (button->set_state (onoff));
1127                                 }
1128                         }
1129                 }
1130         }
1131
1132         if (!text.empty()) {
1133                 display_message_for (text, 1000);
1134         }
1135 }
1136
1137 void
1138 Surface::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& routes)
1139 {
1140         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
1141                 (*s)->gui_selection_changed (routes);
1142         }
1143 }
1144
1145 void
1146 Surface::say_hello ()
1147 {
1148         /* wakeup for Mackie Control */
1149         MidiByteArray wakeup (7, MIDI::sysex, 0x00, 0x00, 0x66, 0x14, 0x00, MIDI::eox);
1150         _port->write (wakeup);
1151         wakeup[4] = 0x15; /* wakup Mackie XT */
1152         _port->write (wakeup);
1153         wakeup[4] = 0x10; /* wakeup Logic Control */
1154         _port->write (wakeup);
1155         wakeup[4] = 0x11; /* wakeup Logic Control XT */
1156         _port->write (wakeup);
1157 }
1158
1159 void
1160 Surface::next_jog_mode ()
1161 {
1162 }
1163
1164 void
1165 Surface::set_jog_mode (JogWheel::Mode)
1166 {
1167 }
1168
1169 bool
1170 Surface::route_is_locked_to_strip (boost::shared_ptr<Route> r) const
1171 {
1172         for (Strips::const_iterator s = strips.begin(); s != strips.end(); ++s) {
1173                 if ((*s)->route() == r && (*s)->locked()) {
1174                         return true;
1175                 }
1176         }
1177         return false;
1178 }
1179
1180 void
1181 Surface::notify_metering_state_changed()
1182 {
1183         for (Strips::const_iterator s = strips.begin(); s != strips.end(); ++s) {
1184                 (*s)->notify_metering_state_changed ();
1185         }
1186 }
1187
1188 void
1189 Surface::reset ()
1190 {
1191         if (_port) {
1192                 /* reset msg for Mackie Control */
1193                 MidiByteArray msg;
1194                 msg << sysex_hdr();
1195                 msg << 0x08;
1196                 msg << 0x00;
1197                 msg << MIDI::eox;
1198                 _port->write (msg);
1199         }
1200 }
1201
1202 void
1203 Surface::toggle_backlight ()
1204 {
1205         if (_port) {
1206                 int onoff = random() %2;
1207                 MidiByteArray msg;
1208                 msg << sysex_hdr ();
1209                 msg << 0xa;
1210                 msg << (onoff ? 0x1 : 0x0);
1211                 msg << MIDI::eox;
1212                 _port->write (msg);
1213         }
1214 }
1215
1216 void
1217 Surface::recalibrate_faders ()
1218 {
1219         if (_port) {
1220                 MidiByteArray msg;
1221                 msg << sysex_hdr ();
1222                 msg << 0x09;
1223                 msg << 0x00;
1224                 msg << MIDI::eox;
1225                 _port->write (msg);
1226         }
1227 }
1228
1229 void
1230 Surface::set_touch_sensitivity (int sensitivity)
1231 {
1232         /* NOTE: assumed called from GUI code, hence sleep() */
1233
1234         /* sensitivity already clamped by caller */
1235
1236         if (_port) {
1237                 MidiByteArray msg;
1238
1239                 msg << sysex_hdr ();
1240                 msg << 0x0e;
1241                 msg << 0xff; /* overwritten for each fader below */
1242                 msg << (sensitivity & 0x7f);
1243                 msg << MIDI::eox;
1244
1245                 for (int fader = 0; fader < 9; ++fader) {
1246                         msg[6] = fader;
1247                         _port->write (msg);
1248                 }
1249         }
1250 }
1251
1252 void
1253 Surface::hui_heartbeat ()
1254 {
1255         if (!_port) {
1256                 return;
1257         }
1258
1259         MidiByteArray msg (3, MIDI::on, 0x0, 0x0);
1260         _port->write (msg);
1261 }
1262
1263 void
1264 Surface::connected ()
1265 {
1266         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 now connected, trying to ping device...\n", _name));
1267
1268         say_hello ();
1269
1270         if (_mcp.device_info().no_handshake()) {
1271                 turn_it_on ();
1272         }
1273 }
1274
1275 MidiByteArray
1276 Surface::display_line (string const& msg, int line_num)
1277 {
1278         MidiByteArray midi_msg;
1279         midi_msg << sysex_hdr ();
1280         midi_msg << 0x12;
1281         midi_msg << (line_num ? 0x38 : 0x0); /* offsets into char array
1282                                               * on device that
1283                                               * correspond to line
1284                                               * starts
1285                                               */
1286         if (msg.empty()) {
1287
1288                 midi_msg.insert (midi_msg.end(), 55, ' ');
1289
1290         } else {
1291
1292                 /* ascii data to display. @param msg is UTF-8 which is not legal. */
1293                 string ascii = Glib::convert_with_fallback (msg, "UTF-8", "ISO-8859-1", "_");
1294                 string::size_type len = ascii.length();
1295
1296                 if (len > 55) {
1297                         midi_msg << ascii.substr (0, 55);
1298                 } else {
1299                         midi_msg << ascii;
1300
1301                         for (string::size_type i = len; i < 55; ++i) {
1302                                 midi_msg << ' ';
1303                         }
1304                 }
1305         }
1306
1307         midi_msg << MIDI::eox;
1308
1309         return midi_msg;
1310 }
1311
1312 /** display @param msg on the 55x2 screen for @param msecs milliseconds
1313  *
1314  *  @param msg is assumed to be UTF-8 encoded, and will be converted
1315  *  to ASCII with an underscore as fallback character before being
1316  *  sent to the device.
1317  */
1318 void
1319 Surface::display_message_for (string const& msg, uint64_t msecs)
1320 {
1321         string::size_type newline;
1322
1323         if ((newline = msg.find ('\n')) == string::npos) {
1324
1325                 _port->write (display_line (msg, 0));
1326                 _port->write (display_line (string(), 1));
1327
1328         } else if (newline == 0) {
1329
1330                 _port->write (display_line (string(), 0));
1331                 _port->write (display_line (msg.substr (1), 1));
1332
1333         } else {
1334
1335                 string first_line = msg.substr (0, newline-1);
1336                 string second_line = msg.substr (newline+1);
1337
1338                 _port->write (display_line (first_line, 0));
1339                 _port->write (display_line (second_line.substr (0, second_line.find_first_of ('\n')), 1));
1340         }
1341
1342         for (Strips::const_iterator s = strips.begin(); s != strips.end(); ++s) {
1343                 (*s)->block_screen_display_for (msecs);
1344         }
1345 }