midway snapshot of work done on managing Region & Source lifetimes correctly. may...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 23 Jun 2010 20:14:07 +0000 (20:14 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 23 Jun 2010 20:14:07 +0000 (20:14 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@7291 d708f5d6-7413-0410-9779-e7cbd77b26cf

36 files changed:
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_regions.cc
libs/ardour/ardour/diskstream.h
libs/ardour/ardour/playlist.h
libs/ardour/ardour/public_diskstream.h
libs/ardour/ardour/region.h
libs/ardour/ardour/region_factory.h
libs/ardour/ardour/session.h
libs/ardour/ardour/session_playlists.h
libs/ardour/ardour/source.h
libs/ardour/ardour/track.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_playlist.cc
libs/ardour/audioregion.cc
libs/ardour/diskstream.cc
libs/ardour/midi_diskstream.cc
libs/ardour/midi_playlist.cc
libs/ardour/midi_region.cc
libs/ardour/playlist.cc
libs/ardour/region.cc
libs/ardour/region_factory.cc
libs/ardour/session.cc
libs/ardour/session_playlists.cc
libs/ardour/session_state.cc
libs/ardour/source.cc
libs/ardour/track.cc
libs/evoral/src/SMF.cpp
libs/pbd/pbd/command.h
libs/pbd/pbd/properties.h
libs/pbd/pbd/property_basics.h
libs/pbd/pbd/stateful.h
libs/pbd/pbd/stateful_diff_command.h
libs/pbd/pbd/undo.h
libs/pbd/stateful.cc
libs/pbd/stateful_diff_command.cc
libs/pbd/undo.cc

index bd786481073faaa124d4f7615b0fce9e8e79e8e8..b267bcd37b15d14cd7896a6d5c24d19d62ba6ae3 100644 (file)
@@ -4419,10 +4419,12 @@ Editor::remove_last_capture ()
 
                if (prompter.run () == 1) {
                        _session->remove_last_capture ();
+                        _regions->redisplay ();
                }
 
        } else {
                _session->remove_last_capture();
+                _regions->redisplay ();
        }
 }
 
index dca382415a2e651a4c6aae2fd7adb016c791fce5..ab6ce7656729b9cd230dca1ac527a9abd6fb2d72 100644 (file)
@@ -365,7 +365,6 @@ EditorRegions::selection_changed ()
 
                                        } else {
                                                _change_connection.block (true);
-                                               cerr << "\tpush to region selection\n";
                                                _editor->set_selected_regionview_from_region_list (region, Selection::Add);
 
                                                _change_connection.block (false);
@@ -392,13 +391,11 @@ EditorRegions::set_selected (RegionSelection& regions)
                        boost::shared_ptr<Region> compared_region = (*i)[_columns.region];
 
                        if (r == compared_region) {
-                               cerr << "\tpush into region list\n";
                                _display.get_selection()->select(*i);
                                break;
                        }
 
                        if (!(*i).children().empty()) {
-                               cerr << "\tlook for " << r->name() << " among children of " << (compared_region ? compared_region->name() : string ("NO REGION")) << endl;
                                if (set_selected_in_subrow(r, (*i), 2)) {
                                        break;
                                }
@@ -559,7 +556,6 @@ EditorRegions::update_all_rows ()
                boost::shared_ptr<Region> region = (*i)[_columns.region];
 
                if (!region->automatic()) {
-                       cerr << "level 1 : Updating " << region->name() << "\n";
                        populate_row(region, (*i));
                }
 
@@ -580,7 +576,6 @@ EditorRegions::update_all_subrows (TreeModel::Row const &parent_row, int level)
                boost::shared_ptr<Region> region = (*i)[_columns.region];
 
                if (!region->automatic()) {
-                       cerr << "level " << level << " : Updating " << region->name() << "\n";
                        populate_row(region, (*i));
                }
 
index c089a39736105d36e20a1609ca2db6a256c2dd94..d0d2bcbc365f5c48c03960d68c1f6638c4195fc0 100644 (file)
@@ -45,7 +45,7 @@ namespace ARDOUR {
 class IO;
 class Playlist;
 class Processor;
-class Region;
+class Source;
 class Session;
 class Track;
 class Location;        
@@ -134,12 +134,10 @@ class Diskstream : public SessionObject, public PublicDiskstream
 
        int set_loop (Location *loc);
 
-       std::list<boost::shared_ptr<Region> >& last_capture_regions () { return _last_capture_regions; }
+       std::list<boost::shared_ptr<Source> >& last_capture_sources () { return _last_capture_sources; }
 
        void handle_input_change (IOChange, void *src);
 
-       void remove_region_from_last_capture (boost::weak_ptr<Region> wregion);
-
        void move_processor_automation (boost::weak_ptr<Processor>,
                        std::list<Evoral::RangeMove<framepos_t> > const &);
 
@@ -228,7 +226,7 @@ class Diskstream : public SessionObject, public PublicDiskstream
 
        virtual bool realtime_set_speed (double, bool global_change);
 
-       std::list<boost::shared_ptr<Region> > _last_capture_regions;
+       std::list<boost::shared_ptr<Source> > _last_capture_sources;
 
        virtual int use_pending_capture_data (XMLNode& node) = 0;
 
index 4b42fc0bd6a2b58ef235eb4ad978529a2ce4a387..7afc074b4def9f7e47c953a51f936127d6cda552 100644 (file)
@@ -65,7 +65,8 @@ class RegionListProperty : public PBD::SequenceProperty<std::list<boost::shared_
         RegionListProperty (Playlist&);
 
         boost::shared_ptr<Region> lookup_id (const PBD::ID& id);
-        void diff (PBD::PropertyList& undo, PBD::PropertyList& redo) const;
+        void diff (PBD::PropertyList& undo, PBD::PropertyList& redo, Command*) const;
+        bool involves (boost::shared_ptr<Region>);
 
   private:
         friend class Playlist;
index c31e88a79bf9f9f144b77d1577af1bdaabd89720..9e25cb24c6d958cb3f31cd11e0ce6bb7425bac22 100755 (executable)
@@ -23,7 +23,7 @@
 namespace ARDOUR {
 
 class Playlist;
-class Region;
+class Source;
 class Location;
 
 /** Public interface to a Diskstream */        
@@ -34,7 +34,7 @@ public:
        virtual boost::shared_ptr<Playlist> playlist () = 0;
        virtual void monitor_input (bool) = 0;
        virtual bool destructive () const = 0;
-       virtual std::list<boost::shared_ptr<Region> > & last_capture_regions () = 0;
+       virtual std::list<boost::shared_ptr<Source> > & last_capture_sources () = 0;
        virtual void set_capture_offset () = 0;
        virtual void reset_write_sources (bool, bool force = false) = 0;
        virtual float playback_buffer_load () const = 0;
index 2cf9bab97b6905c93cde04707811389b75efac2b..a30bb8660c7296f8e2b32b0ba601a136fde33625 100644 (file)
@@ -270,6 +270,8 @@ class Region
                return _pending_explicit_relayer;
        }
 
+        void drop_sources ();
+
   protected:
        friend class RegionFactory;
 
index c9f387f1724543bcbc7fc4f2095ecb4cb9a24735..459699d810c8959014eb34ecc523300eebc56012 100644 (file)
@@ -21,6 +21,7 @@
 #define __ardour_region_factory_h__
 
 #include <map>
+#include <set>
 #include <glibmm/thread.h>
 
 #include "pbd/id.h"
@@ -78,7 +79,10 @@ class RegionFactory {
        /** create a region with specified sources @param srcs and XML state */
        static boost::shared_ptr<Region> create (SourceList& srcs, const XMLNode&);
 
+        static void get_regions_using_source (boost::shared_ptr<Source>, std::set<boost::shared_ptr<Region> >& );
+
        static void map_remove (boost::shared_ptr<Region>);
+       static void map_remove_with_equivalents (boost::shared_ptr<Region>);
         static void delete_all_regions ();
         static const RegionMap& regions() { return region_map; }
         static uint32_t nregions ();
index f7692e09cb4b8e3a7b967ba0084dece9b0fd235f..bca65c88e4453a3cca100615804fa2b5ba88013a 100644 (file)
@@ -512,8 +512,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
        int  cleanup_sources (CleanupReport&);
        int  cleanup_trash_sources (CleanupReport&);
 
-       int destroy_region (boost::shared_ptr<Region>);
-       int destroy_regions (std::list<boost::shared_ptr<Region> >);
+       int destroy_sources (std::list<boost::shared_ptr<Source> >);
 
        int remove_last_capture ();
 
index d654595d6044d49a2d4c44dd0d197bf7024c24ef..1c83a312a53782b00d2b6fe140610493f9a9ab91 100644 (file)
@@ -53,6 +53,7 @@ public:
        template<class T> void foreach (T *obj, void (T::*func)(boost::shared_ptr<Playlist>));
        void get (std::vector<boost::shared_ptr<Playlist> >&);
        void unassigned (std::list<boost::shared_ptr<Playlist> > & list);
+        void destroy_region (boost::shared_ptr<Region>);
 
 private:
        friend class Session;
@@ -69,7 +70,7 @@ private:
        int load (Session &, const XMLNode&);
        int load_unused (Session &, const XMLNode&);
        boost::shared_ptr<Playlist> XMLPlaylistFactory (Session &, const XMLNode&);
-
+        
        mutable Glib::Mutex lock;
        typedef std::set<boost::shared_ptr<Playlist> > List;
        List playlists;
index bf92e5a6e47bc2855e7d71137438068b957699a6..16a762eb9459b884a53432b54fa5865c3d3bbf68 100644 (file)
@@ -23,6 +23,8 @@
 #include <string>
 #include <set>
 
+#include <glib.h>
+
 #include <boost/utility.hpp>
 #include "pbd/statefuldestructible.h"
 
@@ -102,6 +104,15 @@ class Source : public SessionObject
        Glib::Mutex& mutex()       { return _lock; }
        Flag         flags() const { return _flags; }
 
+        void inc_use_count () { g_atomic_int_inc (&_use_count); }
+        void dec_use_count () { 
+                gint oldval = g_atomic_int_exchange_and_add (&_use_count, -1);
+                assert (oldval > 0);
+        }
+
+        int  use_count() const { return g_atomic_int_get (&_use_count); }
+        bool used() const { return use_count() > 0; }
+
   protected:
        DataType            _type;
        Flag                _flags;
@@ -111,6 +122,7 @@ class Source : public SessionObject
        mutable Glib::Mutex _lock;
        mutable Glib::Mutex _analysis_lock;
        Glib::Mutex         _playlist_lock;
+        gint                _use_count; /* atomic */
 
   private:
        void fix_writable_flags ();
index ac948f12df7448a535c202cbf1ecbbd49c003beb..d72d29e563f9253020e3e1e4fd6ad42f733d40d8 100644 (file)
@@ -29,6 +29,7 @@ namespace ARDOUR {
 class Session;
 class Playlist;
 class RouteGroup;
+class Source;
 class Region;
 class Diskstream;
 
@@ -100,7 +101,7 @@ class Track : public Route, public PublicDiskstream
        boost::shared_ptr<Playlist> playlist ();
        void monitor_input (bool);
        bool destructive () const;
-       std::list<boost::shared_ptr<Region> > & last_capture_regions ();
+       std::list<boost::shared_ptr<Source> > & last_capture_sources ();
        void set_capture_offset ();
        void reset_write_sources (bool, bool force = false);
        float playback_buffer_load () const;
index b3204c38b66d67a81c74964192b020ffa547f5fe..ae80690b8107f8d371c384b07f8c37c38b5739e5 100644 (file)
@@ -480,8 +480,8 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
                 was_recording = true;
         }
 
-       if (can_record && !_last_capture_regions.empty()) {
-               _last_capture_regions.clear ();
+       if (can_record && !_last_capture_sources.empty()) {
+               _last_capture_sources.clear ();
        }
 
        if (rec_nframes) {
@@ -1447,7 +1447,6 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
                        plist.add (Properties::start, c->front()->write_source->last_capture_start_frame());
                        plist.add (Properties::length, total_capture);
                        plist.add (Properties::name, whole_file_region_name);
-
                        boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist));
                        rx->set_automatic (true);
                        rx->set_whole_file (true);
@@ -1462,7 +1461,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
                        /* XXX what now? */
                }
 
-               _last_capture_regions.push_back (region);
+               _last_capture_sources.insert (_last_capture_sources.end(), srcs.begin(), srcs.end());
 
                // cerr << _name << ": there are " << capture_info.size() << " capture_info records\n";
 
@@ -1494,10 +1493,6 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
                                continue; /* XXX is this OK? */
                        }
 
-                       region->DropReferences.connect_same_thread (*this, boost::bind (&Diskstream::remove_region_from_last_capture, this, boost::weak_ptr<Region>(region)));
-
-                       _last_capture_regions.push_back (region);
-
                        i_am_the_modifier++;
                        _playlist->add_region (region, (*ci)->start, 1, non_layered());
                        i_am_the_modifier--;
@@ -1914,6 +1909,8 @@ AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/)
        boost::shared_ptr<ChannelList> c = channels.reader();
        uint32_t n;
 
+        cerr << name() << " resetting write sources, recrodable " << recordable() << " chans = " << c->size() << endl;
+
        if (!_session.writable() || !recordable()) {
                return;
        }
@@ -2356,6 +2353,7 @@ void
 AudioDiskstream::ChannelInfo::resize_capture (nframes_t capture_bufsize)
 {
         delete capture_buf;
+
        capture_buf = new RingBufferNPT<Sample> (capture_bufsize);
        memset (capture_buf->buffer(), 0, sizeof (Sample) * capture_buf->bufsize());
 }
index bd09af4e1f8d11b56df3ee485f78288d53cc17d7..6a27541bcd1fe2c18f4fa13c0f7c5285c93e701a 100644 (file)
@@ -663,17 +663,15 @@ bool
 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
 {
        boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
+
+        if (!r) {
+                return false;
+        }
+
        bool changed = false;
        Crossfades::iterator c, ctmp;
        set<boost::shared_ptr<Crossfade> > unique_xfades;
 
-       if (r == 0) {
-               fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
-                     << endmsg;
-               /*NOTREACHED*/
-               return false;
-       }
-
        {
                RegionLock rlock (this);
 
index 0ef79b7018807e234b0c64201c80f009f4893d77..80f8baef0e52f691b1b277b05ae8d8b2bc308b06 100644 (file)
@@ -263,6 +263,9 @@ AudioRegion::connect_to_header_position_offset_changed ()
 
        for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
 
+                /* connect only once to HeaderPositionOffsetChanged, even if sources are replicated
+                 */
+
                if (unique_srcs.find (*i) == unique_srcs.end ()) {
                        unique_srcs.insert (*i);
                        boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
@@ -520,24 +523,8 @@ AudioRegion::state (bool full)
        XMLNode& node (Region::state (full));
        XMLNode *child;
        char buf[64];
-       char buf2[64];
        LocaleGuard lg (X_("POSIX"));
 
-
-       // XXX these should move into Region
-
-       for (uint32_t n=0; n < _sources.size(); ++n) {
-               snprintf (buf2, sizeof(buf2), "source-%d", n);
-               _sources[n]->id().print (buf, sizeof (buf));
-               node.add_property (buf2, buf);
-       }
-
-       for (uint32_t n=0; n < _master_sources.size(); ++n) {
-               snprintf (buf2, sizeof(buf2), "master-source-%d", n);
-               _master_sources[n]->id().print (buf, sizeof (buf));
-               node.add_property (buf2, buf);
-       }
-
        snprintf (buf, sizeof (buf), "%u", (uint32_t) _sources.size());
        node.add_property ("channels", buf);
 
@@ -571,10 +558,6 @@ AudioRegion::state (bool full)
                child->add_property ("default", "yes");
        }
 
-       if (full && _extra_xml) {
-               node.add_child_copy (*_extra_xml);
-       }
-
        return node;
 }
 
index 40a2714dc0735e9ea865109d5bbf9797d41e236f..5dd9a3b3061dd0d025ba54da82a1220dc0b76dcd 100644 (file)
@@ -435,18 +435,6 @@ Diskstream::set_name (const string& str)
        return true;
 }
 
-void
-Diskstream::remove_region_from_last_capture (boost::weak_ptr<Region> wregion)
-{
-       boost::shared_ptr<Region> region (wregion.lock());
-
-       if (!region) {
-               return;
-       }
-
-       _last_capture_regions.remove (region);
-}
-
 void
 Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<framepos_t> > const & movements_frames)
 {
index fa2cdce0140e8664149e8a0fea55cf94785d0414..444e4d378889530072baa9b84042f5bb23d83dde 100644 (file)
@@ -524,8 +524,8 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_
        }
 
 
-       if (can_record && !_last_capture_regions.empty()) {
-               _last_capture_regions.clear ();
+       if (can_record && !_last_capture_sources.empty()) {
+               _last_capture_sources.clear ();
        }
 
        if (nominally_recording || rec_nframes) {
@@ -975,9 +975,7 @@ MidiDiskstream::transport_stopped_wallclock (struct tm& /*when*/, time_t /*twhen
                        /* XXX what now? */
                }
 
-               _last_capture_regions.push_back (region);
-
-               // cerr << _name << ": there are " << capture_info.size() << " capture_info records\n";
+               _last_capture_sources.insert (_last_capture_sources.end(), srcs.begin(), srcs.end());
 
                _playlist->clear_history ();
                _playlist->freeze ();
@@ -1007,10 +1005,6 @@ MidiDiskstream::transport_stopped_wallclock (struct tm& /*when*/, time_t /*twhen
                                continue; /* XXX is this OK? */
                        }
 
-                       region->DropReferences.connect_same_thread (*this, boost::bind (&Diskstream::remove_region_from_last_capture, this, boost::weak_ptr<Region>(region)));
-
-                       _last_capture_regions.push_back (region);
-
                        // cerr << "add new region, buffer position = " << buffer_position << " @ " << (*ci)->start << endl;
 
                        i_am_the_modifier++;
@@ -1312,6 +1306,8 @@ MidiDiskstream::set_state (const XMLNode& node, int /*version*/)
 int
 MidiDiskstream::use_new_write_source (uint32_t n)
 {
+        cerr << name() << " use new write source for n = " << n << " recordable ? " << recordable() << endl;
+
        if (!recordable()) {
                return 1;
        }
index 152735de85f930bc62cae0ebf33b32eff43bcc51..6f5dee979a7e676901a6822008d0a43010f2ce89 100644 (file)
@@ -359,15 +359,13 @@ bool
 MidiPlaylist::destroy_region (boost::shared_ptr<Region> region)
 {
        boost::shared_ptr<MidiRegion> r = boost::dynamic_pointer_cast<MidiRegion> (region);
-       bool changed = false;
 
-       if (r == 0) {
-               PBD::fatal << _("programming error: non-midi Region passed to remove_overlap in midi playlist")
-               << endmsg;
-               /*NOTREACHED*/
+       if (!r) {
                return false;
        }
 
+       bool changed = false;
+
        {
                RegionLock rlock (this);
                RegionList::iterator i;
index fe03e64f72a3b1ba7b040777f6e67735f7532c67..abb3191463446af0d9a69a92029daeb7386b4757 100644 (file)
@@ -193,30 +193,7 @@ MidiRegion::_read_at (const SourceList& /*srcs*/, Evoral::EventSink<nframes_t>&
 XMLNode&
 MidiRegion::state (bool full)
 {
-       XMLNode& node (Region::state (full));
-       char buf[64];
-       char buf2[64];
-       LocaleGuard lg (X_("POSIX"));
-
-       // XXX these should move into Region
-
-       for (uint32_t n=0; n < _sources.size(); ++n) {
-               snprintf (buf2, sizeof(buf2), "source-%d", n);
-               _sources[n]->id().print (buf, sizeof(buf));
-               node.add_property (buf2, buf);
-       }
-
-       for (uint32_t n=0; n < _master_sources.size(); ++n) {
-               snprintf (buf2, sizeof(buf2), "master-source-%d", n);
-               _master_sources[n]->id().print (buf, sizeof (buf));
-               node.add_property (buf2, buf);
-       }
-
-       if (full && _extra_xml) {
-               node.add_child_copy (*_extra_xml);
-       }
-
-       return node;
+       return Region::state (full);
 }
 
 int
index 0526d48b11b9aa434044d42f1e3f1c40154e0dac..f07cd645f191e5327f0515e752f0ed98a803ca97 100644 (file)
@@ -134,7 +134,7 @@ RegionListProperty::copy_for_history () const
 }
 
 void 
-RegionListProperty::diff (PropertyList& undo, PropertyList& redo) const
+RegionListProperty::diff (PropertyList& undo, PropertyList& redo, Command* cmd) const
 {
         if (changed()) {
                /* list of the removed/added regions since clear_history() was last called */
@@ -144,6 +144,18 @@ RegionListProperty::diff (PropertyList& undo, PropertyList& redo) const
                 RegionListProperty* b = copy_for_history ();
                 b->invert_changes ();
 
+                if (cmd) {
+                        /* whenever one of the regions emits DropReferences, make sure
+                           that the Destructible we've been told to notify hears about
+                           it. the Destructible is likely to be the Command being built
+                           with this diff().
+                        */
+                        
+                        for (set<boost::shared_ptr<Region> >::iterator i = a->change().added.begin(); i != a->change().added.end(); ++i) {
+                                (*i)->DropReferences.connect_same_thread (*cmd, boost::bind (&Destructible::drop_references, cmd));
+                        }
+                }
+
                 undo.add (b);
                 redo.add (a);
         }
index 2589f94f81e0500ce0ebb6a36a1e65b82c9010b4..e620319633576fcb397bcddfcc7a9f342db3dfaf 100644 (file)
@@ -415,6 +415,7 @@ Region::Region (boost::shared_ptr<const Region> other)
 Region::~Region ()
 {
        DEBUG_TRACE (DEBUG::Destruction, string_compose ("Region %1 destructor @ %2\n", _name, this));
+        drop_sources ();
 }
 
 void
@@ -1126,10 +1127,12 @@ Region::set_layer (layer_t l)
 }
 
 XMLNode&
-Region::state (bool /*full_state*/)
+Region::state (bool full)
 {
        XMLNode *node = new XMLNode ("Region");
        char buf[64];
+       char buf2[64];
+       LocaleGuard lg (X_("POSIX"));
        const char* fe = NULL;
 
        add_properties (*node);
@@ -1164,6 +1167,22 @@ Region::state (bool /*full_state*/)
                node->add_property ("bbt-position", str.str());
        }
 
+       for (uint32_t n=0; n < _sources.size(); ++n) {
+               snprintf (buf2, sizeof(buf2), "source-%d", n);
+               _sources[n]->id().print (buf, sizeof(buf));
+               node->add_property (buf2, buf);
+       }
+
+       for (uint32_t n=0; n < _master_sources.size(); ++n) {
+               snprintf (buf2, sizeof(buf2), "master-source-%d", n);
+               _master_sources[n]->id().print (buf, sizeof (buf));
+               node->add_property (buf2, buf);
+       }
+
+       if (full && _extra_xml) {
+               node->add_child_copy (*_extra_xml);
+       }
+
        return *node;
 }
 
@@ -1237,11 +1256,6 @@ Region::_set_state (const XMLNode& node, int version, PropertyChange& what_chang
        }
 
        if (send) {
-               cerr << _name << ": final change to be sent: ";
-               for (PropertyChange::iterator i = what_changed.begin(); i != what_changed.end(); ++i) {
-                       cerr << g_quark_to_string ((GQuark) *i) << ' ';
-               }
-               cerr << endl;
                send_change (what_changed);
        }
        
@@ -1335,7 +1349,7 @@ Region::region_list_equivalent (boost::shared_ptr<const Region> other) const
 void
 Region::source_deleted (boost::weak_ptr<Source>)
 {
-       _sources.clear ();
+        drop_sources ();
 
        if (!_session.deletion_in_progress()) {
                /* this is a very special case: at least one of the region's
@@ -1366,8 +1380,16 @@ Region::master_source_names ()
 void
 Region::set_master_sources (const SourceList& srcs)
 {
+        for (SourceList::const_iterator i = _master_sources.begin (); i != _master_sources.end(); ++i) {
+                (*i)->dec_use_count ();
+        }
+
        _master_sources = srcs;
        assert (_sources.size() == _master_sources.size());
+
+        for (SourceList::const_iterator i = _master_sources.begin (); i != _master_sources.end(); ++i) {
+                (*i)->inc_use_count ();
+        }
 }
 
 bool
@@ -1408,6 +1430,7 @@ Region::uses_source (boost::shared_ptr<const Source> source) const
 sframes_t
 Region::source_length(uint32_t n) const
 {
+        assert (n < _sources.size());
        return _sources[n]->length(_position - _start);
 }
 
@@ -1420,7 +1443,7 @@ Region::verify_length (framecnt_t len)
 
        framecnt_t maxlen = 0;
 
-       for (uint32_t n=0; n < _sources.size(); ++n) {
+       for (uint32_t n = 0; n < _sources.size(); ++n) {
                maxlen = max (maxlen, source_length(n) - _start);
        }
 
@@ -1438,7 +1461,7 @@ Region::verify_start_and_length (framepos_t new_start, framecnt_t& new_length)
 
        framecnt_t maxlen = 0;
 
-       for (uint32_t n=0; n < _sources.size(); ++n) {
+       for (uint32_t n = 0; n < _sources.size(); ++n) {
                maxlen = max (maxlen, source_length(n) - new_start);
        }
 
@@ -1454,7 +1477,7 @@ Region::verify_start (framepos_t pos)
                return true;
        }
 
-       for (uint32_t n=0; n < _sources.size(); ++n) {
+       for (uint32_t n = 0; n < _sources.size(); ++n) {
                if (pos > source_length(n) - _length) {
                        return false;
                }
@@ -1469,7 +1492,7 @@ Region::verify_start_mutable (framepos_t& new_start)
                return true;
        }
 
-       for (uint32_t n=0; n < _sources.size(); ++n) {
+       for (uint32_t n = 0; n < _sources.size(); ++n) {
                if (new_start > source_length(n) - _length) {
                        new_start = source_length(n) - _length;
                }
@@ -1508,6 +1531,21 @@ Region::invalidate_transients ()
        _transients.clear ();
 }
 
+void
+Region::drop_sources ()
+{
+        for (SourceList::const_iterator i = _sources.begin (); i != _sources.end(); ++i) {
+                (*i)->dec_use_count ();
+        }
+
+       _sources.clear ();
+
+        for (SourceList::const_iterator i = _master_sources.begin (); i != _master_sources.end(); ++i) {
+                (*i)->dec_use_count ();
+        }
+
+        _master_sources.clear ();
+}
 
 void
 Region::use_sources (SourceList const & s)
@@ -1515,16 +1553,19 @@ Region::use_sources (SourceList const & s)
        set<boost::shared_ptr<Source> > unique_srcs;
 
        for (SourceList::const_iterator i = s.begin (); i != s.end(); ++i) {
-               _sources.push_back (*i);
-               (*i)->DropReferences.connect_same_thread (*this, boost::bind (&Region::source_deleted, this, boost::weak_ptr<Source>(*i)));
-               unique_srcs.insert (*i);
-       }
 
-       for (SourceList::const_iterator i = s.begin (); i != s.end(); ++i) {
+               _sources.push_back (*i);
+                (*i)->inc_use_count ();
                _master_sources.push_back (*i);
-               if (unique_srcs.find (*i) == unique_srcs.end()) {
-                       (*i)->DropReferences.connect_same_thread (*this, boost::bind (&Region::source_deleted, this, boost::weak_ptr<Source>(*i)));
-               }
+                (*i)->inc_use_count ();
+
+                /* connect only once to DropReferences, even if sources are replicated
+                 */
+
+               if (unique_srcs.find (*i) == unique_srcs.end ()) {
+                       unique_srcs.insert (*i);
+                        (*i)->DropReferences.connect_same_thread (*this, boost::bind (&Region::source_deleted, this, boost::weak_ptr<Source>(*i)));
+                }
        }
 }
 
index 5a4b129710464a5824133473ecae6141abb182a0..65649ad8f745d15ba5a853bce0011c97396eb61f 100644 (file)
@@ -73,6 +73,7 @@ RegionFactory::create (boost::shared_ptr<const Region> region)
        }
 
        if (ret) {
+                cerr << "Pure copy constructor region " << ret << " named " << ret->name() << endl;
                map_add (ret);
 
                /* pure copy constructor - no property list */
@@ -124,6 +125,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, frameoffset_t offset, b
 
        if (ret) {
                ret->set_properties (plist);
+                cerr << "Partial copy constructor region\n";
                map_add (ret);
 
                if (announce) {
@@ -163,6 +165,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, const SourceList& srcs,
        if (ret) {
 
                ret->set_properties (plist);
+                cerr << "New sources copy constructor region\n";
                map_add (ret);
 
                if (announce) {
@@ -208,6 +211,7 @@ RegionFactory::create (const SourceList& srcs, const PropertyList& plist, bool a
        if (ret) {
 
                ret->set_properties (plist);
+                cerr << "de-novo constructor region " << ret << " named " << ret->name() << endl;
                map_add (ret);
 
                if (announce) {
@@ -281,6 +285,8 @@ RegionFactory::map_add (boost::shared_ptr<Region> r)
                boost::bind (&RegionFactory::region_changed, _1, boost::weak_ptr<Region> (r))
                );
 
+        cerr << "Added region with ID = " << r->id() << " named " << r->name() << endl;
+
        update_region_name_map (r);
 }
 
@@ -292,7 +298,32 @@ RegionFactory::map_remove (boost::shared_ptr<Region> r)
 
         if (i != region_map.end()) {
                 region_map.erase (i);
+                cerr << "Removed region with ID = " << r->id() << " named " << r->name() << endl;;
         }
+
+}
+
+void
+RegionFactory::map_remove_with_equivalents (boost::shared_ptr<Region> r)
+{
+        Glib::Mutex::Lock lm (region_map_lock);
+
+        for (RegionMap::iterator i = region_map.begin(); i != region_map.end(); ) {
+                RegionMap::iterator tmp = i;
+                ++tmp;
+
+                if (r->region_list_equivalent (i->second)) {
+                        cerr << "Removed equivalent region " << i->second->name() << '/' << i->first << endl;
+                        region_map.erase (i);
+                } else if (r == i->second) {
+                        cerr << "Removed actual region " << i->second->name() << '/' << i->first << endl;
+                        region_map.erase (i);
+                } 
+
+                i = tmp;
+        }
+
+
 }
 
 boost::shared_ptr<Region>
@@ -487,3 +518,15 @@ RegionFactory::new_region_name (string old)
        error << string_compose (_("cannot create new name for region \"%1\""), old) << endmsg;
        return old;
 }
+
+void 
+RegionFactory::get_regions_using_source (boost::shared_ptr<Source> s, std::set<boost::shared_ptr<Region> >& r)
+{
+        Glib::Mutex::Lock lm (region_map_lock);
+
+        for (RegionMap::iterator i = region_map.begin(); i != region_map.end(); ++i) {
+                if (i->second->uses_source (s)) {
+                        r.insert (i->second);
+                }
+        }
+}
index 3d5430d2593cee03331db58b0523ff1ecd0f7ab0..91b1e2a0f95465e1e7c2a8087b199add54fd4b11 100644 (file)
@@ -1484,6 +1484,7 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m
                        auto_connect_route (track, existing_inputs, existing_outputs);
 
                        track->non_realtime_input_change();
+
                        if (route_group) {
                                route_group->add (track);
                        }
@@ -2483,46 +2484,58 @@ Session::find_whole_file_parent (boost::shared_ptr<Region const> child) const
 }
 
 int
-Session::destroy_region (boost::shared_ptr<Region> region)
+Session::destroy_sources (list<boost::shared_ptr<Source> > srcs)
 {
-       vector<boost::shared_ptr<Source> > srcs;
-
-       {
-               if (region->playlist()) {
-                       region->playlist()->destroy_region (region);
-               }
+        set<boost::shared_ptr<Region> > relevant_regions;
 
-               for (uint32_t n = 0; n < region->n_channels(); ++n) {
-                       srcs.push_back (region->source (n));
-               }
+       for (list<boost::shared_ptr<Source> >::iterator s = srcs.begin(); s != srcs.end(); ++s) {
+                RegionFactory::get_regions_using_source (*s, relevant_regions);
        }
 
-       region->drop_references ();
+        cerr << "There are " << relevant_regions.size() << " using " << srcs.size() << " sources" << endl;
+
+        for (set<boost::shared_ptr<Region> >::iterator r = relevant_regions.begin(); r != relevant_regions.end(); ) {
+                set<boost::shared_ptr<Region> >::iterator tmp;
+
+                tmp = r;
+                ++tmp;
+
+                cerr << "Cleanup " << (*r)->name() << " UC = " << (*r).use_count() << endl;
 
-       for (vector<boost::shared_ptr<Source> >::iterator i = srcs.begin(); i != srcs.end(); ++i) {
+                playlists->destroy_region (*r);
+                RegionFactory::map_remove (*r);
 
-                (*i)->mark_for_remove ();
-                (*i)->drop_references ();
+                (*r)->drop_sources ();
+                (*r)->drop_references ();
+
+                cerr << "\tdone UC = " << (*r).use_count() << endl;
+
+                relevant_regions.erase (r);
+
+                r = tmp;
+        }
+
+       for (list<boost::shared_ptr<Source> >::iterator s = srcs.begin(); s != srcs.end(); ) {
                 
-                cerr << "source was not used by any playlist\n";
-       }
+                {
+                        Glib::Mutex::Lock ls (source_lock);
+                        /* remove from the main source list */
+                        sources.erase ((*s)->id());
+                }
 
-       return 0;
-}
+                (*s)->mark_for_remove ();
+                (*s)->drop_references ();
+
+                s = srcs.erase (s);
+        }
 
-int
-Session::destroy_regions (list<boost::shared_ptr<Region> > regions)
-{
-       for (list<boost::shared_ptr<Region> >::iterator i = regions.begin(); i != regions.end(); ++i) {
-               destroy_region (*i);
-       }
        return 0;
 }
 
 int
 Session::remove_last_capture ()
 {
-       list<boost::shared_ptr<Region> > r;
+       list<boost::shared_ptr<Source> > srcs;
 
        boost::shared_ptr<RouteList> rl = routes.reader ();
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
@@ -2531,15 +2544,15 @@ Session::remove_last_capture ()
                        continue;
                }
                
-               list<boost::shared_ptr<Region> >& l = tr->last_capture_regions();
+               list<boost::shared_ptr<Source> >& l = tr->last_capture_sources();
 
                if (!l.empty()) {
-                       r.insert (r.end(), l.begin(), l.end());
+                       srcs.insert (srcs.end(), l.begin(), l.end());
                        l.clear ();
                }
        }
 
-       destroy_regions (r);
+       destroy_sources (srcs);
 
        save_state (_current_snapshot_name);
 
@@ -2563,16 +2576,19 @@ Session::add_source (boost::shared_ptr<Source> source)
        }
 
        if (result.second) {
-               set_dirty();
-       }
 
-       boost::shared_ptr<AudioFileSource> afs;
+                /* yay, new source */
 
-       if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
-               if (Config->get_auto_analyse_audio()) {
-                       Analyser::queue_source_for_analysis (source, false);
-               }
-       }
+               set_dirty();
+
+                boost::shared_ptr<AudioFileSource> afs;
+                
+                if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
+                        if (Config->get_auto_analyse_audio()) {
+                                Analyser::queue_source_for_analysis (source, false);
+                        }
+                }
+        }
 }
 
 void
index 2f8ae9a8f02cbbf3381aab856c0285a22800ce2b..38c6744d06c2864aef3b59f4ad83f584c009551c 100644 (file)
@@ -219,6 +219,21 @@ SessionPlaylists::get (vector<boost::shared_ptr<Playlist> >& s)
        }
 }
 
+void
+SessionPlaylists::destroy_region (boost::shared_ptr<Region> r)
+{
+       Glib::Mutex::Lock lm (lock);
+
+       for (List::iterator i = playlists.begin(); i != playlists.end(); ++i) {
+                (*i)->destroy_region (r);
+       }
+       
+       for (List::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
+                (*i)->destroy_region (r);
+       }
+}
+
+
 void
 SessionPlaylists::find_equivalent_playlist_regions (boost::shared_ptr<Region> region, vector<boost::shared_ptr<Region> >& result)
 {
@@ -262,14 +277,12 @@ SessionPlaylists::add_state (XMLNode* node, bool full_state)
        XMLNode* child = node->add_child ("Playlists");
        for (List::iterator i = playlists.begin(); i != playlists.end(); ++i) {
                if (!(*i)->hidden()) {
-                       if (!(*i)->empty()) {
-                               if (full_state) {
-                                       child->add_child_nocopy ((*i)->get_state());
-                               } else {
-                                       child->add_child_nocopy ((*i)->get_template());
-                               }
-                       }
-               }
+                        if (full_state) {
+                                child->add_child_nocopy ((*i)->get_state());
+                        } else {
+                                child->add_child_nocopy ((*i)->get_template());
+                        }
+                }
        }
 
        child = node->add_child ("UnusedPlaylists");
index a490bb10c92259ffbc8d42355fa985913ea02676..0f8583a822c5364caf208439f0c7966c4a3331b5 100644 (file)
@@ -1040,13 +1040,18 @@ Session::state(bool full_state)
 
                for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
 
-                       /* Don't save information about non-destructive file sources that are empty */
-                       /* FIXME: MIDI breaks if this is made FileSource like it should be... */
+                       /* Don't save information about non-destructive file sources that are empty
+                           and unused by any regions.
+                        */
 
-                       boost::shared_ptr<AudioFileSource> fs;
-                       if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
+                        cerr << "Source " << siter->second->name() << " has UC = " << siter->second->used() 
+                             << " length = " <<  siter->second->length (0)
+                             << endl;
+
+                       boost::shared_ptr<FileSource> fs;
+                       if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
                                if (!fs->destructive()) {
-                                       if (fs->length(fs->timeline_position()) == 0) {
+                                       if (fs->length(fs->timeline_position()) == 0 && !fs->used()) {
                                                continue;
                                        }
                                }
index 5ec9631e40ba9684c34f633d29c50ee64db4f3b7..55ce9f8bef2846d51c8822f444961105b285e56c 100644 (file)
@@ -52,6 +52,7 @@ Source::Source (Session& s, DataType type, const string& name, Flag flags)
        , _type(type)
        , _flags(flags)
        , _timeline_position(0)
+        , _use_count (0)
 {
        _analysed = false;
        _timestamp = 0;
@@ -63,6 +64,7 @@ Source::Source (Session& s, const XMLNode& node)
        , _type(DataType::AUDIO)
        , _flags (Flag (Writable|CanRename))
        , _timeline_position(0)
+        , _use_count (0)
 {
        _timestamp = 0;
        _analysed = false;
index ad4c7658677ab017c6c694a85d7fdac30003f8e0..b2079e0a2e3cc0a7134ed9fe4a20aca07ff34327 100644 (file)
@@ -425,10 +425,10 @@ Track::destructive () const
        return _diskstream->destructive ();
 }
 
-list<boost::shared_ptr<Region> > &
-Track::last_capture_regions ()
+list<boost::shared_ptr<Source> > &
+Track::last_capture_sources ()
 {
-       return _diskstream->last_capture_regions ();
+       return _diskstream->last_capture_sources ();
 }
 
 void
index b8705afbf061b73943feef230537318dfc75cb3f..cf838455ce4bd872a7c70722d5e9a70f968f63fe 100644 (file)
@@ -275,6 +275,16 @@ SMF::begin_write()
 void
 SMF::end_write() THROW_FILE_ERROR
 {
+#if 0
+        /* don't create empty MIDI files 
+         */
+
+        smf_rewind (_smf); // smf_save() would have done this anyway
+        if (smf_peek_next_event (_smf) == 0) {
+                return;
+        }
+#endif
+
        PBD::StdioFileDescriptor d (_file_path, "w+");
        FILE* f = d.allocate ();
        if (f == 0) {
index 5a7290bc89cab89cb740b15b1914575bf3fc2107..c6c3c8d3fd21b02d818be71e00fbdc4e150aa990 100644 (file)
 #ifndef __lib_pbd_command_h__
 #define __lib_pbd_command_h__
 
+#include <string>
+
+#include "pbd/signals.h"
 #include "pbd/statefuldestructible.h"
-#include <boost/utility.hpp>
 
-class Command : public PBD::StatefulDestructible, public boost::noncopyable
+class Command : public PBD::StatefulDestructible, public PBD::ScopedConnectionList
 {
 public:
        virtual ~Command() { /* NOTE: derived classes must call drop_references() */ }
@@ -34,7 +36,7 @@ public:
        
        void set_name (const std::string& str) { _name = str; }
        const std::string& name() const { return _name; }
-       
+
        virtual void undo() = 0;
        virtual void redo() { (*this)(); }
        
index 784282ee9c55d0228411e5e538843af9c9cb0bea..1914344db9c0704f91ef6f2cfc9cd18efe454d2b 100644 (file)
@@ -165,7 +165,7 @@ public:
                : PropertyTemplate<T> (q, v)
        {}
         
-        void diff (PropertyList& undo, PropertyList& redo) const {
+        void diff (PropertyList& undo, PropertyList& redo, Command* /*ignored*/) const {
                 if (this->_have_old) {
                         undo.add (new Property<T> (this->property_id(), this->_old));
                         redo.add (new Property<T> (this->property_id(), this->_current));
@@ -227,7 +227,7 @@ public:
                : PropertyTemplate<std::string> (q, v)
        {}
 
-        void diff (PropertyList& before, PropertyList& after) const {
+        void diff (PropertyList& before, PropertyList& after, Command* /*ignored*/) const {
                 if (this->_have_old) {
                         before.add (new Property<std::string> (PropertyDescriptor<std::string> (this->property_id()), this->_old));
                         after.add (new Property<std::string> (PropertyDescriptor<std::string> (this->property_id()), this->_current));
index 5e94abdfc37d882bc27ddb7dba6a8402cc179456..2dea20e251ff75bf9fdd5f87d7382c8c3da2f859 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "pbd/xml++.h"
 
+class Command;
+
 namespace PBD {
 
 class PropertyList;
@@ -83,7 +85,7 @@ public:
        {}
 
        virtual ~PropertyBase () {}
-
+        
        /** Forget about any old value for this state */
        virtual void clear_history () = 0;
 
@@ -97,7 +99,7 @@ public:
         *  the last call to clear_history, and one that allows redo
         *  of those changes.
         */
-       virtual void diff (PropertyList& undo, PropertyList& redo) const = 0;
+       virtual void diff (PropertyList& undo, PropertyList& redo, Command*) const = 0;
         
         virtual PropertyBase* maybe_clone_self_if_found_in_history_node (const XMLNode&) const { return 0; }
 
index 4352e8820159c6758999076bf48ff1025effa2b0..1272a735f93d7487650ecf46795ff71a78dcc555 100644 (file)
@@ -67,7 +67,7 @@ class Stateful {
         /* history management */
 
        void clear_history ();
-        void diff (PropertyList&, PropertyList&) const;
+        void diff (PropertyList&, PropertyList&, Command*) const;
         bool changed() const;
 
         /* create a property list from an XMLNode
index 21245f029aa51cb9e8e5699e9a3c3c03fbe9c02b..25cdfbba12c24f12a92bed4f6884b15d3735eed9 100644 (file)
@@ -27,7 +27,7 @@
 namespace PBD
 {
 
-class Stateful;        
+class StatefulDestructible;    
 class PropertyList;
 
 /** A Command which stores its action as the differences between the before and after
@@ -36,13 +36,13 @@ class PropertyList;
 class StatefulDiffCommand : public Command
 {
 public:
-       StatefulDiffCommand (boost::shared_ptr<Stateful>);
-       StatefulDiffCommand (boost::shared_ptr<Stateful>, XMLNode const &);
+       StatefulDiffCommand (boost::shared_ptr<StatefulDestructible>);
+       StatefulDiffCommand (boost::shared_ptr<StatefulDestructible>, XMLNode const &);
        ~StatefulDiffCommand ();
 
        void operator() ();
        void undo ();
-
+        
        XMLNode& get_state ();
 
 private:
index 6eb9e00056c140bddf6d67981fdbc1057c3a7d3e..fb5152c29312aad1f29d86479f87cbed6f8c8edc 100644 (file)
 #include <sigc++/bind.h>
 #include <sys/time.h>
 
-#include "pbd/signals.h"
 #include "pbd/command.h"
 
 typedef sigc::slot<void> UndoAction;
 
-class UndoTransaction : public Command, public PBD::ScopedConnectionList
+class UndoTransaction : public Command
 {
   public:
        UndoTransaction ();
index b486319c4cff9c0d4a31a3db7bd272dd9a3ea52a..1c3d08b3a9c348fdf77df1a9baa090288dbc114b 100644 (file)
@@ -167,10 +167,10 @@ Stateful::clear_history ()
 }
 
 void
-Stateful::diff (PropertyList& before, PropertyList& after) const
+Stateful::diff (PropertyList& before, PropertyList& after, Command* cmd) const
 {
        for (OwnedPropertyList::const_iterator i = _properties->begin(); i != _properties->end(); ++i) {
-               i->second->diff (before, after);
+               i->second->diff (before, after, cmd);
        }
 }
 
index 635fe4829ab0f5e9d3f9abecb1ef90c62c8c39a1..2c58acee142a0963ee77b134bb8e78fac6a4c50d 100644 (file)
@@ -32,15 +32,21 @@ using namespace PBD;
  *  @param s Stateful object.
  */
 
-StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<Stateful> s)
-       : _object (s)
+StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s)
+        : _object (s)
         , _undo (new PropertyList)
         , _redo (new PropertyList)
 {
-        s->diff (*_undo, *_redo);
+        s->diff (*_undo, *_redo, this);
+
+        /* if the stateful object that this command refers to goes away,
+           be sure to notify owners of this command.
+        */
+
+        s->DropReferences.connect_same_thread (*this, boost::bind (&Destructible::drop_references, this));
 }
 
-StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<Stateful> s, XMLNode const & n)
+StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s, XMLNode const & n)
        : _object (s)
         , _undo (0)
         , _redo (0)
@@ -57,10 +63,18 @@ StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<Stateful> s, XMLNode
 
         assert (_undo != 0);
         assert (_redo != 0);
+
+        /* if the stateful object that this command refers to goes away,
+           be sure to notify owners of this command.
+        */
+
+        s->DropReferences.connect_same_thread (*this, boost::bind (&Destructible::drop_references, this));
 }
 
 StatefulDiffCommand::~StatefulDiffCommand ()
 {
+        drop_references ();
+
         delete _undo;
         delete _redo;
 }
index a06127926f74e6397c4d05210e515480b6030519..120f62c3512c78d263ae48a3aa6e9990b6eea30b 100644 (file)
@@ -39,7 +39,6 @@ UndoTransaction::UndoTransaction ()
 
 UndoTransaction::UndoTransaction (const UndoTransaction& rhs)
        : Command(rhs._name)
-       , PBD::ScopedConnectionList ()
        , _clearing(false)
 {
        clear ();
@@ -77,15 +76,15 @@ UndoTransaction::operator= (const UndoTransaction& rhs)
 }
 
 void
-UndoTransaction::add_command (Command *const action)
+UndoTransaction::add_command (Command *const cmd)
 {
        /* catch death of command (e.g. caused by death of object to
           which it refers. command_death() is a normal static function
           so there is no need to manage this connection.
         */
 
-       action->DropReferences.connect_same_thread (*this, boost::bind (&command_death, this, action));
-       actions.push_back (action);
+       cmd->DropReferences.connect_same_thread (*this, boost::bind (&command_death, this, cmd));
+       actions.push_back (cmd);
 }
 
 void
@@ -250,9 +249,6 @@ UndoHistory::undo (unsigned int n)
                return;
        }
 
-       struct timeval start, end, diff;
-       gettimeofday (&start, 0);
-
        {
                UndoRedoSignaller exception_safe_signaller (*this);
 
@@ -265,16 +261,8 @@ UndoHistory::undo (unsigned int n)
                        ut->undo ();
                        RedoList.push_back (ut);
                }
-               gettimeofday (&end, 0);
-               timersub (&end, &start, &diff);
-               cerr << "Undo-pre-signals took " << diff.tv_sec << '.' << diff.tv_usec << endl;
-
        }
 
-       gettimeofday (&end, 0);
-       timersub (&end, &start, &diff);
-       cerr << "Undo took " << diff.tv_sec << '.' << diff.tv_usec << endl;
-
        Changed (); /* EMIT SIGNAL */
 }
 
@@ -285,9 +273,6 @@ UndoHistory::redo (unsigned int n)
                return;
        }
 
-       struct timeval start, end, diff;
-       gettimeofday (&start, 0);
-
        {
                UndoRedoSignaller exception_safe_signaller (*this);
                
@@ -300,15 +285,8 @@ UndoHistory::redo (unsigned int n)
                        ut->redo ();
                        UndoList.push_back (ut);
                }
-               gettimeofday (&end, 0);
-               timersub (&end, &start, &diff);
-               cerr << "Redo-pre-signals took " << diff.tv_sec << '.' << diff.tv_usec << endl;
        }
 
-       gettimeofday (&end, 0);
-       timersub (&end, &start, &diff);
-       cerr << "Redo took " << diff.tv_sec << '.' << diff.tv_usec << endl;
-
        Changed (); /* EMIT SIGNAL */
 }