if an xfade involves only 2 regions, clamp its length to the overlap between them
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 10 May 2012 12:14:26 +0000 (12:14 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Thu, 10 May 2012 12:14:26 +0000 (12:14 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@12238 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/editor_drag.cc
gtk2_ardour/editor_drag.h
libs/ardour/ardour/audioregion.h
libs/ardour/audioregion.cc

index a075008d201ec7f9baad1ba995e3973791a0743d..e9ab0d3a6034d7066111484be899f5e16b4ed31a 100644 (file)
@@ -4559,12 +4559,6 @@ CrossfadeEdgeDrag::CrossfadeEdgeDrag (Editor* e, AudioRegionView* rv, ArdourCanv
        , arv (rv)
        , start (start_yn)
 {
-       cerr << "new xfade drag\n";
-}
-
-CrossfadeEdgeDrag::~CrossfadeEdgeDrag ()
-{
-       cerr << "destory xfade drag\n";
 }
 
 void
@@ -4590,8 +4584,14 @@ CrossfadeEdgeDrag::motion (GdkEvent*, bool)
                len = ar->fade_out()->back()->when;
        }
 
+       /* how long should it be ? */
+
        new_length = len + _editor->unit_to_frame (distance);
-       
+
+       /* now check with the region that this is legal */
+
+       new_length = ar->verify_xfade_bounds (new_length, start);
+
        if (start) {
                arv->redraw_start_xfade_to (ar, new_length);
        } else {
@@ -4616,7 +4616,7 @@ CrossfadeEdgeDrag::finished (GdkEvent*, bool)
                len = ar->fade_out()->back()->when;
        }
 
-       new_length = len + _editor->unit_to_frame (distance);
+       new_length = ar->verify_xfade_bounds (len + _editor->unit_to_frame (distance), start);
        
        if (start) {
                ar->set_fade_in_length (new_length);
index 70ec45ac9925c7434dbb517be9947918d2ec0872..724c2eb355cbc352bfec05ee2dc838bbfed8b19d 100644 (file)
@@ -978,7 +978,6 @@ class CrossfadeEdgeDrag : public Drag
 {
   public:
        CrossfadeEdgeDrag (Editor*, AudioRegionView*, ArdourCanvas::Item*, bool start);
-       ~CrossfadeEdgeDrag ();
 
        void start_grab (GdkEvent*, Gdk::Cursor* c = 0);
        void motion (GdkEvent*, bool);
index fe9f991ed04889fb8ee1a2cf2788d348d4a5e41c..fd6c3a85288565f56a45758a6507f8c5004c32c4 100644 (file)
@@ -142,6 +142,8 @@ class AudioRegion : public Region
 
        void set_default_fade_in ();
        void set_default_fade_out ();
+
+       framecnt_t verify_xfade_bounds (framecnt_t, bool start);
        
        void set_envelope_active (bool yn);
        void set_default_envelope ();
index e2177837606ba1cbdc013403dd8951183b54b344..4ba383b37e7ed8514723d8a0598853436654ca90 100644 (file)
@@ -1801,6 +1801,59 @@ AudioRegion::set_fade_out_is_xfade (bool yn)
        _fade_out_is_xfade = yn;
 }
 
+framecnt_t
+AudioRegion::verify_xfade_bounds (framecnt_t len, bool start)
+{
+       boost::shared_ptr<Playlist> pl (playlist());
+
+       if (!pl) {
+               /* not currently in a playlist - xfade length is unbounded
+                  (and irrelevant)
+               */
+               return len;
+       }
+
+       boost::shared_ptr<RegionList> rl;
+       framecnt_t maxlen;
+
+       if (start) {
+               rl = pl->regions_at (position());
+       } else {
+               rl = pl->regions_at (last_frame());
+       }
+       
+       RegionList::iterator i;
+       boost::shared_ptr<Region> other;
+       uint32_t n = 0;
+
+       /* count and find the other region in a single pass through the list */
+
+       for (i = rl->begin(); i != rl->end(); ++i) {
+               if ((*i).get() != this) {
+                       other = *i;
+               }
+               ++n;
+       }
+
+       if (n != 2) {
+               /* zero or multiple regions stacked here - don't care about xfades */
+               return len;
+       }
+
+       /* we overlap a single region. clamp the length of an xfade to
+          the duration of the overlap.
+       */
+
+       if (start) {
+               maxlen = other->last_frame() - position();
+       } else {
+               maxlen = last_frame() - other->position();
+       }
+
+       return min (maxlen, len);
+               
+}
+
 extern "C" {
 
        int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t cnt, intptr_t data, uint32_t n_chan, double samples_per_unit)