Session API changes to enable VCAs to set soloed-by-upstream on assigned routes
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 8 Mar 2016 15:42:20 +0000 (10:42 -0500)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 31 May 2016 19:30:39 +0000 (15:30 -0400)
libs/ardour/ardour/session.h
libs/ardour/session_rtevents.cc
libs/ardour/vca.cc

index 47329f73951d1be248fe4a85b7c1a7de6b09293d..2976fec8f3307a48534101bd3a501c9275feda54 100644 (file)
@@ -792,6 +792,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        static const SessionEvent::RTeventCallback rt_cleanup;
 
        void set_solo (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
+       void set_implicit_solo (boost::shared_ptr<RouteList>, int delta, bool up_or_downstream, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
        void clear_all_solo_state (boost::shared_ptr<RouteList>);
        void set_just_one_solo (boost::shared_ptr<Route>, bool, SessionEvent::RTeventCallback after = rt_cleanup);
        void set_mute (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, PBD::Controllable::GroupControlDisposition group_override = PBD::Controllable::UseGroup);
@@ -1922,7 +1923,20 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
                return ev;
        }
 
+       /* specialized version realtime "apply to set of routes" operations */
+       template<typename T1, typename T2> SessionEvent*
+               get_rt_event (boost::shared_ptr<RouteList> rl, T1 t1arg, T2 t2arg, SessionEvent::RTeventCallback after, PBD::Controllable::GroupControlDisposition group_override,
+                             void (Session::*method) (boost::shared_ptr<RouteList>, T1, T2, PBD::Controllable::GroupControlDisposition)) {
+               SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
+               ev->rt_slot = boost::bind (method, this, rl, t1arg, t2arg, group_override);
+               ev->rt_return = after;
+               ev->event_loop = PBD::EventLoop::get_event_loop_for_thread ();
+
+               return ev;
+       }
+
        void rt_set_solo (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
+       void rt_set_implicit_solo (boost::shared_ptr<RouteList>, int delta, bool up_or_downstream, PBD::Controllable::GroupControlDisposition);
        void rt_clear_all_solo_state (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
        void rt_set_just_one_solo (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition  /* ignored*/ );
        void rt_set_mute (boost::shared_ptr<RouteList>, bool yn, PBD::Controllable::GroupControlDisposition group_override);
index 5850643739b23a73a33a5b765be6824c163cf067..68ba15550e7d49ed04aa56292c52ceda89face2a 100644 (file)
@@ -90,6 +90,35 @@ Session::rt_set_solo (boost::shared_ptr<RouteList> rl, bool yn, Controllable::Gr
        }
 
        set_dirty();
+
+       /* XXX boost::shared_ptr<RouteList>  goes out of scope here and is likley free()ed in RT context
+        * because boost's shared_ptr does reference counting and free/delete in the dtor.
+        * (this also applies to other rt_  methods here)
+        */
+}
+
+void
+Session::set_implicit_solo (boost::shared_ptr<RouteList> rl, int delta, bool upstream, SessionEvent::RTeventCallback after,
+                   Controllable::GroupControlDisposition group_override)
+{
+       queue_event (get_rt_event (rl, delta, upstream, after, group_override, &Session::rt_set_implicit_solo));
+}
+
+void
+Session::rt_set_implicit_solo (boost::shared_ptr<RouteList> rl, int delta, bool upstream, PBD::Controllable::GroupControlDisposition)
+{
+       for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
+               if (!(*i)->is_auditioner()) {
+                       if (upstream) {
+                               (*i)->mod_solo_by_others_upstream (delta);
+                       } else {
+                               (*i)->mod_solo_by_others_downstream (delta);
+                       }
+               }
+       }
+
+       set_dirty();
+
        /* XXX boost::shared_ptr<RouteList>  goes out of scope here and is likley free()ed in RT context
         * because boost's shared_ptr does reference counting and free/delete in the dtor.
         * (this also applies to other rt_  methods here)
index 8c4fe260ecc289342578442a6fc4602671cc6556..3fec2d93057553b9a4e1e0d77d179bae70a44730 100644 (file)
@@ -180,7 +180,7 @@ VCA::set_solo (bool yn)
                if (Config->get_solo_control_is_listen_control()) {
                        _session.set_listen (rl, yn, Session::rt_cleanup, Controllable::NoGroup);
                } else {
-                       _session.set_solo (rl, yn, Session::rt_cleanup, Controllable::NoGroup);
+                       _session.set_implicit_solo (rl, (yn ? 1 : -1), true, Session::rt_cleanup, Controllable::NoGroup);
                }
        }