fixes for endemic (compiler?) issues with virtual inheritance of sigc::trackable...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 25 Oct 2006 20:11:42 +0000 (20:11 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 25 Oct 2006 20:11:42 +0000 (20:11 +0000)
git-svn-id: svn://localhost/ardour2/trunk@1007 d708f5d6-7413-0410-9779-e7cbd77b26cf

42 files changed:
gtk2_ardour/audio_regionview.cc
gtk2_ardour/audio_streamview.cc
gtk2_ardour/automation_line.cc
gtk2_ardour/automation_line.h
gtk2_ardour/crossfade_view.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/public_editor.h
gtk2_ardour/region_gain_line.cc
gtk2_ardour/region_gain_line.h
gtk2_ardour/route_ui.cc
libs/ardour/ardour/automation_event.h
libs/ardour/ardour/curve.h
libs/ardour/ardour/io.h
libs/ardour/ardour/location.h
libs/ardour/ardour/session.h
libs/ardour/ardour/tempo.h
libs/ardour/audio_playlist.cc
libs/ardour/audio_track.cc
libs/ardour/audioregion.cc
libs/ardour/automation_event.cc
libs/ardour/crossfade.cc
libs/ardour/curve.cc
libs/ardour/insert.cc
libs/ardour/io.cc
libs/ardour/location.cc
libs/ardour/panner.cc
libs/ardour/redirect.cc
libs/ardour/send.cc
libs/ardour/session.cc
libs/ardour/session_click.cc
libs/ardour/session_command.cc
libs/ardour/session_state.cc
libs/ardour/tempo.cc
libs/pbd/controllable.cc
libs/pbd/pbd/command.h
libs/pbd/pbd/controllable.h
libs/pbd/pbd/destructible.h
libs/pbd/pbd/memento_command.h
libs/pbd/pbd/shiva.h
libs/pbd/pbd/statefuldestructible.h
libs/pbd/pbd/undo.h
libs/pbd/undo.cc

index fdbb961ab6cc088f883e28447ffa0d1458106709..b50ea72be2b77e98370e5a6a065927cf75b5067f 100644 (file)
@@ -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
index 24924fec4f91d17aef40549aebf6cbcaba76b4c8..75eb28e7d5c388b691373a39cb013f9d058510d8 100644 (file)
@@ -202,6 +202,7 @@ AudioStreamView::remove_region_view (boost::weak_ptr<Region> weak_r)
                }
        }
 
+
        StreamView::remove_region_view(r);
 }
 
index ee74fabfa4418d21068ee399eda8e267bff91a82..371552fbfc1ed37a0b0984a311f11a0475309dc6 100644 (file)
@@ -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)
index eb2d2045134ac9fb4c17aaa553b380dccdaf35ce..0e44c95a3371940594fd37bd9e49a4f9fc1ec9db 100644 (file)
@@ -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*);
        
index 42a1a47227b4c0b6049b9d9c421e9c8bb12367a1..e8a97c4cf465d76acc0ec42ba24dd937eda9da05 100644 (file)
@@ -89,7 +89,7 @@ CrossfadeView::CrossfadeView (ArdourCanvas::Group *parent,
 
 CrossfadeView::~CrossfadeView ()
 {
-        GoingAway (this) ; /* EMIT_SIGNAL */
+       GoingAway (this) ; /* EMIT_SIGNAL */
 }
 
 void
index c7a10df5a061be716853eaa8009852c8756a2403..280804c94f93a690034476d8996f392daa07a701 100644 (file)
@@ -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 ();
index 189e2100bbf7a650098799adfd2edc31f636c551..0c68eb6221d44a43f6212c3aca4640f326b6be18 100644 (file)
@@ -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;
 
index 467f24bd947264192f8149e7a87d6a995cb0d478..58a8a9acad0838f1d924b448289fc5fb0a9ed7d8 100644 (file)
@@ -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
index 3781fe60bb2ee0abbcaac9b185c8d582e69f06b5..916bf78a78dd75314d6055b31a59788f268eac54 100644 (file)
@@ -31,7 +31,9 @@ class AudioRegionGainLine : public AutomationLine
        ARDOUR::Session& session;
        AudioRegionView& rv;
 
+#ifdef STATE_MANAGER
        UndoAction get_memento();
+#endif
 };
 
 
index 482f5df22fe278bba1fa3636fa2cc3643b453be5..bb24dcc426943b886b38f88e66ec93e33da8591e 100644 (file)
@@ -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));
 
index 22ab706f82bed73e946ac2532a2f0b6d57827b9f..e2940bc2e1ca0aeb6f5e5fc998d44e55be015445 100644 (file)
@@ -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;
index 7ba6b5fa6c4438f02ff9ac40793879233dabd2b2..9de7d0ef48b058c6f89c44ccf4052176ed74d311 100644 (file)
@@ -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;
index 96ae75f29811345c2f4f532b995d7491fb0a65f9..cbac6295932b82adca7fb181e81502cf74d99fba 100644 (file)
@@ -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;
index 1f1c02d67cac36d19de28437576bb90119f66192..e618f46dfe881aca0733791f6770667410d57093 100644 (file)
@@ -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
index 0cbc1683290b503f9f8982478bcf796a3840d04a..da5a098aa06e14541f7989108f78e38b1a2289b7 100644 (file)
@@ -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
         {
index 7cdbe56cf2839ab7b93a2372199dd26c5c353143..eaadcb1c99235279abce1f6c384264b77793797f 100644 (file)
@@ -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 */
index cce6e188f8b3bb8a484ba93f68fe314485cb605e..19609da2a4c6df4f70fc236d930b4f20e9fa3c81 100644 (file)
@@ -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;
                }
index 677c9a04972082d1609daad5db604376dba839e1..d61ec7b00393ae7fbba959019ffb7629aa90c12d 100644 (file)
@@ -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 */
index 2f2c67ec5036d476d47f7f5013d73b3818a34dbe..d2cf279d3ec677ebba3111b513721542803fd781 100644 (file)
@@ -306,7 +306,6 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
 
 AudioRegion::~AudioRegion ()
 {
-       cerr << "====== " << _name << " DESTRUCTOR @ " << this << endl;
        notify_callbacks ();
        GoingAway (); /* EMIT SIGNAL */
 }
index f286b11607319cd7b10931088176d8871aca2a83..6b7f0ff0162b5312ab253bc8426b77571aad3795 100644 (file)
@@ -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 ()
index 739ea1cc0e5cc89654c1bd99fefefd6ddad0e733..46a8e6e40086cc34276cb85a2eb575ebcd2cd246 100644 (file)
@@ -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
index 20f7053f2e9466e4ef43f82b5f561e02cd4ed38a..5f7d69247161d1521bdce3159afec0d84239bca5 100644 (file)
@@ -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" {
 
index d64cce36f90b3673411cb589c3d5585fc14dd695..5531e4136b73f4802f6a30156a796281d5294104 100644 (file)
@@ -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
index bcd3ee794026d5d87d81be0636b31ecda2f3b17b..a9751268ffba557dd9b110683f6d504f4d503375 100644 (file)
@@ -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.
index 39331cfda644284474e453a165b6ac8cc049004a..f9bcd76a0b4b4bc33fa65ebe2fa5e291c37c8723 100644 (file)
@@ -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
index 22053ce56b717f1656c834141ef45f462e4e1965..229c4c5e1cf753ab81a1cad565ddabd424148d97 100644 (file)
@@ -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;
index 9323966f96f4879270b50ed5df33dff3f97cd3e5..18b16eaa73e4291c3189f8ddd47f0d32a0704490 100644 (file)
@@ -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 ();
 }
index b37168807e9e06f04435a12e51a7737bb7ef1526..1479eab420566fe5247d7c9ef0a9b406cad1541c 100644 (file)
@@ -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 */
 }
 
index 66cb1f89fa38e7f4835d59d91d39930603167ed1..fddd289882af84661475aea460f4eb7cd96d7d0d 100644 (file)
@@ -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";
        
index 7f9b1426796b3600e6ce1705f83cec1285a32ed4..ba7f7ae8117fed35b8642bef01c966595cd6ad3b 100644 (file)
@@ -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(); ) {
index c5c31b7c178674551f34a3ed7f9010d2417146a1..1492136b887486e7ce3cf4ee11dcbf6ddc12751a 100644 (file)
@@ -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 */
index c3e0fe9388af51f8213ab2b2fd8024e7ce7e650a..d742186d6b60a933f8138c3cf14bfa50504c380f 100644 (file)
@@ -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;
index 913218c91ca2d411d8ceccb943c4f5f7ac47ea32..e9d46f83e3736177cb84a9d6cb9f1f24f5f3820c 100644 (file)
@@ -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
index 80c6811e6aed84be96ec20fb8c1f1c375fda648b..2264a955ae1accfda27633482b812beea5f0de35 100644 (file)
@@ -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;
 
index 7c367e7462598f501cd7263662905ef52db79568..8044b51a83cd7cd7f8e6f04275e0cce78c1b0737 100644 (file)
 #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() {}
index ff8f8a9b52004a1b8342bdf67fed3d526a28da19..c88eb298bcca4193dc57a5408d3a35d3fc2dcd31 100644 (file)
@@ -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&);
index 6692ff564c742d3fb7a9109501feb2ab520b2fa2..7c5080633489dd7ce2050dc25d99d39aea2d4ea9 100644 (file)
@@ -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(); }
+
 };
 
 }
index d42972d54627b5da0d6e8daa9d3e433f92f63da9..fe1aa8e7d049dd827fbdf4b784a980935bcc01b0 100644 (file)
@@ -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 () {
index 5110f483324b950485c4e8517edaa817fc8ba504..53b613ea2b0cc14e1f66e1a096a477d31145b5f6 100644 (file)
@@ -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 ();
        }
 
index e78cc4bdaa2cf0ad819900f73f92c640696f1903..708c10fc8e513d5066159a45ca34888fb1a631ba 100644 (file)
@@ -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__ */
index 943c115af2a1f9a6e913fe1833192ae9b76ae4d1..277c41c2af71abb791ec0db984e912d94ef51b3f 100644 (file)
@@ -70,6 +70,8 @@ class UndoTransaction : public Command
        struct timeval        _timestamp;
        std::string           _name;
        bool                  _clearing;
+
+       friend void command_death (UndoTransaction*, Command *);
 };
 
 class UndoHistory
index af408a24a4a9eaf9ac5f2b507d2682e795aa4d03..442a5439f2bff705f911692da57133014713eb05 100644 (file)
 
 #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);
 }