OSC: Catch new strips, gone strips and redo banks and observers. Add more select...
authorLen Ovens <len@ovenwerks.net>
Mon, 13 Jun 2016 18:57:15 +0000 (11:57 -0700)
committerLen Ovens <len@ovenwerks.net>
Mon, 13 Jun 2016 18:57:15 +0000 (11:57 -0700)
libs/surfaces/osc/osc.cc
libs/surfaces/osc/osc.h
libs/surfaces/osc/osc_route_observer.cc
libs/surfaces/osc/osc_select_observer.cc

index edaf5b76b4c8f525722aae0d68e254b7ec1c65cc..80b79c9be2d06a8824133a1e51dce2649837a0c3 100644 (file)
@@ -49,6 +49,7 @@
 #include "ardour/phase_control.h"
 #include "ardour/solo_isolate_control.h"
 #include "ardour/solo_safe_control.h"
+#include "ardour/vca_manager.h"
 
 #include "osc_select_observer.h"
 #include "osc.h"
@@ -90,6 +91,8 @@ OSC::OSC (Session& s, uint32_t port)
        , _osc_unix_server (0)
        , _send_route_changes (true)
        , _debugmode (Off)
+       , tick (true)
+       , bank_dirty (false)
        , gui (0)
 {
        _instance = this;
@@ -246,8 +249,15 @@ OSC::start ()
        periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &OSC::periodic));
        periodic_timeout->attach (main_loop()->get_context());
 
+       // catch GUI select changes for GUI_select mode
        StripableSelectionChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::gui_selection_changed, this, _1), this);
 
+       // catch track reordering
+       // receive routes added
+       session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::notify_routes_added, this, _1), this);
+       // receive VCAs added
+       session->vca_manager().VCAAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::notify_vca_added, this, _1), this);
+
        return 0;
 }
 
@@ -646,7 +656,15 @@ OSC::listen_to_route (boost::shared_ptr<Stripable> strip, lo_address addr)
        OSCRouteObserver* o = new OSCRouteObserver (strip, addr, sid, s->gainmode, s->feedback);
        route_observers.push_back (o);
 
-       strip->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::drop_route, this, boost::weak_ptr<Stripable> (strip)), this);
+       strip->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::route_lost, this, boost::weak_ptr<Stripable> (strip)), this);
+}
+
+void
+OSC::route_lost (boost::weak_ptr<Stripable> wr)
+{
+       tick = false;
+       drop_route (wr);
+       bank_dirty = true;
 }
 
 void
@@ -1251,6 +1269,29 @@ OSC::global_feedback (bitset<32> feedback, lo_address msg, uint32_t gainmode)
        }
 }
 
+void
+OSC::notify_routes_added (ARDOUR::RouteList &)
+{
+       recalcbanks();
+}
+
+void
+OSC::notify_vca_added (ARDOUR::VCAList &)
+{
+       recalcbanks();
+}
+
+void
+OSC::recalcbanks ()
+{
+       for (uint32_t it = 0; it < _surface.size(); ++it) {
+               OSCSurface* sur = &_surface[it];
+               // find lo_address
+               lo_address addr = lo_address_new_from_url (sur->remote_url.c_str());
+               _set_bank (sur->bank, addr);
+       }
+}
+
 /*
  * This gets called not only when bank changes but also:
  *  - bank size change
@@ -1263,6 +1304,12 @@ OSC::global_feedback (bitset<32> feedback, lo_address msg, uint32_t gainmode)
  */
 int
 OSC::set_bank (uint32_t bank_start, lo_message msg)
+{
+       return _set_bank (bank_start, lo_message_get_source (msg));
+}
+
+int
+OSC::_set_bank (uint32_t bank_start, lo_address addr)
 {
        if (!session) {
                return -1;
@@ -1281,18 +1328,18 @@ OSC::set_bank (uint32_t bank_start, lo_message msg)
                nstrips = session->nroutes() - 1;
        }
        // reset local select
-       _strip_select (0, lo_message_get_source (msg));
+       _strip_select (0, addr);
        // undo all listeners for this url
        for (int n = 0; n <= (int) nstrips; ++n) {
 
                boost::shared_ptr<Stripable> stp = session->get_remote_nth_stripable (n, PresentationInfo::Route);
 
                if (stp) {
-                       end_listen (stp, lo_message_get_source (msg));
+                       end_listen (stp, addr);
                }
        }
 
-       OSCSurface *s = get_surface (lo_message_get_source (msg));
+       OSCSurface *s = get_surface (addr);
        uint32_t b_size;
 
        if (!s->bank_size) {
@@ -1318,15 +1365,17 @@ OSC::set_bank (uint32_t bank_start, lo_message msg)
                        boost::shared_ptr<Stripable> stp = session->get_remote_nth_stripable (n - 1, PresentationInfo::Route);
 
                        if (stp) {
-                               listen_to_route(stp, lo_message_get_source (msg));
+                               listen_to_route(stp, addr);
                                if (!s->feedback[10]) {
                                        if (stp->is_selected()) {
-                                               _strip_select (n, lo_message_get_source (msg));
+                                               _strip_select (n, addr);
                                        }
                                }
                        }
                }
        }
+       bank_dirty = false;
+       tick = true;
        return 0;
 }
 
@@ -1832,6 +1881,7 @@ OSC::_strip_select (int ssid, lo_address addr)
        if (s) {
                sur->surface_sel = ssid;
                OSCSelectObserver* sel_fb = new OSCSelectObserver (s, addr, ssid, sur->gainmode, sur->feedback);
+               s->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
                sur->sel_obs = sel_fb;
        } else {
                route_send_fail ("select", ssid, 0 , addr);
@@ -2338,6 +2388,12 @@ OSC::gui_selection_changed (StripableNotificationListPtr stripables)
 bool
 OSC::periodic (void)
 {
+       if (!tick) {
+               if (bank_dirty) {
+                       recalcbanks ();
+               }
+       }
+       
        for (GlobalObservers::iterator x = global_observers.begin(); x != global_observers.end(); x++) {
 
                OSCGlobalObserver* go;
@@ -2354,7 +2410,7 @@ OSC::periodic (void)
                        ro->tick();
                }
        }
-       for (uint32_t it = 0; it < _surface.size(); ++it) {
+       for (uint32_t it = 0; it < _surface.size(); it++) {
                OSCSurface* sur = &_surface[it];
                OSCSelectObserver* so;
                if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
index 7ef4b5aaf5dbc66bc063a49e99d0b4f48f9d2aa4..a2ebc80510b6e9696c39f456260e7b5c9710b58a 100644 (file)
@@ -167,6 +167,8 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
        std::string _osc_url_file;
        bool _send_route_changes;
        OSCDebugMode _debugmode;
+       bool tick;
+       bool bank_dirty;
 
        void register_callbacks ();
 
@@ -451,6 +453,7 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
 
        //banking functions
        int set_bank (uint32_t bank_start, lo_message msg);
+       int _set_bank (uint32_t bank_start, lo_address addr);
        int bank_up (lo_message msg);
        int bank_down (lo_message msg);
        int set_surface (uint32_t b_size, uint32_t strips, uint32_t fb, uint32_t gmode, lo_message msg);
@@ -487,9 +490,13 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
        void listen_to_route (boost::shared_ptr<ARDOUR::Stripable>, lo_address);
        void end_listen (boost::shared_ptr<ARDOUR::Stripable>, lo_address);
        void drop_route (boost::weak_ptr<ARDOUR::Stripable>);
+       void route_lost (boost::weak_ptr<ARDOUR::Stripable>);
        void gui_selection_changed (ARDOUR::StripableNotificationListPtr stripables);
 
        void route_name_changed (const PBD::PropertyChange&, boost::weak_ptr<ARDOUR::Route> r, lo_address addr);
+       void recalcbanks ();
+       void notify_routes_added (ARDOUR::RouteList &);
+       void notify_vca_added (ARDOUR::VCAList &);
 
        void update_clock ();
        bool periodic (void);
index e077fc923aa2d0863eab8b429e5a569b8f9d713a..3626c5764c66a504f598d90f52f842267dc36977 100644 (file)
@@ -378,7 +378,6 @@ OSCRouteObserver::send_select_status ()
                } else {
                        lo_message_add_int32 (msg, ssid);
                }
-               //std::cout << "strip: " << ssid << " strip name: " << _strip->name() << " select: " << _strip->is_selected() << "\n";
                lo_message_add_float (msg, _strip->is_selected());
                lo_send_message (addr, path.c_str(), msg);
                lo_message_free (msg);
index a51f9e702aba38570cc7b307bf613f1021a5927c..8836de37922883e200b4dd98258c24a63683f6af 100644 (file)
@@ -27,6 +27,7 @@
 #include "ardour/phase_control.h"
 #include "ardour/solo_isolate_control.h"
 #include "ardour/solo_safe_control.h"
+#include "ardour/route.h"
 
 #include "osc.h"
 #include "osc_select_observer.h"
@@ -324,18 +325,33 @@ OSCSelectObserver::name_changed (const PBD::PropertyChange& what_changed)
 
        lo_message msg = lo_message_new ();
 
-       // ssid is the strip on the surface this observer refers to
-       // not part of the internal ordering.
        string path = "/select/name";
-       /*if (feedback[2]) {
-               path = set_path (path);
-       } else {
-               lo_message_add_int32 (msg, ssid);
-       }*/
        lo_message_add_string (msg, _strip->name().c_str());
 
        lo_send_message (addr, path.c_str(), msg);
        lo_message_free (msg);
+
+       //spit out the comment at the same time
+       msg = lo_message_new ();
+       path = "/select/comment";
+       boost::shared_ptr<Route> route = boost::dynamic_pointer_cast<Route> (_strip);
+       lo_message_add_string (msg, route->comment().c_str());
+       lo_send_message (addr, path.c_str(), msg);
+       lo_message_free (msg);
+
+       // lets tell the surface how many inputs this strip has
+       msg = lo_message_new ();
+       path = "/select/n_inputs";
+       lo_message_add_int32 (msg, route->n_inputs().n_total());
+       lo_send_message (addr, path.c_str(), msg);
+       lo_message_free (msg);
+       // lets tell the surface how many outputs this strip has
+       msg = lo_message_new ();
+       path = "/select/n_outputs";
+       lo_message_add_int32 (msg, route->n_outputs().n_total());
+       lo_send_message (addr, path.c_str(), msg);
+       lo_message_free (msg);
+
 }
 
 void