From 6f80a5ba0fc7516a14492e357fe036a9bed5638d Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 30 Jul 2017 02:34:14 +0200 Subject: Turn AutomationCtrl into a SessionHandleRef This fixes a crash with GUI elements which are only deleted during GUI Idle and hold a Reference to a Controllable, The session is already destroyed at that point: ARDOUR::CoreSelection::remove_control_by_id(PBD::ID const&) ARDOUR::AutomationControl::~AutomationControl() ARDOUR::SlavableAutomationControl::~SlavableAutomationControl() ARDOUR::MonitorControl::~MonitorControl() boost::detail::sp_counted_base::destroy() boost::detail::sp_counted_impl_p::Input>::dispose() boost::detail::sp_counted_base::release() boost::detail::shared_count::~shared_count() boost::shared_ptr::~shared_ptr() boost::shared_ptr::~shared_ptr() ArdourWidgets::BindingProxy::~BindingProxy() ArdourWidgets::ArdourButton::~ArdourButton() VCAMasterStrip::~VCAMasterStrip() int idle_delete(VCAMasterStrip*) --- libs/ardour/ardour/automation_control.h | 6 +++++- libs/ardour/automation_control.cc | 19 ++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/libs/ardour/ardour/automation_control.h b/libs/ardour/ardour/automation_control.h index 6ffcb3b866..e875ea98a6 100644 --- a/libs/ardour/ardour/automation_control.h +++ b/libs/ardour/ardour/automation_control.h @@ -36,6 +36,7 @@ #include "ardour/automation_list.h" #include "ardour/control_group_member.h" #include "ardour/parameter_descriptor.h" +#include "ardour/session_handle.h" #include "ardour/libardour_visibility.h" @@ -52,6 +53,7 @@ class LIBARDOUR_API AutomationControl , public Evoral::Control , public boost::enable_shared_from_this , public ControlGroupMember + , public SessionHandleRef { public: AutomationControl(ARDOUR::Session&, @@ -124,7 +126,6 @@ public: ControlList grouped_controls () const; protected: - ARDOUR::Session& _session; boost::shared_ptr _group; const ParameterDescriptor _desc; @@ -147,6 +148,8 @@ protected: /* this will be invoked in turn on behalf of the group or the control by itself */ virtual void do_pre_realtime_queue_stuff (double new_value) {} + void session_going_away (); + private: /* I am unclear on why we have to make ControlGroup a friend in order to get access to the ::set_group() method when it is already @@ -155,6 +158,7 @@ private: friend class ControlGroup; void set_group (boost::shared_ptr); PBD::ScopedConnection _state_changed_connection; + bool _no_session; }; diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc index 1c4525470b..7deeac4221 100644 --- a/libs/ardour/automation_control.cc +++ b/libs/ardour/automation_control.cc @@ -56,8 +56,9 @@ AutomationControl::AutomationControl(ARDOUR::Session& s : Controllable (name.empty() ? EventTypeMap::instance().to_symbol(parameter) : name, flags) , Evoral::Control(parameter, desc, list) - , _session(session) + , SessionHandleRef (session) , _desc(desc) + , _no_session(false) { if (_desc.toggled) { set_flags (Controllable::Toggle); @@ -70,10 +71,18 @@ AutomationControl::AutomationControl(ARDOUR::Session& s AutomationControl::~AutomationControl () { - if (!_session.deletion_in_progress ()) { + if (!_no_session && !_session.deletion_in_progress ()) { _session.selection().remove_control_by_id (id()); + DropReferences (); /* EMIT SIGNAL */ } +} + +void +AutomationControl::session_going_away () +{ + SessionHandleRef::session_going_away (); DropReferences (); /* EMIT SIGNAL */ + _no_session = true; } bool @@ -90,7 +99,7 @@ AutomationControl::writable() const double AutomationControl::get_value() const { - bool from_list = _list && boost::dynamic_pointer_cast(_list)->automation_playback(); + bool from_list = alist() && alist()->automation_playback(); return Control::get_double (from_list, _session.transport_frame()); } @@ -176,7 +185,7 @@ AutomationControl::automation_run (framepos_t start, pframes_t nframes) void AutomationControl::actually_set_value (double value, PBD::Controllable::GroupControlDisposition gcd) { - boost::shared_ptr al = boost::dynamic_pointer_cast (_list); + boost::shared_ptr al = alist (); const framepos_t pos = _session.transport_frame(); bool to_list; @@ -232,7 +241,7 @@ AutomationControl::set_automation_state (AutoState as) if (flags() & NotAutomatable) { return; } - if (_list && as != alist()->automation_state()) { + if (alist() && as != alist()->automation_state()) { const double val = get_value (); -- cgit v1.2.3