Ardour  8.7-14-g57a6773833
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/mode.h"
36 #include "ardour/types.h"
37 
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:
62 };
63 
64 class LCXLGUI;
65 class LaunchControlMenu;
66 
68  public AbstractUI<LaunchControlRequest>
69 {
70 public:
71  enum TrackMode {
75  };
76 
77  enum ButtonID {
78  Focus1 = 0,
102  };
103 
104  enum FaderID {
105  Fader1 = 0,
112  Fader8
113  };
114 
115  enum KnobID {
116  SendA1 = 0,
139  Pan8
140  };
141 
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  };
157 #endif
158 
159  struct Controller {
160  Controller(uint8_t cn, uint8_t val, boost::function<void ()> action)
161  : _controller_number(cn)
162  , _value(val)
163  , action_method(action) {}
164 
165  uint8_t controller_number() const { return _controller_number; }
166  uint8_t value() const { return _value; }
167  void set_value(uint8_t val) { _value = val; }
168 
169  protected:
171  uint8_t _value;
172 
173  public:
174  boost::function<void ()> action_method;
175  };
176 
177  struct LED {
178  LED(uint8_t i, LEDColor c, LaunchControlXL& l) : _index(i), _color(c), _flag(Normal), lcxl(&l) {}
179  LED(uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& lcxl) : _index(i), _color(c), _flag(f) {}
180  virtual ~LED() {}
181 
182  LEDColor color() const { return _color; }
183  LEDFlag flag() const { return _flag; }
184  uint8_t index() const { return _index; }
185  void set_flag(LEDFlag f) { _flag = f; }
186 
187  virtual MidiByteArray state_msg(bool light) const = 0;
188 
189  protected:
190  uint8_t _index;
195  };
196 
197  struct MultiColorLED : public LED {
198  MultiColorLED (uint8_t i, LEDColor c, LaunchControlXL& l) : LED(i, c, l) {}
200  : LED(i, c, f, l) {}
201 
202  void set_color(LEDColor c) { _color = c; }
203  };
204 
205  struct Button {
206  Button(ButtonID id, boost::function<void ()> press, boost::function<void ()> release,
207  boost::function<void ()> long_press)
210  , long_press_method(long_press),
211  _id(id) {}
212 
213  virtual ~Button() {}
214 
215  ButtonID id() const { return _id; }
216 
217  boost::function<void ()> press_method;
218  boost::function<void ()> release_method;
219  boost::function<void ()> long_press_method;
220 
221  sigc::connection timeout_connection;
222 
223  protected:
225  };
226 
227  struct ControllerButton : public Button {
228  ControllerButton(ButtonID id, uint8_t cn,
229  boost::function<void ()> press,
230  boost::function<void ()> release,
231  boost::function<void ()> long_release)
232  : Button(id, press, release, long_release), _controller_number(cn) {}
233 
234 
235 
236  uint8_t controller_number() const { return _controller_number; }
237 
238  private:
240  };
241 
242  struct NoteButton : public Button {
243  NoteButton(ButtonID id, uint8_t cn,
244  boost::function<void ()> press,
245  boost::function<void ()> release,
246  boost::function<void ()> release_long)
247  : Button(id, press, release, release_long), _note_number(cn) {}
248 
249  uint8_t note_number() const { return _note_number; }
250 
251  private:
252  uint8_t _note_number;
253  };
254 
255  struct TrackButton : public NoteButton, public MultiColorLED {
256  TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor c_on, LEDColor c_off,
257  boost::function<void ()> press,
258  boost::function<void ()> release,
259  boost::function<void ()> release_long,
260  boost::function<uint8_t ()> check,
261  LaunchControlXL& l)
262  : NoteButton(id, nn, press, release, release_long)
263  , MultiColorLED(index, Off, l)
264  , check_method(check)
265  , _color_enabled (c_on)
266  , _color_disabled (c_off) {}
267 
268 
269 
270 
273  void set_color_enabled (LEDColor c_on) { _color_enabled = c_on; }
274  void set_color_disabled (LEDColor c_off) { _color_disabled = c_off; }
275  boost::function<uint8_t ()> check_method;
276 
277 
278  MidiByteArray state_msg(bool light = true) const;
279 
280  private:
283  };
284 
285  struct SelectButton : public ControllerButton, public LED {
286  SelectButton(ButtonID id, uint8_t cn, uint8_t index,
287  boost::function<void ()> press,
288  boost::function<void ()> release,
289  boost::function<void ()> long_release,
290  LaunchControlXL& l)
291  : ControllerButton(id, cn, press, release, long_release), LED(index, RedFull, l) {}
292 
293 
294  MidiByteArray state_msg(bool light) const;
295  };
296 
297  struct TrackStateButton : public NoteButton, public LED {
298  TrackStateButton(ButtonID id, uint8_t nn, uint8_t index,
299  boost::function<void ()> press,
300  boost::function<void ()> release,
301  boost::function<void ()> release_long,
302  LaunchControlXL& l)
303  : NoteButton(id, nn, press, release, release_long)
304  , LED(index, YellowLow, l) {}
305 
306  MidiByteArray state_msg(bool light) const;
307  };
308 
309  struct Fader : public Controller {
310  Fader(FaderID id, uint8_t cn, boost::function<void ()> action)
311  : Controller(cn, 0, action), _id(id) {} // minimal value
312 
313  FaderID id() const { return _id; }
314 
316 
317  private:
319  };
320 
321  struct Knob : public Controller, public MultiColorLED {
322  Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, boost::function<void ()> action,
323  LaunchControlXL &l)
324  : Controller(cn, 64, action)
325  , MultiColorLED(index, Off, l)
326  , _id(id)
327  , _color_enabled (c_on)
328  , _color_disabled (c_off) {} // knob 50/50 value
329 
330  Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, boost::function<void ()> action,
331  boost::function<uint8_t ()> check, LaunchControlXL &l)
332  : Controller(cn, 64, action)
333  , MultiColorLED(index, Off, l)
334  , check_method(check)
335  , _id(id)
336  , _color_enabled (c_on)
337  , _color_disabled (c_off) {} // knob 50/50 value
338 
339 
340 
341  KnobID id() const { return _id; }
344  boost::function<uint8_t ()> check_method;
345 
346  MidiByteArray state_msg(bool light = true) const;
347 
348  private:
352  };
353 
354 public:
357 
358  std::list<std::shared_ptr<ARDOUR::Bundle> > bundles();
359 
360  bool has_editor() const { return true; }
361  void *get_gui() const;
363 
365 
366  int set_active(bool yn);
367  XMLNode& get_state() const;
368  int set_state(const XMLNode &node, int version);
369 
370  PBD::Signal0<void> ConnectionChange;
371 
372  std::shared_ptr<ARDOUR::Port> input_port();
373  std::shared_ptr<ARDOUR::Port> output_port();
374 
376 
377  static std::string button_name_by_id(ButtonID);
378  static std::string knob_name_by_id(KnobID);
379  static std::string fader_name_by_id(FaderID);
380 
381  void write(const MidiByteArray &);
382  void reset(uint8_t chan);
383 
384  void set_fader8master (bool yn);
385  bool fader8master () const { return _fader8master; }
386 
387  void set_refresh_leds_flag (bool yn);
388  bool refresh_leds_flag () const { return _refresh_leds_flag; }
389 
390  void set_device_mode (bool yn);
391  bool device_mode () const { return _device_mode; }
392 
393 #ifdef MIXBUS
394  void set_ctrllowersends (bool yn);
395  bool ctrllowersends () const { return _ctrllowersends; }
396 
397  void store_fss_type();
398  bool fss_is_mixbus() const { return _fss_is_mixbus; }
399 #endif
400  TrackMode track_mode() const { return _track_mode; }
402 
403  uint8_t template_number() const { return _template_number; }
404 
405  void set_send_bank (int offset);
406  void send_bank_switch(bool up);
407  int send_bank_base () const { return _send_bank_base; }
408 
410 
411 private:
412  bool in_use;
415 
418 #ifdef MIXBUS
419  bool _ctrllowersends;
420  bool _fss_is_mixbus;
421 #endif
423 
425 
427 
434 
435  void relax() {}
436 
437  /* map of NoteButtons by NoteNumber */
438  typedef std::map<int, std::shared_ptr<NoteButton> > NNNoteButtonMap;
440  /* map of NoteButtons by ButtonID */
441  typedef std::map<ButtonID, std::shared_ptr<NoteButton> > IDNoteButtonMap;
443  /* map of ControllerNoteButtons by CC */
444  typedef std::map<int, std::shared_ptr<ControllerButton> > CCControllerButtonMap;
446  /* map of ControllerButtons by ButtonID */
447  typedef std::map<ButtonID, std::shared_ptr<ControllerButton> > IDControllerButtonMap;
449 
450 
451  /* map of Fader by CC */
452  typedef std::map<int, std::shared_ptr<Fader> > CCFaderMap;
454  /* map of Fader by FaderID */
455  typedef std::map<FaderID, std::shared_ptr<Fader> > IDFaderMap;
457 
458  /* map of Knob by CC */
459  typedef std::map<int, std::shared_ptr<Knob> > CCKnobMap;
461  /* map of Knob by KnobID */
462  typedef std::map<KnobID, std::shared_ptr<Knob> > IDKnobMap;
464 
465  std::set<ButtonID> buttons_down;
466  std::set<ButtonID> consumed;
467 
468  bool button_long_press_timeout(ButtonID id, std::shared_ptr<Button> button);
469  void start_press_timeout(std::shared_ptr<Button> , ButtonID);
470 
471  void init_buttons();
472  void init_buttons(bool startup);
473  void init_buttons (ButtonID buttons[], uint8_t i);
474  void init_knobs();
475  void init_knobs(KnobID knobs[], uint8_t i);
477 
480 
481  void switch_template(uint8_t t);
483 
484  void build_maps();
485 
486  // Bundle to represent our input ports
487  std::shared_ptr<ARDOUR::Bundle> _input_bundle;
488  // Bundle to represent our output ports
489  std::shared_ptr<ARDOUR::Bundle> _output_bundle;
490 
493  std::shared_ptr<ARDOUR::Port> _async_in;
494  std::shared_ptr<ARDOUR::Port> _async_out;
495 
497  void handle_button_message(std::shared_ptr<Button> button, MIDI::EventTwoBytes *);
498 
499  bool check_pick_up(std::shared_ptr<Controller> controller, std::shared_ptr<ARDOUR::AutomationControl> ac, bool rotary = false);
500 
504  void handle_midi_sysex(MIDI::Parser &, MIDI::byte *, size_t count);
505 
506  bool midi_input_handler(Glib::IOCondition ioc, MIDI::Port *port);
507 
508  void thread_init();
509 
514  void notify_parameter_changed(std::string);
515 
516  /* Knob methods */
517  std::shared_ptr<Knob> knob_by_id(KnobID id);
518  std::shared_ptr<Knob>* knobs_by_column(uint8_t col, std::shared_ptr<Knob>* knob_col);
519  void update_knob_led_by_strip(uint8_t n);
521 
522  void knob_sendA(uint8_t n);
523  void knob_sendB(uint8_t n);
524  void knob_pan(uint8_t n);
525 
527 
528  void dm_fader(FaderID id);
529  uint8_t dm_check_pan_azi ();
533  uint8_t dm_check_trim ();
534  void dm_trim(KnobID k);
535  uint8_t dm_mute_enabled();
537  uint8_t dm_solo_enabled();
543 
544 #ifdef MIXBUS
545  void dm_mb_eq_switch();
546  void dm_mb_eq (KnobID k, bool gain, uint8_t band);
547  uint8_t dm_mb_eq_freq_enabled();
548  uint8_t dm_mb_eq_gain_enabled(uint8_t band);
549  void dm_mb_eq_shape_switch(uint8_t band);
550  uint8_t dm_mb_eq_shape_enabled(uint8_t band);
551  uint8_t dm_mb_flt_enabled();
552  void dm_mb_flt_frq (KnobID k, bool hpf);
553  void dm_mb_flt_switch();
554  void dm_mb_send_enabled(KnobID k);
555  uint8_t dm_mb_check_send_knob(KnobID k);
556  uint8_t dm_mb_check_send_button(uint8_t s);
557  void dm_mb_sends (KnobID k);
558  void dm_mb_send_switch (ButtonID b);
559  uint8_t dm_mb_comp_enabled();
560  void dm_mb_comp_switch();
561  void dm_mb_comp (KnobID k, CompParam c);
562  void dm_mb_comp_thresh (FaderID id);
563  uint8_t dm_mb_has_tapedrive();
564  void dm_mb_tapedrive (KnobID k);
565  uint8_t dm_mb_master_assign_enabled();
566  void dm_mb_master_assign_switch();
567 #endif
568 
569  /* Fader methods */
570  void fader(uint8_t n);
571 
572 
573  /* Button methods */
574  std::shared_ptr<TrackButton> track_button_by_range(uint8_t n, uint8_t first, uint8_t middle);
575  std::shared_ptr<TrackButton> focus_button_by_column(uint8_t col) { return track_button_by_range(col, 41, 57) ; }
576  std::shared_ptr<TrackButton> control_button_by_column(uint8_t col) { return track_button_by_range(col, 73, 89) ; }
577 
578 
582  void button_mute();
584  void button_solo();
591 
592  void button_track_focus(uint8_t n);
593  void button_press_track_control(uint8_t n);
595 
596  std::shared_ptr<ARDOUR::AutomationControl> get_ac_by_state(uint8_t n);
597  void update_track_focus_led(uint8_t n);
598  void update_track_control_led(uint8_t n);
599 
602 
603  /* stripables */
604 
605  int32_t bank_start;
607  std::shared_ptr<ARDOUR::Stripable> stripable[8];
608 
610 
611  void stripable_property_change (PBD::PropertyChange const& what_changed, uint32_t which);
612 
613  void switch_bank (uint32_t base);
614 
615  void solo_changed (uint32_t n) { solo_mute_rec_changed(n); }
616  void mute_changed (uint32_t n) { solo_mute_rec_changed(n); }
617  void rec_changed (uint32_t n) { solo_mute_rec_changed(n); }
618  void solo_iso_changed (uint32_t n);
620 #ifdef MIXBUS
621  void master_send_changed (uint32_t n);
622  void master_send_led_bank ();
623 #endif
624 
625  void solo_mute_rec_changed (uint32_t n);
626 
627  /* special Stripable */
628 
629  std::shared_ptr<ARDOUR::Stripable> master;
630 
632 
634 
636  bool connection_handler(std::weak_ptr<ARDOUR::Port>, std::string name1,
637  std::weak_ptr<ARDOUR::Port>, std::string name2,
638  bool yn);
640  void connected();
641 
642  /* GUI */
643 
644  mutable LCXLGUI *gui;
645  void build_gui();
646 
648 
650 };
651 
652 
653 } // namespace ArdourSurface
654 
655 #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()
PBD::Signal0< void > ConnectionChange
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)
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
boost::function< void()> long_press_method
Button(ButtonID id, boost::function< void()> press, boost::function< void()> release, boost::function< void()> long_press)
ControllerButton(ButtonID id, uint8_t cn, boost::function< void()> press, boost::function< void()> release, boost::function< void()> long_release)
Controller(uint8_t cn, uint8_t val, boost::function< void()> action)
Fader(FaderID id, uint8_t cn, boost::function< void()> action)
void controller_changed(Controller *controller)
MidiByteArray state_msg(bool light=true) const
boost::function< uint8_t()> check_method
Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, boost::function< void()> action, LaunchControlXL &l)
Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, boost::function< void()> action, boost::function< uint8_t()> check, LaunchControlXL &l)
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, boost::function< void()> press, boost::function< void()> release, boost::function< void()> release_long)
SelectButton(ButtonID id, uint8_t cn, uint8_t index, boost::function< void()> press, boost::function< void()> release, boost::function< void()> long_release, LaunchControlXL &l)
MidiByteArray state_msg(bool light) const
MidiByteArray state_msg(bool light=true) const
TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor c_on, LEDColor c_off, boost::function< void()> press, boost::function< void()> release, boost::function< void()> release_long, boost::function< uint8_t()> check, LaunchControlXL &l)
TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, boost::function< void()> press, boost::function< void()> release, boost::function< void()> release_long, LaunchControlXL &l)
MidiByteArray state_msg(bool light) const