/* * Copyright (C) 2018 Jan Lentfer * Copyright (C) 2018 Robin Gareus * Copyright (C) 2018 Térence Clastres * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __ardour_launch_control_h__ #define __ardour_launch_control_h__ #include #include #include #include #include #define ABSTRACT_UI_EXPORTS #include "pbd/abstract_ui.h" #include "midi++/types.h" #include "ardour/mode.h" #include "ardour/types.h" #include "control_protocol/control_protocol.h" #include "control_protocol/types.h" #include "midi_byte_array.h" namespace MIDI { class Parser; class Port; } // namespace MIDI namespace ARDOUR { class AsyncMIDIPort; class Port; class MidiBuffer; class MidiTrack; } // namespace ARDOUR namespace ArdourSurface { struct LaunchControlRequest : public BaseUI::BaseRequestObject { public: LaunchControlRequest() {} ~LaunchControlRequest() {} }; class LCXLGUI; class LaunchControlMenu; class LaunchControlXL : public ARDOUR::ControlProtocol, public AbstractUI { public: enum TrackMode { TrackMute, TrackSolo, TrackRecord }; enum ButtonID { Focus1 = 0, Focus2, Focus3, Focus4, Focus5, Focus6, Focus7, Focus8, Control1, Control2, Control3, Control4, Control5, Control6, Control7, Control8, Device, Mute, Solo, Record, SelectUp, SelectDown, SelectLeft, SelectRight }; enum FaderID { Fader1 = 0, Fader2, Fader3, Fader4, Fader5, Fader6, Fader7, Fader8 }; enum KnobID { SendA1 = 0, SendA2, SendA3, SendA4, SendA5, SendA6, SendA7, SendA8, SendB1, SendB2, SendB3, SendB4, SendB5, SendB6, SendB7, SendB8, Pan1, Pan2, Pan3, Pan4, Pan5, Pan6, Pan7, Pan8 }; enum DeviceStatus { dev_nonexistant = 0, dev_inactive, dev_active }; enum LEDFlag { Normal = 0xC, Blink = 0x8, DoubleBuffering = 0x0 }; enum LEDColor { Off=0, RedLow = 1, RedFull = 3, GreenLow = 16, GreenFull = 48, YellowLow = 34, YellowFull = 51, AmberLow = 18, AmberFull = 35}; #ifdef MIXBUS enum CompParam { CompMakeup, CompMode, }; #endif struct Controller { Controller(uint8_t cn, uint8_t val, std::function action) : _controller_number(cn) , _value(val) , action_method(action) {} uint8_t controller_number() const { return _controller_number; } uint8_t value() const { return _value; } void set_value(uint8_t val) { _value = val; } protected: uint8_t _controller_number; uint8_t _value; public: std::function action_method; }; struct LED { LED(uint8_t i, LEDColor c, LaunchControlXL& l) : _index(i), _color(c), _flag(Normal), lcxl(&l) {} LED(uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& lcxl) : _index(i), _color(c), _flag(f) {} virtual ~LED() {} LEDColor color() const { return _color; } LEDFlag flag() const { return _flag; } uint8_t index() const { return _index; } void set_flag(LEDFlag f) { _flag = f; } virtual MidiByteArray state_msg(bool light) const = 0; protected: uint8_t _index; LEDColor _color; LEDFlag _flag; MidiByteArray _state_msg; LaunchControlXL* lcxl; }; struct MultiColorLED : public LED { MultiColorLED (uint8_t i, LEDColor c, LaunchControlXL& l) : LED(i, c, l) {} MultiColorLED (uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& l) : LED(i, c, f, l) {} void set_color(LEDColor c) { _color = c; } }; struct Button { Button(ButtonID id, std::function press, std::function release, std::function long_press) : press_method(press) , release_method(release) , long_press_method(long_press), _id(id) {} virtual ~Button() {} ButtonID id() const { return _id; } std::function press_method; std::function release_method; std::function long_press_method; sigc::connection timeout_connection; protected: ButtonID _id; }; struct ControllerButton : public Button { ControllerButton(ButtonID id, uint8_t cn, std::function press, std::function release, std::function long_release) : Button(id, press, release, long_release), _controller_number(cn) {} uint8_t controller_number() const { return _controller_number; } private: uint8_t _controller_number; }; struct NoteButton : public Button { NoteButton(ButtonID id, uint8_t cn, std::function press, std::function release, std::function release_long) : Button(id, press, release, release_long), _note_number(cn) {} uint8_t note_number() const { return _note_number; } private: uint8_t _note_number; }; struct TrackButton : public NoteButton, public MultiColorLED { TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor c_on, LEDColor c_off, std::function press, std::function release, std::function release_long, std::function check, LaunchControlXL& l) : NoteButton(id, nn, press, release, release_long) , MultiColorLED(index, Off, l) , check_method(check) , _color_enabled (c_on) , _color_disabled (c_off) {} LEDColor color_enabled() const { return _color_enabled; } LEDColor color_disabled() const { return _color_disabled; } void set_color_enabled (LEDColor c_on) { _color_enabled = c_on; } void set_color_disabled (LEDColor c_off) { _color_disabled = c_off; } std::function check_method; MidiByteArray state_msg(bool light = true) const; private: LEDColor _color_enabled; LEDColor _color_disabled; }; struct SelectButton : public ControllerButton, public LED { SelectButton(ButtonID id, uint8_t cn, uint8_t index, std::function press, std::function release, std::function long_release, LaunchControlXL& l) : ControllerButton(id, cn, press, release, long_release), LED(index, RedFull, l) {} MidiByteArray state_msg(bool light) const; }; struct TrackStateButton : public NoteButton, public LED { TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, std::function press, std::function release, std::function release_long, LaunchControlXL& l) : NoteButton(id, nn, press, release, release_long) , LED(index, YellowLow, l) {} MidiByteArray state_msg(bool light) const; }; struct Fader : public Controller { Fader(FaderID id, uint8_t cn, std::function action) : Controller(cn, 0, action), _id(id) {} // minimal value FaderID id() const { return _id; } void controller_changed(Controller* controller); private: FaderID _id; }; struct Knob : public Controller, public MultiColorLED { Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, std::function action, LaunchControlXL &l) : Controller(cn, 64, action) , MultiColorLED(index, Off, l) , _id(id) , _color_enabled (c_on) , _color_disabled (c_off) {} // knob 50/50 value Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, std::function action, std::function check, LaunchControlXL &l) : Controller(cn, 64, action) , MultiColorLED(index, Off, l) , check_method(check) , _id(id) , _color_enabled (c_on) , _color_disabled (c_off) {} // knob 50/50 value KnobID id() const { return _id; } LEDColor color_enabled() const { return _color_enabled; } LEDColor color_disabled() const { return _color_disabled; } std::function check_method; MidiByteArray state_msg(bool light = true) const; private: KnobID _id; LEDColor _color_enabled; LEDColor _color_disabled; }; public: LaunchControlXL(ARDOUR::Session &); ~LaunchControlXL(); std::list > bundles(); bool has_editor() const { return true; } void *get_gui() const; void tear_down_gui(); int get_amount_of_tracks(); int set_active(bool yn); XMLNode& get_state() const; int set_state(const XMLNode &node, int version); PBD::Signal ConnectionChange; std::shared_ptr input_port(); std::shared_ptr output_port(); Button *button_by_id(ButtonID); static std::string button_name_by_id(ButtonID); static std::string knob_name_by_id(KnobID); static std::string fader_name_by_id(FaderID); void write(const MidiByteArray &); void reset(uint8_t chan); void set_fader8master (bool yn); bool fader8master () const { return _fader8master; } void set_refresh_leds_flag (bool yn); bool refresh_leds_flag () const { return _refresh_leds_flag; } void set_device_mode (bool yn); bool device_mode () const { return _device_mode; } #ifdef MIXBUS void set_ctrllowersends (bool yn); bool ctrllowersends () const { return _ctrllowersends; } void store_fss_type(); bool fss_is_mixbus() const { return _fss_is_mixbus; } #endif TrackMode track_mode() const { return _track_mode; } void set_track_mode(TrackMode mode); uint8_t template_number() const { return _template_number; } void set_send_bank (int offset); void send_bank_switch(bool up); int send_bank_base () const { return _send_bank_base; } CONTROL_PROTOCOL_THREADS_NEED_TEMPO_MAP_DECL(); private: bool in_use; TrackMode _track_mode; uint8_t _template_number; bool _fader8master; bool _device_mode; #ifdef MIXBUS bool _ctrllowersends; bool _fss_is_mixbus; #endif bool _refresh_leds_flag; int _send_bank_base; void do_request(LaunchControlRequest *); int begin_using_device(); int stop_using_device(); int ports_acquire(); void ports_release(); void run_event_loop(); void stop_event_loop(); void relax() {} /* map of NoteButtons by NoteNumber */ typedef std::map > NNNoteButtonMap; NNNoteButtonMap nn_note_button_map; /* map of NoteButtons by ButtonID */ typedef std::map > IDNoteButtonMap; IDNoteButtonMap id_note_button_map; /* map of ControllerNoteButtons by CC */ typedef std::map > CCControllerButtonMap; CCControllerButtonMap cc_controller_button_map; /* map of ControllerButtons by ButtonID */ typedef std::map > IDControllerButtonMap; IDControllerButtonMap id_controller_button_map; /* map of Fader by CC */ typedef std::map > CCFaderMap; CCFaderMap cc_fader_map; /* map of Fader by FaderID */ typedef std::map > IDFaderMap; IDFaderMap id_fader_map; /* map of Knob by CC */ typedef std::map > CCKnobMap; CCKnobMap cc_knob_map; /* map of Knob by KnobID */ typedef std::map > IDKnobMap; IDKnobMap id_knob_map; std::set buttons_down; std::set consumed; bool button_long_press_timeout(ButtonID id, std::shared_ptr