diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2006-10-25 20:11:42 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2006-10-25 20:11:42 +0000 |
commit | bcd511aa3fec59e1527c8b7ab80dabda4db1a6f9 (patch) | |
tree | 0e704409baaaa22a43b918adc126c76990208f5f | |
parent | 1b39adc4ce8566fd731cf433094b1faf4fe63205 (diff) |
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
42 files changed, 357 insertions, 122 deletions
diff --git a/gtk2_ardour/audio_regionview.cc b/gtk2_ardour/audio_regionview.cc index fdbb961ab6..b50ea72be2 100644 --- a/gtk2_ardour/audio_regionview.cc +++ b/gtk2_ardour/audio_regionview.cc @@ -1143,9 +1143,10 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev) 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().add_undo (region.envelope().get_memento()); - +#endif if (!region.envelope_active()) { 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); +#ifdef FIX_ME_TO_NOT_USE_STATE_MANAGER trackview.session().add_redo_no_execute (region.envelope().get_memento()); trackview.session().commit_reversible_command (); +#endif } void diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc index 24924fec4f..75eb28e7d5 100644 --- a/gtk2_ardour/audio_streamview.cc +++ b/gtk2_ardour/audio_streamview.cc @@ -202,6 +202,7 @@ AudioStreamView::remove_region_view (boost::weak_ptr<Region> weak_r) } } + StreamView::remove_region_view(r); } diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index ee74fabfa4..371552fbfc 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -1169,12 +1169,14 @@ AutomationLine::hide_selection () } +#ifdef STATE_MANAGER // This is copied into AudioRegionGainLine UndoAction AutomationLine::get_memento () { return alist.get_memento(); } +#endif void AutomationLine::list_changed (Change ignored) diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h index eb2d204513..0e44c95a33 100644 --- a/gtk2_ardour/automation_line.h +++ b/gtk2_ardour/automation_line.h @@ -96,7 +96,7 @@ class ControlPoint ShapeType _shape; }; -class AutomationLine : public PBD::StatefulDestructible +class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoingAway { public: 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 list_changed (ARDOUR::Change); +#ifdef STATE_MANAGER UndoAction get_memento(); +#endif virtual bool event_handler (GdkEvent*); diff --git a/gtk2_ardour/crossfade_view.cc b/gtk2_ardour/crossfade_view.cc index 42a1a47227..e8a97c4cf4 100644 --- a/gtk2_ardour/crossfade_view.cc +++ b/gtk2_ardour/crossfade_view.cc @@ -89,7 +89,7 @@ CrossfadeView::CrossfadeView (ArdourCanvas::Group *parent, CrossfadeView::~CrossfadeView () { - GoingAway (this) ; /* EMIT_SIGNAL */ + GoingAway (this) ; /* EMIT_SIGNAL */ } void diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index c7a10df5a0..280804c94f 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -3340,7 +3340,7 @@ Editor::normalize_region () continue; XMLNode &before = arv->region()->get_state(); 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 (); diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 189e2100bb..0c68eb6221 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -53,7 +53,7 @@ class ImageFrameView; class ImageFrameTimeAxis; class MarkerView; -class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible { +class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway { public: PublicEditor(); virtual ~PublicEditor(); @@ -135,6 +135,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible { sigc::signal<void> ZoomChanged; sigc::signal<void> Resized; sigc::signal<void> Realized; + sigc::signal<void> GoingAway; Glib::RefPtr<Gtk::ActionGroup> editor_actions; diff --git a/gtk2_ardour/region_gain_line.cc b/gtk2_ardour/region_gain_line.cc index 467f24bd94..58a8a9acad 100644 --- a/gtk2_ardour/region_gain_line.cc +++ b/gtk2_ardour/region_gain_line.cc @@ -89,9 +89,11 @@ AudioRegionGainLine::end_drag (ControlPoint* cp) } +#ifdef STATE_MANAGER // This is a copy from AutomationList UndoAction AudioRegionGainLine::get_memento () { return alist.get_memento(); } +#endif diff --git a/gtk2_ardour/region_gain_line.h b/gtk2_ardour/region_gain_line.h index 3781fe60bb..916bf78a78 100644 --- a/gtk2_ardour/region_gain_line.h +++ b/gtk2_ardour/region_gain_line.h @@ -31,7 +31,9 @@ class AudioRegionGainLine : public AutomationLine ARDOUR::Session& session; AudioRegionView& rv; +#ifdef STATE_MANAGER UndoAction get_memento(); +#endif }; diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index 482f5df22f..bb24dcc426 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -66,7 +66,7 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co 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)); diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h index 22ab706f82..e2940bc2e1 100644 --- a/libs/ardour/ardour/automation_event.h +++ b/libs/ardour/ardour/automation_event.h @@ -54,7 +54,7 @@ struct ControlEvent { }; - class AutomationList : public StateManager, public PBD::StatefulDestructible +class AutomationList : public PBD::StatefulDestructible { public: typedef std::list<ControlEvent*> AutomationEventList; @@ -151,7 +151,11 @@ struct ControlEvent { (obj.*method)(*this); } + sigc::signal<void,Change> StateChanged; + +#ifdef STATE_MANAGER UndoAction get_memento () const; +#endif virtual void store_state (XMLNode& node) const; virtual void load_state (const XMLNode&); @@ -242,8 +246,10 @@ struct ControlEvent { virtual double unlocked_eval (double where); +#ifdef STATE_MANAGER Change restore_state (StateManager::State&); StateManager::State* state_factory (std::string why) const; +#endif virtual ControlEvent* point_factory (double,double) const; virtual ControlEvent* point_factory (const ControlEvent&) const; diff --git a/libs/ardour/ardour/curve.h b/libs/ardour/ardour/curve.h index 7ba6b5fa6c..9de7d0ef48 100644 --- a/libs/ardour/ardour/curve.h +++ b/libs/ardour/ardour/curve.h @@ -66,7 +66,9 @@ class Curve : public AutomationList ControlEvent* point_factory (double,double) const; ControlEvent* point_factory (const ControlEvent&) const; +#ifdef STATE_MANAGER Change restore_state (StateManager::State&); +#endif private: AutomationList::iterator last_bound; diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 96ae75f298..cbac629593 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -59,7 +59,7 @@ class Panner; * An IO can contain ports of varying types, making routes/inserts/etc with * varied combinations of types (eg MIDI and audio) possible. */ -class IO : public PBD::StatefulDestructible, public ARDOUR::StateManager +class IO : public PBD::StatefulDestructible { public: @@ -167,8 +167,9 @@ virtual ~IO(); XMLNode& get_state (void); int set_state (const XMLNode&); +#ifdef STATE_MANAGER virtual UndoAction get_memento() const; - +#endif static int disable_connecting (void); @@ -300,8 +301,10 @@ public: /* state management */ +#ifdef STATE_MANAGER Change restore_state (State&); StateManager::State* state_factory (std::string why) const; +#endif AutoState _gain_automation_state; AutoStyle _gain_automation_style; diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h index 1f1c02d67c..e618f46dfe 100644 --- a/libs/ardour/ardour/location.h +++ b/libs/ardour/ardour/location.h @@ -131,7 +131,7 @@ class Location : public PBD::StatefulDestructible bool set_flag_internal (bool yn, Flags flag); }; -class Locations : public StateManager, public PBD::StatefulDestructible +class Locations : public PBD::StatefulDestructible { public: typedef std::list<Location *> LocationList; @@ -169,6 +169,7 @@ class Locations : public StateManager, public PBD::StatefulDestructible sigc::signal<void> changed; sigc::signal<void,Location*> added; sigc::signal<void,Location*> removed; + sigc::signal<void,Change> StateChanged; template<class T> void apply (T& obj, void (T::*method)(LocationList&)) { Glib::Mutex::Lock lm (lock); @@ -180,26 +181,30 @@ class Locations : public StateManager, public PBD::StatefulDestructible (obj.*method)(locations, arg); } +#ifdef STATE_MANAGER UndoAction get_memento () const; +#endif private: +#ifdef STATE_MANAGER struct State : public ARDOUR::StateManager::State { LocationList locations; LocationList states; State (std::string why) : ARDOUR::StateManager::State (why) {} }; - +#endif LocationList locations; Location *current_location; mutable Glib::Mutex lock; int set_current_unlocked (Location *); void location_changed (Location*); - +#ifdef STATE_MANAGER Change restore_state (StateManager::State&); StateManager::State* state_factory (std::string why) const; +#endif }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 0cbc168329..da5a098aa0 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -757,11 +757,11 @@ class Session : public PBD::StatefulDestructible 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 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 { diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index 7cdbe56cf2..eaadcb1c99 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -162,6 +162,7 @@ class TempoSection : public MetricSection, public Tempo { typedef list<MetricSection*> Metrics; +#ifdef STATE_MANAGER class TempoMapState : public StateManager::State { public: TempoMapState (std::string why) @@ -171,8 +172,9 @@ class TempoMapState : public StateManager::State { Metrics *metrics; }; +#endif -class TempoMap : public StateManager, public PBD::StatefulDestructible +class TempoMap : public PBD::StatefulDestructible { public: @@ -246,7 +248,9 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible void dump (std::ostream&) const; void clear (); +#ifdef STATE_MANAGER UndoAction get_memento() const; +#endif /* this is a helper class that we use to be able to keep 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; void bbt_time_with_metric (nframes_t, BBT_Time&, const Metric&) const; + sigc::signal<void,ARDOUR::Change> StateChanged; + private: static Tempo _default_tempo; static Meter _default_meter; @@ -310,6 +316,7 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible int move_metric_section (MetricSection&, const BBT_Time& to); void do_insert (MetricSection* section); +#ifdef STATE_MANAGER Change restore_state (StateManager::State&); 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 */ void save_state (std::string why); - +#endif }; }; /* namespace ARDOUR */ diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index cce6e188f8..19609da2a4 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -120,9 +120,6 @@ AudioPlaylist::~AudioPlaylist () /* drop connections to signals */ notify_callbacks (); - - - cerr << "deleting crossfades " << _crossfades.size() << endl; for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ) { Crossfades::iterator tmp; @@ -132,12 +129,8 @@ AudioPlaylist::~AudioPlaylist () delete *x; - cerr << _crossfades.size() << " to go\n"; - x = tmp; } - - cerr << "done\n"; } struct RegionSortByLayer { @@ -372,8 +365,6 @@ AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh) return; } - cerr << "Check dependents of " << r->name() << endl; - if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) { fatal << _("programming error: non-audio Region tested for overlap in audio playlist") << endmsg; @@ -461,10 +452,7 @@ AudioPlaylist::add_crossfade (Crossfade& xfade) { Crossfades::iterator ci; - cerr << "adding xfade involving " << xfade.in()->name() << " and " << xfade.out()->name() << endl; - for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) { - cerr << "\tcompare to " << (*ci)->in()->name() << " and " << (*ci)->out()->name() << endl; if (*(*ci) == xfade) { // Crossfade::operator==() break; } diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 677c9a0497..d61ec7b003 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -794,8 +794,9 @@ AudioTrack::freeze (InterThreadInfo& itt) FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state(), insert); frii->id = insert->id(); +#ifdef STATE_MANAGER frii->memento = (*r)->get_memento(); - +#endif _freeze_record.insert_info.push_back (frii); /* now deactivate the insert */ diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 2f2c67ec50..d2cf279d3e 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -306,7 +306,6 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node) AudioRegion::~AudioRegion () { - cerr << "====== " << _name << " DESTRUCTOR @ " << this << endl; notify_callbacks (); GoingAway (); /* EMIT SIGNAL */ } diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc index f286b11607..6b7f0ff016 100644 --- a/libs/ardour/automation_event.cc +++ b/libs/ardour/automation_event.cc @@ -64,7 +64,9 @@ AutomationList::AutomationList (double defval, bool with_state) lookup_cache.range.first = events.end(); if (!no_state) { +#ifdef STATE_MANAGER save_state (_("initial")); +#endif } AutomationListCreated(this); @@ -133,15 +135,16 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl AutomationList::~AutomationList() { - std::set<ControlEvent*> all_events; - AutomationList::State* asp; - GoingAway (); 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) { 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) { delete (*i); } +#endif } bool @@ -237,7 +241,9 @@ AutomationList::clear () Glib::Mutex::Lock lm (lock); events.clear (); if (!no_state) { +#ifdef STATE_MANAGER save_state (_("cleared")); +#endif } mark_dirty (); } @@ -270,7 +276,9 @@ void AutomationList::_x_scale (double factor) (*i)->when = floor ((*i)->when * factor); } +#ifdef STATE_MANAGER save_state ("x-scaled"); +#endif mark_dirty (); } @@ -409,7 +417,9 @@ AutomationList::add (double when, double value, bool for_loading) mark_dirty (); if (!no_state && !for_loading) { +#ifdef STATE_MANAGER save_state (_("added event")); +#endif } } @@ -426,7 +436,9 @@ AutomationList::erase (AutomationList::iterator i) events.erase (i); reposition_for_rt_add (0); if (!no_state) { +#ifdef STATE_MANAGER save_state (_("removed event")); +#endif } mark_dirty (); } @@ -441,7 +453,9 @@ AutomationList::erase (AutomationList::iterator start, AutomationList::iterator events.erase (start, end); reposition_for_rt_add (0); if (!no_state) { +#ifdef STATE_MANAGER save_state (_("removed multiple events")); +#endif } mark_dirty (); } @@ -472,7 +486,9 @@ AutomationList::reset_range (double start, double endt) reset = true; if (!no_state) { +#ifdef STATE_MANAGER save_state (_("removed range")); +#endif } mark_dirty (); @@ -503,7 +519,9 @@ AutomationList::erase_range (double start, double endt) reposition_for_rt_add (0); erased = true; if (!no_state) { +#ifdef STATE_MANAGER save_state (_("removed range")); +#endif } mark_dirty (); } @@ -533,7 +551,9 @@ AutomationList::move_range (iterator start, iterator end, double xdelta, double } if (!no_state) { +#ifdef STATE_MANAGER save_state (_("event range adjusted")); +#endif } mark_dirty (); @@ -555,7 +575,9 @@ AutomationList::modify (iterator iter, double when, double val) (*iter)->when = when; (*iter)->value = val; if (!no_state) { +#ifdef STATE_MANAGER save_state (_("event adjusted")); +#endif } mark_dirty (); @@ -613,6 +635,7 @@ AutomationList::thaw () } } +#ifdef STATE_MANAGER StateManager::State* 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); } +#endif void AutomationList::set_max_xval (double x) @@ -1084,7 +1108,9 @@ AutomationList::cut_copy_clear (double start, double end, int op) if (changed) { reposition_for_rt_add (0); if (!no_state) { +#ifdef STATE_MANAGER save_state (_("cut/copy/clear")); +#endif } } @@ -1117,7 +1143,9 @@ AutomationList::copy (iterator start, iterator end) } if (!no_state) { +#ifdef STATE_MANAGER save_state (_("copy")); +#endif } } @@ -1185,7 +1213,9 @@ AutomationList::paste (AutomationList& alist, double pos, float times) reposition_for_rt_add (0); if (!no_state) { +#ifdef STATE_MANAGER save_state (_("paste")); +#endif } mark_dirty (); @@ -1235,6 +1265,8 @@ AutomationList::load_state (const XMLNode& node) nframes_t x; double y; + freeze (); + clear (); for (i = elist.begin(); i != elist.end(); ++i) { @@ -1253,6 +1285,8 @@ AutomationList::load_state (const XMLNode& node) add (x, y); } + + thaw (); } XMLNode &AutomationList::get_state () diff --git a/libs/ardour/crossfade.cc b/libs/ardour/crossfade.cc index 739ea1cc0e..46a8e6e400 100644 --- a/libs/ardour/crossfade.cc +++ b/libs/ardour/crossfade.cc @@ -160,6 +160,8 @@ Crossfade::Crossfade (const Playlist& playlist, XMLNode& node) } _length = 0; + _active = Config->get_xfades_active(); + initialize(); if (set_state (node)) { @@ -197,9 +199,7 @@ Crossfade::Crossfade (const Crossfade &orig, boost::shared_ptr<AudioRegion> newi Crossfade::~Crossfade () { - cerr << "Deleting xfade @ " << this << endl; Invalidated (this); - cerr << "invalidation signal sent\n"; } void diff --git a/libs/ardour/curve.cc b/libs/ardour/curve.cc index 20f7053f2e..5f7d692471 100644 --- a/libs/ardour/curve.cc +++ b/libs/ardour/curve.cc @@ -435,13 +435,14 @@ Curve::point_factory (const ControlEvent& other) const return new CurvePoint (other.when, other.value); } +#ifdef STATE_MANAGER Change Curve::restore_state (StateManager::State& state) { mark_dirty (); return AutomationList::restore_state (state); } - +#endif extern "C" { diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc index d64cce36f9..5531e4136b 100644 --- a/libs/ardour/insert.cc +++ b/libs/ardour/insert.cc @@ -81,7 +81,9 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placemen init (); +#ifdef STATE_MANAGER save_state (_("initial state")); +#endif { Glib::Mutex::Lock em (_session.engine().process_lock()); @@ -100,7 +102,9 @@ PluginInsert::PluginInsert (Session& s, const XMLNode& node) set_automatable (); +#ifdef STATE_MANAGER save_state (_("initial state")); +#endif _plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed)); @@ -125,7 +129,9 @@ PluginInsert::PluginInsert (const PluginInsert& other) init (); +#ifdef STATE_MANAGER save_state (_("initial state")); +#endif RedirectCreated (this); /* EMIT SIGNAL */ } @@ -841,16 +847,22 @@ PortInsert::PortInsert (Session& s, Placement p) : Insert (s, p, 1, -1, 1, -1) { init (); +#ifdef STATE_MANAGER save_state (_("initial state")); RedirectCreated (this); /* EMIT SIGNAL */ +#endif + } PortInsert::PortInsert (const PortInsert& other) : Insert (other._session, other.placement(), 1, -1, 1, -1) { init (); +#ifdef STATE_MANAGER save_state (_("initial state")); RedirectCreated (this); /* EMIT SIGNAL */ +#endif + } void diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index bcd3ee7940..a9751268ff 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -2313,6 +2313,7 @@ IO::setup_peak_meters () } } +#ifdef STATE_MANAGER UndoAction IO::get_memento() const { @@ -2331,6 +2332,7 @@ IO::state_factory (std::string why) const StateManager::State* state = new StateManager::State (why); return state; } +#endif /** 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")); +#endif return 0; } @@ -2615,9 +2619,11 @@ IO::transport_stopped (nframes_t frame) if (_gain_automation_curve.automation_state() != Off) { +#ifdef STATE_MANAGER if (gain_automation_recording()) { _gain_automation_curve.save_state (_("automation write/touch")); } +#endif /* the src=0 condition is a special signal to not propagate automation gain changes into the mix group when locating. diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc index 39331cfda6..f9bcd76a0b 100644 --- a/libs/ardour/location.cc +++ b/libs/ardour/location.cc @@ -372,13 +372,25 @@ Locations::Locations () { current_location = 0; +#ifdef STATE_MANAGER save_state (_("initial")); +#endif } 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; + for (StateMap::iterator siter = states.begin(); siter != states.end(); ++siter) { State* lstate = dynamic_cast<State*> (*siter); @@ -393,6 +405,7 @@ Locations::~Locations () } set_delete (&all_locations); +#endif } int @@ -445,7 +458,9 @@ Locations::clear () current_location = 0; } +#ifdef STATE_MANAGER save_state (_("clear")); +#endif changed (); /* EMIT SIGNAL */ current_changed (0); /* EMIT SIGNAL */ @@ -470,7 +485,9 @@ Locations::clear_markers () } } +#ifdef STATE_MANAGER save_state (_("clear markers")); +#endif changed (); /* EMIT SIGNAL */ } @@ -498,7 +515,9 @@ Locations::clear_ranges () current_location = 0; } +#ifdef STATE_MANAGER save_state (_("clear ranges")); +#endif changed (); /* EMIT SIGNAL */ current_changed (0); /* EMIT SIGNAL */ @@ -516,7 +535,9 @@ Locations::add (Location *loc, bool make_current) } } +#ifdef STATE_MANAGER save_state (_("add")); +#endif added (loc); /* EMIT SIGNAL */ @@ -554,7 +575,9 @@ Locations::remove (Location *loc) } if (was_removed) { +#ifdef STATE_MANAGER save_state (_("remove")); +#endif removed (loc); /* EMIT SIGNAL */ @@ -569,7 +592,9 @@ Locations::remove (Location *loc) void Locations::location_changed (Location* loc) { +#ifdef STATE_MANAGER save_state (X_("location changed")); +#endif changed (); /* EMIT SIGNAL */ } @@ -809,6 +834,7 @@ Locations::auto_punch_location () const return 0; } +#ifdef STATE_MANAGER StateManager::State* 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); } +#endif uint32_t Locations::num_range_markers () const diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc index 22053ce56b..229c4c5e1c 100644 --- a/libs/ardour/panner.cc +++ b/libs/ardour/panner.cc @@ -208,7 +208,9 @@ BaseStereoPanner::transport_stopped (nframes_t frame) if (_automation.automation_state() != Off) { if (_automation.automation_write()) { +#ifdef STATE_MANAGER _automation.save_state (_("automation write pass")); +#endif } set_position (_automation.eval (frame)); @@ -285,7 +287,9 @@ BaseStereoPanner::load (istream& in, string path, uint32_t& linecnt) /* now that we are done loading */ +#ifdef STATE_MANAGER _automation.save_state (_("loaded from disk")); +#endif _automation.StateChanged (Change (0)); return 0; diff --git a/libs/ardour/redirect.cc b/libs/ardour/redirect.cc index 9323966f96..18b16eaa73 100644 --- a/libs/ardour/redirect.cc +++ b/libs/ardour/redirect.cc @@ -144,9 +144,11 @@ Redirect::load_automation (string path) tosave.insert (port); } +#ifdef STATE_MANAGER for (set<uint32_t>::iterator i = tosave.begin(); i != tosave.end(); ++i) { automation_list (*i).save_state (_("loaded from disk")); } +#endif return 0; @@ -464,7 +466,9 @@ void Redirect::set_active (bool yn, void* src) { _active = yn; +#ifdef STATE_MANAGER save_state (_("active_changed")); +#endif active_changed (this, src); _session.set_dirty (); } diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc index b37168807e..1479eab420 100644 --- a/libs/ardour/send.cc +++ b/libs/ardour/send.cc @@ -36,7 +36,9 @@ Send::Send (Session& s, Placement p) { _metering = false; expected_inputs = 0; +#ifdef STATE_MANAGER save_state (_("initial state")); +#endif RedirectCreated (this); /* EMIT SIGNAL */ } @@ -50,7 +52,10 @@ Send::Send (Session& s, const XMLNode& node) throw failed_constructor(); } +#ifdef STATE_MANAGER save_state (_("initial state")); +#endif + RedirectCreated (this); /* EMIT SIGNAL */ } @@ -59,7 +64,10 @@ Send::Send (const Send& other) { _metering = false; expected_inputs = 0; +#ifdef STATE_MANAGER save_state (_("initial state")); +#endif + RedirectCreated (this); /* EMIT SIGNAL */ } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 66cb1f89fa..fddd289882 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -430,6 +430,10 @@ Session::~Session () } AudioDiskstream::free_working_buffers(); + + /* this should cause deletion of the auditioner */ + + // auditioner.reset (); #undef TRACK_DESTRUCTION #ifdef TRACK_DESTRUCTION @@ -469,9 +473,7 @@ Session::~Session () tmp = i; ++tmp; - cerr << "dropping refs on an audio region (" << i->second->name() << " @ " << i->second << ") with UC = " << i->second.use_count() << endl; i->second->drop_references (); - cerr << "AFTER: UC = " << i->second.use_count() << endl; i = tmp; } @@ -1548,11 +1550,17 @@ Session::resort_routes_using (shared_ptr<RouteList> r) for (i = r->begin(); i != r->end(); ++i) { trace_terminal (*i, *i); - } - + } + RouteSorter 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 cerr << "finished route resort\n"; diff --git a/libs/ardour/session_click.cc b/libs/ardour/session_click.cc index 7f9b142679..ba7f7ae811 100644 --- a/libs/ardour/session_click.cc +++ b/libs/ardour/session_click.cc @@ -64,30 +64,31 @@ Session::click (nframes_t start, nframes_t nframes, nframes_t offset) goto run_clicks; } - if (points->empty()) { - delete points; - goto run_clicks; - } - - for (TempoMap::BBTPointList::iterator i = points->begin(); i != points->end(); ++i) { - switch ((*i).type) { - case TempoMap::Beat: - if (click_emphasis_data == 0 || (click_emphasis_data && (*i).beat != 1)) { - clicks.push_back (new Click ((*i).frame, click_length, click_data)); + if (!points->empty()) { + + for (TempoMap::BBTPointList::iterator i = points->begin(); i != points->end(); ++i) { + switch ((*i).type) { + case TempoMap::Beat: + if (click_emphasis_data == 0 || (click_emphasis_data && (*i).beat != 1)) { + clicks.push_back (new Click ((*i).frame, click_length, click_data)); + } + break; + + case TempoMap::Bar: + if (click_emphasis_data) { + clicks.push_back (new Click ((*i).frame, click_emphasis_length, click_emphasis_data)); + } + break; } - break; - - case TempoMap::Bar: - if (click_emphasis_data) { - clicks.push_back (new Click ((*i).frame, click_emphasis_length, click_emphasis_data)); - } - break; } } + + delete points; delete points; run_clicks: + memset (buf, 0, sizeof (Sample) * nframes); for (list<Click*>::iterator i = clicks.begin(); i != clicks.end(); ) { diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc index c5c31b7c17..1492136b88 100644 --- a/libs/ardour/session_command.cc +++ b/libs/ardour/session_command.cc @@ -7,13 +7,15 @@ #include <ardour/audiosource.h> #include <ardour/audioregion.h> #include <pbd/error.h> +#include <pbd/statefuldestructible.h> + using namespace PBD; -#include "i18n.h" +#include "i18n.h" 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; } @@ -78,7 +80,7 @@ Command *Session::memento_command_factory(XMLNode *n) if (automation_lists.count(id)) return new MementoCommand<AutomationList>(*automation_lists[id], before, after); } 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 */ diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index c3e0fe9388..d742186d6b 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -243,7 +243,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve)); 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)); @@ -1147,7 +1147,9 @@ Session::set_state (const XMLNode& node) start_location = location; } +#ifdef STATE_MANAGER _locations.save_state (_("initial state")); +#endif if ((child = find_named_node (node, "EditGroups")) == 0) { error << _("Session: XML state has no edit groups section") << endmsg; diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 913218c91c..e9d46f83e3 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -206,7 +206,9 @@ TempoMap::TempoMap (nframes_t fr) _frame_rate = fr; last_bbt_valid = false; BBT_Time start; +#ifdef STATE_MANAGER in_set_state = false; +#endif start.bars = 1; start.beats = 1; @@ -223,7 +225,9 @@ TempoMap::TempoMap (nframes_t fr) metrics->push_back (t); metrics->push_back (m); +#ifdef STATE_MANAGER save_state (_("initial")); +#endif } TempoMap::~TempoMap () @@ -256,7 +260,9 @@ TempoMap::move_metric_section (MetricSection& section, const BBT_Time& when) section.set_start (corrected); metrics->sort (cmp); timestamp_metrics (); +#ifdef STATE_MANAGER save_state (_("move metric")); +#endif return 0; } @@ -265,7 +271,7 @@ void TempoMap::move_tempo (TempoSection& tempo, const BBT_Time& when) { 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) { 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) { - send_state_changed (Change (0)); + StateChanged (Change (0)); } } @@ -327,12 +333,14 @@ TempoMap::remove_meter (const MeterSection& tempo) } if (removed) { +#ifdef STATE_MANAGER save_state (_("metric removed")); +#endif } } 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())); +#ifdef STATE_MANAGER save_state (_("add tempo")); +#endif } - send_state_changed (Change (0)); + StateChanged (Change (0)); } void @@ -399,12 +409,14 @@ TempoMap::replace_tempo (TempoSection& existing, const Tempo& replacement) } if (replaced) { +#ifdef STATE_MANAGER save_state (_("replace tempo")); +#endif } } 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())); +#ifdef STATE_MANAGER save_state (_("add meter")); +#endif } - send_state_changed (Change (0)); + StateChanged (Change (0)); } void @@ -460,12 +474,14 @@ TempoMap::replace_meter (MeterSection& existing, const Meter& replacement) } if (replaced) { +#ifdef STATE_MANAGER save_state (_("replaced meter")); +#endif } } if (replaced) { - send_state_changed (Change (0)); + StateChanged (Change (0)); } } @@ -1266,7 +1282,9 @@ TempoMap::set_state (const XMLNode& node) XMLNodeConstIterator niter; Metrics old_metrics (*metrics); +#ifdef STATE_MANAGER in_set_state = true; +#endif metrics->clear(); @@ -1308,7 +1326,9 @@ TempoMap::set_state (const XMLNode& node) timestamp_metrics (); } +#ifdef STATE_MANAGER in_set_state = false; +#endif } /* 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. */ + +#ifdef STATE_MANAGER save_state(_("load XML data")); +#endif - send_state_changed (Change (0)); + StateChanged (Change (0)); return 0; } @@ -1343,6 +1366,7 @@ TempoMap::dump (std::ostream& o) const } } +#ifdef STATE_MANAGER UndoAction TempoMap::get_memento () const { @@ -1405,3 +1429,4 @@ TempoMap::save_state (std::string why) StateManager::save_state (why); } } +#endif diff --git a/libs/pbd/controllable.cc b/libs/pbd/controllable.cc index 80c6811e6a..2264a955ae 100644 --- a/libs/pbd/controllable.cc +++ b/libs/pbd/controllable.cc @@ -6,7 +6,7 @@ using namespace PBD; -sigc::signal<void,Controllable*> Controllable::GoingAway; +sigc::signal<void,Controllable*> Controllable::Destroyed; sigc::signal<bool,Controllable*> Controllable::StartLearning; sigc::signal<void,Controllable*> Controllable::StopLearning; diff --git a/libs/pbd/pbd/command.h b/libs/pbd/pbd/command.h index 7c367e7462..8044b51a83 100644 --- a/libs/pbd/pbd/command.h +++ b/libs/pbd/pbd/command.h @@ -21,10 +21,9 @@ #ifndef __lib_pbd_command_h__ #define __lib_pbd_command_h__ -#include <pbd/stateful.h> -#include <pbd/destructible.h> +#include <pbd/statefuldestructible.h> -class Command : public Stateful, public PBD::Destructible +class Command : public PBD::StatefulDestructible { public: virtual ~Command() {} diff --git a/libs/pbd/pbd/controllable.h b/libs/pbd/pbd/controllable.h index ff8f8a9b52..c88eb298bc 100644 --- a/libs/pbd/pbd/controllable.h +++ b/libs/pbd/pbd/controllable.h @@ -6,17 +6,16 @@ #include <sigc++/trackable.h> #include <sigc++/signal.h> -#include <pbd/stateful.h> -#include <pbd/id.h> +#include <pbd/statefuldestructible.h> class XMLNode; namespace PBD { -class Controllable : public virtual sigc::trackable, public Stateful { +class Controllable : public PBD::StatefulDestructible { public: Controllable (std::string name); - virtual ~Controllable() { GoingAway (this); } + virtual ~Controllable() { Destroyed (this); } virtual void set_value (float) = 0; virtual float get_value (void) const = 0; @@ -25,11 +24,11 @@ class Controllable : public virtual sigc::trackable, public Stateful { sigc::signal<void> LearningFinished; - static sigc::signal<void,Controllable*> GoingAway; - static sigc::signal<bool,PBD::Controllable*> StartLearning; static sigc::signal<void,PBD::Controllable*> StopLearning; + static sigc::signal<void,Controllable*> Destroyed; + sigc::signal<void> Changed; int set_state (const XMLNode&); diff --git a/libs/pbd/pbd/destructible.h b/libs/pbd/pbd/destructible.h index 6692ff564c..7c50806334 100644 --- a/libs/pbd/pbd/destructible.h +++ b/libs/pbd/pbd/destructible.h @@ -5,14 +5,22 @@ namespace PBD { -class Destructible : public virtual sigc::trackable { - public: - Destructible() {} - virtual ~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 ThingWithGoingAway { + public: + virtual ~ThingWithGoingAway () {} sigc::signal<void> GoingAway; +}; +class Destructible : public sigc::trackable, public ThingWithGoingAway { + public: + virtual ~Destructible () {} void drop_references () const { GoingAway(); } + }; } diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h index d42972d546..fe1aa8e7d0 100644 --- a/libs/pbd/pbd/memento_command.h +++ b/libs/pbd/pbd/memento_command.h @@ -28,19 +28,11 @@ using std::endl; #include <pbd/command.h> #include <pbd/stacktrace.h> #include <pbd/xml++.h> +#include <pbd/shiva.h> + #include <sigc++/slot.h> #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 * (from Stateful::get_state()), so undo becomes restoring the before * memento, and redo is restoring the after memento. @@ -55,8 +47,8 @@ class MementoCommand : public Command XMLNode *after ) : obj(object), before(before), after(after) { - cerr << "MC @ " << this << " is a " << typeid (obj_T).name() << endl; - obj.GoingAway.connect (sigc::bind (sigc::ptr_fun (object_death), static_cast<Command*>(this))); + /* catch destruction of the object */ + new PBD::Shiva<obj_T,MementoCommand<obj_T> > (object, *this); } ~MementoCommand () { diff --git a/libs/pbd/pbd/shiva.h b/libs/pbd/pbd/shiva.h index 5110f48332..53b613ea2b 100644 --- a/libs/pbd/pbd/shiva.h +++ b/libs/pbd/pbd/shiva.h @@ -5,28 +5,96 @@ namespace PBD { -template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed> - /* named after the Hindu god Shiva, The Destroyer */ +template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed> class Shiva { public: Shiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) { /* if the emitter goes away, destroy the receiver */ - _connection1 = emitter.GoingAway.connect + _connection = emitter.GoingAway.connect (sigc::bind (sigc::mem_fun (*this, &Shiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy), &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 */ _connection2 = receiver.GoingAway.connect - (sigc::mem_fun (*this, &Shiva<ObjectWithGoingAway,ObjectToBeDestroyed>::forget)); + (sigc::mem_fun (*this, &PairedShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::forget)); } - ~Shiva() { + ~PairedShiva() { forget (); } diff --git a/libs/pbd/pbd/statefuldestructible.h b/libs/pbd/pbd/statefuldestructible.h index e78cc4bdaa..708c10fc8e 100644 --- a/libs/pbd/pbd/statefuldestructible.h +++ b/libs/pbd/pbd/statefuldestructible.h @@ -5,9 +5,21 @@ #include <pbd/destructible.h> namespace PBD { + 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__ */ diff --git a/libs/pbd/pbd/undo.h b/libs/pbd/pbd/undo.h index 943c115af2..277c41c2af 100644 --- a/libs/pbd/pbd/undo.h +++ b/libs/pbd/pbd/undo.h @@ -70,6 +70,8 @@ class UndoTransaction : public Command struct timeval _timestamp; std::string _name; bool _clearing; + + friend void command_death (UndoTransaction*, Command *); }; class UndoHistory diff --git a/libs/pbd/undo.cc b/libs/pbd/undo.cc index af408a24a4..442a5439f2 100644 --- a/libs/pbd/undo.cc +++ b/libs/pbd/undo.cc @@ -24,31 +24,13 @@ #include <pbd/undo.h> #include <pbd/xml++.h> +#include <pbd/shiva.h> #include <sigc++/bind.h> using namespace std; 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 () { _clearing = false; @@ -68,6 +50,20 @@ UndoTransaction::~UndoTransaction () clear (); } +void +command_death (UndoTransaction* ut, Command* c) +{ + if (ut->clearing()) { + return; + } + + ut->remove_command (c); + + if (ut->empty()) { + delete ut; + } +} + UndoTransaction& UndoTransaction::operator= (const UndoTransaction& rhs) { @@ -81,7 +77,8 @@ UndoTransaction::operator= (const UndoTransaction& rhs) void 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); } |