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