redesign Route and VCA objects to inherit from ARDOUR::Stripable
authorPaul Davis <paul@linuxaudiosystems.com>
Mon, 7 Mar 2016 19:59:40 +0000 (14:59 -0500)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 31 May 2016 19:30:39 +0000 (15:30 -0400)
libs/ardour/ardour/route.h
libs/ardour/ardour/session.h
libs/ardour/ardour/stripable.h [new file with mode: 0644]
libs/ardour/ardour/vca.h
libs/ardour/gain_control.cc
libs/ardour/route.cc
libs/ardour/session.cc
libs/ardour/session_rtevents.cc
libs/ardour/vca.cc
libs/ardour/vca_manager.cc

index ed3276905819032434fd28e31a4168912d8b9e47..b187c39629203ad36493fa9ab9222bf86c090a01 100644 (file)
@@ -48,6 +48,7 @@
 #include "ardour/types.h"
 #include "ardour/mute_master.h"
 #include "ardour/route_group_member.h"
+#include "ardour/stripable.h"
 #include "ardour/graphnode.h"
 #include "ardour/automatable.h"
 #include "ardour/unknown_processor.h"
@@ -74,7 +75,7 @@ class CapturingProcessor;
 class InternalSend;
 class VCA;
 
-class LIBARDOUR_API Route : public SessionObject, public Automatable, public RouteGroupMember, public GraphNode, public boost::enable_shared_from_this<Route>
+class LIBARDOUR_API Route : public Stripable, public Automatable, public RouteGroupMember, public GraphNode, public boost::enable_shared_from_this<Route>
 {
 public:
 
@@ -203,8 +204,8 @@ public:
 
        boost::shared_ptr<Amp> amp() const  { return _amp; }
        boost::shared_ptr<Amp> trim() const { return _trim; }
-       PeakMeter&       peak_meter()       { return *_meter.get(); }
-       const PeakMeter& peak_meter() const { return *_meter.get(); }
+       boost::shared_ptr<PeakMeter>       peak_meter()       { return _meter; }
+       boost::shared_ptr<const PeakMeter> peak_meter() const { return _meter; }
        boost::shared_ptr<PeakMeter> shared_peak_meter() const { return _meter; }
        boost::shared_ptr<DelayLine> delay_line() const  { return _delayline; }
 
@@ -560,11 +561,11 @@ public:
 
        void set_control (AutomationType, double val, PBD::Controllable::GroupControlDisposition group_override);
 
-       boost::shared_ptr<SoloControllable> solo_control() const {
+       boost::shared_ptr<AutomationControl> solo_control() const {
                return _solo_control;
        }
 
-       boost::shared_ptr<MuteControllable> mute_control() const {
+       boost::shared_ptr<AutomationControl> mute_control() const {
                return _mute_control;
        }
 
@@ -572,11 +573,11 @@ public:
                return _mute_master;
        }
 
-       boost::shared_ptr<SoloIsolateControllable> solo_isolate_control() const {
+       boost::shared_ptr<AutomationControl> solo_isolate_control() const {
                return _solo_isolate_control;
        }
 
-       boost::shared_ptr<SoloSafeControllable> solo_safe_control() const {
+       boost::shared_ptr<AutomationControl> solo_safe_control() const {
                return _solo_safe_control;
        }
 
@@ -594,11 +595,11 @@ public:
 
        boost::shared_ptr<Panner> panner() const;  /* may return null */
        boost::shared_ptr<PannerShell> panner_shell() const;
-       boost::shared_ptr<GainControl> gain_control() const;
        boost::shared_ptr<Pannable> pannable() const;
-       boost::shared_ptr<GainControl> trim_control() const;
 
-       boost::shared_ptr<PhaseControllable> phase_control() const;
+       boost::shared_ptr<GainControl> gain_control() const;
+       boost::shared_ptr<AutomationControl> trim_control() const;
+       boost::shared_ptr<AutomationControl> phase_control() const;
 
        /**
           Return the first processor that accepts has at least one MIDI input
index e774666ce5888ba14fd7d3df90d97ae83114d919..47329f73951d1be248fe4a85b7c1a7de6b09293d 100644 (file)
@@ -305,6 +305,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        boost::shared_ptr<Route> route_by_name (std::string);
        boost::shared_ptr<Route> route_by_id (PBD::ID);
        boost::shared_ptr<Route> route_by_remote_id (uint32_t id);
+       boost::shared_ptr<Stripable> stripable_by_remote_id (uint32_t id);
        boost::shared_ptr<Route> route_by_selected_count (uint32_t cnt);
        boost::shared_ptr<Track> track_by_diskstream_id (PBD::ID);
        void routes_using_input_from (const std::string& str, RouteList& rl);
diff --git a/libs/ardour/ardour/stripable.h b/libs/ardour/ardour/stripable.h
new file mode 100644 (file)
index 0000000..e97fe79
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+  Copyright (C) 2016 Paul Davis
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __libardour_stripable_h__
+#define __libardour_stripable_h__
+
+#include <stdint.h>
+
+#include <string>
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include "ardour/gain_control.h"
+#include "ardour/session_object.h"
+
+namespace ARDOUR {
+
+class AutomationControl;
+class PeakMeter;
+
+/* This is a virtual base class for any object that needs to be potentially
+ * represented by a control-centric user interface using the general model of a
+ * mixing console "strip" - a collection of controls that determine the state
+ * and behaviour of the object.
+ */
+
+class Stripable : public SessionObject {
+   public:
+       Stripable (Session& session, const std::string& name)
+               : SessionObject (session, name) {}
+
+       /* XXX
+          midi on/off
+          selected status
+          visible/hidden
+        */
+
+       virtual uint32_t remote_control_id () const = 0;
+
+       virtual boost::shared_ptr<PeakMeter>       peak_meter() = 0;
+       virtual boost::shared_ptr<const PeakMeter> peak_meter() const = 0;
+
+       virtual boost::shared_ptr<GainControl> gain_control() const = 0;
+
+       virtual boost::shared_ptr<AutomationControl> solo_control() const = 0;
+       virtual boost::shared_ptr<AutomationControl> mute_control() const = 0;
+       virtual boost::shared_ptr<AutomationControl> phase_control() const = 0;
+       virtual boost::shared_ptr<AutomationControl> trim_control() const = 0;
+
+       virtual boost::shared_ptr<AutomationControl> monitoring_control() const = 0;
+       virtual boost::shared_ptr<AutomationControl> recenable_control() const { return boost::shared_ptr<AutomationControl>(); }
+
+       /* "well-known" controls for panning. Any or all of these may return
+         * null.
+         */
+
+       virtual boost::shared_ptr<AutomationControl> pan_azimuth_control() const = 0;
+       virtual boost::shared_ptr<AutomationControl> pan_elevation_control() const = 0;
+       virtual boost::shared_ptr<AutomationControl> pan_width_control() const = 0;
+       virtual boost::shared_ptr<AutomationControl> pan_frontback_control() const = 0;
+       virtual boost::shared_ptr<AutomationControl> pan_lfe_control() const = 0;
+
+        /* "well-known" controls for an EQ in this route. Any or all may
+         * be null. eq_band_cnt() must return 0 if there is no EQ present.
+         * Passing an @param band value >= eq_band_cnt() will guarantee the
+         * return of a null ptr (or an empty string for eq_band_name()).
+         */
+       virtual uint32_t eq_band_cnt () const = 0;
+       virtual std::string eq_band_name (uint32_t) const = 0;
+       virtual boost::shared_ptr<AutomationControl> eq_gain_controllable (uint32_t band) const = 0;
+       virtual boost::shared_ptr<AutomationControl> eq_freq_controllable (uint32_t band) const = 0;
+       virtual boost::shared_ptr<AutomationControl> eq_q_controllable (uint32_t band) const = 0;
+       virtual boost::shared_ptr<AutomationControl> eq_shape_controllable (uint32_t band) const = 0;
+       virtual boost::shared_ptr<AutomationControl> eq_enable_controllable () const = 0;
+       virtual boost::shared_ptr<AutomationControl> eq_hpf_controllable () const = 0;
+
+        /* "well-known" controls for a compressor in this route. Any or all may
+         * be null.
+         */
+       virtual boost::shared_ptr<AutomationControl> comp_enable_controllable () const = 0;
+       virtual boost::shared_ptr<AutomationControl> comp_threshold_controllable () const = 0;
+       virtual boost::shared_ptr<AutomationControl> comp_speed_controllable () const = 0;
+       virtual boost::shared_ptr<AutomationControl> comp_mode_controllable () const = 0;
+       virtual boost::shared_ptr<AutomationControl> comp_makeup_controllable () const = 0;
+       virtual boost::shared_ptr<AutomationControl> comp_redux_controllable () const = 0;
+
+        /* @param mode must be supplied by the comp_mode_controllable(). All other values
+         * result in undefined behaviour
+         */
+       virtual std::string comp_mode_name (uint32_t mode) const = 0;
+        /* @param mode - as for comp mode name. This returns the name for the
+         * parameter/control accessed via comp_speed_controllable(), which can
+         * be mode dependent.
+         */
+       virtual std::string comp_speed_name (uint32_t mode) const = 0;
+
+        /* "well-known" controls for sends to well-known busses in this route. Any or all may
+         * be null.
+         *
+         * In Mixbus, these are the sends that connect to the mixbusses.
+         * In Ardour, these are user-created sends that connect to user-created
+         * Aux busses.
+         */
+       virtual boost::shared_ptr<AutomationControl> send_level_controllable (uint32_t n) const = 0;
+       virtual boost::shared_ptr<AutomationControl> send_enable_controllable (uint32_t n) const = 0;
+        /* for the same value of @param n, this returns the name of the send
+         * associated with the pair of controllables returned by the above two methods.
+         */
+       virtual std::string send_name (uint32_t n) const = 0;
+
+        /* well known control that enables/disables sending to the master bus.
+         *
+         * In Ardour, this returns null.
+         * In Mixbus, it will return a suitable control, or null depending on
+         * the route.
+         */
+       virtual boost::shared_ptr<AutomationControl> master_send_enable_controllable () const = 0;
+};
+
+
+}
+
+#endif /* __libardour_stripable_h__ */
index 15850242cc3cac14d8b6d60820a407b88309f091..cca83a13f2093a9a6a0d98cd79ea5d7a8d03b63d 100644 (file)
 
 #include <string>
 #include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
 
 #include "pbd/controllable.h"
 #include "pbd/statefuldestructible.h"
 
 #include "ardour/automatable.h"
-#include "ardour/session_handle.h"
+#include "ardour/stripable.h"
 
 namespace ARDOUR {
 
 class GainControl;
 class Route;
 
-class LIBARDOUR_API VCA : public SessionHandleRef, public PBD::StatefulDestructible, public Automatable {
+class LIBARDOUR_API VCA : public Stripable, public Automatable, public boost::enable_shared_from_this<VCA> {
   public:
        VCA (Session& session,  uint32_t num, const std::string& name);
-       VCA (Session& session, XMLNode const&, int version);
        ~VCA();
 
-       std::string name() const { return _name; }
        uint32_t number () const { return _number; }
+       uint32_t remote_control_id() const;
 
-       void set_name (std::string const&);
-
-       void set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
-       double get_value () const;
-
-       boost::shared_ptr<GainControl> control() const { return _control; }
-
+       int init ();
        XMLNode& get_state();
        int set_state (XMLNode const&, int version);
 
        void add_solo_mute_target (boost::shared_ptr<Route>);
        void remove_solo_mute_target (boost::shared_ptr<Route>);
 
-       void set_solo (bool yn);
        bool soloed () const;
-
-       void set_mute (bool yn);
        bool muted () const;
 
-       PBD::Signal0<void> SoloChange;
-       PBD::Signal0<void> MuteChange;
-
        static std::string default_name_template ();
        static int next_vca_number ();
        static std::string xml_node_name;
 
+       virtual boost::shared_ptr<GainControl> gain_control() const { return _gain_control; }
+       virtual boost::shared_ptr<AutomationControl> solo_control() const { return _solo_control; }
+       virtual boost::shared_ptr<AutomationControl> mute_control() const { return _mute_control; }
+
+       /* null Stripable API, because VCAs don't have any of this */
+
+       virtual boost::shared_ptr<PeakMeter>       peak_meter() { return boost::shared_ptr<PeakMeter>(); }
+       virtual boost::shared_ptr<const PeakMeter> peak_meter() const { return boost::shared_ptr<PeakMeter>(); }
+       virtual boost::shared_ptr<AutomationControl> phase_control() const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> trim_control() const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> monitoring_control() const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> recenable_control() const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> pan_azimuth_control() const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> pan_elevation_control() const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> pan_width_control() const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> pan_frontback_control() const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> pan_lfe_control() const { return boost::shared_ptr<AutomationControl>(); }
+       virtual uint32_t eq_band_cnt () const { return 0; }
+       virtual std::string eq_band_name (uint32_t) const { return std::string(); }
+       virtual boost::shared_ptr<AutomationControl> eq_gain_controllable (uint32_t band) const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> eq_freq_controllable (uint32_t band) const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> eq_q_controllable (uint32_t band) const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> eq_shape_controllable (uint32_t band) const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> eq_enable_controllable () const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> eq_hpf_controllable () const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> comp_enable_controllable () const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> comp_threshold_controllable () const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> comp_speed_controllable () const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> comp_mode_controllable () const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> comp_makeup_controllable () const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> comp_redux_controllable () const { return boost::shared_ptr<AutomationControl>(); }
+       virtual std::string comp_mode_name (uint32_t mode) const { return std::string(); }
+       virtual std::string comp_speed_name (uint32_t mode) const { return std::string(); }
+       virtual boost::shared_ptr<AutomationControl> send_level_controllable (uint32_t n) const { return boost::shared_ptr<AutomationControl>(); }
+       virtual boost::shared_ptr<AutomationControl> send_enable_controllable (uint32_t n) const { return boost::shared_ptr<AutomationControl>(); }
+       virtual std::string send_name (uint32_t n) const { return std::string(); }
+       virtual boost::shared_ptr<AutomationControl> master_send_enable_controllable () const { return boost::shared_ptr<AutomationControl>(); }
+
   private:
+       class VCASoloControllable : public AutomationControl {
+          public:
+               VCASoloControllable (std::string const & name, boost::shared_ptr<VCA> vca);
+               void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
+               void set_value_unchecked (double);
+               double get_value () const;
+         private:
+               void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
+               boost::weak_ptr<VCA> _vca;
+       };
+
+       class VCAMuteControllable : public AutomationControl {
+          public:
+               VCAMuteControllable (std::string const & name, boost::shared_ptr<VCA> vca);
+               void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
+               void set_value_unchecked (double);
+               double get_value () const;
+         private:
+               void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
+               boost::weak_ptr<VCA> _vca;
+       };
+
+       friend class VCASoloControllable;
+       friend class VCAMuteControllable;
+
        uint32_t    _number;
-       std::string _name;
-       boost::shared_ptr<GainControl> _control;
        RouteList solo_mute_targets;
        PBD::ScopedConnectionList solo_mute_connections;
        mutable Glib::Threads::RWLock solo_mute_lock;
+       boost::shared_ptr<GainControl> _gain_control;
+       boost::shared_ptr<VCASoloControllable> _solo_control;
+       boost::shared_ptr<VCAMuteControllable> _mute_control;
        bool _solo_requested;
        bool _mute_requested;
 
@@ -84,6 +136,9 @@ class LIBARDOUR_API VCA : public SessionHandleRef, public PBD::StatefulDestructi
        bool soloed_locked () const;
        bool muted_locked () const;
 
+       void set_solo (bool yn);
+       void set_mute (bool yn);
+
 };
 
 } /* namespace */
index 3eff20b1f10bb378885cb6be3e2944a5457ced3f..3415f7c620d3415642263c1ffe5662b6a36f4034 100644 (file)
@@ -180,7 +180,7 @@ GainControl::add_master (boost::shared_ptr<VCA> vca)
 
                /* ratio will be recomputed below */
 
-               res = _masters.insert (make_pair<uint32_t,MasterRecord> (vca->number(), MasterRecord (vca->control(), 0.0)));
+               res = _masters.insert (make_pair<uint32_t,MasterRecord> (vca->number(), MasterRecord (vca->gain_control(), 0.0)));
 
                if (res.second) {
 
@@ -197,7 +197,7 @@ GainControl::add_master (boost::shared_ptr<VCA> vca)
                           and we no longer hear about changes to the VCA.
                        */
 
-                       vca->control()->Changed.connect_same_thread (res.first->second.connection, boost::bind (&PBD::Signal0<void>::operator(), &Changed));
+                       vca->gain_control()->Changed.connect_same_thread (res.first->second.connection, boost::bind (&PBD::Signal0<void>::operator(), &Changed));
                }
        }
 
index 581031c4050c635c65951129e1a7d6f6ff41a98f..db92edf786f2df78cdf8ed4c6c993af17afc1560 100644 (file)
@@ -83,7 +83,7 @@ PBD::Signal3<int,boost::shared_ptr<Route>, boost::shared_ptr<PluginInsert>, Rout
 
 /** Base class for all routable/mixable objects (tracks and busses) */
 Route::Route (Session& sess, string name, Flag flg, DataType default_type)
-       : SessionObject (sess, name)
+       : Stripable (sess, name)
        , Automatable (sess)
        , GraphNode (sess._process_graph)
        , _active (true)
@@ -4732,13 +4732,13 @@ Route::gain_control() const
        return _gain_control;
 }
 
-boost::shared_ptr<GainControl>
+boost::shared_ptr<AutomationControl>
 Route::trim_control() const
 {
        return _trim_control;
 }
 
-boost::shared_ptr<Route::PhaseControllable>
+boost::shared_ptr<AutomationControl>
 Route::phase_control() const
 {
        if (phase_invert().size()) {
index b9dbaa72fdcdef6c95f9d4f6bd102938b97869f8..86d698a2cb932993d6a60479ff208930659aea1b 100644 (file)
@@ -4195,6 +4195,21 @@ Session::route_by_remote_id (uint32_t id)
 }
 
 
+boost::shared_ptr<Stripable>
+Session::stripable_by_remote_id (uint32_t id)
+{
+       boost::shared_ptr<RouteList> r = routes.reader ();
+
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+               if ((*i)->remote_control_id() == id) {
+                       return *i;
+               }
+       }
+
+       return boost::shared_ptr<Route> ((Route*) 0);
+}
+
+
 boost::shared_ptr<Route>
 Session::route_by_selected_count (uint32_t id)
 {
index 132f706c66def58a7e065dd42d3e12c388221e03..5850643739b23a73a33a5b765be6824c163cf067 100644 (file)
@@ -150,7 +150,7 @@ Session::set_mute (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeve
 {
        /* Set superficial value of mute controls for automation. */
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
-               boost::shared_ptr<Route::MuteControllable> mc = (*i)->mute_control();
+               boost::shared_ptr<Route::MuteControllable> mc = boost::dynamic_pointer_cast<Route::MuteControllable> ((*i)->mute_control());
                mc->set_superficial_value(yn);
        }
 
index 6a696b5a55e734a24a95ca6b65a45bca58bba76e..f627dc033e2fc8fc5f59c0bc41e53d08b2ec5c71 100644 (file)
@@ -1,19 +1,19 @@
 /*
-    Copyright (C) 2016 Paul Davis
+  Copyright (C) 2016 Paul Davis
 
-    This program is free software; you can redistribute it and/or modify it
-    under the terms of the GNU General Public License as published by the Free
-    Software Foundation; either version 2 of the License, or (at your option)
-    any later version.
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the Free
+  Software Foundation; either version 2 of the License, or (at your option)
+  any later version.
 
-    This program is distributed in the hope that it will be useful, but WITHOUT
-    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-    for more details.
+  This program is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  for more details.
 
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    675 Mass Ave, Cambridge, MA 02139, USA.
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 #include "pbd/convert.h"
@@ -48,28 +48,26 @@ VCA::next_vca_number ()
 }
 
 VCA::VCA (Session& s,  uint32_t num, const string& name)
-       : SessionHandleRef (s)
+       : Stripable (s, name)
        , Automatable (s)
        , _number (num)
-       , _name (name)
-       , _control (new GainControl (s, Evoral::Parameter (GainAutomation), boost::shared_ptr<AutomationList> ()))
+       , _gain_control (new GainControl (s, Evoral::Parameter (GainAutomation), boost::shared_ptr<AutomationList> ()))
        , _solo_requested (false)
        , _mute_requested (false)
 {
-       add_control (_control);
 }
 
-VCA::VCA (Session& s, XMLNode const & node, int version)
-       : SessionHandleRef (s)
-       , Automatable (s)
-       , _number (0)
-       , _control (new GainControl (s, Evoral::Parameter (GainAutomation), boost::shared_ptr<AutomationList> ()))
-       , _solo_requested (false)
-       , _mute_requested (false)
+int
+VCA::init ()
 {
-       add_control (_control);
+       _solo_control.reset (new VCASoloControllable (X_("solo"), shared_from_this()));
+       _mute_control.reset (new VCAMuteControllable (X_("mute"), shared_from_this()));
 
-       set_state (node, version);
+       add_control (_gain_control);
+       add_control (_solo_control);
+       add_control (_mute_control);
+
+       return 0;
 }
 
 VCA::~VCA ()
@@ -77,22 +75,10 @@ VCA::~VCA ()
        DropReferences (); /* emit signal */
 }
 
-void
-VCA::set_value (double val, Controllable::GroupControlDisposition gcd)
-{
-       _control->set_value (val, gcd);
-}
-
-double
-VCA::get_value() const
-{
-       return _control->get_value();
-}
-
-void
-VCA::set_name (string const& str)
+uint32_t
+VCA::remote_control_id () const
 {
-       _name = str;
+       return 9999999 + _number;
 }
 
 XMLNode&
@@ -104,7 +90,7 @@ VCA::get_state ()
        node->add_property (X_("soloed"), (_solo_requested ? X_("yes") : X_("no")));
        node->add_property (X_("muted"), (_mute_requested ? X_("yes") : X_("no")));
 
-       node->add_child_nocopy (_control->get_state());
+       node->add_child_nocopy (_gain_control->get_state());
        node->add_child_nocopy (get_automation_xml_state());
 
        return *node;
@@ -128,7 +114,7 @@ VCA::set_state (XMLNode const& node, int version)
                if ((*i)->name() == Controllable::xml_node_name) {
                        XMLProperty* prop = (*i)->property ("name");
                        if (prop && prop->value() == X_("gaincontrol")) {
-                               _control->set_state (**i, version);
+                               _gain_control->set_state (**i, version);
                        }
                }
        }
@@ -187,7 +173,6 @@ VCA::set_solo (bool yn)
        }
 
        _solo_requested = yn;
-       SoloChange(); /* EMIT SIGNAL */
 }
 
 void
@@ -204,7 +189,6 @@ VCA::set_mute (bool yn)
        }
 
        _mute_requested = yn;
-       MuteChange(); /* EMIT SIGNAL */
 }
 
 bool
@@ -218,3 +202,91 @@ VCA::muted () const
 {
        return _mute_requested;
 }
+
+VCA::VCASoloControllable::VCASoloControllable (string const & name, boost::shared_ptr<VCA> vca)
+       : AutomationControl (vca->session(), Evoral::Parameter (SoloAutomation), ParameterDescriptor (Evoral::Parameter (SoloAutomation)),
+                            boost::shared_ptr<AutomationList>(), name)
+       , _vca (vca)
+{
+}
+
+void
+VCA::VCASoloControllable::set_value (double val, PBD::Controllable::GroupControlDisposition gcd)
+{
+       if (writable()) {
+               _set_value (val, gcd);
+       }
+}
+
+void
+VCA::VCASoloControllable::_set_value (double val, PBD::Controllable::GroupControlDisposition /*gcd*/)
+{
+       boost::shared_ptr<VCA> vca = _vca.lock();
+       if (!vca) {
+               return;
+       }
+       vca->set_solo (val >= 0.5);
+}
+
+void
+VCA::VCASoloControllable::set_value_unchecked (double val)
+{
+       /* used only by automation playback */
+       _set_value (val, Controllable::NoGroup);
+}
+
+double
+VCA::VCASoloControllable::get_value() const
+{
+       boost::shared_ptr<VCA> vca = _vca.lock();
+       if (!vca) {
+               return 0.0;
+       }
+
+       return vca->soloed() ? 1.0 : 0.0;
+}
+
+/*----*/
+
+VCA::VCAMuteControllable::VCAMuteControllable (string const & name, boost::shared_ptr<VCA> vca)
+       : AutomationControl (vca->session(), Evoral::Parameter (MuteAutomation), ParameterDescriptor (Evoral::Parameter (MuteAutomation)),
+                            boost::shared_ptr<AutomationList>(), name)
+       , _vca (vca)
+{
+}
+
+void
+VCA::VCAMuteControllable::set_value (double val, PBD::Controllable::GroupControlDisposition gcd)
+{
+       if (writable()) {
+               _set_value (val, gcd);
+       }
+}
+
+void
+VCA::VCAMuteControllable::_set_value (double val, PBD::Controllable::GroupControlDisposition /*gcd*/)
+{
+       boost::shared_ptr<VCA> vca = _vca.lock();
+       if (!vca) {
+               return;
+       }
+       vca->set_mute (val >= 0.5);
+}
+
+void
+VCA::VCAMuteControllable::set_value_unchecked (double val)
+{
+       /* used only by automation playback */
+       _set_value (val, Controllable::NoGroup);
+}
+
+double
+VCA::VCAMuteControllable::get_value() const
+{
+       boost::shared_ptr<VCA> vca = _vca.lock();
+       if (!vca) {
+               return 0.0;
+       }
+
+       return vca->muted() ? 1.0 : 0.0;
+}
index 71c3fe8029a31957fbf51531f461f5983145bb86..6cc287554afd035b1bf9feb49fa6ee3fe37a129c 100644 (file)
@@ -18,6 +18,7 @@
 */
 
 #include "pbd/convert.h"
+#include "pbd/error.h"
 #include "pbd/replace_all.h"
 
 #include "ardour/vca.h"
@@ -27,6 +28,7 @@
 
 using namespace ARDOUR;
 using namespace Glib::Threads;
+using namespace PBD;
 using std::string;
 
 string VCAManager::xml_node_name (X_("VCAManager"));
@@ -76,6 +78,8 @@ VCAManager::create_vca (uint32_t howmany, std::string const & name_template)
 
                        boost::shared_ptr<VCA> vca = boost::shared_ptr<VCA> (new VCA (_session, num, name));
 
+                       vca->init ();
+
                        _vcas.push_back (vca);
                        vcal.push_back (vca);
                }
@@ -145,7 +149,12 @@ 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) {
-                       boost::shared_ptr<VCA> vca = boost::shared_ptr<VCA> (new VCA (_session, **i, version));
+                       boost::shared_ptr<VCA> vca = boost::shared_ptr<VCA> (new VCA (_session, 0, X_("tobereset")));
+
+                       if (vca->init() || vca->set_state (**i, version)) {
+                               error << _("Cannot set state of a VCA") << endmsg;
+                               return -1;
+                       }
 
                        /* can't hold the lock for the entire loop,
                         * because the new VCA maybe slaved and needs