Ardour  9.2-541-gc1841a13dd
launch_control_xl.h
Go to the documentation of this file.
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/types.h"
36 
38 #include "control_protocol/types.h"
39 
40 #include "midi_byte_array.h"
41 
42 namespace MIDI {
43 class Parser;
44 class Port;
45 } // namespace MIDI
46 
47 namespace ARDOUR {
48 class AsyncMIDIPort;
49 class Port;
50 class MidiBuffer;
51 class MidiTrack;
52 } // namespace ARDOUR
53 
54 namespace ArdourSurface {
55 
56 
57 struct LaunchControlRequest : public BaseUI::BaseRequestObject {
58  public:
61 };
62 
63 class LCXLGUI;
64 class LaunchControlMenu;
65 
67  public AbstractUI<LaunchControlRequest>
68 {
69 public:
70  enum TrackMode {
74  };
75 
76  enum ButtonID {
77  Focus1 = 0,
101  };
102 
103  enum FaderID {
104  Fader1 = 0,
111  Fader8
112  };
113 
114  enum KnobID {
115  SendA1 = 0,
138  Pan8
139  };
140 
144  dev_active
145  };
146 
147  enum LEDFlag { Normal = 0xC, Blink = 0x8, DoubleBuffering = 0x0 };
148  enum LEDColor { Off=0, RedLow = 1, RedFull = 3, GreenLow = 16, GreenFull = 48, YellowLow = 34, YellowFull = 51, AmberLow = 18, AmberFull = 35};
149 
150 
151 #ifdef MIXBUS
152  enum CompParam {
153  CompMakeup,
154  CompMode,
155  };
156 #endif
157 
158  struct Controller {
159  Controller(uint8_t cn, uint8_t val, std::function<void ()> action)
160  : _controller_number(cn)
161  , _value(val)
162  , action_method(action) {}
163 
164  uint8_t controller_number() const { return _controller_number; }
165  uint8_t value() const { return _value; }
166  void set_value(uint8_t val) { _value = val; }
167 
168  protected:
170  uint8_t _value;
171 
172  public:
173  std::function<void ()> action_method;
174  };
175 
176  struct LED {
177  LED(uint8_t i, LEDColor c, LaunchControlXL& l) : _index(i), _color(c), _flag(Normal), lcxl(&l) {}
178  LED(uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& lcxl) : _index(i), _color(c), _flag(f) {}
179  virtual ~LED() {}
180 
181  LEDColor color() const { return _color; }
182  LEDFlag flag() const { return _flag; }
183  uint8_t index() const { return _index; }
184  void set_flag(LEDFlag f) { _flag = f; }
185 
186  virtual MidiByteArray state_msg(bool light) const = 0;
187 
188  protected:
189  uint8_t _index;
194  };
195 
196  struct MultiColorLED : public LED {
197  MultiColorLED (uint8_t i, LEDColor c, LaunchControlXL& l) : LED(i, c, l) {}
199  : LED(i, c, f, l) {}
200 
201  void set_color(LEDColor c) { _color = c; }
202  };
203 
204  struct Button {
205  Button(ButtonID id, std::function<void ()> press, std::function<void ()> release,
206  std::function<void ()> long_press)
209  , long_press_method(long_press),
210  _id(id) {}
211 
212  virtual ~Button() {}
213 
214  ButtonID id() const { return _id; }
215 
216  std::function<void ()> press_method;
217  std::function<void ()> release_method;
218  std::function<void ()> long_press_method;
219 
220  sigc::connection timeout_connection;
221 
222  protected:
224  };
225 
226  struct ControllerButton : public Button {
227  ControllerButton(ButtonID id, uint8_t cn,
228  std::function<void ()> press,
229  std::function<void ()> release,
230  std::function<void ()> long_release)
231  : Button(id, press, release, long_release), _controller_number(cn) {}
232 
233 
234 
235  uint8_t controller_number() const { return _controller_number; }
236 
237  private:
239  };
240 
241  struct NoteButton : public Button {
242  NoteButton(ButtonID id, uint8_t cn,
243  std::function<void ()> press,
244  std::function<void ()> release,
245  std::function<void ()> release_long)
246  : Button(id, press, release, release_long), _note_number(cn) {}
247 
248  uint8_t note_number() const { return _note_number; }
249 
250  private:
251  uint8_t _note_number;
252  };
253 
254  struct TrackButton : public NoteButton, public MultiColorLED {
255  TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor c_on, LEDColor c_off,
256  std::function<void ()> press,
257  std::function<void ()> release,
258  std::function<void ()> release_long,
259  std::function<uint8_t ()> check,
260  LaunchControlXL& l)
261  : NoteButton(id, nn, press, release, release_long)
262  , MultiColorLED(index, Off, l)
263  , check_method(check)
264  , _color_enabled (c_on)
265  , _color_disabled (c_off) {}
266 
267 
268 
269 
272  void set_color_enabled (LEDColor c_on) { _color_enabled = c_on; }
273  void set_color_disabled (LEDColor c_off) { _color_disabled = c_off; }
274  std::function<uint8_t ()> check_method;
275 
276 
277  MidiByteArray state_msg(bool light = true) const;
278 
279  private:
282  };
283 
284  struct SelectButton : public ControllerButton, public LED {
285  SelectButton(ButtonID id, uint8_t cn, uint8_t index,
286  std::function<void ()> press,
287  std::function<void ()> release,
288  std::function<void ()> long_release,
289  LaunchControlXL& l)
290  : ControllerButton(id, cn, press, release, long_release), LED(index, RedFull, l) {}
291 
292 
293  MidiByteArray state_msg(bool light) const;
294  };
295 
296  struct TrackStateButton : public NoteButton, public LED {
297  TrackStateButton(ButtonID id, uint8_t nn, uint8_t index,
298  std::function<void ()> press,
299  std::function<void ()> release,
300  std::function<void ()> release_long,
301  LaunchControlXL& l)
302  : NoteButton(id, nn, press, release, release_long)
303  , LED(index, YellowLow, l) {}
304 
305  MidiByteArray state_msg(bool light) const;
306  };
307 
308  struct Fader : public Controller {
309  Fader(FaderID id, uint8_t cn, std::function<void ()> action)
310  : Controller(cn, 0, action), _id(id) {} // minimal value
311 
312  FaderID id() const { return _id; }
313 
315 
316  private:
318  };
319 
320  struct Knob : public Controller, public MultiColorLED {
321  Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, std::function<void ()> action,
322  LaunchControlXL &l)
323  : Controller(cn, 64, action)
324  , MultiColorLED(index, Off, l)
325  , _id(id)
326  , _color_enabled (c_on)
327  , _color_disabled (c_off) {} // knob 50/50 value
328 
329  Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, std::function<void ()> action,
330  std::function<uint8_t ()> check, LaunchControlXL &l)
331  : Controller(cn, 64, action)
332  , MultiColorLED(index, Off, l)
333  , check_method(check)
334  , _id(id)
335  , _color_enabled (c_on)
336  , _color_disabled (c_off) {} // knob 50/50 value
337 
338 
339 
340  KnobID id() const { return _id; }
343  std::function<uint8_t ()> check_method;
344 
345  MidiByteArray state_msg(bool light = true) const;
346 
347  private:
351  };
352 
353 public:
356 
357  std::list<std::shared_ptr<ARDOUR::Bundle> > bundles();
358 
359  bool has_editor() const { return true; }
360  void *get_gui() const;
362 
364 
365  int set_active(bool yn);
366  XMLNode& get_state() const;
367  int set_state(const XMLNode &node, int version);
368 
370 
371  std::shared_ptr<ARDOUR::Port> input_port();
372  std::shared_ptr<ARDOUR::Port> output_port();
373 
375 
376  static std::string button_name_by_id(ButtonID);
377  static std::string knob_name_by_id(KnobID);
378  static std::string fader_name_by_id(FaderID);
379 
380  void write(const MidiByteArray &);
381  void reset(uint8_t chan);
382 
383  void set_fader8master (bool yn);
384  bool fader8master () const { return _fader8master; }
385 
386  void set_refresh_leds_flag (bool yn);
387  bool refresh_leds_flag () const { return _refresh_leds_flag; }
388 
389  void set_device_mode (bool yn);
390  bool device_mode () const { return _device_mode; }
391 
392 #ifdef MIXBUS
393  void set_ctrllowersends (bool yn);
394  bool ctrllowersends () const { return _ctrllowersends; }
395 
396  void store_fss_type();
397  bool fss_is_mixbus() const { return _fss_is_mixbus; }
398 #endif
399  TrackMode track_mode() const { return _track_mode; }
401 
402  uint8_t template_number() const { return _template_number; }
403 
404  void set_send_bank (int offset);
405  void send_bank_switch(bool up);
406  int send_bank_base () const { return _send_bank_base; }
407 
409 
410 private:
411  bool in_use;
414 
417 #ifdef MIXBUS
418  bool _ctrllowersends;
419  bool _fss_is_mixbus;
420 #endif
422 
424 
426 
433 
434  void relax() {}
435 
436  /* map of NoteButtons by NoteNumber */
437  typedef std::map<int, std::shared_ptr<NoteButton> > NNNoteButtonMap;
439  /* map of NoteButtons by ButtonID */
440  typedef std::map<ButtonID, std::shared_ptr<NoteButton> > IDNoteButtonMap;
442  /* map of ControllerNoteButtons by CC */
443  typedef std::map<int, std::shared_ptr<ControllerButton> > CCControllerButtonMap;
445  /* map of ControllerButtons by ButtonID */
446  typedef std::map<ButtonID, std::shared_ptr<ControllerButton> > IDControllerButtonMap;
448 
449 
450  /* map of Fader by CC */
451  typedef std::map<int, std::shared_ptr<Fader> > CCFaderMap;
453  /* map of Fader by FaderID */
454  typedef std::map<FaderID, std::shared_ptr<Fader> > IDFaderMap;
456 
457  /* map of Knob by CC */
458  typedef std::map<int, std::shared_ptr<Knob> > CCKnobMap;
460  /* map of Knob by KnobID */
461  typedef std::map<KnobID, std::shared_ptr<Knob> > IDKnobMap;
463 
464  std::set<ButtonID> buttons_down;
465  std::set<ButtonID> consumed;
466 
467  bool button_long_press_timeout(ButtonID id, std::shared_ptr<Button> button);
468  void start_press_timeout(std::shared_ptr<Button> , ButtonID);
469 
470  void init_buttons();
471  void init_buttons(bool startup);
472  void init_buttons (ButtonID buttons[], uint8_t i);
473  void init_knobs();
474  void init_knobs(KnobID knobs[], uint8_t i);
476 
479 
480  void switch_template(uint8_t t);
482 
483  void build_maps();
484 
485  // Bundle to represent our input ports
486  std::shared_ptr<ARDOUR::Bundle> _input_bundle;
487  // Bundle to represent our output ports
488  std::shared_ptr<ARDOUR::Bundle> _output_bundle;
489 
492  std::shared_ptr<ARDOUR::Port> _async_in;
493  std::shared_ptr<ARDOUR::Port> _async_out;
494 
496  void handle_button_message(std::shared_ptr<Button> button, MIDI::EventTwoBytes *);
497 
498  bool check_pick_up(std::shared_ptr<Controller> controller, std::shared_ptr<ARDOUR::AutomationControl> ac, bool rotary = false);
499 
503  void handle_midi_sysex(MIDI::Parser &, MIDI::byte *, size_t count);
504 
505  bool midi_input_handler(Glib::IOCondition ioc, MIDI::Port *port);
506 
507  void thread_init();
508 
513  void notify_parameter_changed(std::string);
514 
515  /* Knob methods */
516  std::shared_ptr<Knob> knob_by_id(KnobID id);
517  std::shared_ptr<Knob>* knobs_by_column(uint8_t col, std::shared_ptr<Knob>* knob_col);
518  void update_knob_led_by_strip(uint8_t n);
520 
521  void knob_sendA(uint8_t n);
522  void knob_sendB(uint8_t n);
523  void knob_pan(uint8_t n);
524 
526 
527  void dm_fader(FaderID id);
528  uint8_t dm_check_pan_azi ();
532  uint8_t dm_check_trim ();
533  void dm_trim(KnobID k);
534  uint8_t dm_mute_enabled();
536  uint8_t dm_solo_enabled();
542 
543 #ifdef MIXBUS
544  void dm_mb_eq_switch();
545  void dm_mb_eq (KnobID k, bool gain, uint8_t band);
546  uint8_t dm_mb_eq_freq_enabled();
547  uint8_t dm_mb_eq_gain_enabled(uint8_t band);
548  void dm_mb_eq_shape_switch(uint8_t band);
549  uint8_t dm_mb_eq_shape_enabled(uint8_t band);
550  uint8_t dm_mb_flt_enabled();
551  void dm_mb_flt_frq (KnobID k, bool hpf);
552  void dm_mb_flt_switch();
553  void dm_mb_send_enabled(KnobID k);
554  uint8_t dm_mb_check_send_knob(KnobID k);
555  uint8_t dm_mb_check_send_button(uint8_t s);
556  void dm_mb_sends (KnobID k);
557  void dm_mb_send_switch (ButtonID b);
558  uint8_t dm_mb_comp_enabled();
559  void dm_mb_comp_switch();
560  void dm_mb_comp (KnobID k, CompParam c);
561  void dm_mb_comp_thresh (FaderID id);
562  uint8_t dm_mb_has_tapedrive();
563  void dm_mb_tapedrive (KnobID k);
564  uint8_t dm_mb_master_assign_enabled();
565  void dm_mb_master_assign_switch();
566 #endif
567 
568  /* Fader methods */
569  void fader(uint8_t n);
570 
571 
572  /* Button methods */
573  std::shared_ptr<TrackButton> track_button_by_range(uint8_t n, uint8_t first, uint8_t middle);
574  std::shared_ptr<TrackButton> focus_button_by_column(uint8_t col) { return track_button_by_range(col, 41, 57) ; }
575  std::shared_ptr<TrackButton> control_button_by_column(uint8_t col) { return track_button_by_range(col, 73, 89) ; }
576 
577 
581  void button_mute();
583  void button_solo();
590 
591  void button_track_focus(uint8_t n);
592  void button_press_track_control(uint8_t n);
594 
595  std::shared_ptr<ARDOUR::AutomationControl> get_ac_by_state(uint8_t n);
596  void update_track_focus_led(uint8_t n);
597  void update_track_control_led(uint8_t n);
598 
601 
602  /* stripables */
603 
604  int32_t bank_start;
606  std::shared_ptr<ARDOUR::Stripable> stripable[8];
607 
609 
610  void stripable_property_change (PBD::PropertyChange const& what_changed, uint32_t which);
611 
612  void switch_bank (uint32_t base);
613 
614  void solo_changed (uint32_t n) { solo_mute_rec_changed(n); }
615  void mute_changed (uint32_t n) { solo_mute_rec_changed(n); }
616  void rec_changed (uint32_t n) { solo_mute_rec_changed(n); }
617  void solo_iso_changed (uint32_t n);
619 #ifdef MIXBUS
620  void master_send_changed (uint32_t n);
621  void master_send_led_bank ();
622 #endif
623 
624  void solo_mute_rec_changed (uint32_t n);
625 
626  /* special Stripable */
627 
628  std::shared_ptr<ARDOUR::Stripable> master;
629 
631 
633 
635  bool connection_handler(std::weak_ptr<ARDOUR::Port>, std::string name1,
636  std::weak_ptr<ARDOUR::Port>, std::string name2,
637  bool yn);
639  void connected();
640 
641  /* GUI */
642 
643  mutable LCXLGUI *gui;
644  void build_gui();
645 
647 
649 };
650 
651 
652 } // namespace ArdourSurface
653 
654 #endif /* __ardour_launch_control_h__ */
static std::string knob_name_by_id(KnobID)
std::map< FaderID, std::shared_ptr< Fader > > IDFaderMap
void handle_midi_note_on_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan)
Button * button_by_id(ButtonID)
void do_request(LaunchControlRequest *)
void update_track_control_led(uint8_t n)
std::shared_ptr< ARDOUR::Stripable > stripable[8]
PBD::ScopedConnectionList stripable_connections
void start_press_timeout(std::shared_ptr< Button >, ButtonID)
bool connection_handler(std::weak_ptr< ARDOUR::Port >, std::string name1, std::weak_ptr< ARDOUR::Port >, std::string name2, bool yn)
void handle_button_message(std::shared_ptr< Button > button, MIDI::EventTwoBytes *)
std::shared_ptr< ARDOUR::Port > input_port()
void set_track_mode(TrackMode mode)
std::shared_ptr< ARDOUR::Bundle > _output_bundle
std::map< int, std::shared_ptr< Knob > > CCKnobMap
void handle_midi_controller_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan)
std::shared_ptr< ARDOUR::Port > output_port()
LaunchControlXL(ARDOUR::Session &)
std::shared_ptr< TrackButton > control_button_by_column(uint8_t col)
PBD::ScopedConnection port_connection
void write(const MidiByteArray &)
void init_buttons(bool startup)
int set_state(const XMLNode &node, int version)
std::shared_ptr< TrackButton > focus_button_by_column(uint8_t col)
std::map< ButtonID, std::shared_ptr< ControllerButton > > IDControllerButtonMap
std::map< int, std::shared_ptr< Fader > > CCFaderMap
void switch_bank(uint32_t base)
std::shared_ptr< ARDOUR::Stripable > master
void solo_iso_changed(uint32_t n)
void solo_mute_rec_changed(uint32_t n)
void update_knob_led_by_id(uint8_t id, LEDColor color)
std::shared_ptr< ARDOUR::Port > _async_out
void button_track_focus(uint8_t n)
bool check_pick_up(std::shared_ptr< Controller > controller, std::shared_ptr< ARDOUR::AutomationControl > ac, bool rotary=false)
uint8_t dm_check_dummy(DeviceStatus ds)
void init_knobs(KnobID knobs[], uint8_t i)
PBD::Signal< void()> ConnectionChange
void init_buttons(ButtonID buttons[], uint8_t i)
std::shared_ptr< Knob > * knobs_by_column(uint8_t col, std::shared_ptr< Knob > *knob_col)
std::map< KnobID, std::shared_ptr< Knob > > IDKnobMap
void handle_midi_sysex(MIDI::Parser &, MIDI::byte *, size_t count)
std::shared_ptr< ARDOUR::Port > _async_in
void stripable_property_change(PBD::PropertyChange const &what_changed, uint32_t which)
std::shared_ptr< ARDOUR::AutomationControl > get_ac_by_state(uint8_t n)
bool button_long_press_timeout(ButtonID id, std::shared_ptr< Button > button)
std::shared_ptr< Knob > knob_by_id(KnobID id)
std::shared_ptr< TrackButton > track_button_by_range(uint8_t n, uint8_t first, uint8_t middle)
std::shared_ptr< ARDOUR::Bundle > _input_bundle
void button_press_track_control(uint8_t n)
void button_release_track_control(uint8_t n)
void update_knob_led_by_strip(uint8_t n)
static std::string button_name_by_id(ButtonID)
void set_send_bank(int offset)
CCControllerButtonMap cc_controller_button_map
static std::string fader_name_by_id(FaderID)
std::list< std::shared_ptr< ARDOUR::Bundle > > bundles()
std::map< int, std::shared_ptr< ControllerButton > > CCControllerButtonMap
bool midi_input_handler(Glib::IOCondition ioc, MIDI::Port *port)
std::map< int, std::shared_ptr< NoteButton > > NNNoteButtonMap
std::set< ButtonID > buttons_down
void update_track_focus_led(uint8_t n)
std::map< ButtonID, std::shared_ptr< NoteButton > > IDNoteButtonMap
void button_track_mode(TrackMode state)
IDControllerButtonMap id_controller_button_map
void notify_parameter_changed(std::string)
void filter_stripables(ARDOUR::StripableList &strips) const
void handle_midi_note_off_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan)
PBD::ScopedConnectionList session_connections
Definition: xml++.h:114
PBD::PropertyDescriptor< gain_t > gain
PBD::PropertyDescriptor< uint32_t > color
std::list< std::shared_ptr< Stripable > > StripableList
Button(ButtonID id, std::function< void()> press, std::function< void()> release, std::function< void()> long_press)
ControllerButton(ButtonID id, uint8_t cn, std::function< void()> press, std::function< void()> release, std::function< void()> long_release)
Controller(uint8_t cn, uint8_t val, std::function< void()> action)
void controller_changed(Controller *controller)
Fader(FaderID id, uint8_t cn, std::function< void()> action)
MidiByteArray state_msg(bool light=true) const
Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, std::function< void()> action, LaunchControlXL &l)
Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, std::function< void()> action, std::function< uint8_t()> check, LaunchControlXL &l)
std::function< uint8_t()> check_method
virtual MidiByteArray state_msg(bool light) const =0
LED(uint8_t i, LEDColor c, LaunchControlXL &l)
LED(uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL &lcxl)
MultiColorLED(uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL &l)
MultiColorLED(uint8_t i, LEDColor c, LaunchControlXL &l)
NoteButton(ButtonID id, uint8_t cn, std::function< void()> press, std::function< void()> release, std::function< void()> release_long)
SelectButton(ButtonID id, uint8_t cn, uint8_t index, std::function< void()> press, std::function< void()> release, std::function< void()> long_release, LaunchControlXL &l)
MidiByteArray state_msg(bool light) const
TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor c_on, LEDColor c_off, std::function< void()> press, std::function< void()> release, std::function< void()> release_long, std::function< uint8_t()> check, LaunchControlXL &l)
MidiByteArray state_msg(bool light=true) const
TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, std::function< void()> press, std::function< void()> release, std::function< void()> release_long, LaunchControlXL &l)
MidiByteArray state_msg(bool light) const