OSC: add optional paging to sends in select.
authorLen Ovens <len@ovenwerks.net>
Tue, 6 Jun 2017 14:35:24 +0000 (07:35 -0700)
committerLen Ovens <len@ovenwerks.net>
Tue, 6 Jun 2017 16:08:35 +0000 (09:08 -0700)
libs/surfaces/osc/osc.cc
libs/surfaces/osc/osc.h
libs/surfaces/osc/osc_select_observer.cc
libs/surfaces/osc/osc_select_observer.h

index 4818f9340c9a47c23a4e8a0aba9282c41aa337c1..72d8010c3ffce6c332f96d32bc37e4cef32a5fb2 100644 (file)
@@ -565,6 +565,11 @@ OSC::register_callbacks()
                REGISTER_CALLBACK (serv, "/select/send_gain", "if", sel_sendgain);
                REGISTER_CALLBACK (serv, "/select/send_fader", "if", sel_sendfader);
                REGISTER_CALLBACK (serv, "/select/send_enable", "if", sel_sendenable);
+               REGISTER_CALLBACK (serv, "/select/send_page", "f", sel_send_page);
+               REGISTER_CALLBACK (serv, "/select/send_page_size", "f", sel_send_pagesize);
+               REGISTER_CALLBACK (serv, "/select/plug_page", "f", sel_plug_page);
+               REGISTER_CALLBACK (serv, "/select/plug_page_size", "f", sel_plug_pagesize);
+               REGISTER_CALLBACK (serv, "/select/plugin", "f", sel_plugin);
                REGISTER_CALLBACK (serv, "/select/expand", "i", sel_expand);
                REGISTER_CALLBACK (serv, "/select/pan_elevation_position", "f", sel_pan_elevation);
                REGISTER_CALLBACK (serv, "/select/pan_frontback_position", "f", sel_pan_frontback);
@@ -1394,7 +1399,6 @@ OSC::set_surface_feedback (uint32_t fb, lo_message msg)
        return 0;
 }
 
-
 int
 OSC::set_surface_gainmode (uint32_t gm, lo_message msg)
 {
@@ -1461,6 +1465,11 @@ OSC::get_surface (lo_address addr)
        s.cue = false;
        s.aux = 0;
        s.strips = get_sorted_stripables(s.strip_types, s.cue);
+       s.send_page = 1;
+       s.send_page_size = 0;
+       s.plug_page = 1;
+       s.plug_page_size = 0;
+       s.plugin = 1;
 
        s.nstrips = s.strips.size();
        _surface.push_back (s);
@@ -1727,6 +1736,57 @@ OSC::get_strip (uint32_t ssid, lo_address addr)
        return boost::shared_ptr<ARDOUR::Stripable>();
 }
 
+// send and plugin paging commands
+int
+OSC::sel_send_pagesize (uint32_t size, lo_message msg)
+{
+       OSCSurface *s = get_surface(get_address (msg));
+       if  (size != s->send_page_size) {
+               s->send_page_size = size;
+               s->sel_obs->renew_sends();
+       }
+       return 0;
+}
+
+int
+OSC::sel_send_page (int page, lo_message msg)
+{
+       OSCSurface *s = get_surface(get_address (msg));
+       s->send_page = s->send_page + page;
+       s->sel_obs->renew_sends();
+       return 0;
+}
+
+int
+OSC::sel_plug_pagesize (uint32_t size, lo_message msg)
+{
+       OSCSurface *s = get_surface(get_address (msg));
+       if (size != s->plug_page_size) {
+               s->plug_page_size = size;
+               s->sel_obs->renew_plugin();
+       }
+       return 0;
+}
+
+int
+OSC::sel_plug_page (int page, lo_message msg)
+{
+       OSCSurface *s = get_surface(get_address (msg));
+       s->plug_page = s->plug_page + page;
+       s->sel_obs->renew_plugin();
+       return 0;
+}
+
+int
+OSC::sel_plugin (uint32_t id, lo_message msg)
+{
+       OSCSurface *s = get_surface(get_address (msg));
+       s->plugin = id;
+       s->plug_page = 1;
+       s->sel_obs->renew_plugin();
+       return 0;
+}
+
 void
 OSC::transport_frame (lo_message msg)
 {
@@ -2762,14 +2822,14 @@ OSC::_strip_select (boost::shared_ptr<Stripable> s, lo_address addr)
        }
        bool feedback_on = sur->feedback.to_ulong();
        if (s && feedback_on) {
-               OSCSelectObserver* sel_fb = new OSCSelectObserver (s, addr, sur->gainmode, sur->feedback);
+               OSCSelectObserver* sel_fb = new OSCSelectObserver (s, addr, sur);
                s->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
                sur->sel_obs = sel_fb;
        } else if (sur->expand_enable) {
                sur->expand = 0;
                sur->expand_enable = false;
                if (_select && feedback_on) {
-                       OSCSelectObserver* sel_fb = new OSCSelectObserver (_select, addr, sur->gainmode, sur->feedback);
+                       OSCSelectObserver* sel_fb = new OSCSelectObserver (_select, addr, sur);
                        _select->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
                        sur->sel_obs = sel_fb;
                }
@@ -3144,6 +3204,9 @@ int
 OSC::sel_sendgain (int id, float val, lo_message msg)
 {
        OSCSurface *sur = get_surface(get_address (msg));
+       if (sur->send_page_size && (id > (int)sur->send_page_size)) {
+               return sel_send_fail ("send_gain", id, -193, get_address (msg));
+       }
        boost::shared_ptr<Stripable> s;
        if (sur->expand_enable) {
                s = get_strip (sur->expand, get_address (msg));
@@ -3151,9 +3214,10 @@ OSC::sel_sendgain (int id, float val, lo_message msg)
                s = _select;
        }
        float abs;
+       int send_id;
        if (s) {
                if (id > 0) {
-                       --id;
+                       send_id = id - 1;
                }
 #ifdef MIXBUS
                abs = val;
@@ -3164,18 +3228,24 @@ OSC::sel_sendgain (int id, float val, lo_message msg)
                        abs = dB_to_coefficient (val);
                }
 #endif
-               if (s->send_level_controllable (id)) {
-                       s->send_level_controllable (id)->set_value (abs, PBD::Controllable::NoGroup);
+               if (sur->send_page_size) {
+                       send_id = send_id + ((sur->send_page - 1) * sur->send_page_size);
+               }
+               if (s->send_level_controllable (send_id)) {
+                       s->send_level_controllable (send_id)->set_value (abs, PBD::Controllable::NoGroup);
                        return 0;
                }
        }
-       return sel_send_fail ("send_gain", id + 1, -193, get_address (msg));
+       return sel_send_fail ("send_gain", id, -193, get_address (msg));
 }
 
 int
 OSC::sel_sendfader (int id, float val, lo_message msg)
 {
        OSCSurface *sur = get_surface(get_address (msg));
+       if (sur->send_page_size && (id > (int)sur->send_page_size)) {
+               return sel_send_fail ("send_fader", id, 0, get_address (msg));
+       }
        boost::shared_ptr<Stripable> s;
        if (sur->expand_enable) {
                s = get_strip (sur->expand, get_address (msg));
@@ -3183,19 +3253,23 @@ OSC::sel_sendfader (int id, float val, lo_message msg)
                s = _select;
        }
        float abs;
+       int send_id;
        if (s) {
 
                if (id > 0) {
-                       --id;
+                       send_id = id - 1;
+               }
+               if (sur->send_page_size) {
+                       send_id = send_id + ((sur->send_page - 1) * sur->send_page_size);
                }
 
-               if (s->send_level_controllable (id)) {
+               if (s->send_level_controllable (send_id)) {
 #ifdef MIXBUS
-                       abs = s->send_level_controllable(id)->interface_to_internal (val);
+                       abs = s->send_level_controllable(send_id)->interface_to_internal (val);
 #else
                        abs = slider_position_to_gain_with_max (val, 2.0);
 #endif
-                       s->send_level_controllable (id)->set_value (abs, PBD::Controllable::NoGroup);
+                       s->send_level_controllable (send_id)->set_value (abs, PBD::Controllable::NoGroup);
                        return 0;
                }
        }
@@ -3248,27 +3322,34 @@ int
 OSC::sel_sendenable (int id, float val, lo_message msg)
 {
        OSCSurface *sur = get_surface(get_address (msg));
+       if (sur->send_page_size && (id > (int)sur->send_page_size)) {
+               return sel_send_fail ("send_enable", id, 0, get_address (msg));
+       }
        boost::shared_ptr<Stripable> s;
        if (sur->expand_enable) {
                s = get_strip (sur->expand, get_address (msg));
        } else {
                s = _select;
        }
+       int send_id;
        if (s) {
                if (id > 0) {
-                       --id;
+                       send_id = id - 1;
+               }
+               if (sur->send_page_size) {
+                       send_id = send_id + ((sur->send_page - 1) * sur->send_page_size);
                }
-               if (s->send_enable_controllable (id)) {
-                       s->send_enable_controllable (id)->set_value (val, PBD::Controllable::NoGroup);
+               if (s->send_enable_controllable (send_id)) {
+                       s->send_enable_controllable (send_id)->set_value (val, PBD::Controllable::NoGroup);
                        return 0;
                }
-               if (s->send_level_controllable (id)) {
+               if (s->send_level_controllable (send_id)) {
                        boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
                        if (!r) {
                                // should never get here
-                               return sel_send_fail ("send_enable", id + 1, 0, get_address (msg));
+                               return sel_send_fail ("send_enable", id, 0, get_address (msg));
                        }
-                       boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (r->nth_send(id));
+                       boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (r->nth_send(send_id));
                        if (snd) {
                                if (val) {
                                        snd->activate();
@@ -3279,7 +3360,7 @@ OSC::sel_sendenable (int id, float val, lo_message msg)
                        return 0;
                }
        }
-       return sel_send_fail ("send_enable", id + 1, 0, get_address (msg));
+       return sel_send_fail ("send_enable", id, 0, get_address (msg));
 }
 
 int
index fb8a5e5365dc972789f65047db06abace1617bcf..5bb55113c0597484b61a150586e1d0c6ba624303 100644 (file)
@@ -121,9 +121,10 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
                JogMode jogmode;                        // current jogmode
                uint32_t bank;                          // current bank
                uint32_t bank_size;                     // size of banks for this surface
-               uint32_t plug_page;                     // current plugin page
+               int plug_page;                          // current plugin page
                uint32_t plug_page_size;        // plugin page size (number of controls)
-               uint32_t send_page;                     // current send page
+               uint32_t plugin;                        // id of current plugin
+               int send_page;                          // current send page
                uint32_t send_page_size;        // send page size in channels
                std::bitset<32> strip_types;// what strip types are a part of this bank
                uint32_t nstrips;                       // how many strips are there for strip_types
@@ -425,6 +426,11 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
        PATH_CALLBACK1_MSG(sel_pan_elevation,f);
        PATH_CALLBACK1_MSG(sel_pan_frontback,f);
        PATH_CALLBACK1_MSG(sel_pan_lfe,f);
+       PATH_CALLBACK1_MSG(sel_send_page,f);
+       PATH_CALLBACK1_MSG(sel_send_pagesize,f);
+       PATH_CALLBACK1_MSG(sel_plug_page,f);
+       PATH_CALLBACK1_MSG(sel_plug_pagesize,f);
+       PATH_CALLBACK1_MSG(sel_plugin,f);
        PATH_CALLBACK1_MSG(sel_comp_enable,f);
        PATH_CALLBACK1_MSG(sel_comp_threshold,f);
        PATH_CALLBACK1_MSG(sel_comp_speed,f);
@@ -581,6 +587,11 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
        int set_surface_feedback (uint32_t fb, lo_message msg);
        int set_surface_gainmode (uint32_t gm, lo_message msg);
        int refresh_surface (lo_message msg);
+       int sel_send_pagesize (uint32_t size, lo_message msg);
+       int sel_send_page (int page, lo_message msg);
+       int sel_plug_pagesize (uint32_t size, lo_message msg);
+       int sel_plug_page (int page, lo_message msg);
+       int sel_plugin (uint32_t id, lo_message msg);
 
        int scrub (float delta, lo_message msg);
        int jog (float delta, lo_message msg);
index 2071f0455dfac6f74a0ba9c98a61d65905404a51..c4a5eae09cea26e1bf5f9b80c84a304c8e3eeeed 100644 (file)
@@ -45,15 +45,17 @@ using namespace PBD;
 using namespace ARDOUR;
 using namespace ArdourSurface;
 
-OSCSelectObserver::OSCSelectObserver (boost::shared_ptr<Stripable> s, lo_address a, uint32_t gm, std::bitset<32> fb)
+OSCSelectObserver::OSCSelectObserver (boost::shared_ptr<Stripable> s, lo_address a, ArdourSurface::OSC::OSCSurface* su)
        : _strip (s)
-       ,gainmode (gm)
-       ,feedback (fb)
+       ,sur (su)
        ,nsends (0)
        ,_last_gain (0.0)
 {
        addr = lo_address_new (lo_address_get_hostname(a) , lo_address_get_port(a));
+       gainmode = sur->gainmode;
+       feedback = sur->feedback;
        as = ARDOUR::Off;
+       send_size = 0;
 
        if (feedback[0]) { // buttons are separate feedback
                _strip->PropertyChanged.connect (strip_connections, MISSING_INVALIDATOR, boost::bind (&OSCSelectObserver::name_changed, this, boost::lambda::_1), OSC::instance());
@@ -234,53 +236,86 @@ OSCSelectObserver::~OSCSelectObserver ()
        lo_address_free (addr);
 }
 
+void
+OSCSelectObserver::renew_sends () {
+       send_end();
+       send_init();
+}
+
+void
+OSCSelectObserver::renew_plugin () {
+       // to be written :)
+}
+
 void
 OSCSelectObserver::send_init()
 {
        // we don't know how many there are, so find out.
        bool sends;
+       nsends  = 0;
        do {
                sends = false;
                if (_strip->send_level_controllable (nsends)) {
-                       _strip->send_level_controllable(nsends)->Changed.connect (send_connections, MISSING_INVALIDATOR, boost::bind (&OSCSelectObserver::send_gain, this, nsends, _strip->send_level_controllable(nsends)), OSC::instance());
-                       send_timeout.push_back (0);
-                       send_gain (nsends, _strip->send_level_controllable(nsends));
                        sends = true;
+                       nsends++;
                }
+       } while (sends);
+       if (!nsends) {
+               return;
+       }
 
-               if (_strip->send_enable_controllable (nsends)) {
-                       _strip->send_enable_controllable(nsends)->Changed.connect (send_connections, MISSING_INVALIDATOR, boost::bind (&OSCSelectObserver::enable_message_with_id, this, X_("/select/send_enable"), nsends + 1, _strip->send_enable_controllable(nsends)), OSC::instance());
-                       enable_message_with_id ("/select/send_enable", nsends + 1, _strip->send_enable_controllable(nsends));
-                       sends = true;
-               } else if (sends) {
+       send_size = nsends;
+       if (sur->send_page_size) {
+               send_size = sur->send_page_size;
+       }
+       // check limits
+       uint32_t max_page = (uint32_t)(nsends / send_size) + 1;
+       if (sur->send_page < 1) {
+               sur->send_page = 1;
+       } else if ((uint32_t)sur->send_page > max_page) {
+               sur->send_page = max_page;
+       }
+       uint32_t page_start = ((sur->send_page - 1) * send_size);
+       uint32_t last_send = sur->send_page * send_size;
+       uint32_t c = 1;
+
+       for (uint32_t s = page_start; s < last_send; ++s, ++c) {
+
+               bool send_valid = false;
+               if (_strip->send_level_controllable (s)) {
+                       _strip->send_level_controllable(s)->Changed.connect (send_connections, MISSING_INVALIDATOR, boost::bind (&OSCSelectObserver::send_gain, this, c, _strip->send_level_controllable(s)), OSC::instance());
+                       send_timeout.push_back (0);
+                       send_gain (c, _strip->send_level_controllable(s));
+                       send_valid = true;
+               }
+
+               if (_strip->send_enable_controllable (s)) {
+                       _strip->send_enable_controllable(s)->Changed.connect (send_connections, MISSING_INVALIDATOR, boost::bind (&OSCSelectObserver::enable_message_with_id, this, X_("/select/send_enable"), c, _strip->send_enable_controllable(s)), OSC::instance());
+                       enable_message_with_id ("/select/send_enable", c, _strip->send_enable_controllable(s));
+               } else if (send_valid) {
                        boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (_strip);
                        if (!r) {
                                // should never get here
-                               send_float_with_id ("/select/send_enable", nsends + 1, 0);
+                               send_float_with_id ("/select/send_enable", c, 0);
                        }
-                       boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (r->nth_send(nsends));
+                       boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (r->nth_send(s));
                        if (snd) {
                                boost::shared_ptr<Processor> proc = boost::dynamic_pointer_cast<Processor> (snd);
-                               proc->ActiveChanged.connect (send_connections, MISSING_INVALIDATOR, boost::bind (&OSCSelectObserver::send_enable, this, X_("/select/send_enable"), nsends + 1, proc), OSC::instance());
-                               send_float_with_id ("/select/send_enable", nsends + 1, proc->enabled());
+                               proc->ActiveChanged.connect (send_connections, MISSING_INVALIDATOR, boost::bind (&OSCSelectObserver::send_enable, this, X_("/select/send_enable"), c, proc), OSC::instance());
+                               send_float_with_id ("/select/send_enable", c, proc->enabled());
                        }
                }
-               // this should get signalled by the route the send goes to, (TODO)
-               if (!gainmode && sends) { // if the gain control is there, this is too
-                       text_with_id ("/select/send_name", nsends + 1, _strip->send_name(nsends));
+               if (!gainmode && send_valid) {
+                       text_with_id ("/select/send_name", c, _strip->send_name(s));
                }
-               // Send numbers are 0 based, OSC is 1 based so this gets incremented at the end
-               if (sends) {
-                       nsends++;
-               }
-       } while (sends);
+       }
 }
 
 void
 OSCSelectObserver::send_end ()
 {
        send_connections.drop_connections ();
-       for (uint32_t i = 1; i <= nsends; i++) {
+       for (uint32_t i = 1; i <= send_size; i++) {
                if (gainmode) {
                        send_float_with_id ("/select/send_fader", i, 0);
                } else {
@@ -291,6 +326,8 @@ OSCSelectObserver::send_end ()
                // next name
                text_with_id ("/select/send_name", i, " ");
        }
+       // need to delete or clear send_timeout
+       send_timeout.clear();
        nsends = 0;
 }
 
@@ -580,7 +617,7 @@ OSCSelectObserver::send_gain (uint32_t id, boost::shared_ptr<PBD::Controllable>
 #else
                value = gain_to_slider_position (controllable->get_value());
 #endif
-       text_with_id ("/select/send_name" , id + 1, string_compose ("%1%2%3", std::fixed, std::setprecision(2), db));
+       text_with_id ("/select/send_name" , id, string_compose ("%1%2%3", std::fixed, std::setprecision(2), db));
        if (send_timeout.size() > id) {
                send_timeout[id] = 8;
        }
@@ -590,9 +627,9 @@ OSCSelectObserver::send_gain (uint32_t id, boost::shared_ptr<PBD::Controllable>
        }
 
        if (feedback[2]) {
-               path = set_path (path, id + 1);
+               path = set_path (path, id);
        } else {
-               lo_message_add_int32 (msg, id + 1);
+               lo_message_add_int32 (msg, id);
        }
 
        lo_message_add_float (msg, value);
index 6cd20a7769a8408cdd6b170faf60d63920086598..5fdb976aca422c59fc8ab593e862dd95f3c0ccc1 100644 (file)
 #include "ardour/types.h"
 #include "ardour/processor.h"
 
+#include "osc.h"
+
 class OSCSelectObserver
 {
 
   public:
-       OSCSelectObserver (boost::shared_ptr<ARDOUR::Stripable>, lo_address addr, uint32_t gainmode, std::bitset<32> feedback);
+       OSCSelectObserver (boost::shared_ptr<ARDOUR::Stripable>, lo_address addr, ArdourSurface::OSC::OSCSurface* sur);
        ~OSCSelectObserver ();
 
        boost::shared_ptr<ARDOUR::Stripable> strip () const { return _strip; }
        lo_address address() const { return addr; };
        void tick (void);
+       void renew_sends (void);
+       void renew_plugin (void);
 
   private:
        boost::shared_ptr<ARDOUR::Stripable> _strip;
@@ -54,12 +58,14 @@ class OSCSelectObserver
        std::string path;
        uint32_t gainmode;
        std::bitset<32> feedback;
+       ArdourSurface::OSC::OSCSurface* sur;
        std::vector<int> send_timeout;
        uint32_t gain_timeout;
        float _last_meter;
        uint32_t nsends;
        float _last_gain;
        ARDOUR::AutoState as;
+       uint32_t send_size;
 
        void name_changed (const PBD::PropertyChange& what_changed);
        void change_message (std::string path, boost::shared_ptr<PBD::Controllable> controllable);