push2: basic GUI dialog
[ardour.git] / libs / surfaces / push2 / push2.h
index 48359b6637af26bd87d65b60676da061cfb6e17a..7e480495ad6e5bba6c90fcb8ff30679f177d8b11 100644 (file)
@@ -27,7 +27,6 @@
 #include <libusb.h>
 
 #include <cairomm/refptr.h>
-#include <glibmm/threads.h>
 
 #define ABSTRACT_UI_EXPORTS
 #include "pbd/abstract_ui.h"
 
 namespace Cairo {
        class ImageSurface;
+       class Context;
+}
+
+namespace Pango {
+       class Layout;
 }
 
 namespace MIDI {
@@ -49,6 +53,7 @@ namespace MIDI {
 namespace ARDOUR {
        class AsyncMIDIPort;
        class Port;
+       class MidiBuffer;
 }
 
 namespace ArdourSurface {
@@ -69,20 +74,36 @@ class Push2 : public ARDOUR::ControlProtocol
        static bool probe ();
        static void* request_factory (uint32_t);
 
+       bool has_editor () const { return true; }
+       void* get_gui () const;
+       void  tear_down_gui ();
+
        int set_active (bool yn);
        XMLNode& get_state();
        int set_state (const XMLNode & node, int version);
 
+       PBD::Signal0<void> ConnectionChange;
+
+       boost::shared_ptr<ARDOUR::Port> input_port();
+       boost::shared_ptr<ARDOUR::Port> output_port();
+
    private:
        libusb_device_handle *handle;
-       Glib::Threads::Mutex fb_lock;
        uint8_t   frame_header[16];
-       uint16_t* device_frame_buffer[2];
+       uint16_t* device_frame_buffer;
        int  device_buffer;
        Cairo::RefPtr<Cairo::ImageSurface> frame_buffer;
        sigc::connection vblank_connection;
        sigc::connection periodic_connection;
 
+       enum ModifierState {
+               None = 0,
+               ModShift = 0x1,
+               ModSelect = 0x2,
+       };
+
+       ModifierState modifier_state;
+
        static const int cols;
        static const int rows;
        static const int pixels_per_row;
@@ -91,7 +112,8 @@ class Push2 : public ARDOUR::ControlProtocol
        int stop ();
        int open ();
        int close ();
-       int render ();
+       bool redraw ();
+       int blit_to_device_frame_buffer ();
        bool vblank ();
 
        enum ButtonID {
@@ -151,7 +173,7 @@ class Push2 : public ARDOUR::ControlProtocol
        struct LED
        {
                enum State {
-                       Off,
+                       NoTransition,
                        OneShot24th,
                        OneShot16th,
                        OneShot8th,
@@ -169,7 +191,17 @@ class Push2 : public ARDOUR::ControlProtocol
                        Blinking2th
                };
 
-               LED (uint8_t e) : _extra (e), _color_index (0), _state (Off) {}
+               enum Colors {
+                       Black = 0,
+                       Red = 127,
+                       Green = 126,
+                       Blue = 125,
+                       DarkGray = 124,
+                       LightGray = 123,
+                       White = 122
+               };
+
+               LED (uint8_t e) : _extra (e), _color_index (0), _state (NoTransition) {}
                virtual ~LED() {}
 
                uint8_t extra () const { return _extra; }
@@ -193,7 +225,7 @@ class Push2 : public ARDOUR::ControlProtocol
                        , x (xx)
                        , y (yy) {}
 
-               MidiByteArray state_msg () const { return MidiByteArray (3, 0x90|_state, _extra, (_state == Off) ? 0 : _color_index); }
+               MidiByteArray state_msg () const { return MidiByteArray (3, 0x90|_state, _extra, _color_index); }
 
                int coord () const { return (y * 8) + x; }
                int note_number() const { return extra(); }
@@ -208,6 +240,7 @@ class Push2 : public ARDOUR::ControlProtocol
                        , id (bb)
                        , press_method (&Push2::relax)
                        , release_method (&Push2::relax)
+                       , long_press_method (&Push2::relax)
                {}
 
                Button (ButtonID bb, uint8_t ex, void (Push2::*press)())
@@ -215,6 +248,7 @@ class Push2 : public ARDOUR::ControlProtocol
                        , id (bb)
                        , press_method (press)
                        , release_method (&Push2::relax)
+                       , long_press_method (&Push2::relax)
                {}
 
                Button (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)())
@@ -222,14 +256,25 @@ class Push2 : public ARDOUR::ControlProtocol
                        , id (bb)
                        , press_method (press)
                        , release_method (release)
+                       , long_press_method (&Push2::relax)
                {}
 
-               MidiByteArray state_msg () const { return MidiByteArray (3, 0xb0|_state, _extra, (_state == Off) ? 0 : _color_index); }
+               Button (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)(), void (Push2::*long_press)())
+                       : LED (ex)
+                       , id (bb)
+                       , press_method (press)
+                       , release_method (release)
+                       , long_press_method (long_press)
+               {}
+
+               MidiByteArray state_msg () const { return MidiByteArray (3, 0xb0|_state, _extra, _color_index); }
                int controller_number() const { return extra(); }
 
                ButtonID id;
                void (Push2::*press_method)();
                void (Push2::*release_method)();
+               void (Push2::*long_press_method)();
+               sigc::connection timeout_connection;
        };
 
        struct ColorButton : public Button {
@@ -242,6 +287,9 @@ class Push2 : public ARDOUR::ControlProtocol
 
                ColorButton (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)())
                        : Button (bb, ex, press, release) {}
+
+               ColorButton (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)(), void (Push2::*long_press)())
+                       : Button (bb, ex, press, release, long_press) {}
        };
 
        struct WhiteButton : public Button {
@@ -253,6 +301,9 @@ class Push2 : public ARDOUR::ControlProtocol
 
                WhiteButton (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)())
                        : Button (bb, ex, press, release) {}
+
+               WhiteButton (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)(), void (Push2::*long_press)())
+                       : Button (bb, ex, press, release, long_press) {}
        };
 
        void relax () {}
@@ -263,6 +314,14 @@ class Push2 : public ARDOUR::ControlProtocol
        /* map of Buttons by ButtonID */
        typedef std::map<ButtonID,Button*> IDButtonMap;
        IDButtonMap id_button_map;
+       std::set<ButtonID> buttons_down;
+       std::set<ButtonID> consumed;
+
+       bool button_long_press_timeout (ButtonID id);
+       void start_press_timeout (Button&, ButtonID);
+
+       void init_buttons (bool startup);
+       void init_touch_strip ();
 
        /* map of Pads by note number */
        typedef std::map<int,Pad*> NNPadMap;
@@ -283,10 +342,10 @@ class Push2 : public ARDOUR::ControlProtocol
 
        void build_maps ();
 
-       MIDI::Port* _input_port[2];
-       MIDI::Port* _output_port[2];
-       boost::shared_ptr<ARDOUR::Port> _async_in[2];
-       boost::shared_ptr<ARDOUR::Port> _async_out[2];
+       MIDI::Port* _input_port;
+       MIDI::Port* _output_port;
+       boost::shared_ptr<ARDOUR::Port> _async_in;
+       boost::shared_ptr<ARDOUR::Port> _async_out;
 
        void connect_to_parser ();
        void handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t);
@@ -295,7 +354,7 @@ class Push2 : public ARDOUR::ControlProtocol
        void handle_midi_note_off_message (MIDI::Parser&, MIDI::EventTwoBytes*);
        void handle_midi_sysex (MIDI::Parser&, MIDI::byte *, size_t count);
 
-       void write (int port, const MidiByteArray&);
+       void write (const MidiByteArray&);
        bool midi_input_handler (Glib::IOCondition ioc, MIDI::Port* port);
        bool periodic ();
 
@@ -314,6 +373,112 @@ class Push2 : public ARDOUR::ControlProtocol
        void button_recenable ();
        void button_up ();
        void button_down ();
+       void button_right ();
+       void button_left ();
+       void button_metronome ();
+       void button_repeat ();
+       void button_solo ();
+       void button_fixed_length ();
+       void button_new ();
+       void button_browse ();
+       void button_clip ();
+       void button_upper (uint32_t n);
+       void button_lower (uint32_t n);
+       void button_upper_1 () { button_upper (0); }
+       void button_upper_2 () { button_upper (1); }
+       void button_upper_3 () { button_upper (2); }
+       void button_upper_4 () { button_upper (3); }
+       void button_upper_5 () { button_upper (4); }
+       void button_upper_6 () { button_upper (5); }
+       void button_upper_7 () { button_upper (6); }
+       void button_upper_8 () { button_upper (7); }
+       void button_lower_1 () { button_lower (0); }
+       void button_lower_2 () { button_lower (1); }
+       void button_lower_3 () { button_lower (2); }
+       void button_lower_4 () { button_lower (3); }
+       void button_lower_5 () { button_lower (4); }
+       void button_lower_6 () { button_lower (5); }
+       void button_lower_7 () { button_lower (6); }
+       void button_lower_8 () { button_lower (7); }
+       void button_undo ();
+       void button_fwd32t ();
+       void button_fwd32 ();
+       void button_fwd16t ();
+       void button_fwd16 ();
+       void button_fwd8t ();
+       void button_fwd8 ();
+       void button_fwd4t ();
+       void button_fwd4 ();
+       void button_add_track ();
+       void button_stop ();
+       void button_shift_press ();
+       void button_shift_release ();
+       void button_shift_long_press ();
+       void button_select_press ();
+       void button_select_release ();
+       void button_select_long_press ();
+       void button_page_left ();
+       void button_page_right ();
+
+       void start_shift ();
+       void end_shift ();
+       void start_select ();
+       void end_select ();
+
+       /* encoders */
+
+       void strip_vpot (int, int);
+       void other_vpot (int, int);
+       void strip_vpot_touch (int, bool);
+       void other_vpot_touch (int, bool);
+
+       /* widgets */
+
+       Cairo::RefPtr<Cairo::Context> context;
+       Glib::RefPtr<Pango::Layout> tc_clock_layout;
+       Glib::RefPtr<Pango::Layout> bbt_clock_layout;
+       Glib::RefPtr<Pango::Layout> upper_layout[8];
+       Glib::RefPtr<Pango::Layout> mid_layout[8];
+       Glib::RefPtr<Pango::Layout> lower_layout[8];
+
+       void splash ();
+       ARDOUR::microseconds_t splash_start;
+
+       /* stripables */
+
+       int32_t bank_start;
+       PBD::ScopedConnectionList stripable_connections;
+       boost::shared_ptr<ARDOUR::Stripable> stripable[8];
+       boost::shared_ptr<ARDOUR::Stripable> master;
+       boost::shared_ptr<ARDOUR::Stripable> monitor;
+
+       void solo_change (int);
+       void mute_change (int);
+       void stripable_property_change (PBD::PropertyChange const& what_changed, int which);
+
+       void switch_bank (uint32_t base);
+
+       bool pad_filter (ARDOUR::MidiBuffer& in, ARDOUR::MidiBuffer& out) const;
+
+       boost::weak_ptr<ARDOUR::Stripable> first_selected_stripable;
+
+       PBD::ScopedConnection port_reg_connection;
+       void port_registration_handler ();
+
+       enum ConnectionState {
+               InputConnected = 0x1,
+               OutputConnected = 0x2
+       };
+
+       int connection_state;
+       bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn);
+       PBD::ScopedConnection port_connection;
+
+       /* GUI */
+
+       mutable void *gui;
+       void build_gui ();
+
 };