Re-add Controllable registry
To facilitate a central registry with weak/shared pointer lookup, enable_shared_from_this<ARDOUR::AutomationControl> was migrated to enable_shared_from_this<PBD::Controllable> The main (and only) user is generic-midi surface's state interface :(
This commit is contained in:
@@ -26,7 +26,6 @@
|
||||
#include <glibmm/threads.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
|
||||
#include "pbd/controllable.h"
|
||||
|
||||
@@ -51,7 +50,6 @@ class ControlGroup;
|
||||
class LIBARDOUR_API AutomationControl
|
||||
: public PBD::Controllable
|
||||
, public Evoral::Control
|
||||
, public boost::enable_shared_from_this<AutomationControl>
|
||||
, public ControlGroupMember
|
||||
, public SessionHandleRef
|
||||
{
|
||||
|
||||
@@ -141,7 +141,7 @@ AutomationControl::set_value (double val, PBD::Controllable::GroupControlDisposi
|
||||
}
|
||||
|
||||
if (_group && _group->use_me (gcd)) {
|
||||
_group->set_group_value (shared_from_this(), val);
|
||||
_group->set_group_value (boost::dynamic_pointer_cast<AutomationControl>(shared_from_this()), val);
|
||||
} else {
|
||||
actually_set_value (val, gcd);
|
||||
}
|
||||
@@ -252,7 +252,7 @@ AutomationControl::set_automation_state (AutoState as)
|
||||
}
|
||||
|
||||
if (as == Write) {
|
||||
AutomationWatch::instance().add_automation_watch (shared_from_this());
|
||||
AutomationWatch::instance().add_automation_watch (boost::dynamic_pointer_cast<AutomationControl>(shared_from_this()));
|
||||
} else if (as & (Touch | Latch)) {
|
||||
if (alist()->empty()) {
|
||||
Control::set_double (val, _session.current_start_sample (), true);
|
||||
@@ -260,17 +260,17 @@ AutomationControl::set_automation_state (AutoState as)
|
||||
Changed (true, Controllable::NoGroup);
|
||||
}
|
||||
if (!touching()) {
|
||||
AutomationWatch::instance().remove_automation_watch (shared_from_this());
|
||||
AutomationWatch::instance().remove_automation_watch (boost::dynamic_pointer_cast<AutomationControl>(shared_from_this()));
|
||||
} else {
|
||||
/* this seems unlikely, but the combination of
|
||||
* a control surface and the mouse could make
|
||||
* it possible to put the control into Touch
|
||||
* mode *while* touching it.
|
||||
*/
|
||||
AutomationWatch::instance().add_automation_watch (shared_from_this());
|
||||
AutomationWatch::instance().add_automation_watch (boost::dynamic_pointer_cast<AutomationControl>(shared_from_this()));
|
||||
}
|
||||
} else {
|
||||
AutomationWatch::instance().remove_automation_watch (shared_from_this());
|
||||
AutomationWatch::instance().remove_automation_watch (boost::dynamic_pointer_cast<AutomationControl>(shared_from_this()));
|
||||
Changed (false, Controllable::NoGroup);
|
||||
}
|
||||
}
|
||||
@@ -293,7 +293,7 @@ AutomationControl::start_touch (double when)
|
||||
AutomationControl::actually_set_value (get_value (), Controllable::NoGroup);
|
||||
alist()->start_touch (when);
|
||||
if (!_desc.toggled) {
|
||||
AutomationWatch::instance().add_automation_watch (shared_from_this());
|
||||
AutomationWatch::instance().add_automation_watch (boost::dynamic_pointer_cast<AutomationControl>(shared_from_this()));
|
||||
}
|
||||
set_touching (true);
|
||||
}
|
||||
@@ -315,7 +315,7 @@ AutomationControl::stop_touch (double when)
|
||||
if (alist()->automation_state() & (Touch | Latch)) {
|
||||
alist()->stop_touch (when);
|
||||
if (!_desc.toggled) {
|
||||
AutomationWatch::instance().remove_automation_watch (shared_from_this());
|
||||
AutomationWatch::instance().remove_automation_watch (boost::dynamic_pointer_cast<AutomationControl>(shared_from_this()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -378,7 +378,7 @@ AutomationControl::check_rt (double val, Controllable::GroupControlDisposition g
|
||||
{
|
||||
if (!_session.loading() && (flags() & Controllable::RealTime) && !AudioEngine::instance()->in_process_thread()) {
|
||||
/* queue change in RT context */
|
||||
_session.set_control (shared_from_this(), val, gcd);
|
||||
_session.set_control (boost::dynamic_pointer_cast<AutomationControl>(shared_from_this()), val, gcd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,5 +57,5 @@ PanControllable::actually_set_value (double v, Controllable::GroupControlDisposi
|
||||
std::string
|
||||
PanControllable::get_user_string () const
|
||||
{
|
||||
return owner->value_as_string (shared_from_this());
|
||||
return owner->value_as_string (boost::dynamic_pointer_cast<const AutomationControl>(shared_from_this()));
|
||||
}
|
||||
|
||||
@@ -34,13 +34,19 @@ PBD::Signal1<bool, boost::weak_ptr<PBD::Controllable> > Controllable::StartLearn
|
||||
PBD::Signal1<void, boost::weak_ptr<PBD::Controllable> > Controllable::StopLearning;
|
||||
PBD::Signal1<void, boost::weak_ptr<PBD::Controllable> > Controllable::GUIFocusChanged;
|
||||
|
||||
Glib::Threads::RWLock Controllable::registry_lock;
|
||||
Controllable::Controllables Controllable::registry;
|
||||
PBD::ScopedConnectionList Controllable::registry_connections;
|
||||
|
||||
const std::string Controllable::xml_node_name = X_("Controllable");
|
||||
|
||||
Controllable::Controllable (const string& name, Flag f)
|
||||
: _name (name)
|
||||
, _flags (f)
|
||||
, _touching (false)
|
||||
{}
|
||||
{
|
||||
add (*this);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Controllable::get_state ()
|
||||
@@ -91,3 +97,34 @@ Controllable::set_flags (Flag f)
|
||||
{
|
||||
_flags = f;
|
||||
}
|
||||
|
||||
void
|
||||
Controllable::add (Controllable& ctl)
|
||||
{
|
||||
Glib::Threads::RWLock::WriterLock lm (registry_lock);
|
||||
registry.insert (&ctl);
|
||||
ctl.DropReferences.connect_same_thread (registry_connections, boost::bind (&Controllable::remove, &ctl));
|
||||
}
|
||||
|
||||
void
|
||||
Controllable::remove (Controllable* ctl)
|
||||
{
|
||||
Glib::Threads::RWLock::WriterLock lm (registry_lock);
|
||||
Controllables::iterator i = std::find (registry.begin(), registry.end(), ctl);
|
||||
if (i != registry.end()) {
|
||||
registry.erase (i);
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<Controllable>
|
||||
Controllable::by_id (const ID& id)
|
||||
{
|
||||
Glib::Threads::RWLock::ReaderLock lm (registry_lock);
|
||||
|
||||
for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
|
||||
if ((*i)->id() == id) {
|
||||
return (*i)->shared_from_this ();
|
||||
}
|
||||
}
|
||||
return boost::shared_ptr<Controllable>();
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "pbd/signals.h"
|
||||
#include <glibmm/threads.h>
|
||||
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
|
||||
#include "pbd/statefuldestructible.h"
|
||||
|
||||
using std::min;
|
||||
@@ -49,7 +51,8 @@ namespace PBD {
|
||||
* as a control whose value can range between 0 and 1.0.
|
||||
*
|
||||
*/
|
||||
class LIBPBD_API Controllable : public PBD::StatefulDestructible {
|
||||
class LIBPBD_API Controllable : public PBD::StatefulDestructible, public boost::enable_shared_from_this<Controllable>
|
||||
{
|
||||
public:
|
||||
enum Flag {
|
||||
Toggle = 0x1,
|
||||
@@ -150,6 +153,8 @@ public:
|
||||
Flag flags() const { return _flags; }
|
||||
void set_flags (Flag f);
|
||||
|
||||
static boost::shared_ptr<Controllable> by_id (const PBD::ID&);
|
||||
|
||||
static const std::string xml_node_name;
|
||||
|
||||
protected:
|
||||
@@ -160,11 +165,20 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::string _name;
|
||||
std::string _units;
|
||||
Flag _flags;
|
||||
bool _touching;
|
||||
|
||||
typedef std::set<PBD::Controllable*> Controllables;
|
||||
|
||||
static ScopedConnectionList registry_connections;
|
||||
static Glib::Threads::RWLock registry_lock;
|
||||
static Controllables registry;
|
||||
|
||||
static void add (Controllable&);
|
||||
static void remove (Controllable*);
|
||||
|
||||
};
|
||||
|
||||
/* a utility class for the occasions when you need but do not have
|
||||
|
||||
Reference in New Issue
Block a user