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