X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fpbd%2Fpbd%2Fmemento_command.h;h=45cb100a36e6d967e28771b6f935b565ad1d465e;hb=350ed31655b00f3043e5d723606cdd50099fa91b;hp=a46aea0002cbef84ed563f694f2739086da9c9ae;hpb=66062a85b6388b28ed04f90bab3d302eec0f2a77;p=ardour.git diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h index a46aea0002..45cb100a36 100644 --- a/libs/pbd/pbd/memento_command.h +++ b/libs/pbd/pbd/memento_command.h @@ -34,20 +34,32 @@ /** A class that can return a Stateful object which is the subject of a MementoCommand. * * The existence of this class means that the undo record can refer to objects which - * don't exist in the session file. Currently this is just used for MIDI automation; - * when MIDI automation is edited, undo records are written for the AutomationList being - * changed. However this AutomationList is a temporary structure, built by a MidiModel, - * which doesn't get written to the session file. Hence we need to be able to go from - * a MidiSource and Parameter to an AutomationList. This Binder mechanism allows this - * through MidiAutomationListBinder; the undo record stores the source and parameter, + * don't exist in the session file. Currently this is used for + * + * 1. MIDI automation; when MIDI automation is edited, undo records are + * written for the AutomationList being changed. However this AutomationList + * is a temporary structure, built by a MidiModel, which doesn't get written + * to the session file. Hence we need to be able to go from a MidiSource and + * Parameter to an AutomationList. This Binder mechanism allows this through + * MidiAutomationListBinder; the undo record stores the source and parameter, * and these are bound to an AutomationList by the Binder. + * + * 2. Crossfades; unlike regions, these are completely removed from a session + * when they are deleted. This means that the undo record can contain + * references to non-existant crossfades. To get around this, CrossfadeBinder + * can do `just-in-time' binding from the crossfade ID. */ template class MementoCommandBinder : public PBD::Destructible { public: /** @return Stateful object to operate on */ - virtual obj_T* get () = 0; + virtual obj_T* get () const = 0; + + /** @return Name of our type */ + virtual std::string type_name () const { + return PBD::demangled_name (*get ()); + } /** Add our own state to an XMLNode */ virtual void add_state (XMLNode *) = 0; @@ -64,7 +76,7 @@ public: _object.Destroyed.connect_same_thread (_object_death_connection, boost::bind (&SimpleMementoCommandBinder::object_died, this)); } - obj_T* get () { + obj_T* get () const { return &_object; } @@ -73,6 +85,7 @@ public: } void object_died () { + /* The object we are binding died, so drop references to ourselves */ this->drop_references (); } @@ -92,13 +105,15 @@ public: MementoCommand (obj_T& a_object, XMLNode* a_before, XMLNode* a_after) : _binder (new SimpleMementoCommandBinder (a_object)), before (a_before), after (a_after) { - _binder->Destroyed.connect_same_thread (_binder_death_connection, boost::bind (&MementoCommand::binder_died, this)); + /* The binder's object died, so we must die */ + _binder->DropReferences.connect_same_thread (_binder_death_connection, boost::bind (&MementoCommand::binder_dying, this)); } MementoCommand (MementoCommandBinder* b, XMLNode* a_before, XMLNode* a_after) : _binder (b), before (a_before), after (a_after) { - _binder->Destroyed.connect_same_thread (_binder_death_connection, boost::bind (&MementoCommand::binder_died, this)); + /* The binder's object died, so we must die */ + _binder->DropReferences.connect_same_thread (_binder_death_connection, boost::bind (&MementoCommand::binder_dying, this)); } ~MementoCommand () { @@ -108,7 +123,7 @@ public: delete _binder; } - void binder_died () { + void binder_dying () { delete this; } @@ -137,7 +152,7 @@ public: XMLNode* node = new XMLNode(name); _binder->add_state (node); - node->add_property("type_name", demangled_name (*_binder->get())); + node->add_property ("type_name", _binder->type_name ()); if (before) { node->add_child_copy(*before);