2 Copyright (C) 2016 Paul Davis
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.
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.
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.
19 #ifndef __ardour_launch_control_h__
20 #define __ardour_launch_control_h__
28 #define ABSTRACT_UI_EXPORTS
29 #include "pbd/abstract_ui.h"
31 #include "midi++/types.h"
33 #include "ardour/mode.h"
34 #include "ardour/types.h"
36 #include "control_protocol/control_protocol.h"
37 #include "control_protocol/types.h"
39 #include "midi_byte_array.h"
53 namespace ArdourSurface {
56 struct LaunchControlRequest : public BaseUI::BaseRequestObject {
58 LaunchControlRequest() {}
59 ~LaunchControlRequest() {}
63 class LaunchControlMenu;
65 class LaunchControlXL : public ARDOUR::ControlProtocol,
66 public AbstractUI<LaunchControlRequest> {
139 enum LEDFlag { Normal = 0xC, Blink = 0x8, DoubleBuffering = 0x0 };
141 enum LEDColor { Off=0, RedLow = 1, RedFull = 3, GreenLow = 16, GreenFull = 48, Yellow = 50, AmberLow = 17, AmberFull = 51};
145 Controller(uint8_t cn, uint8_t val = 0) : _controller_number(cn), _value(val) {}
147 uint8_t controller_number() const { return _controller_number; }
148 uint8_t value() const { return _value; }
149 void set_value(uint8_t val) { _value = val; }
152 uint8_t _controller_number;
157 LED(uint8_t i, LEDColor c, LaunchControlXL& l) : _index(i), _color(c), _flag(Normal), lcxl(&l) {}
158 LED(uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& lcxl) : _index(i), _color(c), _flag(f) {}
161 LEDColor color() const { return _color; }
162 LEDFlag flag() const { return _flag; }
163 uint8_t index() const { return _index; }
164 void set_flag(LEDFlag f) { _flag = f; }
166 virtual MidiByteArray state_msg(bool light) const = 0;
172 MidiByteArray _state_msg;
173 LaunchControlXL* lcxl;
176 struct MultiColorLED : public LED {
177 MultiColorLED (uint8_t i, LEDColor c, LaunchControlXL& l) : LED(i, c, l) {}
178 MultiColorLED (uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& l)
181 void set_color(LEDColor c) { _color = c; }
186 : press_method(&LaunchControlXL::relax)
187 , release_method(&LaunchControlXL::relax)
188 , long_press_method(&LaunchControlXL::relax), _id(id) {}
190 Button(ButtonID id, void (LaunchControlXL::*press)())
191 : press_method(press)
192 , release_method(&LaunchControlXL::relax)
193 , long_press_method(&LaunchControlXL::relax), _id(id) {}
195 Button(ButtonID id, void (LaunchControlXL::*press)(), void (LaunchControlXL::*release)())
196 : press_method(press), release_method(release)
197 , long_press_method(&LaunchControlXL::relax), _id(id) {}
199 Button(ButtonID id, void (LaunchControlXL::*press)(), void (LaunchControlXL::*release)(), void (LaunchControlXL::*long_press)())
200 : press_method(press), release_method(release)
201 , long_press_method(long_press), _id(id) {}
205 ButtonID id() const { return _id; }
207 void (LaunchControlXL::*press_method)();
208 void (LaunchControlXL::*release_method)();
209 void (LaunchControlXL::*long_press_method)();
211 sigc::connection timeout_connection;
217 struct ControllerButton : public Button {
219 ControllerButton(ButtonID id, uint8_t cn,
220 void (LaunchControlXL::*press)())
221 : Button(id, press), _controller_number(cn) {}
223 ControllerButton(ButtonID id, uint8_t cn,
224 void (LaunchControlXL::*press)(),
225 void (LaunchControlXL::*release)())
226 : Button(id, press, release), _controller_number(cn) {}
229 uint8_t controller_number() const { return _controller_number; }
232 uint8_t _controller_number;
235 struct NoteButton : public Button {
237 NoteButton(ButtonID id, uint8_t cn, void (LaunchControlXL::*press)())
238 : Button(id, press), _note_number(cn) {}
240 NoteButton(ButtonID id, uint8_t cn,
241 void (LaunchControlXL::*press)(),
242 void (LaunchControlXL::*release)())
243 : Button(id, press, release), _note_number(cn) {}
244 NoteButton(ButtonID id, uint8_t cn,
245 void (LaunchControlXL::*press)(),
246 void (LaunchControlXL::*release)(),
247 void (LaunchControlXL::*release_long)())
248 : Button(id, press, release, release_long), _note_number(cn) {}
250 uint8_t note_number() const { return _note_number; }
253 uint8_t _note_number;
256 struct TrackButton : public NoteButton, public MultiColorLED {
257 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor color,
258 void (LaunchControlXL::*press)(), LaunchControlXL& l)
259 : NoteButton(id, nn, press), MultiColorLED(index, color, l) {}
261 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor color,
262 void (LaunchControlXL::*press)(),
263 void (LaunchControlXL::*release)(),
265 : NoteButton(id, nn, press, release), MultiColorLED(index, color, l) {}
267 MidiByteArray state_msg(bool light = true) const;
270 struct SelectButton : public ControllerButton, public LED {
271 SelectButton(ButtonID id, uint8_t cn, uint8_t index, void (LaunchControlXL::*press)(), LaunchControlXL& l)
272 : ControllerButton(id, cn, press), LED(index, RedFull, l) {}
274 MidiByteArray state_msg(bool light) const;
277 struct TrackStateButton : public NoteButton, public LED {
278 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(), LaunchControlXL& l)
279 : NoteButton(id, nn, press)
280 , LED(index, Yellow, l) {}
282 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(),
283 void (LaunchControlXL::*release)(),
285 : NoteButton(id, nn, press, release)
286 , LED(index, Yellow, l) {}
288 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(),
289 void (LaunchControlXL::*release)(),
290 void (LaunchControlXL::*release_long)(),
292 : NoteButton(id, nn, press, release, release_long)
293 , LED(index, Yellow, l) {}
295 MidiByteArray state_msg(bool light) const;
298 struct Fader : public Controller {
299 Fader(FaderID id, uint8_t cn)
300 : Controller(cn, 0), _id(id) {} // minimal value
302 FaderID id() const { return _id; }
304 void controller_changed(Controller* controller);
310 struct Knob : public Controller, public MultiColorLED {
311 Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor color, LaunchControlXL& l)
313 , MultiColorLED(index, color, l)
314 , _id(id) {} // knob 50/50 value
316 KnobID id() const { return _id; }
318 MidiByteArray state_msg(bool light = true) const;
325 LaunchControlXL(ARDOUR::Session &);
330 static void *request_factory(uint32_t);
332 std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles();
334 bool has_editor() const { return true; }
335 void *get_gui() const;
336 void tear_down_gui();
338 int set_active(bool yn);
339 XMLNode &get_state();
340 int set_state(const XMLNode &node, int version);
342 PBD::Signal0<void> ConnectionChange;
344 boost::shared_ptr<ARDOUR::Port> input_port();
345 boost::shared_ptr<ARDOUR::Port> output_port();
347 Button *button_by_id(ButtonID);
349 static std::string button_name_by_id(ButtonID);
350 static std::string knob_name_by_id(KnobID);
351 static std::string fader_name_by_id(FaderID);
353 void write(const MidiByteArray &);
354 void reset(uint8_t chan);
356 TrackMode track_mode() const { return _track_mode; }
357 void set_track_mode(TrackMode mode);
359 uint8_t template_number() const { return _template_number; }
363 TrackMode _track_mode;
364 uint8_t _template_number;
366 void do_request(LaunchControlRequest *);
368 int begin_using_device();
369 int stop_using_device();
371 void ports_release();
372 void run_event_loop();
373 void stop_event_loop();
377 /* map of NoteButtons by NoteNumber */
378 typedef std::map<int, NoteButton *> NNNoteButtonMap;
379 NNNoteButtonMap nn_note_button_map;
380 /* map of NoteButtons by ButtonID */
381 typedef std::map<ButtonID, NoteButton *> IDNoteButtonMap;
382 IDNoteButtonMap id_note_button_map;
383 /* map of ControllerNoteButtons by CC */
384 typedef std::map<int, ControllerButton *> CCControllerButtonMap;
385 CCControllerButtonMap cc_controller_button_map;
386 /* map of ControllerButtons by ButtonID */
387 typedef std::map<ButtonID, ControllerButton *> IDControllerButtonMap;
388 IDControllerButtonMap id_controller_button_map;
391 /* map of Fader by CC */
392 typedef std::map<int, Fader *> CCFaderMap;
393 CCFaderMap cc_fader_map;
394 /* map of Fader by FaderID */
395 typedef std::map<FaderID, Fader *> IDFaderMap;
396 IDFaderMap id_fader_map;
398 /* map of Knob by CC */
399 typedef std::map<int, Knob *> CCKnobMap;
400 CCKnobMap cc_knob_map;
401 /* map of Knob by KnobID */
402 typedef std::map<KnobID, Knob *> IDKnobMap;
403 IDKnobMap id_knob_map;
405 std::set<ButtonID> buttons_down;
406 std::set<ButtonID> consumed;
408 bool button_long_press_timeout(ButtonID id, Button *button);
409 void start_press_timeout(Button *, ButtonID);
411 void init_buttons(bool startup);
413 void switch_template(uint8_t t);
417 // Bundle to represent our input ports
418 boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
419 // Bundle to represent our output ports
420 boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
422 MIDI::Port *_input_port;
423 MIDI::Port *_output_port;
424 boost::shared_ptr<ARDOUR::Port> _async_in;
425 boost::shared_ptr<ARDOUR::Port> _async_out;
427 void connect_to_parser();
428 void handle_button_message(Button* button, MIDI::EventTwoBytes *);
429 void handle_fader_message(Fader* fader);
430 void handle_knob_message(Knob* knob);
432 bool check_pick_up(Controller* controller, boost::shared_ptr<ARDOUR::AutomationControl> ac);
434 void handle_midi_controller_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
435 void handle_midi_note_on_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
436 void handle_midi_note_off_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
437 void handle_midi_sysex(MIDI::Parser &, MIDI::byte *, size_t count);
439 bool midi_input_handler(Glib::IOCondition ioc, MIDI::Port *port);
443 PBD::ScopedConnectionList session_connections;
444 void connect_session_signals();
445 void notify_transport_state_changed();
446 void notify_loop_state_changed();
447 void notify_parameter_changed(std::string);
452 TrackButton* track_button_by_range(uint8_t n, uint8_t first, uint8_t middle);
453 TrackButton* focus_button_by_collumn(uint8_t col) { return track_button_by_range(col, 41, 57) ; }
454 TrackButton* control_button_by_collumn(uint8_t col) { return track_button_by_range(col, 73, 89) ; }
457 void button_device();
458 void button_device_long_press();
459 void button_track_mode(TrackMode state);
462 void button_record();
463 void button_select_up();
464 void button_select_down();
465 void button_select_left();
466 void button_select_right();
468 void button_track_focus(uint8_t n);
469 void button_track_control(uint8_t n);
471 boost::shared_ptr<ARDOUR::AutomationControl> get_ac_by_state(uint8_t n);
472 void update_track_control_led(uint8_t n);
474 void button_track_focus_1() { ControlProtocol::ToggleStripableSelection (stripable[0]); }
475 void button_track_focus_2() { ControlProtocol::ToggleStripableSelection (stripable[1]); }
476 void button_track_focus_3() { ControlProtocol::ToggleStripableSelection (stripable[2]); }
477 void button_track_focus_4() { ControlProtocol::ToggleStripableSelection (stripable[3]); }
478 void button_track_focus_5() { ControlProtocol::ToggleStripableSelection (stripable[4]); }
479 void button_track_focus_6() { ControlProtocol::ToggleStripableSelection (stripable[5]); }
480 void button_track_focus_7() { ControlProtocol::ToggleStripableSelection (stripable[6]); }
481 void button_track_focus_8() { ControlProtocol::ToggleStripableSelection (stripable[7]); }
483 void button_track_control_1() { button_track_control(0); }
484 void button_track_control_2() { button_track_control(1); }
485 void button_track_control_3() { button_track_control(2); }
486 void button_track_control_4() { button_track_control(3); }
487 void button_track_control_5() { button_track_control(4); }
488 void button_track_control_6() { button_track_control(5); }
489 void button_track_control_7() { button_track_control(6); }
490 void button_track_control_8() { button_track_control(7); }
495 PBD::ScopedConnectionList stripable_connections;
496 boost::shared_ptr<ARDOUR::Stripable> stripable[8];
498 void stripables_added ();
500 void stripable_property_change (PBD::PropertyChange const& what_changed, uint32_t which);
502 void switch_bank (uint32_t base);
504 void solo_changed (uint32_t n) { solo_mute_rec_changed(n); }
505 void mute_changed (uint32_t n) { solo_mute_rec_changed(n); }
506 void rec_changed (uint32_t n) { solo_mute_rec_changed(n); }
507 void solo_mute_rec_changed (uint32_t n);
509 /* special Stripable */
511 boost::shared_ptr<ARDOUR::Stripable> master;
513 PBD::ScopedConnection port_reg_connection;
514 void port_registration_handler();
516 enum ConnectionState { InputConnected = 0x1, OutputConnected = 0x2 };
518 int connection_state;
519 bool connection_handler(boost::weak_ptr<ARDOUR::Port>, std::string name1,
520 boost::weak_ptr<ARDOUR::Port>, std::string name2,
522 PBD::ScopedConnection port_connection;
527 mutable LCXLGUI *gui;
530 void stripable_selection_changed();
532 bool in_range_select;
536 } // namespace ArdourSurface
538 #endif /* __ardour_launch_control_h__ */