summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2006-10-25 20:11:42 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2006-10-25 20:11:42 +0000
commitbcd511aa3fec59e1527c8b7ab80dabda4db1a6f9 (patch)
tree0e704409baaaa22a43b918adc126c76990208f5f
parent1b39adc4ce8566fd731cf433094b1faf4fe63205 (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
-rw-r--r--gtk2_ardour/audio_regionview.cc5
-rw-r--r--gtk2_ardour/audio_streamview.cc1
-rw-r--r--gtk2_ardour/automation_line.cc2
-rw-r--r--gtk2_ardour/automation_line.h4
-rw-r--r--gtk2_ardour/crossfade_view.cc2
-rw-r--r--gtk2_ardour/editor_ops.cc2
-rw-r--r--gtk2_ardour/public_editor.h3
-rw-r--r--gtk2_ardour/region_gain_line.cc2
-rw-r--r--gtk2_ardour/region_gain_line.h2
-rw-r--r--gtk2_ardour/route_ui.cc2
-rw-r--r--libs/ardour/ardour/automation_event.h8
-rw-r--r--libs/ardour/ardour/curve.h2
-rw-r--r--libs/ardour/ardour/io.h7
-rw-r--r--libs/ardour/ardour/location.h11
-rw-r--r--libs/ardour/ardour/session.h4
-rw-r--r--libs/ardour/ardour/tempo.h11
-rw-r--r--libs/ardour/audio_playlist.cc12
-rw-r--r--libs/ardour/audio_track.cc3
-rw-r--r--libs/ardour/audioregion.cc1
-rw-r--r--libs/ardour/automation_event.cc42
-rw-r--r--libs/ardour/crossfade.cc4
-rw-r--r--libs/ardour/curve.cc3
-rw-r--r--libs/ardour/insert.cc12
-rw-r--r--libs/ardour/io.cc6
-rw-r--r--libs/ardour/location.cc27
-rw-r--r--libs/ardour/panner.cc4
-rw-r--r--libs/ardour/redirect.cc4
-rw-r--r--libs/ardour/send.cc8
-rw-r--r--libs/ardour/session.cc16
-rw-r--r--libs/ardour/session_click.cc35
-rw-r--r--libs/ardour/session_command.cc8
-rw-r--r--libs/ardour/session_state.cc4
-rw-r--r--libs/ardour/tempo.cc43
-rw-r--r--libs/pbd/controllable.cc2
-rw-r--r--libs/pbd/pbd/command.h5
-rw-r--r--libs/pbd/pbd/controllable.h11
-rw-r--r--libs/pbd/pbd/destructible.h16
-rw-r--r--libs/pbd/pbd/memento_command.h16
-rw-r--r--libs/pbd/pbd/shiva.h78
-rw-r--r--libs/pbd/pbd/statefuldestructible.h12
-rw-r--r--libs/pbd/pbd/undo.h2
-rw-r--r--libs/pbd/undo.cc37
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);
}