Update Slavable API

Do not use AutomationType to identify parameters, use complete
Evoral::Parameter and Automatable.

For "batch connections", a Slavables needs to implement an API to return
the relevant controls.

This is only a first step towards a more generic Master/Slave framework.
This commit is contained in:
Robin Gareus 2017-06-22 21:06:12 +02:00
parent faa52a3349
commit 9334c99b35
11 changed files with 89 additions and 70 deletions

View File

@ -117,6 +117,8 @@ public:
framepos_t _last_automation_snapshot;
SlavableControlList slavables () const { return SlavableControlList(); }
private:
PBD::ScopedConnectionList _control_connections; ///< connections to our controls' signals
};

View File

@ -686,6 +686,8 @@ protected:
boost::shared_ptr<Processor> the_instrument_unlocked() const;
SlavableControlList slavables () const;
private:
int64_t _track_number;

View File

@ -30,6 +30,7 @@
#include "evoral/Parameter.hpp"
#include "ardour/types.h"
#include "ardour/libardour_visibility.h"
class XMLNode;
@ -39,33 +40,39 @@ namespace ARDOUR {
class VCA;
class VCAManager;
class AutomationControl;
class SlavableAutomationControl;
class LIBARDOUR_API Slavable
{
public:
public:
Slavable ();
virtual ~Slavable() {}
XMLNode& get_state () const;
int set_state (XMLNode const&, int);
void assign (boost::shared_ptr<VCA>, bool loading);
void assign (boost::shared_ptr<VCA>);
void unassign (boost::shared_ptr<VCA>);
PBD::Signal2<void,boost::shared_ptr<VCA>,bool> AssignmentChange;
virtual boost::shared_ptr<AutomationControl> automation_control (const Evoral::Parameter& id) = 0;
virtual boost::shared_ptr<AutomationControl> automation_control (const Evoral::Parameter&) = 0;
static std::string xml_node_name;
/* signal sent VCAManager once assignment is possible */
static PBD::Signal1<void,VCAManager*> Assign;
protected:
virtual int assign_controls (boost::shared_ptr<VCA>, bool loading);
virtual int unassign_controls (boost::shared_ptr<VCA>);
protected:
virtual SlavableControlList slavables () const = 0;
private:
bool assign_controls (boost::shared_ptr<VCA>);
void unassign_controls (boost::shared_ptr<VCA>);
bool assign_control (boost::shared_ptr<VCA>, boost::shared_ptr<SlavableAutomationControl>);
void unassign_control (boost::shared_ptr<VCA>, boost::shared_ptr<SlavableAutomationControl>);
private:
mutable Glib::Threads::RWLock master_lock;
std::set<uint32_t> _masters;
PBD::ScopedConnection assign_connection;
@ -73,7 +80,6 @@ class LIBARDOUR_API Slavable
int do_assign (VCAManager* s);
void weak_unassign (boost::weak_ptr<VCA>);
};
} // namespace ARDOUR

View File

@ -40,7 +40,7 @@ public:
double get_value () const;
void add_master (boost::shared_ptr<AutomationControl>, bool loading);
void add_master (boost::shared_ptr<AutomationControl>);
void remove_master (boost::shared_ptr<AutomationControl>);
void clear_masters ();
bool slaved_to (boost::shared_ptr<AutomationControl>) const;

View File

@ -55,6 +55,7 @@ namespace ARDOUR {
class Stripable;
class VCA;
class AutomationControl;
class SlavableAutomationControl;
typedef float Sample;
typedef float pan_t;
@ -588,6 +589,7 @@ namespace ARDOUR {
typedef std::list<boost::weak_ptr <Route> > WeakRouteList;
typedef std::list<boost::weak_ptr <Stripable> > WeakStripableList;
typedef std::list<boost::shared_ptr<AutomationControl> > ControlList;
typedef std::list<boost::shared_ptr<SlavableAutomationControl> > SlavableControlList;
typedef std::list<boost::shared_ptr<VCA> > VCAList;

View File

@ -146,6 +146,9 @@ class LIBARDOUR_API VCA : public Stripable,
boost::shared_ptr<AutomationControl> eq_lpf_controllable () const { return boost::shared_ptr<AutomationControl>(); }
boost::shared_ptr<AutomationControl> filter_enable_controllable () const { return boost::shared_ptr<AutomationControl>(); }
protected:
SlavableControlList slavables () const;
private:
int32_t _number;

View File

@ -5516,3 +5516,13 @@ Route::automation_control_recurse (PBD::ID const & id) const
return boost::shared_ptr<AutomationControl> ();
}
SlavableControlList
Route::slavables () const
{
SlavableControlList rv;
rv.push_back (_gain_control);
rv.push_back (_mute_control);
rv.push_back (_solo_control);
return rv;
}

View File

@ -187,7 +187,7 @@ RouteGroup::add (boost::shared_ptr<Route> r)
boost::shared_ptr<VCA> vca (group_master.lock());
if (vca) {
r->assign (vca, false);
r->assign (vca);
}
_session.set_dirty ();
@ -656,7 +656,7 @@ RouteGroup::assign_master (boost::shared_ptr<VCA> master)
}
for (RouteList::iterator r = routes->begin(); r != routes->end(); ++r) {
(*r)->assign (master, false);
(*r)->assign (master);
}
group_master = master;

View File

@ -82,18 +82,6 @@ Slavable::set_state (XMLNode const& node, int version)
return 0;
}
/* Gain, solo & mute are currently the only controls that are
* automatically slaved to the master's own equivalent controls.
*/
static AutomationType auto_slave_types[] = {
GainAutomation,
SoloAutomation,
MuteAutomation,
NullAutomation
};
int
Slavable::do_assign (VCAManager* manager)
{
@ -117,18 +105,12 @@ Slavable::do_assign (VCAManager* manager)
if (!vcas.empty()) {
for (std::vector<boost::shared_ptr<VCA> >::iterator v = vcas.begin(); v != vcas.end(); ++v) {
assign (*v, true);
assign (*v);
}
for (uint32_t n = 0; auto_slave_types[n] != NullAutomation; ++n) {
boost::shared_ptr<SlavableAutomationControl> slave;
slave = boost::dynamic_pointer_cast<SlavableAutomationControl> (automation_control (auto_slave_types[n]));
if (slave) {
slave->use_saved_master_ratios ();
}
SlavableControlList scl = slavables ();
for (SlavableControlList::iterator i = scl.begin(); i != scl.end(); ++i) {
(*i)->use_saved_master_ratios ();
}
}
@ -138,12 +120,12 @@ Slavable::do_assign (VCAManager* manager)
}
void
Slavable::assign (boost::shared_ptr<VCA> v, bool loading)
Slavable::assign (boost::shared_ptr<VCA> v)
{
assert (v);
{
Glib::Threads::RWLock::WriterLock lm (master_lock);
if (assign_controls (v, loading) == 0) {
if (assign_controls (v)) {
_masters.insert (v->number());
}
@ -175,7 +157,7 @@ Slavable::unassign (boost::shared_ptr<VCA> v)
{
Glib::Threads::RWLock::WriterLock lm (master_lock);
(void) unassign_controls (v);
unassign_controls (v);
if (v) {
_masters.erase (v->number());
} else {
@ -185,47 +167,49 @@ Slavable::unassign (boost::shared_ptr<VCA> v)
AssignmentChange (v, false);
}
int
Slavable::assign_controls (boost::shared_ptr<VCA> vca, bool loading)
bool
Slavable::assign_controls (boost::shared_ptr<VCA> vca)
{
boost::shared_ptr<SlavableAutomationControl> slave;
boost::shared_ptr<AutomationControl> master;
for (uint32_t n = 0; auto_slave_types[n] != NullAutomation; ++n) {
slave = boost::dynamic_pointer_cast<SlavableAutomationControl> (automation_control (auto_slave_types[n]));
master = vca->automation_control (auto_slave_types[n]);
if (slave && master) {
slave->add_master (master, loading);
}
bool rv = false;
SlavableControlList scl = slavables ();
for (SlavableControlList::iterator i = scl.begin(); i != scl.end(); ++i) {
rv |= assign_control (vca, *i);
}
return 0;
return rv;
}
int
void
Slavable::unassign_controls (boost::shared_ptr<VCA> vca)
{
boost::shared_ptr<SlavableAutomationControl> slave;
SlavableControlList scl = slavables ();
for (SlavableControlList::iterator i = scl.begin(); i != scl.end(); ++i) {
unassign_control (vca, *i);
}
}
bool
Slavable::assign_control (boost::shared_ptr<VCA> vca, boost::shared_ptr<SlavableAutomationControl> slave)
{
boost::shared_ptr<AutomationControl> master;
master = vca->automation_control (slave->parameter());
if (!master) {
return false;
}
slave->add_master (master);
return true;
}
for (uint32_t n = 0; auto_slave_types[n] != NullAutomation; ++n) {
slave = boost::dynamic_pointer_cast<SlavableAutomationControl> (automation_control (auto_slave_types[n]));
if (!vca) {
/* unassign from all */
if (slave) {
slave->clear_masters ();
}
} else {
master = vca->automation_control (auto_slave_types[n]);
if (slave && master) {
slave->remove_master (master);
}
void
Slavable::unassign_control (boost::shared_ptr<VCA> vca, boost::shared_ptr<SlavableAutomationControl> slave)
{
if (!vca) {
/* unassign from all */
slave->clear_masters ();
} else {
boost::shared_ptr<AutomationControl> master;
master = vca->automation_control (slave->parameter());
if (master) {
slave->remove_master (master);
}
}
return 0;
}

View File

@ -183,7 +183,7 @@ SlavableAutomationControl::actually_set_value (double value, PBD::Controllable::
}
void
SlavableAutomationControl::add_master (boost::shared_ptr<AutomationControl> m, bool loading)
SlavableAutomationControl::add_master (boost::shared_ptr<AutomationControl> m)
{
std::pair<Masters::iterator,bool> res;

View File

@ -207,3 +207,13 @@ VCA::slaved_to (boost::shared_ptr<VCA> vca) const
return _gain_control->slaved_to (vca->gain_control());
}
SlavableControlList
VCA::slavables () const
{
SlavableControlList rv;
rv.push_back (_gain_control);
rv.push_back (_mute_control);
rv.push_back (_solo_control);
return rv;
}