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:
Robin Gareus
2019-03-23 03:10:49 +01:00
parent e9b36f2bea
commit 087fd57d37
5 changed files with 63 additions and 14 deletions

View File

@@ -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
{

View File

@@ -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;
}

View File

@@ -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()));
}

View File

@@ -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>();
}

View File

@@ -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