diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h index 79bbec5199..2f35fc6b42 100644 --- a/libs/ardour/ardour/automatable.h +++ b/libs/ardour/ardour/automatable.h @@ -58,6 +58,7 @@ public: automation_control (const Evoral::Parameter& id) const; virtual void add_control(boost::shared_ptr); + void clear_controls (); virtual void automation_snapshot(nframes_t now, bool force); virtual void transport_stopped (sframes_t now); diff --git a/libs/ardour/ardour/automation_list.h b/libs/ardour/ardour/automation_list.h index 79acedebf3..77b8d49dc7 100644 --- a/libs/ardour/ardour/automation_list.h +++ b/libs/ardour/ardour/automation_list.h @@ -51,7 +51,6 @@ class AutomationList : public PBD::StatefulDestructible, public Evoral::ControlL bool operator== (const AutomationList&); void thaw (); - void mark_dirty () const; void set_automation_state (AutoState); AutoState automation_state() const { return _state; } @@ -71,7 +70,6 @@ class AutomationList : public PBD::StatefulDestructible, public Evoral::ControlL PBD::Signal0 StateChanged; static PBD::Signal1 AutomationListCreated; - mutable PBD::Signal0 Dirty; void start_touch (); void stop_touch (); diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc index 1e5b497bf7..bed99d5660 100644 --- a/libs/ardour/automatable.cc +++ b/libs/ardour/automatable.cc @@ -484,3 +484,11 @@ Automatable::automation_state_changed (Evoral::Parameter const & p) { AutomationStateChanged (p); /* EMIT SIGNAL */ } + +void +Automatable::clear_controls () +{ + _control_connections.drop_connections (); + ControlSet::clear_controls (); +} + diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc index f34104ce22..e785104367 100644 --- a/libs/ardour/automation_list.cc +++ b/libs/ardour/automation_list.cc @@ -218,13 +218,6 @@ AutomationList::thaw () } } -void -AutomationList::mark_dirty () const -{ - ControlList::mark_dirty (); - Dirty (); /* EMIT SIGNAL */ -} - XMLNode& AutomationList::get_state () { diff --git a/libs/evoral/evoral/Control.hpp b/libs/evoral/evoral/Control.hpp index d79ef25b5a..210ee7c322 100644 --- a/libs/evoral/evoral/Control.hpp +++ b/libs/evoral/evoral/Control.hpp @@ -22,6 +22,7 @@ #include #include #include +#include "pbd/signals.h" #include "evoral/types.hpp" #include "evoral/Parameter.hpp" @@ -55,10 +56,17 @@ public: inline const Parameter& parameter() const { return _parameter; } + /** Emitted when the our ControlList is marked dirty */ + PBD::Signal0 ListMarkedDirty; + protected: Parameter _parameter; boost::shared_ptr _list; float _user_value; + PBD::ScopedConnection _list_marked_dirty_connection; + +private: + void list_marked_dirty (); }; } // namespace Evoral diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp index d68b6a3e5f..5f842775ee 100644 --- a/libs/evoral/evoral/ControlList.hpp +++ b/libs/evoral/evoral/ControlList.hpp @@ -24,6 +24,7 @@ #include #include #include +#include "pbd/signals.h" #include "evoral/types.hpp" #include "evoral/Parameter.hpp" @@ -224,7 +225,7 @@ public: Curve& curve() { assert(_curve); return *_curve; } const Curve& curve() const { assert(_curve); return *_curve; } - virtual void mark_dirty () const; + void mark_dirty () const; enum InterpolationStyle { Discrete, @@ -235,6 +236,9 @@ public: InterpolationStyle interpolation() const { return _interpolation; } void set_interpolation(InterpolationStyle style) { _interpolation = style; } + /** Emitted when mark_dirty() is called on this object */ + mutable PBD::Signal0 Dirty; + protected: /** Called by unlocked_eval() to handle cases of 3 or more control points. */ diff --git a/libs/evoral/evoral/ControlSet.hpp b/libs/evoral/evoral/ControlSet.hpp index f0c6bd0807..b775bb3b4b 100644 --- a/libs/evoral/evoral/ControlSet.hpp +++ b/libs/evoral/evoral/ControlSet.hpp @@ -24,6 +24,7 @@ #include #include #include +#include "pbd/signals.h" #include "evoral/types.hpp" #include "evoral/Parameter.hpp" @@ -67,8 +68,13 @@ public: Glib::Mutex& control_lock() const { return _control_lock; } protected: + virtual void control_list_marked_dirty () {} + mutable Glib::Mutex _control_lock; Controls _controls; + +private: + PBD::ScopedConnectionList _control_connections; }; diff --git a/libs/evoral/evoral/Sequence.hpp b/libs/evoral/evoral/Sequence.hpp index 1ad456b302..3cddeb38ca 100644 --- a/libs/evoral/evoral/Sequence.hpp +++ b/libs/evoral/evoral/Sequence.hpp @@ -79,6 +79,7 @@ protected: }; public: + typedef typename boost::shared_ptr > NotePtr; typedef typename boost::shared_ptr > constNotePtr; @@ -274,6 +275,8 @@ private: void get_notes_by_pitch (Notes&, NoteOperator, uint8_t val, int chan_mask = 0) const; void get_notes_by_velocity (Notes&, NoteOperator, uint8_t val, int chan_mask = 0) const; + void control_list_marked_dirty (); + const TypeMap& _type_map; Notes _notes; // notes indexed by time @@ -283,9 +286,6 @@ private: typedef std::multiset WriteNotes; WriteNotes _write_notes[16]; - typedef std::vector< boost::shared_ptr > ControlLists; - ControlLists _dirty_controls; - const const_iterator _end_iter; bool _percussive; diff --git a/libs/evoral/src/Control.cpp b/libs/evoral/src/Control.cpp index 56277678ba..985c7b1352 100644 --- a/libs/evoral/src/Control.cpp +++ b/libs/evoral/src/Control.cpp @@ -26,9 +26,9 @@ Parameter::TypeMetadata Parameter::_type_metadata; Control::Control(const Parameter& parameter, boost::shared_ptr list) : _parameter(parameter) - , _list(list) , _user_value(list ? list->default_value() : parameter.normal()) { + set_list (list); } @@ -59,7 +59,19 @@ Control::set_float(float value, bool to_list, FrameTime frame) void Control::set_list(boost::shared_ptr list) { + _list_marked_dirty_connection.disconnect (); + _list = list; + + if (_list) { + _list->Dirty.connect_same_thread (_list_marked_dirty_connection, boost::bind (&Control::list_marked_dirty, this)); + } +} + +void +Control::list_marked_dirty () +{ + ListMarkedDirty (); /* EMIT SIGNAL */ } } // namespace Evoral diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp index 00b876d18a..3eb6c7d4ce 100644 --- a/libs/evoral/src/ControlList.cpp +++ b/libs/evoral/src/ControlList.cpp @@ -558,8 +558,12 @@ ControlList::mark_dirty () const { _lookup_cache.left = -1; _search_cache.left = -1; - if (_curve) + + if (_curve) { _curve->mark_dirty(); + } + + Dirty (); /* EMIT SIGNAL */ } void diff --git a/libs/evoral/src/ControlSet.cpp b/libs/evoral/src/ControlSet.cpp index e19acf7689..d985e347d7 100644 --- a/libs/evoral/src/ControlSet.cpp +++ b/libs/evoral/src/ControlSet.cpp @@ -41,6 +41,8 @@ void ControlSet::add_control(boost::shared_ptr ac) { _controls[ac->parameter()] = ac; + + ac->ListMarkedDirty.connect_same_thread (_control_connections, boost::bind (&ControlSet::control_list_marked_dirty, this)); } void @@ -108,6 +110,8 @@ ControlSet::clear_controls () { Glib::Mutex::Lock lm (_control_lock); + _control_connections.drop_connections (); + for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li) li->second->list()->clear(); } diff --git a/libs/evoral/src/Sequence.cpp b/libs/evoral/src/Sequence.cpp index add32fb9bd..a67f32e993 100644 --- a/libs/evoral/src/Sequence.cpp +++ b/libs/evoral/src/Sequence.cpp @@ -534,7 +534,6 @@ Sequence