1 /* 2 * Copyright (C) 2018 Jan Lentfer <jan.lentfer@web.de> 3 * Copyright (C) 2018 Robin Gareus <robin@gareus.org> 4 * Copyright (C) 2018 Térence Clastres <t.clastres@gmail.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 */ 20 21 #ifndef __ardour_launch_control_h__ 22 #define __ardour_launch_control_h__ 23 24 #include <vector> 25 #include <map> 26 #include <stack> 27 #include <list> 28 #include <set> 29 30 #define ABSTRACT_UI_EXPORTS 31 #include "pbd/abstract_ui.h" 32 33 #include "midi++/types.h" 34 35 #include "ardour/mode.h" 36 #include "ardour/types.h" 37 38 #include "control_protocol/control_protocol.h" 39 #include "control_protocol/types.h" 40 41 #include "midi_byte_array.h" 42 43 namespace MIDI { 44 class Parser; 45 class Port; 46 } // namespace MIDI 47 48 namespace ARDOUR { 49 class AsyncMIDIPort; 50 class Port; 51 class MidiBuffer; 52 class MidiTrack; 53 } // namespace ARDOUR 54 55 namespace ArdourSurface { 56 57 58 struct LaunchControlRequest : public BaseUI::BaseRequestObject { 59 public: LaunchControlRequestLaunchControlRequest60 LaunchControlRequest() {} ~LaunchControlRequestLaunchControlRequest61 ~LaunchControlRequest() {} 62 }; 63 64 class LCXLGUI; 65 class LaunchControlMenu; 66 67 class LaunchControlXL : public ARDOUR::ControlProtocol, 68 public AbstractUI<LaunchControlRequest> 69 { 70 public: 71 enum TrackMode { 72 TrackMute, 73 TrackSolo, 74 TrackRecord 75 }; 76 77 enum ButtonID { 78 Focus1 = 0, 79 Focus2, 80 Focus3, 81 Focus4, 82 Focus5, 83 Focus6, 84 Focus7, 85 Focus8, 86 Control1, 87 Control2, 88 Control3, 89 Control4, 90 Control5, 91 Control6, 92 Control7, 93 Control8, 94 Device, 95 Mute, 96 Solo, 97 Record, 98 SelectUp, 99 SelectDown, 100 SelectLeft, 101 SelectRight 102 }; 103 104 enum FaderID { 105 Fader1 = 0, 106 Fader2, 107 Fader3, 108 Fader4, 109 Fader5, 110 Fader6, 111 Fader7, 112 Fader8 113 }; 114 115 enum KnobID { 116 SendA1 = 0, 117 SendA2, 118 SendA3, 119 SendA4, 120 SendA5, 121 SendA6, 122 SendA7, 123 SendA8, 124 SendB1, 125 SendB2, 126 SendB3, 127 SendB4, 128 SendB5, 129 SendB6, 130 SendB7, 131 SendB8, 132 Pan1, 133 Pan2, 134 Pan3, 135 Pan4, 136 Pan5, 137 Pan6, 138 Pan7, 139 Pan8 140 }; 141 142 enum DeviceStatus { 143 dev_nonexistant = 0, 144 dev_inactive, 145 dev_active 146 }; 147 148 enum LEDFlag { Normal = 0xC, Blink = 0x8, DoubleBuffering = 0x0 }; 149 enum LEDColor { Off=0, RedLow = 1, RedFull = 3, GreenLow = 16, GreenFull = 48, YellowLow = 34, YellowFull = 51, AmberLow = 18, AmberFull = 35}; 150 151 152 #ifdef MIXBUS 153 enum CompParam { 154 CompMakeup, 155 CompMode, 156 CompSpeed 157 }; 158 #endif 159 160 struct Controller { ControllerController161 Controller(uint8_t cn, uint8_t val, boost::function<void ()> action) 162 : _controller_number(cn) 163 , _value(val) 164 , action_method(action) {} 165 controller_numberController166 uint8_t controller_number() const { return _controller_number; } valueController167 uint8_t value() const { return _value; } set_valueController168 void set_value(uint8_t val) { _value = val; } 169 170 protected: 171 uint8_t _controller_number; 172 uint8_t _value; 173 174 public: 175 boost::function<void ()> action_method; 176 }; 177 178 struct LED { LEDLED179 LED(uint8_t i, LEDColor c, LaunchControlXL& l) : _index(i), _color(c), _flag(Normal), lcxl(&l) {} LEDLED180 LED(uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& lcxl) : _index(i), _color(c), _flag(f) {} ~LEDLED181 virtual ~LED() {} 182 colorLED183 LEDColor color() const { return _color; } flagLED184 LEDFlag flag() const { return _flag; } indexLED185 uint8_t index() const { return _index; } set_flagLED186 void set_flag(LEDFlag f) { _flag = f; } 187 188 virtual MidiByteArray state_msg(bool light) const = 0; 189 190 protected: 191 uint8_t _index; 192 LEDColor _color; 193 LEDFlag _flag; 194 MidiByteArray _state_msg; 195 LaunchControlXL* lcxl; 196 }; 197 198 struct MultiColorLED : public LED { MultiColorLEDMultiColorLED199 MultiColorLED (uint8_t i, LEDColor c, LaunchControlXL& l) : LED(i, c, l) {} MultiColorLEDMultiColorLED200 MultiColorLED (uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& l) 201 : LED(i, c, f, l) {} 202 set_colorMultiColorLED203 void set_color(LEDColor c) { _color = c; } 204 }; 205 206 struct Button { ButtonButton207 Button(ButtonID id, boost::function<void ()> press, boost::function<void ()> release, 208 boost::function<void ()> long_press) 209 : press_method(press) 210 , release_method(release) 211 , long_press_method(long_press), 212 _id(id) {} 213 ~ButtonButton214 virtual ~Button() {} 215 idButton216 ButtonID id() const { return _id; } 217 218 boost::function<void ()> press_method; 219 boost::function<void ()> release_method; 220 boost::function<void ()> long_press_method; 221 222 sigc::connection timeout_connection; 223 224 protected: 225 ButtonID _id; 226 }; 227 228 struct ControllerButton : public Button { ControllerButtonControllerButton229 ControllerButton(ButtonID id, uint8_t cn, 230 boost::function<void ()> press, 231 boost::function<void ()> release, 232 boost::function<void ()> long_release) 233 : Button(id, press, release, long_release), _controller_number(cn) {} 234 235 236 controller_numberControllerButton237 uint8_t controller_number() const { return _controller_number; } 238 239 private: 240 uint8_t _controller_number; 241 }; 242 243 struct NoteButton : public Button { NoteButtonNoteButton244 NoteButton(ButtonID id, uint8_t cn, 245 boost::function<void ()> press, 246 boost::function<void ()> release, 247 boost::function<void ()> release_long) 248 : Button(id, press, release, release_long), _note_number(cn) {} 249 note_numberNoteButton250 uint8_t note_number() const { return _note_number; } 251 252 private: 253 uint8_t _note_number; 254 }; 255 256 struct TrackButton : public NoteButton, public MultiColorLED { TrackButtonTrackButton257 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor c_on, LEDColor c_off, 258 boost::function<void ()> press, 259 boost::function<void ()> release, 260 boost::function<void ()> release_long, 261 boost::function<uint8_t ()> check, 262 LaunchControlXL& l) 263 : NoteButton(id, nn, press, release, release_long) 264 , MultiColorLED(index, Off, l) 265 , check_method(check) 266 , _color_enabled (c_on) 267 , _color_disabled (c_off) {} 268 269 270 271 color_enabledTrackButton272 LEDColor color_enabled() const { return _color_enabled; } color_disabledTrackButton273 LEDColor color_disabled() const { return _color_disabled; } set_color_enabledTrackButton274 void set_color_enabled (LEDColor c_on) { _color_enabled = c_on; } set_color_disabledTrackButton275 void set_color_disabled (LEDColor c_off) { _color_disabled = c_off; } 276 boost::function<uint8_t ()> check_method; 277 278 279 MidiByteArray state_msg(bool light = true) const; 280 281 private: 282 LEDColor _color_enabled; 283 LEDColor _color_disabled; 284 }; 285 286 struct SelectButton : public ControllerButton, public LED { SelectButtonSelectButton287 SelectButton(ButtonID id, uint8_t cn, uint8_t index, 288 boost::function<void ()> press, 289 boost::function<void ()> release, 290 boost::function<void ()> long_release, 291 LaunchControlXL& l) 292 : ControllerButton(id, cn, press, release, long_release), LED(index, RedFull, l) {} 293 294 295 MidiByteArray state_msg(bool light) const; 296 }; 297 298 struct TrackStateButton : public NoteButton, public LED { TrackStateButtonTrackStateButton299 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, 300 boost::function<void ()> press, 301 boost::function<void ()> release, 302 boost::function<void ()> release_long, 303 LaunchControlXL& l) 304 : NoteButton(id, nn, press, release, release_long) 305 , LED(index, YellowLow, l) {} 306 307 MidiByteArray state_msg(bool light) const; 308 }; 309 310 struct Fader : public Controller { FaderFader311 Fader(FaderID id, uint8_t cn, boost::function<void ()> action) 312 : Controller(cn, 0, action), _id(id) {} // minimal value 313 idFader314 FaderID id() const { return _id; } 315 316 void controller_changed(Controller* controller); 317 318 private: 319 FaderID _id; 320 }; 321 322 struct Knob : public Controller, public MultiColorLED { KnobKnob323 Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, boost::function<void ()> action, 324 LaunchControlXL &l) 325 : Controller(cn, 64, action) 326 , MultiColorLED(index, Off, l) 327 , _id(id) 328 , _color_enabled (c_on) 329 , _color_disabled (c_off) {} // knob 50/50 value 330 KnobKnob331 Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, boost::function<void ()> action, 332 boost::function<uint8_t ()> check, LaunchControlXL &l) 333 : Controller(cn, 64, action) 334 , MultiColorLED(index, Off, l) 335 , check_method(check) 336 , _id(id) 337 , _color_enabled (c_on) 338 , _color_disabled (c_off) {} // knob 50/50 value 339 340 341 idKnob342 KnobID id() const { return _id; } color_enabledKnob343 LEDColor color_enabled() const { return _color_enabled; } color_disabledKnob344 LEDColor color_disabled() const { return _color_disabled; } 345 boost::function<uint8_t ()> check_method; 346 347 MidiByteArray state_msg(bool light = true) const; 348 349 private: 350 KnobID _id; 351 LEDColor _color_enabled; 352 LEDColor _color_disabled; 353 }; 354 355 public: 356 LaunchControlXL(ARDOUR::Session &); 357 ~LaunchControlXL(); 358 359 360 static bool probe(); 361 static void *request_factory(uint32_t); 362 363 std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles(); 364 has_editor()365 bool has_editor() const { return true; } 366 void *get_gui() const; 367 void tear_down_gui(); 368 369 int get_amount_of_tracks(); 370 371 int set_active(bool yn); 372 XMLNode &get_state(); 373 int set_state(const XMLNode &node, int version); 374 375 PBD::Signal0<void> ConnectionChange; 376 377 boost::shared_ptr<ARDOUR::Port> input_port(); 378 boost::shared_ptr<ARDOUR::Port> output_port(); 379 380 Button *button_by_id(ButtonID); 381 382 static std::string button_name_by_id(ButtonID); 383 static std::string knob_name_by_id(KnobID); 384 static std::string fader_name_by_id(FaderID); 385 386 void write(const MidiByteArray &); 387 void reset(uint8_t chan); 388 389 void set_fader8master (bool yn); fader8master()390 bool fader8master () const { return _fader8master; } 391 392 void set_refresh_leds_flag (bool yn); refresh_leds_flag()393 bool refresh_leds_flag () const { return _refresh_leds_flag; } 394 395 void set_device_mode (bool yn); device_mode()396 bool device_mode () const { return _device_mode; } 397 398 #ifdef MIXBUS32C 399 void set_ctrllowersends (bool yn); ctrllowersends()400 bool ctrllowersends () const { return _ctrllowersends; } 401 402 void store_fss_type(); fss_is_mixbus()403 bool fss_is_mixbus() const { return _fss_is_mixbus; } 404 #endif track_mode()405 TrackMode track_mode() const { return _track_mode; } 406 void set_track_mode(TrackMode mode); 407 template_number()408 uint8_t template_number() const { return _template_number; } 409 410 void set_send_bank (int offset); 411 void send_bank_switch(bool up); send_bank_base()412 int send_bank_base () const { return _send_bank_base; } 413 414 private: 415 bool in_use; 416 TrackMode _track_mode; 417 uint8_t _template_number; 418 419 bool _fader8master; 420 bool _device_mode; 421 #ifdef MIXBUS32C 422 bool _ctrllowersends; 423 bool _fss_is_mixbus; 424 #endif 425 bool _refresh_leds_flag; 426 427 int _send_bank_base; 428 429 void do_request(LaunchControlRequest *); 430 431 int begin_using_device(); 432 int stop_using_device(); 433 int ports_acquire(); 434 void ports_release(); 435 void run_event_loop(); 436 void stop_event_loop(); 437 relax()438 void relax() {} 439 440 /* map of NoteButtons by NoteNumber */ 441 typedef std::map<int, boost::shared_ptr<NoteButton> > NNNoteButtonMap; 442 NNNoteButtonMap nn_note_button_map; 443 /* map of NoteButtons by ButtonID */ 444 typedef std::map<ButtonID, boost::shared_ptr<NoteButton> > IDNoteButtonMap; 445 IDNoteButtonMap id_note_button_map; 446 /* map of ControllerNoteButtons by CC */ 447 typedef std::map<int, boost::shared_ptr<ControllerButton> > CCControllerButtonMap; 448 CCControllerButtonMap cc_controller_button_map; 449 /* map of ControllerButtons by ButtonID */ 450 typedef std::map<ButtonID, boost::shared_ptr<ControllerButton> > IDControllerButtonMap; 451 IDControllerButtonMap id_controller_button_map; 452 453 454 /* map of Fader by CC */ 455 typedef std::map<int, boost::shared_ptr<Fader> > CCFaderMap; 456 CCFaderMap cc_fader_map; 457 /* map of Fader by FaderID */ 458 typedef std::map<FaderID, boost::shared_ptr<Fader> > IDFaderMap; 459 IDFaderMap id_fader_map; 460 461 /* map of Knob by CC */ 462 typedef std::map<int, boost::shared_ptr<Knob> > CCKnobMap; 463 CCKnobMap cc_knob_map; 464 /* map of Knob by KnobID */ 465 typedef std::map<KnobID, boost::shared_ptr<Knob> > IDKnobMap; 466 IDKnobMap id_knob_map; 467 468 std::set<ButtonID> buttons_down; 469 std::set<ButtonID> consumed; 470 471 bool button_long_press_timeout(ButtonID id, boost::shared_ptr<Button> button); 472 void start_press_timeout(boost::shared_ptr<Button> , ButtonID); 473 474 void init_buttons(); 475 void init_buttons(bool startup); 476 void init_buttons (ButtonID buttons[], uint8_t i); 477 void init_knobs(); 478 void init_knobs(KnobID knobs[], uint8_t i); 479 void init_knobs_and_buttons(); 480 481 void init_device_mode(); 482 void init_dm_callbacks(); 483 484 void switch_template(uint8_t t); 485 void filter_stripables (ARDOUR::StripableList& strips) const; 486 487 void build_maps(); 488 489 // Bundle to represent our input ports 490 boost::shared_ptr<ARDOUR::Bundle> _input_bundle; 491 // Bundle to represent our output ports 492 boost::shared_ptr<ARDOUR::Bundle> _output_bundle; 493 494 MIDI::Port *_input_port; 495 MIDI::Port *_output_port; 496 boost::shared_ptr<ARDOUR::Port> _async_in; 497 boost::shared_ptr<ARDOUR::Port> _async_out; 498 499 void connect_to_parser(); 500 void handle_button_message(boost::shared_ptr<Button> button, MIDI::EventTwoBytes *); 501 502 bool check_pick_up(boost::shared_ptr<Controller> controller, boost::shared_ptr<ARDOUR::AutomationControl> ac, bool rotary = false); 503 504 void handle_midi_controller_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan); 505 void handle_midi_note_on_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan); 506 void handle_midi_note_off_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan); 507 void handle_midi_sysex(MIDI::Parser &, MIDI::byte *, size_t count); 508 509 bool midi_input_handler(Glib::IOCondition ioc, MIDI::Port *port); 510 511 void thread_init(); 512 513 PBD::ScopedConnectionList session_connections; 514 void connect_session_signals(); 515 void notify_transport_state_changed(); 516 void notify_loop_state_changed(); 517 void notify_parameter_changed(std::string); 518 519 /* Knob methods */ 520 boost::shared_ptr<Knob> knob_by_id(KnobID id); 521 boost::shared_ptr<Knob>* knobs_by_column(uint8_t col, boost::shared_ptr<Knob>* knob_col); 522 void update_knob_led_by_strip(uint8_t n); 523 void update_knob_led_by_id(uint8_t id, LEDColor color); 524 525 void knob_sendA(uint8_t n); 526 void knob_sendB(uint8_t n); 527 void knob_pan(uint8_t n); 528 529 uint8_t dm_check_dummy(DeviceStatus ds); 530 531 void dm_fader(FaderID id); 532 uint8_t dm_check_pan_azi (); 533 void dm_pan_azi(KnobID k); 534 uint8_t dm_check_pan_width(); 535 void dm_pan_width (KnobID k); 536 uint8_t dm_check_trim (); 537 void dm_trim(KnobID k); 538 uint8_t dm_mute_enabled(); 539 void dm_mute_switch(); 540 uint8_t dm_solo_enabled(); 541 void dm_solo_switch(); 542 uint8_t dm_recenable_enabled(); 543 void dm_recenable_switch(); 544 void dm_select_prev_strip(); 545 void dm_select_next_strip(); 546 547 #ifdef MIXBUS 548 void dm_mb_eq_switch(); 549 void dm_mb_eq (KnobID k, bool gain, uint8_t band); 550 uint8_t dm_mb_eq_freq_enabled(); 551 uint8_t dm_mb_eq_gain_enabled(uint8_t band); 552 void dm_mb_eq_shape_switch(uint8_t band); 553 uint8_t dm_mb_eq_shape_enabled(uint8_t band); 554 uint8_t dm_mb_flt_enabled(); 555 void dm_mb_flt_frq (KnobID k, bool hpf); 556 void dm_mb_flt_switch(); 557 void dm_mb_send_enabled(KnobID k); 558 uint8_t dm_mb_check_send_knob(KnobID k); 559 uint8_t dm_mb_check_send_button(uint8_t s); 560 void dm_mb_sends (KnobID k); 561 void dm_mb_send_switch (ButtonID b); 562 uint8_t dm_mb_comp_enabled(); 563 void dm_mb_comp_switch(); 564 void dm_mb_comp (KnobID k, CompParam c); 565 void dm_mb_comp_thresh (FaderID id); 566 uint8_t dm_mb_has_tapedrive(); 567 void dm_mb_tapedrive (KnobID k); 568 uint8_t dm_mb_master_assign_enabled(); 569 void dm_mb_master_assign_switch(); 570 #endif 571 572 /* Fader methods */ 573 void fader(uint8_t n); 574 575 576 /* Button methods */ 577 boost::shared_ptr<TrackButton> track_button_by_range(uint8_t n, uint8_t first, uint8_t middle); focus_button_by_column(uint8_t col)578 boost::shared_ptr<TrackButton> focus_button_by_column(uint8_t col) { return track_button_by_range(col, 41, 57) ; } control_button_by_column(uint8_t col)579 boost::shared_ptr<TrackButton> control_button_by_column(uint8_t col) { return track_button_by_range(col, 73, 89) ; } 580 581 582 void button_device(); 583 void button_device_long_press(); 584 void button_track_mode(TrackMode state); 585 void button_mute(); 586 void button_mute_long_press(); 587 void button_solo(); 588 void button_solo_long_press(); 589 void button_record(); 590 void button_select_up(); 591 void button_select_down(); 592 void button_select_left(); 593 void button_select_right(); 594 595 void button_track_focus(uint8_t n); 596 void button_press_track_control(uint8_t n); 597 void button_release_track_control(uint8_t n); 598 599 boost::shared_ptr<ARDOUR::AutomationControl> get_ac_by_state(uint8_t n); 600 void update_track_focus_led(uint8_t n); 601 void update_track_control_led(uint8_t n); 602 send_bank_switch_0()603 void send_bank_switch_0() { send_bank_switch(0); } send_bank_switch_1()604 void send_bank_switch_1() { send_bank_switch(1); } 605 606 /* stripables */ 607 608 int32_t bank_start; 609 PBD::ScopedConnectionList stripable_connections; 610 boost::shared_ptr<ARDOUR::Stripable> stripable[8]; 611 612 void stripables_added (); 613 614 void stripable_property_change (PBD::PropertyChange const& what_changed, uint32_t which); 615 616 void switch_bank (uint32_t base); 617 solo_changed(uint32_t n)618 void solo_changed (uint32_t n) { solo_mute_rec_changed(n); } mute_changed(uint32_t n)619 void mute_changed (uint32_t n) { solo_mute_rec_changed(n); } rec_changed(uint32_t n)620 void rec_changed (uint32_t n) { solo_mute_rec_changed(n); } 621 void solo_iso_changed (uint32_t n); 622 void solo_iso_led_bank (); 623 #ifdef MIXBUS 624 void master_send_changed (uint32_t n); 625 void master_send_led_bank (); 626 #endif 627 628 void solo_mute_rec_changed (uint32_t n); 629 630 /* special Stripable */ 631 632 boost::shared_ptr<ARDOUR::Stripable> master; 633 634 void port_registration_handler(); 635 636 enum ConnectionState { InputConnected = 0x1, OutputConnected = 0x2 }; 637 638 int connection_state; 639 bool connection_handler(boost::weak_ptr<ARDOUR::Port>, std::string name1, 640 boost::weak_ptr<ARDOUR::Port>, std::string name2, 641 bool yn); 642 PBD::ScopedConnection port_connection; 643 void connected(); 644 645 /* GUI */ 646 647 mutable LCXLGUI *gui; 648 void build_gui(); 649 650 void stripable_selection_changed(); 651 652 bool in_range_select; 653 }; 654 655 656 } // namespace ArdourSurface 657 658 #endif /* __ardour_launch_control_h__ */ 659