interpolation.cc/.h: Spline-Bugfixes: Crash bug at tempos close to 0, wrong calculati...
[ardour.git] / libs / ardour / audio_playlist.cc
index 0631c9121b1fcf5e2b2acf257d07dddac6eaf7a0..93bdc333f134413a67faf1ab5e2b91ca3c4beb72 100644 (file)
 
 #include <sigc++/bind.h>
 
-#include <ardour/types.h>
-#include <ardour/configuration.h>
-#include <ardour/audioplaylist.h>
-#include <ardour/audioregion.h>
-#include <ardour/crossfade.h>
-#include <ardour/crossfade_compare.h>
-#include <ardour/session.h>
-#include <pbd/enumwriter.h>
+#include "ardour/types.h"
+#include "ardour/configuration.h"
+#include "ardour/audioplaylist.h"
+#include "ardour/audioregion.h"
+#include "ardour/crossfade.h"
+#include "ardour/crossfade_compare.h"
+#include "ardour/session.h"
+#include "pbd/enumwriter.h"
 
 #include "i18n.h"
 
@@ -123,7 +123,10 @@ ARDOUR::nframes_t
 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t start,
                     nframes_t cnt, unsigned chan_n)
 {
+       nframes_t ret = cnt;
        nframes_t end;
+       nframes_t read_frames;
+       nframes_t skip_frames;
 
        /* optimizing this memset() away involves a lot of conditionals
           that may well cause more of a hit due to cache misses 
@@ -144,17 +147,27 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nf
           its OK to block (for short intervals).
        */
 
-       Glib::Mutex::Lock rm (region_lock);
+       Glib::RecMutex::Lock rm (region_lock);
 
        end =  start + cnt - 1;
+       read_frames = 0;
+       skip_frames = 0;
+       _read_data_count = 0;
 
        _read_data_count = 0;
 
+       RegionList* rlist = regions_to_read (start, start+cnt);
+
+       if (rlist->empty()) {
+               delete rlist;
+               return cnt;
+       }
+
        map<uint32_t,vector<boost::shared_ptr<Region> > > relevant_regions;
        map<uint32_t,vector<boost::shared_ptr<Crossfade> > > relevant_xfades;
        vector<uint32_t> relevant_layers;
 
-       for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+       for (RegionList::iterator i = rlist->begin(); i != rlist->end(); ++i) {
                if ((*i)->coverage (start, end) != OverlapNone) {
                        relevant_regions[(*i)->layer()].push_back (*i);
                        relevant_layers.push_back ((*i)->layer());
@@ -186,7 +199,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nf
                for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
                        boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
                        assert(ar);
-                       ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
+                       ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
                        _read_data_count += ar->read_data_count();
                }
                
@@ -199,7 +212,8 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nf
                }
        }
 
-       return cnt;
+       delete rlist;
+       return ret;
 }
 
 
@@ -354,7 +368,7 @@ AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
        }
 
 
-       if (!Config->get_auto_xfade()) {
+       if (!_session.config.get_auto_xfade()) {
                return;
        }
 
@@ -436,19 +450,19 @@ AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
                                 *   [---- bottom -------------------] 
                                 */
 
-                               if (Config->get_xfade_model() == FullCrossfade) {
+                               if (_session.config.get_xfade_model() == FullCrossfade) {
                                        touched_regions = regions_touched (top->first_frame(), bottom->last_frame());
                                        if (touched_regions->size() <= 2) {
-                                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
+                                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, _session.config.get_xfade_model(), _session.config.get_xfades_active()));
                                                add_crossfade (xfade);
                                        }
                                } else {
 
                                        touched_regions = regions_touched (top->first_frame(), 
-                                                                          top->first_frame() + min ((nframes_t)Config->get_short_xfade_seconds() * _session.frame_rate(), 
+                                                                          top->first_frame() + min ((nframes_t)_session.config.get_short_xfade_seconds() * _session.frame_rate(), 
                                                                                                     top->length()));
                                        if (touched_regions->size() <= 2) {
-                                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
+                                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, _session.config.get_xfade_model(), _session.config.get_xfades_active()));
                                                add_crossfade (xfade);
                                        }
                                }
@@ -460,28 +474,28 @@ AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
                                 *                { ==== bottom ============ } 
                                 */ 
 
-                               if (Config->get_xfade_model() == FullCrossfade) {
+                               if (_session.config.get_xfade_model() == FullCrossfade) {
 
                                        touched_regions = regions_touched (bottom->first_frame(), top->last_frame());
                                        if (touched_regions->size() <= 2) {
                                                xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, 
-                                                                                                    Config->get_xfade_model(), Config->get_xfades_active()));
+                                                                                                    _session.config.get_xfade_model(), _session.config.get_xfades_active()));
                                                add_crossfade (xfade);
                                        }
 
                                } else {
                                        touched_regions = regions_touched (bottom->first_frame(), 
-                                                                          bottom->first_frame() + min ((nframes_t)Config->get_short_xfade_seconds() * _session.frame_rate(), 
+                                                                          bottom->first_frame() + min ((nframes_t)_session.config.get_short_xfade_seconds() * _session.frame_rate(), 
                                                                                                        bottom->length()));
                                        if (touched_regions->size() <= 2) {
-                                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
+                                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, _session.config.get_xfade_model(), _session.config.get_xfades_active()));
                                                add_crossfade (xfade);
                                        }
                                }
                                break;
                        default:
                                xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, 
-                                                                                    Config->get_xfade_model(), Config->get_xfades_active()));
+                                                                                    _session.config.get_xfade_model(), _session.config.get_xfades_active()));
                                add_crossfade (xfade);
                        }
                }
@@ -662,7 +676,7 @@ AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
                return false;
        }
 
-       { 
+       {
                RegionLock rlock (this);
 
                for (RegionList::iterator i = regions.begin(); i != regions.end(); ) {
@@ -715,7 +729,7 @@ AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
 }
 
 void
-AudioPlaylist::crossfade_changed (Change ignored)
+AudioPlaylist::crossfade_changed (Change)
 {
        if (in_flush || in_set_state) {
                return;
@@ -772,3 +786,11 @@ AudioPlaylist::crossfades_at (nframes_t frame, Crossfades& clist)
        }
 }
 
+void
+AudioPlaylist::foreach_crossfade (sigc::slot<void, boost::shared_ptr<Crossfade> > s)
+{
+       RegionLock rl (this, false);
+       for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
+               s (*i);
+       }
+}