US2400: Mark controls dirty and send them from the periodic update thread.
authorBen Loftis <ben@harrisonconsoles.com>
Thu, 19 Oct 2017 16:53:08 +0000 (11:53 -0500)
committerBen Loftis <ben@harrisonconsoles.com>
Thu, 19 Oct 2017 16:54:36 +0000 (11:54 -0500)
12 files changed:
libs/surfaces/us2400/button.h
libs/surfaces/us2400/controls.h
libs/surfaces/us2400/fader.h
libs/surfaces/us2400/led.cc
libs/surfaces/us2400/led.h
libs/surfaces/us2400/meter.h
libs/surfaces/us2400/pot.h
libs/surfaces/us2400/strip.cc
libs/surfaces/us2400/strip.h
libs/surfaces/us2400/surface.cc
libs/surfaces/us2400/surface_port.cc
libs/surfaces/us2400/us2400_control_protocol.cc

index 182e88fefcc49f3ebe7d7e4f8f16c8a1cb8d990d..9091fb21e5512b2e6b242d8aa415bb485fa1ca2a 100644 (file)
@@ -104,6 +104,8 @@ public:
 
        Surface& surface() const { return _surface; }
 
+       void mark_dirty() { _led.mark_dirty(); }
+
        void pressed ();
        void released ();
 
index 11e27b2ac53a8785ee40fd5566df6197c94a599a..1dcc5e41312cf5018b4bf78b69da83c214825c61 100644 (file)
@@ -71,6 +71,8 @@ public:
        virtual void set_control (boost::shared_ptr<ARDOUR::AutomationControl>);
        virtual void reset_control () { normal_ac.reset(); } 
 
+       virtual void mark_dirty() = 0;
+
        float get_value ();
        void set_value (float val, PBD::Controllable::GroupControlDisposition gcd = PBD::Controllable::UseGroup);
 
index 169cf454d4e7a8bcfd38ea00eec3229928905637..2a3c99e9fc068aee50870e93b235783ae479ed6e 100644 (file)
@@ -26,6 +26,8 @@ class Fader : public Control
 
        static Control* factory (Surface&, int id, const char*, Group&);
 
+       void mark_dirty() { last_update_position = llast_update_position = -1; }
+
   private:
        float position;
        int   last_update_position;
index 49466ad957f0e7759be60909d6353e7f659366ee..8b85fc7f20ffd90c96f5e9652098db40765f6182 100644 (file)
@@ -52,12 +52,9 @@ Led::set_state (LedState new_state)
        llast_state = last_state;
        last_state = new_state;
        
-
-       state = new_state;
-
        MIDI::byte msg = 0;
 
-       switch  (state.state()) {
+       switch  (new_state.state()) {
        case LedState::on:
                msg = 0x7f;
                break;
index 4ef4660d553f48c9ab6052698791f9ecde780031..1259723878f9a93e9d364432c94dd1299d20d49a 100644 (file)
@@ -41,12 +41,13 @@ public:
 
        Led (int id, std::string name, Group & group)
                : Control (id, name, group)
-               , state (off)
-               , last_state (off)
-               , llast_state (on)
+               , last_state (none)
+               , llast_state (none)
        {
        }
 
+       void mark_dirty() { last_state = llast_state = none; }
+
        Led & led() { return *this; }
        MidiByteArray set_state (LedState);
 
@@ -55,7 +56,6 @@ public:
        static Control* factory (Surface&, int id, const char*, Group&);
 
   private:
-       LedState state;
        LedState last_state;
        LedState llast_state;
 };
index 0ef9e78c33cc21c37c4f5cddde8e2d85c5813d52..41028d14aea9fb9f97fe2d7fee00cc59f991f8fc 100644 (file)
@@ -46,6 +46,8 @@ public:
        void send_update (Surface&, float dB);
        bool enabled () const { return _enabled; }
 
+       void mark_dirty() {}
+
        MidiByteArray zero();
 
        static Control* factory (Surface&, int id, const char*, Group&);
index 1ee1142fa1822b9ce17659eb9f542d07a89d19b7..1bd8a5c257a8b0444f94f3353bf98a15a8a9fd56 100644 (file)
@@ -51,6 +51,8 @@ public:
 
        static Control* factory (Surface&, int id, const char*, Group&);
 
+       void mark_dirty() { last_update_position = llast_update_position = -1; }
+
        int   last_update_position;
        int   llast_update_position;
        
index 185f49ca52ee870805f47f1b4f9e33c39b7a904f..9071601620069668b647d06c213cf8016c4920c1 100644 (file)
@@ -171,18 +171,9 @@ Strip::set_stripable (boost::shared_ptr<Stripable> r, bool /*with_messages*/)
        _fader->set_control (boost::shared_ptr<AutomationControl>());
        _vpot->set_control (boost::shared_ptr<AutomationControl>());
 
-       _surface->write (_solo->set_state(on));
-       _surface->write (_solo->set_state(off));
-       
-       _surface->write (_mute->set_state(on));
-       _surface->write (_mute->set_state(off));
-       
-       _surface->write (_select->set_state(on));
-       _surface->write (_select->set_state(off));
-
        _stripable = r;
 
-       reset_saved_values ();
+       mark_dirty ();
 
        if (!r) {
                DEBUG_TRACE (DEBUG::US2400, string_compose ("Surface %1 Strip %2 mapped to null route\n", _surface->number(), _index));
@@ -263,7 +254,7 @@ Strip::reset_stripable ()
 
        _stripable.reset();
 
-       reset_saved_values ();
+       mark_dirty ();
 
        notify_all ();
 }
@@ -300,6 +291,7 @@ Strip::notify_solo_changed ()
 //             _surface->write (_solo->set_state (_stripable->solo_control()->soloed() ? on : off));
 //     }
 
+       _solo->mark_dirty ();
        _trickle_counter = 0;
 }
 
@@ -316,6 +308,7 @@ Strip::notify_mute_changed ()
 //             _surface->write (_mute->zero());
 //     }
 
+       _mute->mark_dirty ();
        _trickle_counter = 0;
 }
 
@@ -334,6 +327,7 @@ Strip::notify_stripable_deleted ()
 void
 Strip::notify_gain_changed (bool force_update)
 {
+       _fader->mark_dirty();
        _trickle_counter = 0;
 }
 
@@ -350,6 +344,7 @@ Strip::notify_property_changed (const PropertyChange& what_changed)
 void
 Strip::update_selection_state ()
 {
+       _select->mark_dirty ();
        _trickle_counter = 0;
 
 //     if(_stripable) {
@@ -365,12 +360,14 @@ Strip::show_stripable_name ()
 void
 Strip::notify_vpot_change ()
 {
+       _vpot->mark_dirty();
        _trickle_counter = 0;
 }
 
 void
 Strip::notify_panner_azi_changed (bool force_update)
 {
+       _vpot->mark_dirty();
        _trickle_counter = 0;
 }
 
@@ -402,6 +399,8 @@ Strip::select_event (Button&, ButtonState bs)
                DEBUG_TRACE (DEBUG::US2400, "remove select button on release\n");
                _surface->mcp().remove_down_select_button (_surface->number(), _index);
        }
+
+       _trickle_counter = 0;
 }
 
 void
@@ -602,7 +601,7 @@ Strip::periodic (ARDOUR::microseconds_t now)
 
        update_meter ();
 
-       if ( _trickle_counter %5 == 0 ) {
+       if ( _trickle_counter %24 == 0 ) {
 
                if ( _fader->control() ) {
                        _surface->write (_fader->set_position (_fader->control()->internal_to_interface (_fader->control()->get_value ())));
@@ -627,7 +626,13 @@ Strip::periodic (ARDOUR::microseconds_t now)
                }
        
        }
+       
+       //after a hard write, queue us for trickling data later
+       if (_trickle_counter == 0)
+               _trickle_counter = global_index()+1;
+
        _trickle_counter++;
+       
 }
 
 void
@@ -932,7 +937,7 @@ Strip::set_vpot_parameter (AutomationType p)
 
        DEBUG_TRACE (DEBUG::US2400, string_compose ("switch to vpot mode %1\n", p));
 
-       reset_saved_values ();
+       mark_dirty ();
 
        switch (p) {
        case PanAzimuthAutomation:
@@ -967,8 +972,13 @@ Strip::is_midi_track () const
 }
 
 void
-Strip::reset_saved_values ()
+Strip::mark_dirty ()
 {
+       _fader->mark_dirty();
+       _vpot->mark_dirty();
+       _solo->mark_dirty();
+       _mute->mark_dirty();
+       _trickle_counter=0;
 }
 
 void
index 0836657956aba52364980949d909698e36f7e7e7..d963c12836ffec87e560be8adcf4ca4bfe26c239 100644 (file)
@@ -85,7 +85,8 @@ public:
 
        void update_selection_state ();
 
-       int global_index() { return _surface->mcp().global_index (*this); }
+       void set_global_index( int g ) { _global_index = g; }
+       int global_index() { return _global_index; }
 
 private:
        enum VPotDisplayMode {
@@ -101,6 +102,7 @@ private:
        Fader*   _fader;
        Meter*   _meter;
        int      _index;
+       int      _global_index;
        Surface* _surface;
        bool     _controls_locked;
        bool     _transport_is_rolling;
@@ -139,7 +141,7 @@ private:
        void set_vpot_parameter (ARDOUR::AutomationType);
        void show_stripable_name ();
 
-       void reset_saved_values ();
+       void mark_dirty ();
 
        bool is_midi_track () const;
 
index 08f40e4600780bcbc4583e08430d59cffdcd4084..063d628694fde90deec4fcb25f74d96205d63f51 100644 (file)
@@ -352,6 +352,8 @@ Surface::init_strips (uint32_t n)
 
                Strip* strip = new Strip (*this, name, i, strip_buttons);
 
+               strip->set_global_index( _number*n + i );
+
                groups[name] = strip;
                strips.push_back (strip);
        }
@@ -801,8 +803,7 @@ Surface::turn_it_on ()
 
        _active = true;
 
-       if ( _stype == st_mcu )  //do this once, when we hear from the master. this sets up current bank, etc
-               _mcp.device_ready ();
+       _mcp.device_ready ();  //this gets redundantly called with each new surface connection; but this is desirable to get the banks set up correctly
 
        for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
                (*s)->notify_all ();
@@ -896,9 +897,11 @@ Surface::zero_controls ()
 void
 Surface::periodic (uint64_t now_usecs)
 {
-       master_gain_changed();
-       for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
-               (*s)->periodic (now_usecs);
+       if (_active) {
+               master_gain_changed();
+               for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
+                       (*s)->periodic (now_usecs);
+               }
        }
 }
 
index 88c1df11c92ae9cdc40e7868f381fd2c5c91c929..c090bcb47fc4ff17e152cafcd0ab166fef283c8b 100644 (file)
@@ -155,7 +155,7 @@ int
 SurfacePort::write (const MidiByteArray & mba)
 {
        if (mba.empty()) {
-               DEBUG_TRACE (DEBUG::US2400, string_compose ("port %1 asked to write an empty MBA\n", output_port().name()));
+//             DEBUG_TRACE (DEBUG::US2400, string_compose ("port %1 asked to write an empty MBA\n", output_port().name()));
                return 0;
        }
 
@@ -170,6 +170,7 @@ SurfacePort::write (const MidiByteArray & mba)
         */
 
        int count = output_port().write (&mba[0], mba.size(), 0);
+       g_usleep (1000);
 
        if  (count != (int) mba.size()) {
 
index 4a1ba6231ebb425e88271b8b8582bec31ca4efe5..0a6f950d44a17772a7bbe4e92fbba190c8e145ba 100644 (file)
@@ -412,7 +412,7 @@ US2400Protocol::set_active (bool yn)
                /* set up periodic task for timecode display and metering and automation
                 */
 
-               Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
+               Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (10); // milliseconds
                periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &US2400Protocol::periodic));
                periodic_timeout->attach (main_loop()->get_context());
 
@@ -540,25 +540,11 @@ void
 US2400Protocol::device_ready ()
 {
        DEBUG_TRACE (DEBUG::US2400, string_compose ("device ready init (active=%1)\n", active()));
-       update_surfaces ();
 
-       update_global_button (Button::Send, on);
-       update_global_button (Button::Send, off);
-
-       update_global_button (Button::Scrub, on);
-       update_global_button (Button::Scrub, off);
-
-       update_global_button (Button::ClearSolo, on);
-       update_global_button (Button::ClearSolo, off);
-
-       update_global_button (Button::Pan, off);
-       update_global_button (Button::Pan, on);
-
-       update_global_button (Button::Flip, on);
-       update_global_button (Button::Flip, off);
-
-       update_global_button (Button::MstrSelect, on);
-       update_global_button (Button::MstrSelect, off);
+       //this gets called every time a new surface appears; we have to do this to reset the banking etc
+       //particularly when the user is setting it up the first time; we can't guarantee the order that they will be connected
+       
+       update_surfaces ();
 
        set_subview_mode (US2400Protocol::None, first_selected_stripable());
 }
@@ -595,7 +581,22 @@ US2400Protocol::initialize()
 
        }
 
-       // update global buttons and displays
+       update_global_button (Button::Send, on);
+       update_global_button (Button::Send, off);
+
+       update_global_button (Button::Scrub, on);
+       update_global_button (Button::Scrub, off);
+
+       notify_solo_active_changed(false);
+
+       update_global_button (Button::Pan, off);
+       update_global_button (Button::Pan, on);
+
+       update_global_button (Button::Flip, on);
+       update_global_button (Button::Flip, off);
+
+       update_global_button (Button::MstrSelect, on);
+       update_global_button (Button::MstrSelect, off);
 
        notify_transport_state_changed();
 
@@ -1853,15 +1854,11 @@ US2400Protocol::stripable_selection_changed ()
                (*si)->update_strip_selection ();
        }
 
-printf("stripable_selection_changed\n");
-
        //first check for the dedicated Master strip
        boost::shared_ptr<Stripable> s = ControlProtocol::first_selected_stripable();
        if (s && s->is_master()) {
-printf("stripable_selection_changed  found master as selected_stripable\n");
                update_global_button(Button::MstrSelect, on);  //NOTE:  surface does not respond to this
        } else {
-if (s) printf("stripable_selection_changed  not master:  %s\n", s->name().c_str());
                update_global_button(Button::MstrSelect, off);
 
                //not the master;  now check for other strips ( this will only allow a selection if the strip is mapped on our surface )
@@ -1879,7 +1876,6 @@ if (s) printf("stripable_selection_changed  not master:  %s\n", s->name().c_str(
                 */
 
                if (set_subview_mode (TrackView, s)) {
-printf("set_subview_mode failed for master... (?)\n");
                        set_subview_mode (None, boost::shared_ptr<Stripable>());
                }