always check_dependents() after a relayer() (useful for LaterHigher model), don't...
[ardour.git] / libs / ardour / audioregion.cc
index d2cf279d3ec677ebba3111b513721542803fd781..1be0f6612536f1df6b4190aeccdd6c7fd768f0c8 100644 (file)
@@ -80,7 +80,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, n
        set_default_fades ();
        set_default_envelope ();
 
-       _envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
+       listen_to_my_curves ();
 }
 
 AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
@@ -105,7 +105,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, n
        set_default_fades ();
        set_default_envelope ();
 
-       _envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
+       listen_to_my_curves ();
 }
 
 AudioRegion::AudioRegion (SourceList& srcs, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
@@ -132,7 +132,7 @@ AudioRegion::AudioRegion (SourceList& srcs, nframes_t start, nframes_t length, c
        set_default_fades ();
        set_default_envelope ();
 
-       _envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
+       listen_to_my_curves ();
 }
 
 
@@ -196,7 +196,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t
 
        _scale_amplitude = other->_scale_amplitude;
 
-       _envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
+       listen_to_my_curves ();
 }
 
 AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
@@ -237,7 +237,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
        _fade_in_disabled = 0;
        _fade_out_disabled = 0;
        
-       _envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
+       listen_to_my_curves ();
 }
 
 AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& node)
@@ -261,7 +261,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& nod
                throw failed_constructor();
        }
 
-       _envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
+       listen_to_my_curves ();
 }
 
 AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
@@ -301,19 +301,35 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
                throw failed_constructor();
        }
 
-       _envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
+       listen_to_my_curves ();
 }
 
 AudioRegion::~AudioRegion ()
 {
+       if (_playlist) {
+               for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) {
+                       (*i)->remove_playlist (_playlist);
+               }
+       }
+
        notify_callbacks ();
        GoingAway (); /* EMIT SIGNAL */
 }
 
+void
+AudioRegion::listen_to_my_curves ()
+{
+       _envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
+       _fade_in.StateChanged.connect (mem_fun (*this, &AudioRegion::fade_in_changed));
+       _fade_out.StateChanged.connect (mem_fun (*this, &AudioRegion::fade_out_changed));
+}
+
 bool
 AudioRegion::verify_length (nframes_t len)
 {
-       if (boost::dynamic_pointer_cast<DestructiveFileSource>(source())) {
+       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(source());
+
+       if (afs && afs->destructive()) {
                return true;
        }
 
@@ -328,7 +344,9 @@ AudioRegion::verify_length (nframes_t len)
 bool
 AudioRegion::verify_start_and_length (nframes_t new_start, nframes_t new_length)
 {
-       if (boost::dynamic_pointer_cast<DestructiveFileSource>(source())) {
+       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(source());
+
+       if (afs && afs->destructive()) {
                return true;
        }
 
@@ -342,7 +360,9 @@ AudioRegion::verify_start_and_length (nframes_t new_start, nframes_t new_length)
 bool
 AudioRegion::verify_start (nframes_t pos)
 {
-       if (boost::dynamic_pointer_cast<DestructiveFileSource>(source())) {
+       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(source());
+
+       if (afs && afs->destructive()) {
                return true;
        }
 
@@ -357,7 +377,9 @@ AudioRegion::verify_start (nframes_t pos)
 bool
 AudioRegion::verify_start_mutable (nframes_t& new_start)
 {
-       if (boost::dynamic_pointer_cast<DestructiveFileSource>(source())) {
+       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(source());
+
+       if (afs && afs->destructive()) {
                return true;
        }
 
@@ -390,7 +412,7 @@ AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nfra
        if (chan_n >= sources.size()) {
                return 0; 
        }
-       
+
        if (sources[chan_n]->read_peaks (buf, npeaks, offset, cnt, samples_per_unit)) {
                return 0;
        } else {
@@ -598,7 +620,7 @@ AudioRegion::state (bool full)
                if ((_flags & DefaultFadeIn)) {
                        child->add_property (X_("default"), X_("yes"));
                } else {
-                       _fade_in.store_state (*child);
+                       child->add_child_nocopy (_fade_in.get_state ());
                }
 
                child->add_property (X_("active"), _fade_in_disabled ? X_("no") : X_("yes"));
@@ -608,9 +630,9 @@ AudioRegion::state (bool full)
                if ((_flags & DefaultFadeOut)) {
                        child->add_property (X_("default"), X_("yes"));
                } else {
-                       _fade_out.store_state (*child);
+                       child->add_child_nocopy (_fade_out.get_state ());
                }
-
+               
                child->add_property (X_("active"), _fade_out_disabled ? X_("no") : X_("yes"));
        }
        
@@ -621,6 +643,7 @@ AudioRegion::state (bool full)
                
                // If there are only two points, the points are in the start of the region and the end of the region
                // so, if they are both at 1.0f, that means the default region.
+
                if (_envelope.size() == 2 &&
                    _envelope.front()->value == 1.0f &&
                    _envelope.back()->value==1.0f) {
@@ -632,7 +655,7 @@ AudioRegion::state (bool full)
                if (default_env) {
                        child->add_property ("default", "yes");
                } else {
-                       _envelope.store_state (*child);
+                       child->add_child_nocopy (_envelope.get_state ());
                }
 
        } else {
@@ -693,34 +716,28 @@ AudioRegion::set_live_state (const XMLNode& node, Change& what_changed, bool sen
                        
                        _envelope.clear ();
 
-                       if ((prop = child->property ("default")) != 0) {
+                       if ((prop = child->property ("default")) != 0 || _envelope.set_state (*child)) {
                                set_default_envelope ();
-                       } else {
-                               _envelope.load_state (*child);
                        }
 
                        _envelope.set_max_xval (_length);
                        _envelope.truncate_end (_length);
-                       
+
                } else if (child->name() == "FadeIn") {
                        
                        _fade_in.clear ();
                        
-                       if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
+                       if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0 || _fade_in.set_state (*child)) {
                                set_default_fade_in ();
-                       } else {
-                               _fade_in.load_state (*child);
-                       }
+                       } 
 
                } else if (child->name() == "FadeOut") {
                        
                        _fade_out.clear ();
 
-                       if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
+                       if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0 || _fade_out.set_state (*child)) {
                                set_default_fade_out ();
-                       } else {
-                               _fade_out.load_state (*child);
-                       }
+                       } 
                } 
        }
 
@@ -762,49 +779,49 @@ AudioRegion::set_fade_in (FadeShape shape, nframes_t len)
 
        switch (shape) {
        case Linear:
-               _fade_in.add (0.0, 0.0);
-               _fade_in.add (len, 1.0);
+               _fade_in.fast_simple_add (0.0, 0.0);
+               _fade_in.fast_simple_add (len, 1.0);
                break;
 
        case Fast:
-               _fade_in.add (0, 0);
-               _fade_in.add (len * 0.389401, 0.0333333);
-               _fade_in.add (len * 0.629032, 0.0861111);
-               _fade_in.add (len * 0.829493, 0.233333);
-               _fade_in.add (len * 0.9447, 0.483333);
-               _fade_in.add (len * 0.976959, 0.697222);
-               _fade_in.add (len, 1);
+               _fade_in.fast_simple_add (0, 0);
+               _fade_in.fast_simple_add (len * 0.389401, 0.0333333);
+               _fade_in.fast_simple_add (len * 0.629032, 0.0861111);
+               _fade_in.fast_simple_add (len * 0.829493, 0.233333);
+               _fade_in.fast_simple_add (len * 0.9447, 0.483333);
+               _fade_in.fast_simple_add (len * 0.976959, 0.697222);
+               _fade_in.fast_simple_add (len, 1);
                break;
 
        case Slow:
-               _fade_in.add (0, 0);
-               _fade_in.add (len * 0.0207373, 0.197222);
-               _fade_in.add (len * 0.0645161, 0.525);
-               _fade_in.add (len * 0.152074, 0.802778);
-               _fade_in.add (len * 0.276498, 0.919444);
-               _fade_in.add (len * 0.481567, 0.980556);
-               _fade_in.add (len * 0.767281, 1);
-               _fade_in.add (len, 1);
+               _fade_in.fast_simple_add (0, 0);
+               _fade_in.fast_simple_add (len * 0.0207373, 0.197222);
+               _fade_in.fast_simple_add (len * 0.0645161, 0.525);
+               _fade_in.fast_simple_add (len * 0.152074, 0.802778);
+               _fade_in.fast_simple_add (len * 0.276498, 0.919444);
+               _fade_in.fast_simple_add (len * 0.481567, 0.980556);
+               _fade_in.fast_simple_add (len * 0.767281, 1);
+               _fade_in.fast_simple_add (len, 1);
                break;
 
        case LogA:
-               _fade_in.add (0, 0);
-               _fade_in.add (len * 0.0737327, 0.308333);
-               _fade_in.add (len * 0.246544, 0.658333);
-               _fade_in.add (len * 0.470046, 0.886111);
-               _fade_in.add (len * 0.652074, 0.972222);
-               _fade_in.add (len * 0.771889, 0.988889);
-               _fade_in.add (len, 1);
+               _fade_in.fast_simple_add (0, 0);
+               _fade_in.fast_simple_add (len * 0.0737327, 0.308333);
+               _fade_in.fast_simple_add (len * 0.246544, 0.658333);
+               _fade_in.fast_simple_add (len * 0.470046, 0.886111);
+               _fade_in.fast_simple_add (len * 0.652074, 0.972222);
+               _fade_in.fast_simple_add (len * 0.771889, 0.988889);
+               _fade_in.fast_simple_add (len, 1);
                break;
 
        case LogB:
-               _fade_in.add (0, 0);
-               _fade_in.add (len * 0.304147, 0.0694444);
-               _fade_in.add (len * 0.529954, 0.152778);
-               _fade_in.add (len * 0.725806, 0.333333);
-               _fade_in.add (len * 0.847926, 0.558333);
-               _fade_in.add (len * 0.919355, 0.730556);
-               _fade_in.add (len, 1);
+               _fade_in.fast_simple_add (0, 0);
+               _fade_in.fast_simple_add (len * 0.304147, 0.0694444);
+               _fade_in.fast_simple_add (len * 0.529954, 0.152778);
+               _fade_in.fast_simple_add (len * 0.725806, 0.333333);
+               _fade_in.fast_simple_add (len * 0.847926, 0.558333);
+               _fade_in.fast_simple_add (len * 0.919355, 0.730556);
+               _fade_in.fast_simple_add (len, 1);
                break;
        }
 
@@ -822,47 +839,47 @@ AudioRegion::set_fade_out (FadeShape shape, nframes_t len)
 
        switch (shape) {
        case Fast:
-               _fade_out.add (len * 0, 1);
-               _fade_out.add (len * 0.023041, 0.697222);
-               _fade_out.add (len * 0.0553,   0.483333);
-               _fade_out.add (len * 0.170507, 0.233333);
-               _fade_out.add (len * 0.370968, 0.0861111);
-               _fade_out.add (len * 0.610599, 0.0333333);
-               _fade_out.add (len * 1, 0);
+               _fade_out.fast_simple_add (len * 0, 1);
+               _fade_out.fast_simple_add (len * 0.023041, 0.697222);
+               _fade_out.fast_simple_add (len * 0.0553,   0.483333);
+               _fade_out.fast_simple_add (len * 0.170507, 0.233333);
+               _fade_out.fast_simple_add (len * 0.370968, 0.0861111);
+               _fade_out.fast_simple_add (len * 0.610599, 0.0333333);
+               _fade_out.fast_simple_add (len * 1, 0);
                break;
 
        case LogA:
-               _fade_out.add (len * 0, 1);
-               _fade_out.add (len * 0.228111, 0.988889);
-               _fade_out.add (len * 0.347926, 0.972222);
-               _fade_out.add (len * 0.529954, 0.886111);
-               _fade_out.add (len * 0.753456, 0.658333);
-               _fade_out.add (len * 0.9262673, 0.308333);
-               _fade_out.add (len * 1, 0);
+               _fade_out.fast_simple_add (len * 0, 1);
+               _fade_out.fast_simple_add (len * 0.228111, 0.988889);
+               _fade_out.fast_simple_add (len * 0.347926, 0.972222);
+               _fade_out.fast_simple_add (len * 0.529954, 0.886111);
+               _fade_out.fast_simple_add (len * 0.753456, 0.658333);
+               _fade_out.fast_simple_add (len * 0.9262673, 0.308333);
+               _fade_out.fast_simple_add (len * 1, 0);
                break;
 
        case Slow:
-               _fade_out.add (len * 0, 1);
-               _fade_out.add (len * 0.305556, 1);
-               _fade_out.add (len * 0.548611, 0.991736);
-               _fade_out.add (len * 0.759259, 0.931129);
-               _fade_out.add (len * 0.918981, 0.68595);
-               _fade_out.add (len * 0.976852, 0.22865);
-               _fade_out.add (len * 1, 0);
+               _fade_out.fast_simple_add (len * 0, 1);
+               _fade_out.fast_simple_add (len * 0.305556, 1);
+               _fade_out.fast_simple_add (len * 0.548611, 0.991736);
+               _fade_out.fast_simple_add (len * 0.759259, 0.931129);
+               _fade_out.fast_simple_add (len * 0.918981, 0.68595);
+               _fade_out.fast_simple_add (len * 0.976852, 0.22865);
+               _fade_out.fast_simple_add (len * 1, 0);
                break;
 
        case LogB:
-               _fade_out.add (len * 0, 1);
-               _fade_out.add (len * 0.080645, 0.730556);
-               _fade_out.add (len * 0.277778, 0.289256);
-               _fade_out.add (len * 0.470046, 0.152778);
-               _fade_out.add (len * 0.695853, 0.0694444);
-               _fade_out.add (len * 1, 0);
+               _fade_out.fast_simple_add (len * 0, 1);
+               _fade_out.fast_simple_add (len * 0.080645, 0.730556);
+               _fade_out.fast_simple_add (len * 0.277778, 0.289256);
+               _fade_out.fast_simple_add (len * 0.470046, 0.152778);
+               _fade_out.fast_simple_add (len * 0.695853, 0.0694444);
+               _fade_out.fast_simple_add (len * 1, 0);
                break;
 
        case Linear:
-               _fade_out.add (len * 0, 1);
-               _fade_out.add (len * 1, 0);
+               _fade_out.fast_simple_add (len * 0, 1);
+               _fade_out.fast_simple_add (len * 1, 0);
                break;
        }
 
@@ -951,8 +968,8 @@ AudioRegion::set_default_envelope ()
 {
        _envelope.freeze ();
        _envelope.clear ();
-       _envelope.add (0, 1.0f);
-       _envelope.add (_length, 1.0f);
+       _envelope.fast_simple_add (0, 1.0f);
+       _envelope.fast_simple_add (_length, 1.0f);
        _envelope.thaw ();
 }
 
@@ -1140,20 +1157,18 @@ AudioRegion::exportme (Session& session, AudioExportSpecification& spec)
 }
 
 boost::shared_ptr<Region>
-AudioRegion::get_parent()
+AudioRegion::get_parent() const
 {
-       boost::shared_ptr<Region> r;
-
        if (_playlist) {
                boost::shared_ptr<AudioRegion> ar;
-               boost::shared_ptr<AudioRegion> grrr2 = boost::dynamic_pointer_cast<AudioRegion> (shared_from_this());
+               boost::shared_ptr<AudioRegion const> grrr2 = boost::dynamic_pointer_cast<AudioRegion const> (shared_from_this());
                
                if (grrr2 && (ar = _playlist->session().find_whole_file_parent (grrr2))) {
                        return boost::static_pointer_cast<Region> (ar);
                }
        }
        
-       return r;
+       return boost::shared_ptr<Region>();
 }
 
 void
@@ -1241,7 +1256,19 @@ AudioRegion::normalize_to (float target_dB)
 }
 
 void
-AudioRegion::envelope_changed (Change ignored)
+AudioRegion::fade_in_changed ()
+{
+       send_change (FadeInChanged);
+}
+
+void
+AudioRegion::fade_out_changed ()
+{
+       send_change (FadeOutChanged);
+}
+
+void
+AudioRegion::envelope_changed ()
 {
        send_change (EnvelopeChanged);
 }
@@ -1294,12 +1321,45 @@ AudioRegion::speed_mismatch (float sr) const
 void
 AudioRegion::source_offset_changed ()
 {
-       if (boost::dynamic_pointer_cast<DestructiveFileSource>(sources.front())) {
-               set_start (source()->natural_position(), this);
+       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(sources.front());
+
+       if (afs && afs->destructive()) {
+               // set_start (source()->natural_position(), this);
                set_position (source()->natural_position(), this);
        } 
 }
 
+void
+AudioRegion::set_playlist (Playlist* pl)
+{
+       if (pl == _playlist) {
+               return;
+       }
+
+       Playlist* old_playlist = _playlist;
+
+       Region::set_playlist (pl);
+
+       if (pl) {
+               if (old_playlist) {
+                       for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) {
+                               (*i)->remove_playlist (old_playlist);   
+                               (*i)->add_playlist (_playlist);
+                       }
+               } else {
+                       for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) {
+                               (*i)->add_playlist (_playlist);
+                       }
+               }
+       } else {
+               if (old_playlist) {
+                       for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) {
+                               (*i)->remove_playlist (old_playlist);
+                       }
+               }
+       }
+}
+
 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)