change ownership of processor window-proxy

fixes crashes:
* If the Editor-Mixer shows a channel with a plugin that
has been edited in the Mixer, double-clicking the plugin 
will try to bring up a 2nd instance of the plugin-UI.
* When closing Ardour both the Mixer and the Editor-Mixer try to delete the underlying plugin, resulting in a double free.
This commit is contained in:
Robin Gareus 2014-11-29 01:35:49 +01:00
parent 784b96e255
commit 58663db374
4 changed files with 30 additions and 119 deletions

View file

@ -1272,19 +1272,10 @@ ProcessorBox::processor_operation (ProcessorOperation op)
ProcessorWindowProxy* ProcessorWindowProxy*
ProcessorBox::find_window_proxy (boost::shared_ptr<Processor> processor) const ProcessorBox::find_window_proxy (boost::shared_ptr<Processor> processor) const
{ {
for (list<ProcessorWindowProxy*>::const_iterator i = _processor_window_info.begin(); i != _processor_window_info.end(); ++i) { return processor->window_proxy();
boost::shared_ptr<Processor> p = (*i)->processor().lock();
if (p && p == processor) {
return (*i);
}
}
return 0;
} }
bool bool
ProcessorBox::processor_button_press_event (GdkEventButton *ev, ProcessorEntry* child) ProcessorBox::processor_button_press_event (GdkEventButton *ev, ProcessorEntry* child)
{ {
@ -1611,56 +1602,7 @@ ProcessorBox::redisplay_processors ()
&_visible_prefader_processors, &fader_seen)); &_visible_prefader_processors, &fader_seen));
_route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display)); _route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display));
for (ProcessorWindowProxies::iterator i = _processor_window_info.begin(); i != _processor_window_info.end(); ++i) {
(*i)->marked = false;
}
_route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_to_ui_list)); _route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_to_ui_list));
/* trim dead wood from the processor window proxy list */
ProcessorWindowProxies::iterator i = _processor_window_info.begin();
while (i != _processor_window_info.end()) {
ProcessorWindowProxies::iterator j = i;
++j;
if (!(*i)->valid()) {
WM::Manager::instance().remove (*i);
delete *i;
_processor_window_info.erase (i);
} else if (!(*i)->marked) {
/* this processor is no longer part of this processor
* box.
*
* that could be because it was deleted or it could be
* because the route being displayed in the parent
* strip changed.
*
* The latter only happens with the editor mixer strip.
*/
if (is_editor_mixer_strip()) {
/* editor mixer strip .. DO NOTHING
*
* note: the processor window stays visible if
* it is already visible
*/
} else {
(*i)->hide ();
WM::Manager::instance().remove (*i);
delete *i;
_processor_window_info.erase (i);
}
}
i = j;
}
setup_entry_positions (); setup_entry_positions ();
} }
@ -1674,24 +1616,14 @@ ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr<Processor> w)
if (!p) { if (!p) {
return; return;
} }
if (p->window_proxy()) {
ProcessorWindowProxies::iterator i = _processor_window_info.begin (); return;
while (i != _processor_window_info.end()) {
boost::shared_ptr<Processor> t = (*i)->processor().lock ();
if (p == t) {
/* this processor is already on the list; done */
(*i)->marked = true;
return;
}
++i;
} }
/* not on the list; add it */ /* not on the list; add it */
string loc; string loc;
#if 0 // is this still needed? Why?
if (_parent_strip) { if (_parent_strip) {
if (_parent_strip->mixer_owned()) { if (_parent_strip->mixer_owned()) {
loc = X_("M"); loc = X_("M");
@ -1701,6 +1633,9 @@ ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr<Processor> w)
} else { } else {
loc = X_("P"); loc = X_("P");
} }
#else
loc = X_("P");
#endif
ProcessorWindowProxy* wp = new ProcessorWindowProxy ( ProcessorWindowProxy* wp = new ProcessorWindowProxy (
string_compose ("%1-%2-%3", loc, _route->id(), p->id()), string_compose ("%1-%2-%3", loc, _route->id(), p->id()),
@ -1713,19 +1648,13 @@ ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr<Processor> w)
wp->set_state (*ui_xml); wp->set_state (*ui_xml);
} }
wp->marked = true;
/* if the processor already has an existing UI,
note that so that we don't recreate it
*/
void* existing_ui = p->get_ui (); void* existing_ui = p->get_ui ();
if (existing_ui) { if (existing_ui) {
wp->use_window (*(reinterpret_cast<Gtk::Window*>(existing_ui))); wp->use_window (*(reinterpret_cast<Gtk::Window*>(existing_ui)));
} }
_processor_window_info.push_back (wp); p->set_window_proxy (wp);
WM::Manager::instance().register_window (wp); WM::Manager::instance().register_window (wp);
} }
@ -2841,16 +2770,10 @@ ProcessorBox::generate_processor_title (boost::shared_ptr<PluginInsert> pi)
Window * Window *
ProcessorBox::get_processor_ui (boost::shared_ptr<Processor> p) const ProcessorBox::get_processor_ui (boost::shared_ptr<Processor> p) const
{ {
list<ProcessorWindowProxy*>::const_iterator i = _processor_window_info.begin (); ProcessorWindowProxy* wp = p->window_proxy();
while (i != _processor_window_info.end()) { if (wp) {
boost::shared_ptr<Processor> t = (*i)->processor().lock (); return wp->get ();
if (t && t == p) {
return (*i)->get ();
}
++i;
} }
return 0; return 0;
} }
@ -2861,24 +2784,9 @@ ProcessorBox::get_processor_ui (boost::shared_ptr<Processor> p) const
void void
ProcessorBox::set_processor_ui (boost::shared_ptr<Processor> p, Gtk::Window* w) ProcessorBox::set_processor_ui (boost::shared_ptr<Processor> p, Gtk::Window* w)
{ {
list<ProcessorWindowProxy*>::iterator i = _processor_window_info.begin (); assert (p->window_proxy());
p->set_ui (w); p->set_ui (w);
p->window_proxy()->use_window (*w);
while (i != _processor_window_info.end()) {
boost::shared_ptr<Processor> t = (*i)->processor().lock ();
if (t && t == p) {
(*i)->use_window (*w);
return;
}
++i;
}
/* we shouldn't get here, because the ProcessorUIList should always contain
an entry for each processor.
*/
assert (false);
} }
void void
@ -2953,12 +2861,10 @@ ProcessorBox::is_editor_mixer_strip() const
ProcessorWindowProxy::ProcessorWindowProxy (string const & name, ProcessorBox* box, boost::weak_ptr<Processor> processor) ProcessorWindowProxy::ProcessorWindowProxy (string const & name, ProcessorBox* box, boost::weak_ptr<Processor> processor)
: WM::ProxyBase (name, string()) : WM::ProxyBase (name, string())
, marked (false)
, _processor_box (box) , _processor_box (box)
, _processor (processor) , _processor (processor)
, is_custom (false) , is_custom (false)
, want_custom (false) , want_custom (false)
, _valid (true)
{ {
boost::shared_ptr<Processor> p = _processor.lock (); boost::shared_ptr<Processor> p = _processor.lock ();
if (!p) { if (!p) {
@ -2981,7 +2887,7 @@ ProcessorWindowProxy::processor_going_away ()
{ {
delete _window; delete _window;
_window = 0; _window = 0;
_valid = false; WM::Manager::instance().remove (this);
/* should be no real reason to do this, since the object that would /* should be no real reason to do this, since the object that would
send DropReferences is about to be deleted, but lets do it anyway. send DropReferences is about to be deleted, but lets do it anyway.
*/ */
@ -2995,12 +2901,6 @@ ProcessorWindowProxy::session_handle()
return 0; return 0;
} }
bool
ProcessorWindowProxy::valid() const
{
return _valid;
}
XMLNode& XMLNode&
ProcessorWindowProxy::get_state () const ProcessorWindowProxy::get_state () const
{ {

View file

@ -91,9 +91,6 @@ class ProcessorWindowProxy : public WM::ProxyBase
void toggle(); void toggle();
void set_custom_ui_mode(bool use_custom) { want_custom = use_custom; } void set_custom_ui_mode(bool use_custom) { want_custom = use_custom; }
bool marked;
bool valid () const;
void set_state (const XMLNode&); void set_state (const XMLNode&);
XMLNode& get_state () const; XMLNode& get_state () const;
@ -442,8 +439,8 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
void route_property_changed (const PBD::PropertyChange&); void route_property_changed (const PBD::PropertyChange&);
std::string generate_processor_title (boost::shared_ptr<ARDOUR::PluginInsert> pi); std::string generate_processor_title (boost::shared_ptr<ARDOUR::PluginInsert> pi);
typedef std::list<ProcessorWindowProxy*> ProcessorWindowProxies; //typedef std::list<ProcessorWindowProxy*> ProcessorWindowProxies;
ProcessorWindowProxies _processor_window_info; //ProcessorWindowProxies _processor_window_info;
ProcessorWindowProxy* find_window_proxy (boost::shared_ptr<ARDOUR::Processor>) const; ProcessorWindowProxy* find_window_proxy (boost::shared_ptr<ARDOUR::Processor>) const;

View file

@ -35,6 +35,7 @@
#include "ardour/automatable.h" #include "ardour/automatable.h"
class XMLNode; class XMLNode;
class ProcessorWindowProxy;
namespace ARDOUR { namespace ARDOUR {
@ -114,6 +115,9 @@ class LIBARDOUR_API Processor : public SessionObject, public Automatable, public
void set_ui (void*); void set_ui (void*);
void* get_ui () const { return _ui_pointer; } void* get_ui () const { return _ui_pointer; }
ProcessorWindowProxy * window_proxy () const { return _window_proxy; }
void set_window_proxy (ProcessorWindowProxy* wp);
void set_owner (SessionObject*); void set_owner (SessionObject*);
SessionObject* owner() const; SessionObject* owner() const;
@ -129,6 +133,7 @@ protected:
bool _display_to_user; bool _display_to_user;
bool _pre_fader; ///< true if this processor is currently placed before the Amp, otherwise false bool _pre_fader; ///< true if this processor is currently placed before the Amp, otherwise false
void* _ui_pointer; void* _ui_pointer;
ProcessorWindowProxy *_window_proxy;
SessionObject* _owner; SessionObject* _owner;
}; };

View file

@ -63,6 +63,7 @@ Processor::Processor(Session& session, const string& name)
, _display_to_user (true) , _display_to_user (true)
, _pre_fader (false) , _pre_fader (false)
, _ui_pointer (0) , _ui_pointer (0)
, _window_proxy (0)
, _owner (0) , _owner (0)
{ {
} }
@ -79,6 +80,8 @@ Processor::Processor (const Processor& other)
, _display_to_user (true) , _display_to_user (true)
, _pre_fader (false) , _pre_fader (false)
, _ui_pointer (0) , _ui_pointer (0)
, _window_proxy (0)
, _owner (0)
{ {
} }
@ -271,6 +274,12 @@ Processor::set_ui (void* p)
_ui_pointer = p; _ui_pointer = p;
} }
void
Processor::set_window_proxy (ProcessorWindowProxy* wp)
{
_window_proxy = wp;
}
void void
Processor::set_owner (SessionObject* o) Processor::set_owner (SessionObject* o)
{ {