more combine/uncombine fixes including making uncombine push the compound region...
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 26 May 2011 17:22:22 +0000 (17:22 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Thu, 26 May 2011 17:22:22 +0000 (17:22 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@9601 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/route_time_axis.cc
libs/ardour/ardour/audio_playlist_source.h
libs/ardour/ardour/playlist_source.h
libs/ardour/ardour/source_factory.h
libs/ardour/audio_playlist.cc
libs/ardour/audio_playlist_source.cc
libs/ardour/playlist.cc
libs/ardour/playlist_source.cc
libs/ardour/source_factory.cc

index f1e00978e98b39b2940d24116069ec835ce7e4db..86832de764d38aaf2781c263cf41211cf60220cc 100644 (file)
@@ -2498,6 +2498,10 @@ RouteTimeAxisView::combine_regions ()
        boost::shared_ptr<Playlist> playlist = track()->playlist();
 
        _view->foreach_selected_regionview (sigc::bind (sigc::ptr_fun (add_region_to_list), &selected_regions));
+
+       if (selected_regions.size() < 2) {
+               return 0;
+       }
        
        playlist->clear_changes ();
        boost::shared_ptr<Region> compound_region = playlist->combine (selected_regions);
index 3514a06407a88562c64b2bec0741325b0f48ec42..273651b7d11c658acef894d1fd73663f90eda490 100644 (file)
@@ -56,7 +56,7 @@ class AudioPlaylistSource : public AudioSource, public PlaylistSource {
   protected:
     friend class SourceFactory;
 
-    AudioPlaylistSource (Session&, const std::string& name, boost::shared_ptr<AudioPlaylist>, uint32_t chn,
+    AudioPlaylistSource (Session&, const PBD::ID& orig, const std::string& name, boost::shared_ptr<AudioPlaylist>, uint32_t chn,
                          frameoffset_t begin, framecnt_t len, Source::Flag flags);
     AudioPlaylistSource (Session&, const XMLNode&);
     
index ed48fbabd5a1af945e8de3dffe665f7874b5790e..b41569cbddc14ef472b004320a0e74d582ae9ec0 100644 (file)
@@ -37,13 +37,15 @@ class PlaylistSource : virtual public Source {
     
     int set_state (const XMLNode&, int version);
     boost::shared_ptr<const Playlist> playlist() const { return _playlist; }
+    const PBD::ID& original() const { return _original; }
 
   protected:
-    boost::shared_ptr<Playlist>      _playlist;
-    frameoffset_t                    _playlist_offset;
-    framecnt_t                       _playlist_length;
+    boost::shared_ptr<Playlist> _playlist;
+    PBD::ID                     _original;
+    frameoffset_t               _playlist_offset;
+    framecnt_t                  _playlist_length;
 
-    PlaylistSource (Session&, const std::string& name, boost::shared_ptr<Playlist>, DataType,
+    PlaylistSource (Session&, const PBD::ID&, const std::string& name, boost::shared_ptr<Playlist>, DataType,
                    frameoffset_t begin, framecnt_t len, Source::Flag flags);
     PlaylistSource (Session&, const XMLNode&);
     
index 427bf10a5639d663a988a01402f768ce43e723a3..df15653c1d3364de5ef18a2eab45b56caa975daf 100644 (file)
@@ -56,7 +56,7 @@ class SourceFactory {
 
 
        static boost::shared_ptr<Source> createFromPlaylist 
-               (DataType type, Session& s, boost::shared_ptr<Playlist> p, const std::string& name,
+               (DataType type, Session& s, boost::shared_ptr<Playlist> p, const PBD::ID& orig, const std::string& name,
                 uint32_t chn, frameoffset_t start, framecnt_t len, bool copy, bool defer_peaks);
 
        static Glib::Cond*                               PeaksToBuild;
index 59c791b8fbd797fa5c7d3585d969ec512752007b..7e60930e2d4b18cefc7b3474363f792bc48d0194 100644 (file)
@@ -1092,7 +1092,7 @@ AudioPlaylist::pre_combine (vector<boost::shared_ptr<Region> >& copies)
 
        ar = boost::dynamic_pointer_cast<AudioRegion> (copies.front());
 
-       /* copy the fade in of the first into the compound region */
+       /* disable fade in of the first region */
 
        if (ar) {
                ar->set_fade_in_active (false);
@@ -1100,6 +1100,8 @@ AudioPlaylist::pre_combine (vector<boost::shared_ptr<Region> >& copies)
 
        ar = boost::dynamic_pointer_cast<AudioRegion> (copies.back());
 
+       /* disable fade out of the last region */
+
        if (ar) {
                ar->set_fade_out_active (false);
        }
@@ -1124,7 +1126,6 @@ AudioPlaylist::post_combine (vector<boost::shared_ptr<Region> >& originals, boos
 
        if (ar) {
                cr->set_fade_in (ar->fade_in());
-               ar->set_fade_in_active (false);
        }
 
        ar = boost::dynamic_pointer_cast<AudioRegion> (originals.back());
@@ -1132,13 +1133,13 @@ AudioPlaylist::post_combine (vector<boost::shared_ptr<Region> >& originals, boos
        if (ar) {
                /* copy the fade out of the last into the compound region */
                cr->set_fade_out (ar->fade_out());
-               ar->set_fade_out_active (false);
        }
 }
 
 void
 AudioPlaylist::pre_uncombine (vector<boost::shared_ptr<Region> >& originals, boost::shared_ptr<Region> compound_region)
 {
+       RegionSortByPosition cmp;
        boost::shared_ptr<AudioRegion> ar;
        boost::shared_ptr<AudioRegion> cr = boost::dynamic_pointer_cast<AudioRegion>(compound_region);
 
@@ -1146,41 +1147,53 @@ AudioPlaylist::pre_uncombine (vector<boost::shared_ptr<Region> >& originals, boo
                return;
        }
 
+       sort (originals.begin(), originals.end(), cmp);
+
        /* no need to call clear_changes() on the originals because that is
         * done within Playlist::uncombine ()
         */
 
-       if ((ar = boost::dynamic_pointer_cast<AudioRegion> (originals.front())) != 0) {
+       for (vector<boost::shared_ptr<Region> >::iterator i = originals.begin(); i != originals.end(); ++i) {
 
-               /* copy the compound region's fade in back into the first
-                  original region.
-               */
-
-               if (cr->fade_in()->back()->when <= ar->length()) {
-                       /* don't do this if the fade is longer than the
-                        * region
-                        */
-                       ar->set_fade_in (cr->fade_in());
+               if ((ar = boost::dynamic_pointer_cast<AudioRegion> (*i)) == 0) {
+                       continue;
                }
 
-               ar->set_fade_in_active (true);
-               _session.add_command (new StatefulDiffCommand (originals.front()));
-       }
+               /* scale the uncombined regions by any gain setting for the
+                * compound one.
+                */
 
-       if ((ar = boost::dynamic_pointer_cast<AudioRegion> (originals.back())) != 0) {
+               ar->set_scale_amplitude (ar->scale_amplitude() * cr->scale_amplitude());
 
-               /* copy the compound region's fade out back into the last
-                  original region.
-               */
+               if (i == originals.begin()) {
+                       
+                       /* copy the compound region's fade in back into the first
+                          original region.
+                       */
+                       
+                       if (cr->fade_in()->back()->when <= ar->length()) {
+                               /* don't do this if the fade is longer than the
+                                * region
+                                */
+                               ar->set_fade_in (cr->fade_in());
+                       }
+
+                       
+               } else if (*i == originals.back()) {
+
+                       /* copy the compound region's fade out back into the last
+                          original region.
+                       */
+                       
+                       if (cr->fade_out()->back()->when <= ar->length()) {
+                               /* don't do this if the fade is longer than the
+                                * region
+                                */
+                               ar->set_fade_out (cr->fade_out());
+                       }
 
-               if (cr->fade_out()->back()->when <= ar->length()) {
-                       /* don't do this if the fade is longer than the
-                        * region
-                        */
-                       ar->set_fade_out (cr->fade_out());
                }
 
-               ar->set_fade_out_active (true);
-               _session.add_command (new StatefulDiffCommand (originals.back()));
+               _session.add_command (new StatefulDiffCommand (*i));
        }
 }
index 882a1710e77badbab4923627139e83eacf1ccfff..393f90938b4e920acb2dd24b622b787cbd3ce339 100644 (file)
@@ -46,11 +46,11 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-AudioPlaylistSource::AudioPlaylistSource (Session& s, const std::string& name, boost::shared_ptr<AudioPlaylist> p, 
+AudioPlaylistSource::AudioPlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr<AudioPlaylist> p, 
                                          uint32_t chn, frameoffset_t begin, framecnt_t len, Source::Flag flags)
        : Source (s, DataType::AUDIO, name)
        , AudioSource (s, name)
-       , PlaylistSource (s, name, p, DataType::AUDIO, begin, len, flags)
+       , PlaylistSource (s, orig, name, p, DataType::AUDIO, begin, len, flags)
        , _playlist_channel (chn)
 {
        AudioSource::_length = len;
index 3f7eb1852db9d3b8c7655fbe9f6e130a1eddc901..a396732d56956706e9cc5b00a0a224ef39717aa9 100644 (file)
@@ -3133,9 +3133,8 @@ Playlist::combine (const RegionList& r)
        pair<framepos_t,framepos_t> extent = pl->get_extent();
        
        for (uint32_t chn = 0; chn < channels; ++chn) {
-               sources.push_back (SourceFactory::createFromPlaylist (_type, _session, pl, parent_name, chn, 0, extent.second, false, false));
+               sources.push_back (SourceFactory::createFromPlaylist (_type, _session, pl, id(), parent_name, chn, 0, extent.second, false, false));
        }
-
        
        /* now a new whole-file region using the list of sources */
 
@@ -3191,12 +3190,12 @@ Playlist::combine (const RegionList& r)
 void
 Playlist::uncombine (boost::shared_ptr<Region> target)
 {
-       // (1) check that its really a compound region
-       
        boost::shared_ptr<PlaylistSource> pls;
        boost::shared_ptr<const Playlist> pl;
        vector<boost::shared_ptr<Region> > originals;
 
+       // (1) check that its really a compound region
+       
        if ((pls = boost::dynamic_pointer_cast<PlaylistSource>(target->source (0))) == 0) {
                return;
        }
@@ -3215,14 +3214,23 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
           the length of the region.
        */
        
-
-       cerr << "Compound region: bounds within nested playlist = " << adjusted_start << " .. " << adjusted_end << endl;
-                       
        // (2) get all the original regions
 
        const RegionList& rl (pl->region_list().rlist());
        RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
        frameoffset_t move_offset = 0;
+       
+       /* there are two possibilities here:
+          1) the playlist that the playlist source was based on
+          is us, so just add the originals (which belonged to
+          us anyway) back in the right place.
+          
+          2) the playlist that the playlist source was based on
+          is NOT us, so we need to make copies of each of
+          the original regions that we find, and add them
+          instead.
+       */
+       bool same_playlist = (pls->original() == id());
 
        for (RegionList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
 
@@ -3239,19 +3247,18 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
 
                if (i == rl.begin()) {
                        move_offset = (target->position() - original->position()) - target->start();
-
-
-                       cerr << "Move offset is " << target->position() << " - " << original->position()
-                            << " - " << target->start() << " = " << move_offset
-                            << endl;
-
                        adjusted_start = original->position() + target->start();
                        adjusted_end = adjusted_start + target->length();
+               }
 
-                       cerr << "adjusted range = " << adjusted_start << " based on "
-                            << original->position() << " + " << target->start() << " .. "
-                            << adjusted_end << " from " << target->length() 
-                            << endl;
+               if (!same_playlist) {
+                       framepos_t pos = original->position();
+                       /* make a copy, but don't announce it */
+                       original = RegionFactory::create (original, false);
+                       /* the pure copy constructor resets position() to zero,
+                          so fix that up.
+                       */
+                       original->set_position (pos, this);
                }
 
                /* check to see how the original region (in the
@@ -3259,12 +3266,6 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
                 * with the new state of the compound region.
                 */
 
-               cerr << "Original " << original->name() 
-                    << " overlaptype = " << enum_2_string (original->coverage (adjusted_start, adjusted_end))
-                    << " target range: " << adjusted_start << " .. " << adjusted_end
-                    << " orig range: " << original->position() << " .. " << original->last_frame ()
-                    << endl;
-
                original->clear_changes ();
                modified_region = false;
 
@@ -3273,7 +3274,6 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
                        /* original region does not cover any part 
                           of the current state of the compound region
                        */
-                       cerr << "Not present - skip\n";
                        continue;
 
                case OverlapInternal:
@@ -3282,14 +3282,12 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
                         */
                        original->trim_to (adjusted_start, adjusted_end - adjusted_start, this);
                        modified_region = true;
-                       cerr << "trim to\n";
                        break;
                                
                case OverlapExternal:
                        /* overlap fully covers original, so leave it
                           as is
                        */
-                       cerr << "leave as is\n";
                        break;
 
                case OverlapEnd:
@@ -3298,7 +3296,6 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
                        */
                        original->trim_front (adjusted_start, this);
                        modified_region = true;
-                       cerr << "trim front\n";
                        break;
                                
                case OverlapStart:
@@ -3307,14 +3304,12 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
                         */
                        original->trim_end (adjusted_end, this);
                        modified_region = true;
-                       cerr << "trim end\n";
                        break;
                }
 
                if (move_offset) {
                        /* fix the position to match any movement of the compound region.
                         */
-                       cerr << "Moving region to new position based on " << original->position() << " + " << move_offset << endl;
                        original->set_position (original->position() + move_offset, this);
                        modified_region = true;
                }
@@ -3339,8 +3334,7 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
 
        remove_region (target);
 
-       // (4) add the originals. This will reset their playlist reference back
-       // to us, which means they are no longer considered owned by the RegionFactory
+       // (4) add the constituent regions
 
        for (vector<boost::shared_ptr<Region> >::iterator i = originals.begin(); i != originals.end(); ++i) {
                add_region ((*i), (*i)->position());
index a1597a76d2335d4d53c83afdc4e103796d4ee439..7bbfdecd822efb4b2cd8edb922633336babe9251 100644 (file)
@@ -43,10 +43,11 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-PlaylistSource::PlaylistSource (Session& s, const std::string& name, boost::shared_ptr<Playlist> p, DataType type,
+PlaylistSource::PlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr<Playlist> p, DataType type,
                                frameoffset_t begin, framecnt_t len, Source::Flag flags)
        : Source (s, type, name)
        , _playlist (p)
+       , _original (orig)
 {
        /* PlaylistSources are never writable, renameable, removable or destructive */
        _flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy|Destructive));
@@ -85,6 +86,7 @@ PlaylistSource::add_state (XMLNode& node)
        node.add_property ("offset", buf);
        snprintf (buf, sizeof (buf), "%" PRIu64, _playlist_length);
        node.add_property ("length", buf);
+       node.add_property ("original", _id.to_s());
        
        node.add_child_nocopy (_playlist->get_state());
 }
@@ -139,6 +141,12 @@ PlaylistSource::set_state (const XMLNode& node, int version)
 
        sscanf (prop->value().c_str(), "%" PRIu64, &_playlist_length);
 
+       if ((prop = node.property (X_("original"))) == 0) {
+               throw failed_constructor ();
+       }
+
+       _id = prop->value();
+
        _level = _playlist->max_source_level () + 1;
 
        return 0;
index 57f0fdc1ec03e894ad10562096c372b406125842..afc92c450cc0105cc0e361341a1577eb061dce3e 100644 (file)
@@ -347,7 +347,7 @@ SourceFactory::createWritable (DataType type, Session& s, const std::string& pat
 }
 
 boost::shared_ptr<Source>
-SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr<Playlist> p, const std::string& name,
+SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr<Playlist> p, const ID& orig, const std::string& name,
                                   uint32_t chn, frameoffset_t start, framecnt_t len, bool copy, bool defer_peaks)
 {
        if (type == DataType::AUDIO) {
@@ -362,7 +362,7 @@ SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr<
                                        start = 0;
                                }
                                
-                               Source* src = new AudioPlaylistSource (s, name, ap, chn, start, len, Source::Flag (0));
+                               Source* src = new AudioPlaylistSource (s, orig, name, ap, chn, start, len, Source::Flag (0));
                                boost::shared_ptr<Source> ret (src);
                                
                                if (setup_peakfile (ret, defer_peaks)) {