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(LEDFlag::Normal), lcxl(&l) {}
158 LED(uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& lcxl) : _index(i), _color(c), _flag(f) {}
160 LEDColor color() const { return _color; }
161 LEDFlag flag() const { return _flag; }
162 uint8_t index() const { return _index; }
163 void set_flag(LEDFlag f) { _flag = f; }
165 virtual MidiByteArray state_msg(bool light) const = 0;
171 MidiByteArray _state_msg;
172 LaunchControlXL* lcxl;
175 struct MultiColorLED : public LED {
176 MultiColorLED (uint8_t i, LEDColor c, LaunchControlXL& l) : LED(i, c, l) {}
177 MultiColorLED (uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& l)
180 void set_color(LEDColor c) { _color = c; }
185 : press_method(&LaunchControlXL::relax)
186 , release_method(&LaunchControlXL::relax)
187 , long_press_method(&LaunchControlXL::relax), _id(id) {}
189 Button(ButtonID id, void (LaunchControlXL::*press)())
190 : press_method(press)
191 , release_method(&LaunchControlXL::relax)
192 , long_press_method(&LaunchControlXL::relax), _id(id) {}
194 Button(ButtonID id, void (LaunchControlXL::*press)(), void (LaunchControlXL::*release)())
195 : press_method(press), release_method(release)
196 , long_press_method(&LaunchControlXL::relax), _id(id) {}
198 Button(ButtonID id, void (LaunchControlXL::*press)(), void (LaunchControlXL::*release)(), void (LaunchControlXL::*long_press)())
199 : press_method(press), release_method(release)
200 , long_press_method(long_press), _id(id) {}
204 ButtonID id() const { return _id; }
206 void (LaunchControlXL::*press_method)();
207 void (LaunchControlXL::*release_method)();
208 void (LaunchControlXL::*long_press_method)();
210 sigc::connection timeout_connection;
216 struct ControllerButton : public Button {
218 ControllerButton(ButtonID id, uint8_t cn,
219 void (LaunchControlXL::*press)())
220 : Button(id, press), _controller_number(cn) {}
222 ControllerButton(ButtonID id, uint8_t cn,
223 void (LaunchControlXL::*press)(),
224 void (LaunchControlXL::*release)())
225 : Button(id, press, release), _controller_number(cn) {}
228 uint8_t controller_number() const { return _controller_number; }
231 uint8_t _controller_number;
234 struct NoteButton : public Button {
236 NoteButton(ButtonID id, uint8_t cn, void (LaunchControlXL::*press)())
237 : Button(id, press), _note_number(cn) {}
239 NoteButton(ButtonID id, uint8_t cn,
240 void (LaunchControlXL::*press)(),
241 void (LaunchControlXL::*release)())
242 : Button(id, press, release), _note_number(cn) {}
243 NoteButton(ButtonID id, uint8_t cn,
244 void (LaunchControlXL::*press)(),
245 void (LaunchControlXL::*release)(),
246 void (LaunchControlXL::*release_long)())
247 : Button(id, press, release, release_long), _note_number(cn) {}
249 uint8_t note_number() const { return _note_number; }
252 uint8_t _note_number;
255 struct TrackButton : public NoteButton, public MultiColorLED {
256 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor color,
257 void (LaunchControlXL::*press)(), LaunchControlXL& l)
258 : NoteButton(id, nn, press), MultiColorLED(index, color, l) {}
260 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor color,
261 void (LaunchControlXL::*press)(),
262 void (LaunchControlXL::*release)(),
264 : NoteButton(id, nn, press, release), MultiColorLED(index, color, l) {}
266 MidiByteArray state_msg(bool light = true) const;
269 struct SelectButton : public ControllerButton, public LED {
270 SelectButton(ButtonID id, uint8_t cn, uint8_t index, void (LaunchControlXL::*press)(), LaunchControlXL& l)
271 : ControllerButton(id, cn, press), LED(index, LEDColor::RedFull, l) {}
273 MidiByteArray state_msg(bool light) const;
276 struct TrackStateButton : public NoteButton, public LED {
277 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(), LaunchControlXL& l)
278 : NoteButton(id, nn, press)
279 , LED(index, LEDColor::Yellow, l) {}
281 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(),
282 void (LaunchControlXL::*release)(),
284 : NoteButton(id, nn, press, release)
285 , LED(index, LEDColor::Yellow, l) {}
287 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(),
288 void (LaunchControlXL::*release)(),
289 void (LaunchControlXL::*release_long)(),
291 : NoteButton(id, nn, press, release, release_long)
292 , LED(index, LEDColor::Yellow, l) {}
294 MidiByteArray state_msg(bool light) const;
297 struct Fader : public Controller {
298 Fader(FaderID id, uint8_t cn)
299 : Controller(cn, 0), _id(id) {} // minimal value
301 FaderID id() const { return _id; }
303 void controller_changed(Controller* controller);
309 struct Knob : public Controller, public MultiColorLED {
310 Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor color, LaunchControlXL& l)
312 , MultiColorLED(index, color, l)
313 , _id(id) {} // knob 50/50 value
315 KnobID id() const { return _id; }
317 MidiByteArray state_msg(bool light = true) const;
324 LaunchControlXL(ARDOUR::Session &);
329 static void *request_factory(uint32_t);
331 std::list<boost::shared_ptr<ARDOUR::Bundle>> bundles();
333 bool has_editor() const { return true; }
334 void *get_gui() const;
335 void tear_down_gui();
337 int set_active(bool yn);
338 XMLNode &get_state();
339 int set_state(const XMLNode &node, int version);
341 PBD::Signal0<void> ConnectionChange;
343 boost::shared_ptr<ARDOUR::Port> input_port();
344 boost::shared_ptr<ARDOUR::Port> output_port();
346 Button *button_by_id(ButtonID);
348 static std::string button_name_by_id(ButtonID);
349 static std::string knob_name_by_id(KnobID);
350 static std::string fader_name_by_id(FaderID);
352 void write(const MidiByteArray &);
354 TrackMode track_mode() const { return _track_mode; }
355 void set_track_mode(TrackMode mode);
357 uint8_t template_number() const { return _template_number; }
361 TrackMode _track_mode;
362 uint8_t _template_number;
364 void do_request(LaunchControlRequest *);
366 int begin_using_device();
367 int stop_using_device();
369 void ports_release();
370 void run_event_loop();
371 void stop_event_loop();
375 /* map of NoteButtons by NoteNumber */
376 typedef std::map<int, NoteButton *> NNNoteButtonMap;
377 NNNoteButtonMap nn_note_button_map;
378 /* map of NoteButtons by ButtonID */
379 typedef std::map<ButtonID, NoteButton *> IDNoteButtonMap;
380 IDNoteButtonMap id_note_button_map;
381 /* map of ControllerNoteButtons by CC */
382 typedef std::map<int, ControllerButton *> CCControllerButtonMap;
383 CCControllerButtonMap cc_controller_button_map;
384 /* map of ControllerButtons by ButtonID */
385 typedef std::map<ButtonID, ControllerButton *> IDControllerButtonMap;
386 IDControllerButtonMap id_controller_button_map;
389 /* map of Fader by CC */
390 typedef std::map<int, Fader *> CCFaderMap;
391 CCFaderMap cc_fader_map;
392 /* map of Fader by FaderID */
393 typedef std::map<FaderID, Fader *> IDFaderMap;
394 IDFaderMap id_fader_map;
396 /* map of Knob by CC */
397 typedef std::map<int, Knob *> CCKnobMap;
398 CCKnobMap cc_knob_map;
399 /* map of Knob by KnobID */
400 typedef std::map<KnobID, Knob *> IDKnobMap;
401 IDKnobMap id_knob_map;
403 std::set<ButtonID> buttons_down;
404 std::set<ButtonID> consumed;
406 bool button_long_press_timeout(ButtonID id, Button *button);
407 void start_press_timeout(Button *, ButtonID);
409 void init_buttons(bool startup);
411 void switch_template(uint8_t t);
415 // Bundle to represent our input ports
416 boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
417 // Bundle to represent our output ports
418 boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
420 MIDI::Port *_input_port;
421 MIDI::Port *_output_port;
422 boost::shared_ptr<ARDOUR::Port> _async_in;
423 boost::shared_ptr<ARDOUR::Port> _async_out;
425 void connect_to_parser();
426 void handle_button_message(Button* button, MIDI::EventTwoBytes *);
427 void handle_fader_message(Fader* fader);
428 void handle_knob_message(Knob* knob);
430 void handle_midi_controller_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
431 void handle_midi_note_on_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
432 void handle_midi_note_off_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
433 void handle_midi_sysex(MIDI::Parser &, MIDI::byte *, size_t count);
435 bool midi_input_handler(Glib::IOCondition ioc, MIDI::Port *port);
439 PBD::ScopedConnectionList session_connections;
440 void connect_session_signals();
441 void notify_transport_state_changed();
442 void notify_loop_state_changed();
443 void notify_parameter_changed(std::string);
448 TrackButton* track_button_by_number(uint8_t n, uint8_t first, uint8_t middle);
449 TrackButton* focus_button_by_number(uint8_t n) { return track_button_by_number(n, 41, 57) ; }
450 TrackButton* control_button_by_number(uint8_t n) { return track_button_by_number(n, 73, 89) ; }
453 void button_device();
454 void button_device_long_press();
455 void button_track_mode(TrackMode state);
456 void button_mute() { button_track_mode(TrackMode::TrackMute); }
457 void button_solo() { button_track_mode(TrackMode::TrackSolo); }
458 void button_record() { button_track_mode(TrackMode::TrackRecord); }
459 void button_select_up();
460 void button_select_down();
461 void button_select_left();
462 void button_select_right();
464 void button_track_focus(uint8_t n);
465 void button_track_control(uint8_t n);
467 boost::shared_ptr<ARDOUR::AutomationControl> get_ac_by_state(uint8_t n);
468 void update_track_control_led(uint8_t n);
470 void button_track_focus_1() { ControlProtocol::ToggleStripableSelection (stripable[0]); }
471 void button_track_focus_2() { ControlProtocol::ToggleStripableSelection (stripable[1]); }
472 void button_track_focus_3() { ControlProtocol::ToggleStripableSelection (stripable[2]); }
473 void button_track_focus_4() { ControlProtocol::ToggleStripableSelection (stripable[3]); }
474 void button_track_focus_5() { ControlProtocol::ToggleStripableSelection (stripable[4]); }
475 void button_track_focus_6() { ControlProtocol::ToggleStripableSelection (stripable[5]); }
476 void button_track_focus_7() { ControlProtocol::ToggleStripableSelection (stripable[6]); }
477 void button_track_focus_8() { ControlProtocol::ToggleStripableSelection (stripable[7]); }
479 void button_track_control_1() { button_track_control(0); }
480 void button_track_control_2() { button_track_control(1); }
481 void button_track_control_3() { button_track_control(2); }
482 void button_track_control_4() { button_track_control(3); }
483 void button_track_control_5() { button_track_control(4); }
484 void button_track_control_6() { button_track_control(5); }
485 void button_track_control_7() { button_track_control(6); }
486 void button_track_control_8() { button_track_control(7); }
491 PBD::ScopedConnectionList stripable_connections;
492 boost::shared_ptr<ARDOUR::Stripable> stripable[8];
494 void stripables_added ();
496 void stripable_property_change (PBD::PropertyChange const& what_changed, uint32_t which);
498 void switch_bank (uint32_t base);
500 void solo_changed (uint32_t n) { solo_mute_rec_changed(n); }
501 void mute_changed (uint32_t n) { solo_mute_rec_changed(n); }
502 void rec_changed (uint32_t n) { solo_mute_rec_changed(n); }
503 void solo_mute_rec_changed (uint32_t n);
505 /* special Stripable */
507 boost::shared_ptr<ARDOUR::Stripable> master;
509 PBD::ScopedConnection port_reg_connection;
510 void port_registration_handler();
512 enum ConnectionState { InputConnected = 0x1, OutputConnected = 0x2 };
514 int connection_state;
515 bool connection_handler(boost::weak_ptr<ARDOUR::Port>, std::string name1,
516 boost::weak_ptr<ARDOUR::Port>, std::string name2,
518 PBD::ScopedConnection port_connection;
523 mutable LCXLGUI *gui;
526 void stripable_selection_changed();
528 bool in_range_select;
532 } // namespace ArdourSurface
534 #endif /* __ardour_launch_control_h__ */