Merging from trunk
[ardour.git] / libs / ardour / audio_playlist.cc
index be977447b7bd5cdcf82d2e33a26444c4a2d189ca..bbbaf42fef5f1b7e2677355c4ee122150b9089e8 100644 (file)
@@ -37,6 +37,7 @@
 using namespace ARDOUR;
 using namespace sigc;
 using namespace std;
+using namespace PBD;
 
 AudioPlaylist::State::~State ()
 {
@@ -72,6 +73,43 @@ AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, string name, bool hidd
 {
        save_state (_("initial state"));
 
+       list<Region*>::const_iterator in_o  = other.regions.begin();
+       list<Region*>::iterator in_n = regions.begin();
+
+       while (in_o != other.regions.end()) {
+               AudioRegion *ar = dynamic_cast<AudioRegion *>( (*in_o) );
+
+               // We look only for crossfades which begin with the current region, so we don't get doubles
+               for (list<Crossfade *>::const_iterator xfades = other._crossfades.begin(); xfades != other._crossfades.end(); ++xfades) {
+                       if ( &(*xfades)->in() == ar) {
+                               // We found one! Now copy it!
+
+                               list<Region*>::const_iterator out_o = other.regions.begin();
+                               list<Region*>::const_iterator out_n = regions.begin();
+
+                               while (out_o != other.regions.end()) {
+                                       
+                                       AudioRegion *ar2 = dynamic_cast<AudioRegion *>( (*out_o) );
+                                       
+                                       if ( &(*xfades)->out() == ar2) {
+                                               AudioRegion *in  = dynamic_cast<AudioRegion*>( (*in_n) );
+                                               AudioRegion *out = dynamic_cast<AudioRegion*>( (*out_n) );
+                                               Crossfade *new_fade = new Crossfade( *(*xfades), in, out);
+                                               add_crossfade(*new_fade);
+                                               break;
+                                       }
+                                       
+                                       out_o++;
+                                       out_n++;
+                               }
+//                             cerr << "HUH!? second region in the crossfade not found!" << endl;
+                       }
+               }
+
+               in_o++;
+               in_n++;
+       }
+
        if (!hidden) {
                PlaylistCreated (this); /* EMIT SIGNAL */
        }
@@ -139,7 +177,7 @@ struct RegionSortByLayer {
 };
 
 jack_nframes_t
-AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, jack_nframes_t start,
+AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, char * workbuf, jack_nframes_t start,
                     jack_nframes_t cnt, unsigned chan_n)
 {
        jack_nframes_t ret = cnt;
@@ -166,7 +204,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, ja
           its OK to block (for short intervals).
        */
 
-       LockMonitor rm (region_lock, __LINE__, __FILE__);
+       Glib::Mutex::Lock rm (region_lock);
 
        end =  start + cnt - 1;
 
@@ -209,13 +247,13 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, ja
                vector<Crossfade*>& x (relevant_xfades[*l]);
 
                for (vector<Region*>::iterator i = r.begin(); i != r.end(); ++i) {
-                       (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
+                       (*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n, read_frames, skip_frames);
                        _read_data_count += (*i)->read_data_count();
                }
                
                for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
                        
-                       (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
+                       (*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n);
 
                        /* don't JACK up _read_data_count, since its the same data as we just
                           read from the regions, and the OS should handle that for us.
@@ -307,6 +345,46 @@ AudioPlaylist::refresh_dependents (Region& r)
        }
 }
 
+void
+AudioPlaylist::finalize_split_region (Region *o, Region *l, Region *r)
+{
+       AudioRegion *orig  = dynamic_cast<AudioRegion*>(o);
+       AudioRegion *left  = dynamic_cast<AudioRegion*>(l);
+       AudioRegion *right = dynamic_cast<AudioRegion*>(r);
+
+       for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
+               Crossfades::iterator tmp;
+               tmp = x;
+               ++tmp;
+
+               Crossfade *fade = 0;
+               
+               if ((*x)->_in == orig) {
+                       if (! (*x)->covers(right->position())) {
+                               fade = new Crossfade( *(*x), left, (*x)->_out);
+                       } else {
+                               // Overlap, the crossfade is copied on the left side of the right region instead
+                               fade = new Crossfade( *(*x), right, (*x)->_out);
+                       }
+               }
+               
+               if ((*x)->_out == orig) {
+                       if (! (*x)->covers(right->position())) {
+                               fade = new Crossfade( *(*x), (*x)->_in, right);
+                       } else {
+                               // Overlap, the crossfade is copied on the right side of the left region instead
+                               fade = new Crossfade( *(*x), (*x)->_in, left);
+                       }
+               }
+               
+               if (fade) {
+                       _crossfades.remove( (*x) );
+                       add_crossfade (*fade);
+               }
+               x = tmp;
+       }
+}
+
 void
 AudioPlaylist::check_dependents (Region& r, bool norefresh)
 {
@@ -427,7 +505,7 @@ AudioPlaylist::add_crossfade (Crossfade& xfade)
        
 void AudioPlaylist::notify_crossfade_added (Crossfade *x)
 {
-       if (atomic_read(&block_notifications)) {
+       if (g_atomic_int_get(&block_notifications)) {
                _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
        } else {
                NewCrossfade (x); /* EMIT SIGNAL */
@@ -809,8 +887,14 @@ AudioPlaylist::get_equivalent_regions (const AudioRegion& other, vector<AudioReg
 
                AudioRegion* ar = dynamic_cast<AudioRegion*> (*i);
 
-               if (ar && ar->equivalent (other)) {
-                       results.push_back (ar);
+               if (ar) {
+                       if (Config->get_use_overlap_equivalency()) {
+                               if (ar->overlap_equivalent (other)) {
+                                       results.push_back (ar);
+                               } else if (ar->equivalent (other)) {
+                                       results.push_back (ar);
+                               }
+                       }
                }
        }
 }