fixes for endemic (compiler?) issues with virtual inheritance of sigc::trackable. NOTE: automation list undo/redo no longer operational, fix to follow

git-svn-id: svn://localhost/ardour2/trunk@1007 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2006-10-25 20:11:42 +00:00
parent 1b39adc4ce
commit bcd511aa3f
42 changed files with 357 additions and 122 deletions

View file

@ -1143,9 +1143,10 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
gain_line->view_to_model_y (y); gain_line->view_to_model_y (y);
#ifdef FIX_ME_TO_NOT_USE_STATE_MANAGER
trackview.session().begin_reversible_command (_("add gain control point")); trackview.session().begin_reversible_command (_("add gain control point"));
trackview.session().add_undo (region.envelope().get_memento()); trackview.session().add_undo (region.envelope().get_memento());
#endif
if (!region.envelope_active()) { if (!region.envelope_active()) {
trackview.session().add_undo( bind( mem_fun(region, &AudioRegion::set_envelope_active), false) ); trackview.session().add_undo( bind( mem_fun(region, &AudioRegion::set_envelope_active), false) );
@ -1155,8 +1156,10 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
region.envelope().add (fx, y); region.envelope().add (fx, y);
#ifdef FIX_ME_TO_NOT_USE_STATE_MANAGER
trackview.session().add_redo_no_execute (region.envelope().get_memento()); trackview.session().add_redo_no_execute (region.envelope().get_memento());
trackview.session().commit_reversible_command (); trackview.session().commit_reversible_command ();
#endif
} }
void void

View file

@ -202,6 +202,7 @@ AudioStreamView::remove_region_view (boost::weak_ptr<Region> weak_r)
} }
} }
StreamView::remove_region_view(r); StreamView::remove_region_view(r);
} }

View file

@ -1169,12 +1169,14 @@ AutomationLine::hide_selection ()
} }
#ifdef STATE_MANAGER
// This is copied into AudioRegionGainLine // This is copied into AudioRegionGainLine
UndoAction UndoAction
AutomationLine::get_memento () AutomationLine::get_memento ()
{ {
return alist.get_memento(); return alist.get_memento();
} }
#endif
void void
AutomationLine::list_changed (Change ignored) AutomationLine::list_changed (Change ignored)

View file

@ -96,7 +96,7 @@ class ControlPoint
ShapeType _shape; ShapeType _shape;
}; };
class AutomationLine : public PBD::StatefulDestructible class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoingAway
{ {
public: public:
AutomationLine (const string & name, TimeAxisView&, ArdourCanvas::Group&, ARDOUR::AutomationList&); AutomationLine (const string & name, TimeAxisView&, ArdourCanvas::Group&, ARDOUR::AutomationList&);
@ -206,7 +206,9 @@ class AutomationLine : public PBD::StatefulDestructible
void reset_callback (const ARDOUR::AutomationList&); void reset_callback (const ARDOUR::AutomationList&);
void list_changed (ARDOUR::Change); void list_changed (ARDOUR::Change);
#ifdef STATE_MANAGER
UndoAction get_memento(); UndoAction get_memento();
#endif
virtual bool event_handler (GdkEvent*); virtual bool event_handler (GdkEvent*);

View file

@ -89,7 +89,7 @@ CrossfadeView::CrossfadeView (ArdourCanvas::Group *parent,
CrossfadeView::~CrossfadeView () CrossfadeView::~CrossfadeView ()
{ {
GoingAway (this) ; /* EMIT_SIGNAL */ GoingAway (this) ; /* EMIT_SIGNAL */
} }
void void

View file

@ -3340,7 +3340,7 @@ Editor::normalize_region ()
continue; continue;
XMLNode &before = arv->region()->get_state(); XMLNode &before = arv->region()->get_state();
arv->audio_region()->normalize_to (0.0f); arv->audio_region()->normalize_to (0.0f);
// session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state())); session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
} }
commit_reversible_command (); commit_reversible_command ();

View file

@ -53,7 +53,7 @@ class ImageFrameView;
class ImageFrameTimeAxis; class ImageFrameTimeAxis;
class MarkerView; class MarkerView;
class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible { class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway {
public: public:
PublicEditor(); PublicEditor();
virtual ~PublicEditor(); virtual ~PublicEditor();
@ -135,6 +135,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible {
sigc::signal<void> ZoomChanged; sigc::signal<void> ZoomChanged;
sigc::signal<void> Resized; sigc::signal<void> Resized;
sigc::signal<void> Realized; sigc::signal<void> Realized;
sigc::signal<void> GoingAway;
Glib::RefPtr<Gtk::ActionGroup> editor_actions; Glib::RefPtr<Gtk::ActionGroup> editor_actions;

View file

@ -89,9 +89,11 @@ AudioRegionGainLine::end_drag (ControlPoint* cp)
} }
#ifdef STATE_MANAGER
// This is a copy from AutomationList // This is a copy from AutomationList
UndoAction UndoAction
AudioRegionGainLine::get_memento () AudioRegionGainLine::get_memento ()
{ {
return alist.get_memento(); return alist.get_memento();
} }
#endif

View file

@ -31,7 +31,9 @@ class AudioRegionGainLine : public AutomationLine
ARDOUR::Session& session; ARDOUR::Session& session;
AudioRegionView& rv; AudioRegionView& rv;
#ifdef STATE_MANAGER
UndoAction get_memento(); UndoAction get_memento();
#endif
}; };

View file

@ -66,7 +66,7 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
set_color (unique_random_color()); set_color (unique_random_color());
} }
new Shiva<Route,RouteUI> (*_route, *this); new PairedShiva<Route,RouteUI> (*_route, *this);
_route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed)); _route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));

View file

@ -54,7 +54,7 @@ struct ControlEvent {
}; };
class AutomationList : public StateManager, public PBD::StatefulDestructible class AutomationList : public PBD::StatefulDestructible
{ {
public: public:
typedef std::list<ControlEvent*> AutomationEventList; typedef std::list<ControlEvent*> AutomationEventList;
@ -151,7 +151,11 @@ struct ControlEvent {
(obj.*method)(*this); (obj.*method)(*this);
} }
sigc::signal<void,Change> StateChanged;
#ifdef STATE_MANAGER
UndoAction get_memento () const; UndoAction get_memento () const;
#endif
virtual void store_state (XMLNode& node) const; virtual void store_state (XMLNode& node) const;
virtual void load_state (const XMLNode&); virtual void load_state (const XMLNode&);
@ -242,8 +246,10 @@ struct ControlEvent {
virtual double unlocked_eval (double where); virtual double unlocked_eval (double where);
#ifdef STATE_MANAGER
Change restore_state (StateManager::State&); Change restore_state (StateManager::State&);
StateManager::State* state_factory (std::string why) const; StateManager::State* state_factory (std::string why) const;
#endif
virtual ControlEvent* point_factory (double,double) const; virtual ControlEvent* point_factory (double,double) const;
virtual ControlEvent* point_factory (const ControlEvent&) const; virtual ControlEvent* point_factory (const ControlEvent&) const;

View file

@ -66,7 +66,9 @@ class Curve : public AutomationList
ControlEvent* point_factory (double,double) const; ControlEvent* point_factory (double,double) const;
ControlEvent* point_factory (const ControlEvent&) const; ControlEvent* point_factory (const ControlEvent&) const;
#ifdef STATE_MANAGER
Change restore_state (StateManager::State&); Change restore_state (StateManager::State&);
#endif
private: private:
AutomationList::iterator last_bound; AutomationList::iterator last_bound;

View file

@ -59,7 +59,7 @@ class Panner;
* An IO can contain ports of varying types, making routes/inserts/etc with * An IO can contain ports of varying types, making routes/inserts/etc with
* varied combinations of types (eg MIDI and audio) possible. * varied combinations of types (eg MIDI and audio) possible.
*/ */
class IO : public PBD::StatefulDestructible, public ARDOUR::StateManager class IO : public PBD::StatefulDestructible
{ {
public: public:
@ -167,8 +167,9 @@ virtual ~IO();
XMLNode& get_state (void); XMLNode& get_state (void);
int set_state (const XMLNode&); int set_state (const XMLNode&);
#ifdef STATE_MANAGER
virtual UndoAction get_memento() const; virtual UndoAction get_memento() const;
#endif
static int disable_connecting (void); static int disable_connecting (void);
@ -300,8 +301,10 @@ public:
/* state management */ /* state management */
#ifdef STATE_MANAGER
Change restore_state (State&); Change restore_state (State&);
StateManager::State* state_factory (std::string why) const; StateManager::State* state_factory (std::string why) const;
#endif
AutoState _gain_automation_state; AutoState _gain_automation_state;
AutoStyle _gain_automation_style; AutoStyle _gain_automation_style;

View file

@ -131,7 +131,7 @@ class Location : public PBD::StatefulDestructible
bool set_flag_internal (bool yn, Flags flag); bool set_flag_internal (bool yn, Flags flag);
}; };
class Locations : public StateManager, public PBD::StatefulDestructible class Locations : public PBD::StatefulDestructible
{ {
public: public:
typedef std::list<Location *> LocationList; typedef std::list<Location *> LocationList;
@ -169,6 +169,7 @@ class Locations : public StateManager, public PBD::StatefulDestructible
sigc::signal<void> changed; sigc::signal<void> changed;
sigc::signal<void,Location*> added; sigc::signal<void,Location*> added;
sigc::signal<void,Location*> removed; sigc::signal<void,Location*> removed;
sigc::signal<void,Change> StateChanged;
template<class T> void apply (T& obj, void (T::*method)(LocationList&)) { template<class T> void apply (T& obj, void (T::*method)(LocationList&)) {
Glib::Mutex::Lock lm (lock); Glib::Mutex::Lock lm (lock);
@ -180,26 +181,30 @@ class Locations : public StateManager, public PBD::StatefulDestructible
(obj.*method)(locations, arg); (obj.*method)(locations, arg);
} }
#ifdef STATE_MANAGER
UndoAction get_memento () const; UndoAction get_memento () const;
#endif
private: private:
#ifdef STATE_MANAGER
struct State : public ARDOUR::StateManager::State { struct State : public ARDOUR::StateManager::State {
LocationList locations; LocationList locations;
LocationList states; LocationList states;
State (std::string why) : ARDOUR::StateManager::State (why) {} State (std::string why) : ARDOUR::StateManager::State (why) {}
}; };
#endif
LocationList locations; LocationList locations;
Location *current_location; Location *current_location;
mutable Glib::Mutex lock; mutable Glib::Mutex lock;
int set_current_unlocked (Location *); int set_current_unlocked (Location *);
void location_changed (Location*); void location_changed (Location*);
#ifdef STATE_MANAGER
Change restore_state (StateManager::State&); Change restore_state (StateManager::State&);
StateManager::State* state_factory (std::string why) const; StateManager::State* state_factory (std::string why) const;
#endif
}; };
} // namespace ARDOUR } // namespace ARDOUR

View file

@ -757,11 +757,11 @@ class Session : public PBD::StatefulDestructible
current_trans->add_command (cmd); current_trans->add_command (cmd);
} }
std::map<PBD::ID, PBD::StatefulDestructible*> registry; std::map<PBD::ID, PBD::StatefulThingWithGoingAway*> registry;
// these commands are implemented in libs/ardour/session_command.cc // these commands are implemented in libs/ardour/session_command.cc
Command *memento_command_factory(XMLNode *n); Command *memento_command_factory(XMLNode *n);
void register_with_memento_command_factory(PBD::ID, PBD::StatefulDestructible *); void register_with_memento_command_factory(PBD::ID, PBD::StatefulThingWithGoingAway *);
class GlobalSoloStateCommand : public Command class GlobalSoloStateCommand : public Command
{ {

View file

@ -162,6 +162,7 @@ class TempoSection : public MetricSection, public Tempo {
typedef list<MetricSection*> Metrics; typedef list<MetricSection*> Metrics;
#ifdef STATE_MANAGER
class TempoMapState : public StateManager::State { class TempoMapState : public StateManager::State {
public: public:
TempoMapState (std::string why) TempoMapState (std::string why)
@ -171,8 +172,9 @@ class TempoMapState : public StateManager::State {
Metrics *metrics; Metrics *metrics;
}; };
#endif
class TempoMap : public StateManager, public PBD::StatefulDestructible class TempoMap : public PBD::StatefulDestructible
{ {
public: public:
@ -246,7 +248,9 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible
void dump (std::ostream&) const; void dump (std::ostream&) const;
void clear (); void clear ();
#ifdef STATE_MANAGER
UndoAction get_memento() const; UndoAction get_memento() const;
#endif
/* this is a helper class that we use to be able to keep /* this is a helper class that we use to be able to keep
track of which meter *AND* tempo are in effect at track of which meter *AND* tempo are in effect at
@ -279,6 +283,8 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible
Metric metric_at (nframes_t) const; Metric metric_at (nframes_t) const;
void bbt_time_with_metric (nframes_t, BBT_Time&, const Metric&) const; void bbt_time_with_metric (nframes_t, BBT_Time&, const Metric&) const;
sigc::signal<void,ARDOUR::Change> StateChanged;
private: private:
static Tempo _default_tempo; static Tempo _default_tempo;
static Meter _default_meter; static Meter _default_meter;
@ -310,6 +316,7 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible
int move_metric_section (MetricSection&, const BBT_Time& to); int move_metric_section (MetricSection&, const BBT_Time& to);
void do_insert (MetricSection* section); void do_insert (MetricSection* section);
#ifdef STATE_MANAGER
Change restore_state (StateManager::State&); Change restore_state (StateManager::State&);
StateManager::State* state_factory (std::string why) const; StateManager::State* state_factory (std::string why) const;
@ -318,7 +325,7 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible
/* override state_manager::save_state so we can check in_set_state */ /* override state_manager::save_state so we can check in_set_state */
void save_state (std::string why); void save_state (std::string why);
#endif
}; };
}; /* namespace ARDOUR */ }; /* namespace ARDOUR */

View file

@ -121,9 +121,6 @@ AudioPlaylist::~AudioPlaylist ()
notify_callbacks (); notify_callbacks ();
cerr << "deleting crossfades " << _crossfades.size() << endl;
for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ) { for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ) {
Crossfades::iterator tmp; Crossfades::iterator tmp;
@ -132,12 +129,8 @@ AudioPlaylist::~AudioPlaylist ()
delete *x; delete *x;
cerr << _crossfades.size() << " to go\n";
x = tmp; x = tmp;
} }
cerr << "done\n";
} }
struct RegionSortByLayer { struct RegionSortByLayer {
@ -372,8 +365,6 @@ AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
return; return;
} }
cerr << "Check dependents of " << r->name() << endl;
if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) { if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
fatal << _("programming error: non-audio Region tested for overlap in audio playlist") fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
<< endmsg; << endmsg;
@ -461,10 +452,7 @@ AudioPlaylist::add_crossfade (Crossfade& xfade)
{ {
Crossfades::iterator ci; Crossfades::iterator ci;
cerr << "adding xfade involving " << xfade.in()->name() << " and " << xfade.out()->name() << endl;
for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) { for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
cerr << "\tcompare to " << (*ci)->in()->name() << " and " << (*ci)->out()->name() << endl;
if (*(*ci) == xfade) { // Crossfade::operator==() if (*(*ci) == xfade) { // Crossfade::operator==()
break; break;
} }

View file

@ -794,8 +794,9 @@ AudioTrack::freeze (InterThreadInfo& itt)
FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state(), insert); FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state(), insert);
frii->id = insert->id(); frii->id = insert->id();
#ifdef STATE_MANAGER
frii->memento = (*r)->get_memento(); frii->memento = (*r)->get_memento();
#endif
_freeze_record.insert_info.push_back (frii); _freeze_record.insert_info.push_back (frii);
/* now deactivate the insert */ /* now deactivate the insert */

View file

@ -306,7 +306,6 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
AudioRegion::~AudioRegion () AudioRegion::~AudioRegion ()
{ {
cerr << "====== " << _name << " DESTRUCTOR @ " << this << endl;
notify_callbacks (); notify_callbacks ();
GoingAway (); /* EMIT SIGNAL */ GoingAway (); /* EMIT SIGNAL */
} }

View file

@ -64,7 +64,9 @@ AutomationList::AutomationList (double defval, bool with_state)
lookup_cache.range.first = events.end(); lookup_cache.range.first = events.end();
if (!no_state) { if (!no_state) {
#ifdef STATE_MANAGER
save_state (_("initial")); save_state (_("initial"));
#endif
} }
AutomationListCreated(this); AutomationListCreated(this);
@ -133,15 +135,16 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl
AutomationList::~AutomationList() AutomationList::~AutomationList()
{ {
std::set<ControlEvent*> all_events;
AutomationList::State* asp;
GoingAway (); GoingAway ();
for (AutomationEventList::iterator x = events.begin(); x != events.end(); ++x) { for (AutomationEventList::iterator x = events.begin(); x != events.end(); ++x) {
all_events.insert (*x); delete (*x);
} }
#ifdef STATE_MANAGER
std::set<ControlEvent*> all_events;
AutomationList::State* asp;
for (StateMap::iterator i = states.begin(); i != states.end(); ++i) { for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
if ((asp = dynamic_cast<AutomationList::State*> (*i)) != 0) { if ((asp = dynamic_cast<AutomationList::State*> (*i)) != 0) {
@ -155,6 +158,7 @@ AutomationList::~AutomationList()
for (std::set<ControlEvent*>::iterator i = all_events.begin(); i != all_events.end(); ++i) { for (std::set<ControlEvent*>::iterator i = all_events.begin(); i != all_events.end(); ++i) {
delete (*i); delete (*i);
} }
#endif
} }
bool bool
@ -237,7 +241,9 @@ AutomationList::clear ()
Glib::Mutex::Lock lm (lock); Glib::Mutex::Lock lm (lock);
events.clear (); events.clear ();
if (!no_state) { if (!no_state) {
#ifdef STATE_MANAGER
save_state (_("cleared")); save_state (_("cleared"));
#endif
} }
mark_dirty (); mark_dirty ();
} }
@ -270,7 +276,9 @@ void AutomationList::_x_scale (double factor)
(*i)->when = floor ((*i)->when * factor); (*i)->when = floor ((*i)->when * factor);
} }
#ifdef STATE_MANAGER
save_state ("x-scaled"); save_state ("x-scaled");
#endif
mark_dirty (); mark_dirty ();
} }
@ -409,7 +417,9 @@ AutomationList::add (double when, double value, bool for_loading)
mark_dirty (); mark_dirty ();
if (!no_state && !for_loading) { if (!no_state && !for_loading) {
#ifdef STATE_MANAGER
save_state (_("added event")); save_state (_("added event"));
#endif
} }
} }
@ -426,7 +436,9 @@ AutomationList::erase (AutomationList::iterator i)
events.erase (i); events.erase (i);
reposition_for_rt_add (0); reposition_for_rt_add (0);
if (!no_state) { if (!no_state) {
#ifdef STATE_MANAGER
save_state (_("removed event")); save_state (_("removed event"));
#endif
} }
mark_dirty (); mark_dirty ();
} }
@ -441,7 +453,9 @@ AutomationList::erase (AutomationList::iterator start, AutomationList::iterator
events.erase (start, end); events.erase (start, end);
reposition_for_rt_add (0); reposition_for_rt_add (0);
if (!no_state) { if (!no_state) {
#ifdef STATE_MANAGER
save_state (_("removed multiple events")); save_state (_("removed multiple events"));
#endif
} }
mark_dirty (); mark_dirty ();
} }
@ -472,7 +486,9 @@ AutomationList::reset_range (double start, double endt)
reset = true; reset = true;
if (!no_state) { if (!no_state) {
#ifdef STATE_MANAGER
save_state (_("removed range")); save_state (_("removed range"));
#endif
} }
mark_dirty (); mark_dirty ();
@ -503,7 +519,9 @@ AutomationList::erase_range (double start, double endt)
reposition_for_rt_add (0); reposition_for_rt_add (0);
erased = true; erased = true;
if (!no_state) { if (!no_state) {
#ifdef STATE_MANAGER
save_state (_("removed range")); save_state (_("removed range"));
#endif
} }
mark_dirty (); mark_dirty ();
} }
@ -533,7 +551,9 @@ AutomationList::move_range (iterator start, iterator end, double xdelta, double
} }
if (!no_state) { if (!no_state) {
#ifdef STATE_MANAGER
save_state (_("event range adjusted")); save_state (_("event range adjusted"));
#endif
} }
mark_dirty (); mark_dirty ();
@ -555,7 +575,9 @@ AutomationList::modify (iterator iter, double when, double val)
(*iter)->when = when; (*iter)->when = when;
(*iter)->value = val; (*iter)->value = val;
if (!no_state) { if (!no_state) {
#ifdef STATE_MANAGER
save_state (_("event adjusted")); save_state (_("event adjusted"));
#endif
} }
mark_dirty (); mark_dirty ();
@ -613,6 +635,7 @@ AutomationList::thaw ()
} }
} }
#ifdef STATE_MANAGER
StateManager::State* StateManager::State*
AutomationList::state_factory (std::string why) const AutomationList::state_factory (std::string why) const
{ {
@ -646,6 +669,7 @@ AutomationList::get_memento () const
{ {
return sigc::bind (mem_fun (*(const_cast<AutomationList*> (this)), &StateManager::use_state), _current_state_id); return sigc::bind (mem_fun (*(const_cast<AutomationList*> (this)), &StateManager::use_state), _current_state_id);
} }
#endif
void void
AutomationList::set_max_xval (double x) AutomationList::set_max_xval (double x)
@ -1084,7 +1108,9 @@ AutomationList::cut_copy_clear (double start, double end, int op)
if (changed) { if (changed) {
reposition_for_rt_add (0); reposition_for_rt_add (0);
if (!no_state) { if (!no_state) {
#ifdef STATE_MANAGER
save_state (_("cut/copy/clear")); save_state (_("cut/copy/clear"));
#endif
} }
} }
@ -1117,7 +1143,9 @@ AutomationList::copy (iterator start, iterator end)
} }
if (!no_state) { if (!no_state) {
#ifdef STATE_MANAGER
save_state (_("copy")); save_state (_("copy"));
#endif
} }
} }
@ -1185,7 +1213,9 @@ AutomationList::paste (AutomationList& alist, double pos, float times)
reposition_for_rt_add (0); reposition_for_rt_add (0);
if (!no_state) { if (!no_state) {
#ifdef STATE_MANAGER
save_state (_("paste")); save_state (_("paste"));
#endif
} }
mark_dirty (); mark_dirty ();
@ -1235,6 +1265,8 @@ AutomationList::load_state (const XMLNode& node)
nframes_t x; nframes_t x;
double y; double y;
freeze ();
clear (); clear ();
for (i = elist.begin(); i != elist.end(); ++i) { for (i = elist.begin(); i != elist.end(); ++i) {
@ -1253,6 +1285,8 @@ AutomationList::load_state (const XMLNode& node)
add (x, y); add (x, y);
} }
thaw ();
} }
XMLNode &AutomationList::get_state () XMLNode &AutomationList::get_state ()

View file

@ -160,6 +160,8 @@ Crossfade::Crossfade (const Playlist& playlist, XMLNode& node)
} }
_length = 0; _length = 0;
_active = Config->get_xfades_active();
initialize(); initialize();
if (set_state (node)) { if (set_state (node)) {
@ -197,9 +199,7 @@ Crossfade::Crossfade (const Crossfade &orig, boost::shared_ptr<AudioRegion> newi
Crossfade::~Crossfade () Crossfade::~Crossfade ()
{ {
cerr << "Deleting xfade @ " << this << endl;
Invalidated (this); Invalidated (this);
cerr << "invalidation signal sent\n";
} }
void void

View file

@ -435,13 +435,14 @@ Curve::point_factory (const ControlEvent& other) const
return new CurvePoint (other.when, other.value); return new CurvePoint (other.when, other.value);
} }
#ifdef STATE_MANAGER
Change Change
Curve::restore_state (StateManager::State& state) Curve::restore_state (StateManager::State& state)
{ {
mark_dirty (); mark_dirty ();
return AutomationList::restore_state (state); return AutomationList::restore_state (state);
} }
#endif
extern "C" { extern "C" {

View file

@ -81,7 +81,9 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placemen
init (); init ();
#ifdef STATE_MANAGER
save_state (_("initial state")); save_state (_("initial state"));
#endif
{ {
Glib::Mutex::Lock em (_session.engine().process_lock()); Glib::Mutex::Lock em (_session.engine().process_lock());
@ -100,7 +102,9 @@ PluginInsert::PluginInsert (Session& s, const XMLNode& node)
set_automatable (); set_automatable ();
#ifdef STATE_MANAGER
save_state (_("initial state")); save_state (_("initial state"));
#endif
_plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed)); _plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed));
@ -125,7 +129,9 @@ PluginInsert::PluginInsert (const PluginInsert& other)
init (); init ();
#ifdef STATE_MANAGER
save_state (_("initial state")); save_state (_("initial state"));
#endif
RedirectCreated (this); /* EMIT SIGNAL */ RedirectCreated (this); /* EMIT SIGNAL */
} }
@ -841,16 +847,22 @@ PortInsert::PortInsert (Session& s, Placement p)
: Insert (s, p, 1, -1, 1, -1) : Insert (s, p, 1, -1, 1, -1)
{ {
init (); init ();
#ifdef STATE_MANAGER
save_state (_("initial state")); save_state (_("initial state"));
RedirectCreated (this); /* EMIT SIGNAL */ RedirectCreated (this); /* EMIT SIGNAL */
#endif
} }
PortInsert::PortInsert (const PortInsert& other) PortInsert::PortInsert (const PortInsert& other)
: Insert (other._session, other.placement(), 1, -1, 1, -1) : Insert (other._session, other.placement(), 1, -1, 1, -1)
{ {
init (); init ();
#ifdef STATE_MANAGER
save_state (_("initial state")); save_state (_("initial state"));
RedirectCreated (this); /* EMIT SIGNAL */ RedirectCreated (this); /* EMIT SIGNAL */
#endif
} }
void void

View file

@ -2313,6 +2313,7 @@ IO::setup_peak_meters ()
} }
} }
#ifdef STATE_MANAGER
UndoAction UndoAction
IO::get_memento() const IO::get_memento() const
{ {
@ -2331,6 +2332,7 @@ IO::state_factory (std::string why) const
StateManager::State* state = new StateManager::State (why); StateManager::State* state = new StateManager::State (why);
return state; return state;
} }
#endif
/** /**
Update the peak meters. Update the peak meters.
@ -2488,7 +2490,9 @@ IO::load_automation (const string& path)
} }
} }
#ifdef STATE_MANAGER
_gain_automation_curve.save_state (_("loaded from disk")); _gain_automation_curve.save_state (_("loaded from disk"));
#endif
return 0; return 0;
} }
@ -2615,9 +2619,11 @@ IO::transport_stopped (nframes_t frame)
if (_gain_automation_curve.automation_state() != Off) { if (_gain_automation_curve.automation_state() != Off) {
#ifdef STATE_MANAGER
if (gain_automation_recording()) { if (gain_automation_recording()) {
_gain_automation_curve.save_state (_("automation write/touch")); _gain_automation_curve.save_state (_("automation write/touch"));
} }
#endif
/* the src=0 condition is a special signal to not propagate /* the src=0 condition is a special signal to not propagate
automation gain changes into the mix group when locating. automation gain changes into the mix group when locating.

View file

@ -372,13 +372,25 @@ Locations::Locations ()
{ {
current_location = 0; current_location = 0;
#ifdef STATE_MANAGER
save_state (_("initial")); save_state (_("initial"));
#endif
} }
Locations::~Locations () Locations::~Locations ()
{ {
for (LocationList::iterator i = locations.begin(); i != locations.end(); ) {
LocationList::iterator tmp = i;
++tmp;
delete *i;
i = tmp;
}
#ifdef STATE_MANAGER
std::set<Location*> all_locations; std::set<Location*> all_locations;
for (StateMap::iterator siter = states.begin(); siter != states.end(); ++siter) { for (StateMap::iterator siter = states.begin(); siter != states.end(); ++siter) {
State* lstate = dynamic_cast<State*> (*siter); State* lstate = dynamic_cast<State*> (*siter);
@ -393,6 +405,7 @@ Locations::~Locations ()
} }
set_delete (&all_locations); set_delete (&all_locations);
#endif
} }
int int
@ -445,7 +458,9 @@ Locations::clear ()
current_location = 0; current_location = 0;
} }
#ifdef STATE_MANAGER
save_state (_("clear")); save_state (_("clear"));
#endif
changed (); /* EMIT SIGNAL */ changed (); /* EMIT SIGNAL */
current_changed (0); /* EMIT SIGNAL */ current_changed (0); /* EMIT SIGNAL */
@ -470,7 +485,9 @@ Locations::clear_markers ()
} }
} }
#ifdef STATE_MANAGER
save_state (_("clear markers")); save_state (_("clear markers"));
#endif
changed (); /* EMIT SIGNAL */ changed (); /* EMIT SIGNAL */
} }
@ -498,7 +515,9 @@ Locations::clear_ranges ()
current_location = 0; current_location = 0;
} }
#ifdef STATE_MANAGER
save_state (_("clear ranges")); save_state (_("clear ranges"));
#endif
changed (); /* EMIT SIGNAL */ changed (); /* EMIT SIGNAL */
current_changed (0); /* EMIT SIGNAL */ current_changed (0); /* EMIT SIGNAL */
@ -516,7 +535,9 @@ Locations::add (Location *loc, bool make_current)
} }
} }
#ifdef STATE_MANAGER
save_state (_("add")); save_state (_("add"));
#endif
added (loc); /* EMIT SIGNAL */ added (loc); /* EMIT SIGNAL */
@ -554,7 +575,9 @@ Locations::remove (Location *loc)
} }
if (was_removed) { if (was_removed) {
#ifdef STATE_MANAGER
save_state (_("remove")); save_state (_("remove"));
#endif
removed (loc); /* EMIT SIGNAL */ removed (loc); /* EMIT SIGNAL */
@ -569,7 +592,9 @@ Locations::remove (Location *loc)
void void
Locations::location_changed (Location* loc) Locations::location_changed (Location* loc)
{ {
#ifdef STATE_MANAGER
save_state (X_("location changed")); save_state (X_("location changed"));
#endif
changed (); /* EMIT SIGNAL */ changed (); /* EMIT SIGNAL */
} }
@ -809,6 +834,7 @@ Locations::auto_punch_location () const
return 0; return 0;
} }
#ifdef STATE_MANAGER
StateManager::State* StateManager::State*
Locations::state_factory (std::string why) const Locations::state_factory (std::string why) const
{ {
@ -847,6 +873,7 @@ Locations::get_memento () const
{ {
return sigc::bind (mem_fun (*(const_cast<Locations*> (this)), &StateManager::use_state), _current_state_id); return sigc::bind (mem_fun (*(const_cast<Locations*> (this)), &StateManager::use_state), _current_state_id);
} }
#endif
uint32_t uint32_t
Locations::num_range_markers () const Locations::num_range_markers () const

View file

@ -208,7 +208,9 @@ BaseStereoPanner::transport_stopped (nframes_t frame)
if (_automation.automation_state() != Off) { if (_automation.automation_state() != Off) {
if (_automation.automation_write()) { if (_automation.automation_write()) {
#ifdef STATE_MANAGER
_automation.save_state (_("automation write pass")); _automation.save_state (_("automation write pass"));
#endif
} }
set_position (_automation.eval (frame)); set_position (_automation.eval (frame));
@ -285,7 +287,9 @@ BaseStereoPanner::load (istream& in, string path, uint32_t& linecnt)
/* now that we are done loading */ /* now that we are done loading */
#ifdef STATE_MANAGER
_automation.save_state (_("loaded from disk")); _automation.save_state (_("loaded from disk"));
#endif
_automation.StateChanged (Change (0)); _automation.StateChanged (Change (0));
return 0; return 0;

View file

@ -144,9 +144,11 @@ Redirect::load_automation (string path)
tosave.insert (port); tosave.insert (port);
} }
#ifdef STATE_MANAGER
for (set<uint32_t>::iterator i = tosave.begin(); i != tosave.end(); ++i) { for (set<uint32_t>::iterator i = tosave.begin(); i != tosave.end(); ++i) {
automation_list (*i).save_state (_("loaded from disk")); automation_list (*i).save_state (_("loaded from disk"));
} }
#endif
return 0; return 0;
@ -464,7 +466,9 @@ void
Redirect::set_active (bool yn, void* src) Redirect::set_active (bool yn, void* src)
{ {
_active = yn; _active = yn;
#ifdef STATE_MANAGER
save_state (_("active_changed")); save_state (_("active_changed"));
#endif
active_changed (this, src); active_changed (this, src);
_session.set_dirty (); _session.set_dirty ();
} }

View file

@ -36,7 +36,9 @@ Send::Send (Session& s, Placement p)
{ {
_metering = false; _metering = false;
expected_inputs = 0; expected_inputs = 0;
#ifdef STATE_MANAGER
save_state (_("initial state")); save_state (_("initial state"));
#endif
RedirectCreated (this); /* EMIT SIGNAL */ RedirectCreated (this); /* EMIT SIGNAL */
} }
@ -50,7 +52,10 @@ Send::Send (Session& s, const XMLNode& node)
throw failed_constructor(); throw failed_constructor();
} }
#ifdef STATE_MANAGER
save_state (_("initial state")); save_state (_("initial state"));
#endif
RedirectCreated (this); /* EMIT SIGNAL */ RedirectCreated (this); /* EMIT SIGNAL */
} }
@ -59,7 +64,10 @@ Send::Send (const Send& other)
{ {
_metering = false; _metering = false;
expected_inputs = 0; expected_inputs = 0;
#ifdef STATE_MANAGER
save_state (_("initial state")); save_state (_("initial state"));
#endif
RedirectCreated (this); /* EMIT SIGNAL */ RedirectCreated (this); /* EMIT SIGNAL */
} }

View file

@ -431,6 +431,10 @@ Session::~Session ()
AudioDiskstream::free_working_buffers(); AudioDiskstream::free_working_buffers();
/* this should cause deletion of the auditioner */
// auditioner.reset ();
#undef TRACK_DESTRUCTION #undef TRACK_DESTRUCTION
#ifdef TRACK_DESTRUCTION #ifdef TRACK_DESTRUCTION
cerr << "delete named selections\n"; cerr << "delete named selections\n";
@ -469,9 +473,7 @@ Session::~Session ()
tmp = i; tmp = i;
++tmp; ++tmp;
cerr << "dropping refs on an audio region (" << i->second->name() << " @ " << i->second << ") with UC = " << i->second.use_count() << endl;
i->second->drop_references (); i->second->drop_references ();
cerr << "AFTER: UC = " << i->second.use_count() << endl;
i = tmp; i = tmp;
} }
@ -1553,6 +1555,12 @@ Session::resort_routes_using (shared_ptr<RouteList> r)
RouteSorter cmp; RouteSorter cmp;
r->sort (cmp); r->sort (cmp);
/* don't leave dangling references to routes in Route::fed_by */
for (i = r->begin(); i != r->end(); ++i) {
(*i)->fed_by.clear ();
}
#if 0 #if 0
cerr << "finished route resort\n"; cerr << "finished route resort\n";

View file

@ -64,30 +64,31 @@ Session::click (nframes_t start, nframes_t nframes, nframes_t offset)
goto run_clicks; goto run_clicks;
} }
if (points->empty()) { if (!points->empty()) {
delete points;
goto run_clicks;
}
for (TempoMap::BBTPointList::iterator i = points->begin(); i != points->end(); ++i) { for (TempoMap::BBTPointList::iterator i = points->begin(); i != points->end(); ++i) {
switch ((*i).type) { switch ((*i).type) {
case TempoMap::Beat: case TempoMap::Beat:
if (click_emphasis_data == 0 || (click_emphasis_data && (*i).beat != 1)) { if (click_emphasis_data == 0 || (click_emphasis_data && (*i).beat != 1)) {
clicks.push_back (new Click ((*i).frame, click_length, click_data)); clicks.push_back (new Click ((*i).frame, click_length, click_data));
} }
break; break;
case TempoMap::Bar: case TempoMap::Bar:
if (click_emphasis_data) { if (click_emphasis_data) {
clicks.push_back (new Click ((*i).frame, click_emphasis_length, click_emphasis_data)); clicks.push_back (new Click ((*i).frame, click_emphasis_length, click_emphasis_data));
}
break;
} }
break;
} }
} }
delete points; delete points;
delete points;
run_clicks: run_clicks:
memset (buf, 0, sizeof (Sample) * nframes); memset (buf, 0, sizeof (Sample) * nframes);
for (list<Click*>::iterator i = clicks.begin(); i != clicks.end(); ) { for (list<Click*>::iterator i = clicks.begin(); i != clicks.end(); ) {

View file

@ -7,13 +7,15 @@
#include <ardour/audiosource.h> #include <ardour/audiosource.h>
#include <ardour/audioregion.h> #include <ardour/audioregion.h>
#include <pbd/error.h> #include <pbd/error.h>
using namespace PBD; #include <pbd/statefuldestructible.h>
#include "i18n.h"
using namespace PBD;
#include "i18n.h"
namespace ARDOUR { namespace ARDOUR {
void Session::register_with_memento_command_factory(PBD::ID id, StatefulDestructible *ptr) void Session::register_with_memento_command_factory(PBD::ID id, PBD::StatefulThingWithGoingAway *ptr)
{ {
registry[id] = ptr; registry[id] = ptr;
} }
@ -78,7 +80,7 @@ Command *Session::memento_command_factory(XMLNode *n)
if (automation_lists.count(id)) if (automation_lists.count(id))
return new MementoCommand<AutomationList>(*automation_lists[id], before, after); return new MementoCommand<AutomationList>(*automation_lists[id], before, after);
} else if (registry.count(id)) { // For Editor and AutomationLine which are off-limits here } else if (registry.count(id)) { // For Editor and AutomationLine which are off-limits here
return new MementoCommand<StatefulDestructible>(*registry[id], before, after); return new MementoCommand<PBD::StatefulThingWithGoingAway>(*registry[id], before, after);
} }
/* we failed */ /* we failed */

View file

@ -243,7 +243,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve)); Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve));
AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list)); AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable)); Controllable::Destroyed.connect (mem_fun (*this, &Session::remove_controllable));
IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers)); IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
@ -1147,7 +1147,9 @@ Session::set_state (const XMLNode& node)
start_location = location; start_location = location;
} }
#ifdef STATE_MANAGER
_locations.save_state (_("initial state")); _locations.save_state (_("initial state"));
#endif
if ((child = find_named_node (node, "EditGroups")) == 0) { if ((child = find_named_node (node, "EditGroups")) == 0) {
error << _("Session: XML state has no edit groups section") << endmsg; error << _("Session: XML state has no edit groups section") << endmsg;

View file

@ -206,7 +206,9 @@ TempoMap::TempoMap (nframes_t fr)
_frame_rate = fr; _frame_rate = fr;
last_bbt_valid = false; last_bbt_valid = false;
BBT_Time start; BBT_Time start;
#ifdef STATE_MANAGER
in_set_state = false; in_set_state = false;
#endif
start.bars = 1; start.bars = 1;
start.beats = 1; start.beats = 1;
@ -223,7 +225,9 @@ TempoMap::TempoMap (nframes_t fr)
metrics->push_back (t); metrics->push_back (t);
metrics->push_back (m); metrics->push_back (m);
#ifdef STATE_MANAGER
save_state (_("initial")); save_state (_("initial"));
#endif
} }
TempoMap::~TempoMap () TempoMap::~TempoMap ()
@ -256,7 +260,9 @@ TempoMap::move_metric_section (MetricSection& section, const BBT_Time& when)
section.set_start (corrected); section.set_start (corrected);
metrics->sort (cmp); metrics->sort (cmp);
timestamp_metrics (); timestamp_metrics ();
#ifdef STATE_MANAGER
save_state (_("move metric")); save_state (_("move metric"));
#endif
return 0; return 0;
} }
@ -265,7 +271,7 @@ void
TempoMap::move_tempo (TempoSection& tempo, const BBT_Time& when) TempoMap::move_tempo (TempoSection& tempo, const BBT_Time& when)
{ {
if (move_metric_section (tempo, when) == 0) { if (move_metric_section (tempo, when) == 0) {
send_state_changed (Change (0)); StateChanged (Change (0));
} }
} }
@ -273,7 +279,7 @@ void
TempoMap::move_meter (MeterSection& meter, const BBT_Time& when) TempoMap::move_meter (MeterSection& meter, const BBT_Time& when)
{ {
if (move_metric_section (meter, when) == 0) { if (move_metric_section (meter, when) == 0) {
send_state_changed (Change (0)); StateChanged (Change (0));
} }
} }
@ -301,7 +307,7 @@ TempoMap::remove_tempo (const TempoSection& tempo)
} }
if (removed) { if (removed) {
send_state_changed (Change (0)); StateChanged (Change (0));
} }
} }
@ -327,12 +333,14 @@ TempoMap::remove_meter (const MeterSection& tempo)
} }
if (removed) { if (removed) {
#ifdef STATE_MANAGER
save_state (_("metric removed")); save_state (_("metric removed"));
#endif
} }
} }
if (removed) { if (removed) {
send_state_changed (Change (0)); StateChanged (Change (0));
} }
} }
@ -370,10 +378,12 @@ TempoMap::add_tempo (const Tempo& tempo, BBT_Time where)
do_insert (new TempoSection (where, tempo.beats_per_minute())); do_insert (new TempoSection (where, tempo.beats_per_minute()));
#ifdef STATE_MANAGER
save_state (_("add tempo")); save_state (_("add tempo"));
#endif
} }
send_state_changed (Change (0)); StateChanged (Change (0));
} }
void void
@ -399,12 +409,14 @@ TempoMap::replace_tempo (TempoSection& existing, const Tempo& replacement)
} }
if (replaced) { if (replaced) {
#ifdef STATE_MANAGER
save_state (_("replace tempo")); save_state (_("replace tempo"));
#endif
} }
} }
if (replaced) { if (replaced) {
send_state_changed (Change (0)); StateChanged (Change (0));
} }
} }
@ -432,10 +444,12 @@ TempoMap::add_meter (const Meter& meter, BBT_Time where)
do_insert (new MeterSection (where, meter.beats_per_bar(), meter.note_divisor())); do_insert (new MeterSection (where, meter.beats_per_bar(), meter.note_divisor()));
#ifdef STATE_MANAGER
save_state (_("add meter")); save_state (_("add meter"));
#endif
} }
send_state_changed (Change (0)); StateChanged (Change (0));
} }
void void
@ -460,12 +474,14 @@ TempoMap::replace_meter (MeterSection& existing, const Meter& replacement)
} }
if (replaced) { if (replaced) {
#ifdef STATE_MANAGER
save_state (_("replaced meter")); save_state (_("replaced meter"));
#endif
} }
} }
if (replaced) { if (replaced) {
send_state_changed (Change (0)); StateChanged (Change (0));
} }
} }
@ -1266,7 +1282,9 @@ TempoMap::set_state (const XMLNode& node)
XMLNodeConstIterator niter; XMLNodeConstIterator niter;
Metrics old_metrics (*metrics); Metrics old_metrics (*metrics);
#ifdef STATE_MANAGER
in_set_state = true; in_set_state = true;
#endif
metrics->clear(); metrics->clear();
@ -1308,7 +1326,9 @@ TempoMap::set_state (const XMLNode& node)
timestamp_metrics (); timestamp_metrics ();
} }
#ifdef STATE_MANAGER
in_set_state = false; in_set_state = false;
#endif
} }
/* This state needs to be saved. This string will never be a part of the /* This state needs to be saved. This string will never be a part of the
@ -1318,9 +1338,12 @@ TempoMap::set_state (const XMLNode& node)
If this state is not saved, there is no way to reach it through undo actions. If this state is not saved, there is no way to reach it through undo actions.
*/ */
save_state(_("load XML data"));
send_state_changed (Change (0)); #ifdef STATE_MANAGER
save_state(_("load XML data"));
#endif
StateChanged (Change (0));
return 0; return 0;
} }
@ -1343,6 +1366,7 @@ TempoMap::dump (std::ostream& o) const
} }
} }
#ifdef STATE_MANAGER
UndoAction UndoAction
TempoMap::get_memento () const TempoMap::get_memento () const
{ {
@ -1405,3 +1429,4 @@ TempoMap::save_state (std::string why)
StateManager::save_state (why); StateManager::save_state (why);
} }
} }
#endif

View file

@ -6,7 +6,7 @@
using namespace PBD; using namespace PBD;
sigc::signal<void,Controllable*> Controllable::GoingAway; sigc::signal<void,Controllable*> Controllable::Destroyed;
sigc::signal<bool,Controllable*> Controllable::StartLearning; sigc::signal<bool,Controllable*> Controllable::StartLearning;
sigc::signal<void,Controllable*> Controllable::StopLearning; sigc::signal<void,Controllable*> Controllable::StopLearning;

View file

@ -21,10 +21,9 @@
#ifndef __lib_pbd_command_h__ #ifndef __lib_pbd_command_h__
#define __lib_pbd_command_h__ #define __lib_pbd_command_h__
#include <pbd/stateful.h> #include <pbd/statefuldestructible.h>
#include <pbd/destructible.h>
class Command : public Stateful, public PBD::Destructible class Command : public PBD::StatefulDestructible
{ {
public: public:
virtual ~Command() {} virtual ~Command() {}

View file

@ -6,17 +6,16 @@
#include <sigc++/trackable.h> #include <sigc++/trackable.h>
#include <sigc++/signal.h> #include <sigc++/signal.h>
#include <pbd/stateful.h> #include <pbd/statefuldestructible.h>
#include <pbd/id.h>
class XMLNode; class XMLNode;
namespace PBD { namespace PBD {
class Controllable : public virtual sigc::trackable, public Stateful { class Controllable : public PBD::StatefulDestructible {
public: public:
Controllable (std::string name); Controllable (std::string name);
virtual ~Controllable() { GoingAway (this); } virtual ~Controllable() { Destroyed (this); }
virtual void set_value (float) = 0; virtual void set_value (float) = 0;
virtual float get_value (void) const = 0; virtual float get_value (void) const = 0;
@ -25,11 +24,11 @@ class Controllable : public virtual sigc::trackable, public Stateful {
sigc::signal<void> LearningFinished; sigc::signal<void> LearningFinished;
static sigc::signal<void,Controllable*> GoingAway;
static sigc::signal<bool,PBD::Controllable*> StartLearning; static sigc::signal<bool,PBD::Controllable*> StartLearning;
static sigc::signal<void,PBD::Controllable*> StopLearning; static sigc::signal<void,PBD::Controllable*> StopLearning;
static sigc::signal<void,Controllable*> Destroyed;
sigc::signal<void> Changed; sigc::signal<void> Changed;
int set_state (const XMLNode&); int set_state (const XMLNode&);

View file

@ -5,14 +5,22 @@
namespace PBD { namespace PBD {
class Destructible : public virtual sigc::trackable { /* be very very careful using this class. it does not inherit from sigc::trackable and thus
should only be used in multiple-inheritance situations involving another type
that does inherit from sigc::trackable (or sigc::trackable itself)
*/
class ThingWithGoingAway {
public: public:
Destructible() {} virtual ~ThingWithGoingAway () {}
virtual ~Destructible () {}
sigc::signal<void> GoingAway; sigc::signal<void> GoingAway;
};
class Destructible : public sigc::trackable, public ThingWithGoingAway {
public:
virtual ~Destructible () {}
void drop_references () const { GoingAway(); } void drop_references () const { GoingAway(); }
}; };
} }

View file

@ -28,19 +28,11 @@ using std::endl;
#include <pbd/command.h> #include <pbd/command.h>
#include <pbd/stacktrace.h> #include <pbd/stacktrace.h>
#include <pbd/xml++.h> #include <pbd/xml++.h>
#include <pbd/shiva.h>
#include <sigc++/slot.h> #include <sigc++/slot.h>
#include <typeinfo> #include <typeinfo>
/* grrr, strict C++ says that static member functions are not C functions, but we also want
to be able to pack this into a sigc::ptr_fun and not sigc::mem_fun, so we have to make
it a genuine function rather than a member.
*/
static void object_death (Command* mc) {
cerr << "\n\n\n---> OBJECT DEATH FIRED FOR " << mc << endl;
delete mc;
}
/** This command class is initialized with before and after mementos /** This command class is initialized with before and after mementos
* (from Stateful::get_state()), so undo becomes restoring the before * (from Stateful::get_state()), so undo becomes restoring the before
* memento, and redo is restoring the after memento. * memento, and redo is restoring the after memento.
@ -55,8 +47,8 @@ class MementoCommand : public Command
XMLNode *after XMLNode *after
) )
: obj(object), before(before), after(after) { : obj(object), before(before), after(after) {
cerr << "MC @ " << this << " is a " << typeid (obj_T).name() << endl; /* catch destruction of the object */
obj.GoingAway.connect (sigc::bind (sigc::ptr_fun (object_death), static_cast<Command*>(this))); new PBD::Shiva<obj_T,MementoCommand<obj_T> > (object, *this);
} }
~MementoCommand () { ~MementoCommand () {

View file

@ -5,28 +5,96 @@
namespace PBD { namespace PBD {
template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
/* named after the Hindu god Shiva, The Destroyer */ /* named after the Hindu god Shiva, The Destroyer */
template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
class Shiva { class Shiva {
public: public:
Shiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) { Shiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) {
/* if the emitter goes away, destroy the receiver */ /* if the emitter goes away, destroy the receiver */
_connection1 = emitter.GoingAway.connect _connection = emitter.GoingAway.connect
(sigc::bind (sigc::mem_fun (sigc::bind (sigc::mem_fun
(*this, &Shiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy), (*this, &Shiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
&receiver)); &receiver));
}
~Shiva() {
forget ();
}
private:
sigc::connection _connection;
void destroy (ObjectToBeDestroyed* obj) {
delete obj;
forget ();
}
void forget () {
_connection.disconnect ();
}
};
template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
class ProxyShiva {
public:
ProxyShiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver, void (*callback)(ObjectToBeDestroyed*, ObjectWithGoingAway*)) {
/* if the emitter goes away, destroy the receiver */
_callback = callback;
_callback_argument1 = &receiver;
_callback_argument2 = &emitter;
_connection = emitter.GoingAway.connect
(sigc::bind (sigc::mem_fun
(*this, &ProxyShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
&receiver));
}
~ProxyShiva() {
forget ();
}
private:
sigc::connection _connection;
void (*_callback) (ObjectToBeDestroyed*, ObjectWithGoingAway*);
ObjectToBeDestroyed* _callback_argument1;
ObjectWithGoingAway* _callback_argument2;
void destroy (ObjectToBeDestroyed* obj) {
/* callback must destroy obj if appropriate, not done here */
_callback (obj, _callback_argument2);
forget ();
}
void forget () {
_connection.disconnect ();
}
};
template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
class PairedShiva {
public:
PairedShiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) {
/* if the emitter goes away, destroy the receiver */
_connection1 = emitter.GoingAway.connect
(sigc::bind (sigc::mem_fun
(*this, &PairedShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
&receiver));
/* if the receiver goes away, forget all this nonsense */ /* if the receiver goes away, forget all this nonsense */
_connection2 = receiver.GoingAway.connect _connection2 = receiver.GoingAway.connect
(sigc::mem_fun (*this, &Shiva<ObjectWithGoingAway,ObjectToBeDestroyed>::forget)); (sigc::mem_fun (*this, &PairedShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::forget));
} }
~Shiva() { ~PairedShiva() {
forget (); forget ();
} }

View file

@ -5,9 +5,21 @@
#include <pbd/destructible.h> #include <pbd/destructible.h>
namespace PBD { namespace PBD {
class StatefulDestructible : public Stateful, public Destructible class StatefulDestructible : public Stateful, public Destructible
{ {
}; };
/* be very very careful using this class. it does not inherit from sigc::trackable and thus
should only be used in multiple-inheritance situations involving another type
that does inherit from sigc::trackable (or sigc::trackable itself)
*/
class StatefulThingWithGoingAway : public Stateful, public ThingWithGoingAway
{
};
} }
#endif /* __pbd_stateful_destructible_h__ */ #endif /* __pbd_stateful_destructible_h__ */

View file

@ -70,6 +70,8 @@ class UndoTransaction : public Command
struct timeval _timestamp; struct timeval _timestamp;
std::string _name; std::string _name;
bool _clearing; bool _clearing;
friend void command_death (UndoTransaction*, Command *);
}; };
class UndoHistory class UndoHistory

View file

@ -24,31 +24,13 @@
#include <pbd/undo.h> #include <pbd/undo.h>
#include <pbd/xml++.h> #include <pbd/xml++.h>
#include <pbd/shiva.h>
#include <sigc++/bind.h> #include <sigc++/bind.h>
using namespace std; using namespace std;
using namespace sigc; using namespace sigc;
/* grrr, strict C++ says that static member functions are not C functions, but we also want
to be able to pack this into a sigc::ptr_fun and not sigc::mem_fun, so we have to make
it a genuine function rather than a member.
*/
static void command_death (UndoTransaction* ut, Command* c)
{
if (ut->clearing()) {
return;
}
ut->remove_command (c);
if (ut->empty()) {
delete ut;
}
}
UndoTransaction::UndoTransaction () UndoTransaction::UndoTransaction ()
{ {
_clearing = false; _clearing = false;
@ -68,6 +50,20 @@ UndoTransaction::~UndoTransaction ()
clear (); clear ();
} }
void
command_death (UndoTransaction* ut, Command* c)
{
if (ut->clearing()) {
return;
}
ut->remove_command (c);
if (ut->empty()) {
delete ut;
}
}
UndoTransaction& UndoTransaction&
UndoTransaction::operator= (const UndoTransaction& rhs) UndoTransaction::operator= (const UndoTransaction& rhs)
{ {
@ -81,7 +77,8 @@ UndoTransaction::operator= (const UndoTransaction& rhs)
void void
UndoTransaction::add_command (Command *const action) UndoTransaction::add_command (Command *const action)
{ {
action->GoingAway.connect (bind (sigc::ptr_fun (command_death), this, const_cast<Command*>(action))); /* catch death */
new PBD::ProxyShiva<Command,UndoTransaction> (*action, *this, &command_death);
actions.push_back (action); actions.push_back (action);
} }