change API for GainControl, VCA and VCAManager
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 2 Mar 2016 17:09:24 +0000 (12:09 -0500)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 31 May 2016 19:30:39 +0000 (15:30 -0400)
This allows sane state save/restore

libs/ardour/ardour/gain_control.h
libs/ardour/ardour/vca.h
libs/ardour/gain_control.cc
libs/ardour/route.cc
libs/ardour/vca.cc
libs/ardour/vca_manager.cc

index 7845679220f8fece5f738a1ccd0814c24739d682..93d9c4fec0280de0273592a0f747b2ff655c36f2 100644 (file)
@@ -20,7 +20,7 @@
 #define __ardour_gain_control_h__
 
 #include <string>
-#include <list>
+#include <set>
 
 #include <boost/shared_ptr.hpp>
 #include <glibmm/threads.h>
@@ -54,20 +54,28 @@ class LIBARDOUR_API GainControl : public AutomationControl {
        double range_db;
 
        gain_t get_master_gain () const;
-       void add_master (boost::shared_ptr<GainControl>);
-       void remove_master (boost::shared_ptr<GainControl>);
+       void add_master (boost::shared_ptr<VCA>);
+       void remove_master (boost::shared_ptr<VCA>);
        void clear_masters ();
-       bool slaved_to (boost::shared_ptr<GainControl>) const;
+       bool slaved_to (boost::shared_ptr<VCA>) const;
+       std::vector<uint32_t> masters () const;
+
+       int set_state (XMLNode const&, int);
+       XMLNode& get_state();
 
   private:
        void _set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
 
        mutable Glib::Threads::Mutex master_lock;
 
-       typedef std::list<boost::shared_ptr<GainControl> > Masters;
+       typedef std::set<boost::shared_ptr<GainControl> > Masters;
        Masters _masters;
+       PBD::ScopedConnectionList masters_connections;
+       std::set<uint32_t> _masters_numbers;
+       std::string _masters_state_string ();
 
        gain_t get_master_gain_locked () const;
+       void master_going_away (boost::weak_ptr<VCA>);
 };
 
 } /* namespace */
index a4da21e31f913d2541851d2ab0c85da923979ecc..4359899f6f6ed8e3963b95eea77693201959bb6c 100644 (file)
@@ -37,6 +37,7 @@ class LIBARDOUR_API VCA : public SessionHandleRef, public PBD::StatefulDestructi
   public:
        VCA (Session& session, const std::string& name, uint32_t num);
        VCA (Session& session, XMLNode const&, int version);
+       ~VCA();
 
        std::string name() const { return _name; }
        uint32_t number () const { return _number; }
@@ -48,9 +49,6 @@ class LIBARDOUR_API VCA : public SessionHandleRef, public PBD::StatefulDestructi
 
        boost::shared_ptr<GainControl> control() const { return _control; }
 
-       void add (boost::shared_ptr<Route>);
-       void remove (boost::shared_ptr<Route>);
-
        XMLNode& get_state();
        int set_state (XMLNode const&, int version);
 
index 5ba7179231bc291fa4a64e2587ca0b63e1e55dd0..c5f1f25bb7cd9b5986d327bdf34f651035d1f07c 100644 (file)
     675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "pbd/convert.h"
+#include "pbd/strsplit.h"
+
 #include "ardour/dB.h"
 #include "ardour/gain_control.h"
 #include "ardour/session.h"
+#include "ardour/vca.h"
+#include "ardour/vca_manager.h"
 
 #include "i18n.h"
 
@@ -124,7 +129,7 @@ GainControl::get_master_gain_locked () const
 }
 
 void
-GainControl::add_master (boost::shared_ptr<GainControl> m)
+GainControl::add_master (boost::shared_ptr<VCA> vca)
 {
        gain_t old_master_val;
        gain_t new_master_val;
@@ -132,8 +137,17 @@ GainControl::add_master (boost::shared_ptr<GainControl> m)
        {
                Glib::Threads::Mutex::Lock lm (master_lock);
                old_master_val = get_master_gain_locked ();
-               _masters.push_back (m);
+               _masters.insert (vca->control());
+               _masters_numbers.insert (vca->number());
                new_master_val = get_master_gain_locked ();
+
+               /* note that we bind @param m as a weak_ptr<GainControl>, thus
+                  avoiding holding a reference to the control in the binding
+                  itself.
+               */
+
+               vca->DropReferences.connect_same_thread (masters_connections, boost::bind (&GainControl::master_going_away, this, vca));
+
        }
 
        if (old_master_val != new_master_val) {
@@ -142,7 +156,16 @@ GainControl::add_master (boost::shared_ptr<GainControl> m)
 }
 
 void
-GainControl::remove_master (boost::shared_ptr<GainControl> m)
+GainControl::master_going_away (boost::weak_ptr<VCA> wv)
+{
+       boost::shared_ptr<VCA> v = wv.lock();
+       if (v) {
+               remove_master (v);
+       }
+}
+
+void
+GainControl::remove_master (boost::shared_ptr<VCA> vca)
 {
        gain_t old_master_val;
        gain_t new_master_val;
@@ -150,7 +173,8 @@ GainControl::remove_master (boost::shared_ptr<GainControl> m)
        {
                Glib::Threads::Mutex::Lock lm (master_lock);
                old_master_val = get_master_gain_locked ();
-               _masters.remove (m);
+               _masters.erase (vca->control());
+               _masters_numbers.erase (vca->number());
                new_master_val = get_master_gain_locked ();
        }
 
@@ -169,6 +193,7 @@ GainControl::clear_masters ()
                Glib::Threads::Mutex::Lock lm (master_lock);
                old_master_val = get_master_gain_locked ();
                _masters.clear ();
+               _masters_numbers.clear ();
                new_master_val = get_master_gain_locked ();
        }
 
@@ -178,8 +203,61 @@ GainControl::clear_masters ()
 }
 
 bool
-GainControl::slaved_to (boost::shared_ptr<GainControl> gc) const
+GainControl::slaved_to (boost::shared_ptr<VCA> vca) const
 {
        Glib::Threads::Mutex::Lock lm (master_lock);
-       return find (_masters.begin(), _masters.end(), gc) != _masters.end();
+       return find (_masters.begin(), _masters.end(), vca->control()) != _masters.end();
+}
+
+XMLNode&
+GainControl::get_state ()
+{
+       XMLNode& node (AutomationControl::get_state());
+
+       /* store VCA master IDs */
+
+       string str;
+
+       {
+               Glib::Threads::Mutex::Lock lm (master_lock);
+               for (set<uint32_t>::const_iterator m = _masters_numbers.begin(); m != _masters_numbers.end(); ++m) {
+                       if (!str.empty()) {
+                               str += ',';
+                       }
+                       str += PBD::to_string (*m, std::dec);
+               }
+       }
+
+       if (!str.empty()) {
+               node.add_property (X_("masters"), str);
+       }
+
+       return node;
+}
+
+int
+GainControl::set_state (XMLNode const& node, int version)
+{
+       AutomationControl::set_state (node, version);
+
+       XMLProperty const* prop = node.property (X_("masters"));
+
+       /* XXXProblem here if we allow VCA's to be slaved to other VCA's .. we
+        * have to load all VCAs first, then call ::set_state() so that
+        * vca_by_number() will succeed.
+        */
+
+       if (prop) {
+               vector<string> masters;
+               split (prop->value(), masters, ',');
+
+               for (vector<string>::const_iterator m = masters.begin(); m != masters.end(); ++m) {
+                       boost::shared_ptr<VCA> vca = _session.vca_manager().vca_by_number (PBD::atoi (*m));
+                       if (vca) {
+                               add_master (vca);
+                       }
+               }
+       }
+
+       return 0;
 }
index 8b1f47ec4ec22a6409472fe16266dba077523ac5..581031c4050c635c65951129e1a7d6f6ff41a98f 100644 (file)
@@ -5892,5 +5892,5 @@ Route::slaved_to (boost::shared_ptr<VCA> vca) const
                return false;
        }
 
-       return _gain_control->slaved_to (vca->control());
+       return _gain_control->slaved_to (vca);
 }
index 9ae0c5a2dcaec879db0a7c2f57b455bdd35fecb1..5afa31d38d613a2b008d97ab4a97280a2022c4d9 100644 (file)
@@ -66,6 +66,11 @@ VCA::VCA (Session& s, XMLNode const & node, int version)
        set_state (node, version);
 }
 
+VCA::~VCA ()
+{
+       DropReferences (); /* emit signal */
+}
+
 void
 VCA::set_value (double val, Controllable::GroupControlDisposition gcd)
 {
@@ -78,19 +83,6 @@ VCA::get_value() const
        return _control->get_value();
 }
 
-void
-VCA::add (boost::shared_ptr<Route> r)
-{
-       boost::dynamic_pointer_cast<GainControl>(r->gain_control())->add_master (_control);
-       std::cerr << name() << " now controlling " << r->name() << std::endl;
-}
-
-void
-VCA::remove (boost::shared_ptr<Route> r)
-{
-       r->gain_control()->remove_master (_control);
-}
-
 void
 VCA::set_name (string const& str)
 {
index 4daae2e9e28d39b18a9abfc4b487b81ba962936d..420396bf0732609a803f4a81e605f67306b48ea5 100644 (file)
@@ -146,7 +146,6 @@ VCAManager::set_state (XMLNode const& node, int version)
 
                for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
                        if ((*i)->name() == VCA::xml_node_name) {
-                               std::cerr << "Adding VCA from XML\n";
                                boost::shared_ptr<VCA> vca = boost::shared_ptr<VCA> (new VCA (_session, **i, version));
                                _vcas.push_back (vca);
                                vcal.push_back (vca);