fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / audio_playlist.cc
index 6653e2f655a58befc923e6cb1f9254618bd8c5b3..b00252df7412de461b073557d4bc974462ebde2f 100644 (file)
@@ -28,7 +28,7 @@
 #include "ardour/region_sorters.h"
 #include "ardour/session.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace ARDOUR;
 using namespace std;
@@ -38,7 +38,7 @@ AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden
        : Playlist (session, node, DataType::AUDIO, hidden)
 {
 #ifndef NDEBUG
-       const XMLProperty* prop = node.property("type");
+       XMLProperty const * prop = node.property("type");
        assert(!prop || DataType(prop->value()) == DataType::AUDIO);
 #endif
 
@@ -152,7 +152,7 @@ struct ReadSorter {
 /** A segment of region that needs to be read */
 struct Segment {
        Segment (boost::shared_ptr<AudioRegion> r, Evoral::Range<framepos_t> a) : region (r), range (a) {}
-       
+
        boost::shared_ptr<AudioRegion> region; ///< the region
        Evoral::Range<framepos_t> range;       ///< range of the region to read, in session frames
 };
@@ -164,8 +164,8 @@ ARDOUR::framecnt_t
 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, framepos_t start,
                     framecnt_t cnt, unsigned chan_n)
 {
-       DEBUG_TRACE (DEBUG::AudioPlayback, string_compose ("Playlist %1 read @ %2 for %3, channel %4, regions %5\n",
-                                                          name(), start, cnt, chan_n, regions.size()));
+       DEBUG_TRACE (DEBUG::AudioPlayback, string_compose ("Playlist %1 read @ %2 for %3, channel %4, regions %5 mixdown @ %6 gain @ %7\n",
+                                                          name(), start, cnt, chan_n, regions.size(), mixdown_buffer, gain_buffer));
 
        /* optimizing this memset() away involves a lot of conditionals
           that may well cause more of a hit due to cache misses
@@ -207,6 +207,10 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr
        for (RegionList::iterator i = all->begin(); i != all->end(); ++i) {
                boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (*i);
 
+               /* muted regions don't figure into it at all */
+               if ( ar->muted() )
+                       continue;
+
                /* Work out which bits of this region need to be read;
                   first, trim to the range we are reading...
                */
@@ -252,198 +256,6 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr
        return cnt;
 }
 
-void
-AudioPlaylist::check_crossfades (Evoral::Range<framepos_t> range)
-{
-       if (in_set_state || in_partition || !_session.config.get_auto_xfade ()) {
-               return;
-       }
-
-       boost::shared_ptr<RegionList> starts = regions_with_start_within (range);
-       boost::shared_ptr<RegionList> ends = regions_with_end_within (range);
-
-       RegionList all = *starts;
-       std::copy (ends->begin(), ends->end(), back_inserter (all));
-
-       all.sort (RegionSortByLayer ());
-
-       set<boost::shared_ptr<Region> > done_start;
-       set<boost::shared_ptr<Region> > done_end;
-
-       for (RegionList::reverse_iterator i = all.rbegin(); i != all.rend(); ++i) {
-               for (RegionList::reverse_iterator j = all.rbegin(); j != all.rend(); ++j) {
-
-                       if (i == j) {
-                               continue;
-                       }
-
-                       if ((*i)->muted() || (*j)->muted()) {
-                               continue;
-                       }
-
-                       if ((*i)->position() == (*j)->position() && ((*i)->length() == (*j)->length())) {
-                               /* precise overlay: no xfade */
-                               continue;
-                       }
-
-                       if ((*i)->position() == (*j)->position() || ((*i)->last_frame() == (*j)->last_frame())) {
-                               /* starts or ends match: no xfade */
-                               continue;
-                       }
-                       
-                       boost::shared_ptr<AudioRegion> top;
-                       boost::shared_ptr<AudioRegion> bottom;
-               
-                       if ((*i)->layer() < (*j)->layer()) {
-                               top = boost::dynamic_pointer_cast<AudioRegion> (*j);
-                               bottom = boost::dynamic_pointer_cast<AudioRegion> (*i);
-                       } else {
-                               top = boost::dynamic_pointer_cast<AudioRegion> (*i);
-                               bottom = boost::dynamic_pointer_cast<AudioRegion> (*j);
-                       }
-                       
-                       if (!top->opaque ()) {
-                               continue;
-                       }
-
-                       Evoral::OverlapType const c = top->coverage (bottom->position(), bottom->last_frame());
-
-                       if (c == Evoral::OverlapStart) {
-                               
-                               /* top starts within bottom but covers bottom's end */
-                               
-                               /*                   { ==== top ============ } 
-                                *   [---- bottom -------------------] 
-                                */
-
-                               if (done_start.find (top) == done_start.end() && done_end.find (bottom) == done_end.end ()) {
-
-                                       /* Top's fade-in will cause an implicit fade-out of bottom */
-                                       
-                                       if (top->fade_in_is_xfade() && top->fade_in_is_short()) {
-
-                                               /* its already an xfade. if its
-                                                * really short, leave it
-                                                * alone.
-                                                */
-
-                                       } else {
-                                               framecnt_t len = 0;
-                                               
-                                               if (_capture_insertion_underway) {
-                                                       len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
-                                               } else {
-                                                       switch (_session.config.get_xfade_model()) {
-                                                       case FullCrossfade:
-                                                               len = bottom->last_frame () - top->first_frame ();
-                                                               top->set_fade_in_is_short (false);
-                                                               break;
-                                                       case ShortCrossfade:
-                                                               len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
-                                                               top->set_fade_in_is_short (true);
-                                                               break;
-                                                       }
-                                               }
-
-                                               top->set_fade_in_active (true);
-                                               top->set_fade_in_is_xfade (true);
-                                               
-                                               /* XXX may 2012: -3dB and -6dB curves
-                                                * are the same right now 
-                                                */
-                                               
-                                               switch (_session.config.get_xfade_choice ()) {
-                                               case ConstantPowerMinus3dB:
-                                                       top->set_fade_in (FadeConstantPower, len);
-                                                       break;
-                                               case ConstantPowerMinus6dB:
-                                                       top->set_fade_in (FadeConstantPower, len);
-                                                       break;
-                                               case RegionFades:
-                                                       top->set_fade_in_length (len);
-                                                       break;
-                                               }
-                                       }
-
-                                       done_start.insert (top);
-                               }
-
-                       } else if (c == Evoral::OverlapEnd) {
-                               
-                               /* top covers start of bottom but ends within it */
-                               
-                               /* [---- top ------------------------] 
-                                *                { ==== bottom ============ } 
-                                */
-
-                               if (done_end.find (top) == done_end.end() && done_start.find (bottom) == done_start.end ()) {
-                                       /* Top's fade-out will cause an implicit fade-in of bottom */
-                                       
-                                       
-                                       if (top->fade_out_is_xfade() && top->fade_out_is_short()) {
-
-                                               /* its already an xfade. if its
-                                                * really short, leave it
-                                                * alone.
-                                                */
-
-                                       } else {
-                                               framecnt_t len = 0;
-                                               
-                                               if (_capture_insertion_underway) {
-                                                       len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
-                                               } else {
-                                                       switch (_session.config.get_xfade_model()) {
-                                                       case FullCrossfade:
-                                                               len = top->last_frame () - bottom->first_frame ();
-                                                               break;
-                                                       case ShortCrossfade:
-                                                               len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
-                                                               break;
-                                                       }
-                                               }
-                                               
-                                               top->set_fade_out_active (true);
-                                               top->set_fade_out_is_xfade (true);
-                                               
-                                               switch (_session.config.get_xfade_choice ()) {
-                                               case ConstantPowerMinus3dB:
-                                                       top->set_fade_out (FadeConstantPower, len);
-                                                       break;
-                                               case ConstantPowerMinus6dB:
-                                                       top->set_fade_out (FadeConstantPower, len);
-                                                       break;
-                                               case RegionFades:
-                                                       top->set_fade_out_length (len);
-                                                       break;
-                                               }
-                                       }
-
-                                       done_end.insert (top);
-                               }
-                       }
-               }
-       }
-
-       for (RegionList::iterator i = starts->begin(); i != starts->end(); ++i) {
-               if (done_start.find (*i) == done_start.end()) {
-                       boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (*i);
-                       if (r->fade_in_is_xfade()) {
-                               r->set_default_fade_in ();
-                       }
-               }
-       }
-
-       for (RegionList::iterator i = ends->begin(); i != ends->end(); ++i) {
-               if (done_end.find (*i) == done_end.end()) {
-                       boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (*i);
-                       if (r->fade_out_is_xfade()) {
-                               r->set_default_fade_out ();
-                       }
-               }
-       }
-}
-
 void
 AudioPlaylist::dump () const
 {
@@ -523,6 +335,11 @@ AudioPlaylist::region_changed (const PropertyChange& what_changed, boost::shared
                return false;
        }
 
+       PropertyChange bounds;
+       bounds.add (Properties::start);
+       bounds.add (Properties::position);
+       bounds.add (Properties::length);
+
        PropertyChange our_interests;
 
        our_interests.add (Properties::fade_in_active);
@@ -536,8 +353,8 @@ AudioPlaylist::region_changed (const PropertyChange& what_changed, boost::shared
        bool parent_wants_notify;
 
        parent_wants_notify = Playlist::region_changed (what_changed, region);
-
-       if (parent_wants_notify || (what_changed.contains (our_interests))) {
+       /* if bounds changed, we have already done notify_contents_changed ()*/
+       if ((parent_wants_notify || what_changed.contains (our_interests)) && !what_changed.contains (bounds)) {
                notify_contents_changed ();
        }
 
@@ -675,13 +492,13 @@ AudioPlaylist::load_legacy_crossfades (const XMLNode& node, int version)
        for (XMLNodeConstIterator i = children.begin(); i != children.end(); ++i) {
                if ((*i)->name() == X_("Crossfade")) {
 
-                       XMLProperty* p = (*i)->property (X_("active"));
+                       XMLProperty const * p = (*i)->property (X_("active"));
                        assert (p);
 
                        if (!string_is_affirmative (p->value())) {
                                continue;
                        }
-                       
+
                        if ((p = (*i)->property (X_("in"))) == 0) {
                                continue;
                        }
@@ -690,7 +507,7 @@ AudioPlaylist::load_legacy_crossfades (const XMLNode& node, int version)
 
                        if (!in) {
                                warning << string_compose (_("Legacy crossfade involved an incoming region not present in playlist \"%1\" - crossfade discarded"),
-                                                          name()) 
+                                                          name())
                                        << endmsg;
                                continue;
                        }
@@ -706,7 +523,7 @@ AudioPlaylist::load_legacy_crossfades (const XMLNode& node, int version)
 
                        if (!out) {
                                warning << string_compose (_("Legacy crossfade involved an outgoing region not present in playlist \"%1\" - crossfade discarded"),
-                                                          name()) 
+                                                          name())
                                        << endmsg;
                                continue;
                        }
@@ -721,11 +538,11 @@ AudioPlaylist::load_legacy_crossfades (const XMLNode& node, int version)
                        if (in->layer() <= out->layer()) {
 
                                /* incoming region is below the outgoing one,
-                                * so apply a fade out to the outgoing one 
+                                * so apply a fade out to the outgoing one
                                 */
 
                                const XMLNodeList c = (*i)->children ();
-                               
+
                                for (XMLNodeConstIterator j = c.begin(); j != c.end(); ++j) {
                                        if ((*j)->name() == X_("FadeOut")) {
                                                out_a->fade_out()->set_state (**j, version);
@@ -733,14 +550,7 @@ AudioPlaylist::load_legacy_crossfades (const XMLNode& node, int version)
                                                out_a->inverse_fade_out()->set_state (**j, version);
                                        }
                                }
-                               
-                               if ((p = (*i)->property ("follow-overlap")) != 0) {
-                                       out_a->set_fade_out_is_short (!string_is_affirmative (p->value()));
-                               } else {
-                                       out_a->set_fade_out_is_short (false);
-                               }
-                               
-                               out_a->set_fade_out_is_xfade (true);
+
                                out_a->set_fade_out_active (true);
 
                        } else {
@@ -750,7 +560,7 @@ AudioPlaylist::load_legacy_crossfades (const XMLNode& node, int version)
                                 */
 
                                const XMLNodeList c = (*i)->children ();
-                               
+
                                for (XMLNodeConstIterator j = c.begin(); j != c.end(); ++j) {
                                        if ((*j)->name() == X_("FadeIn")) {
                                                in_a->fade_in()->set_state (**j, version);
@@ -758,14 +568,7 @@ AudioPlaylist::load_legacy_crossfades (const XMLNode& node, int version)
                                                in_a->inverse_fade_in()->set_state (**j, version);
                                        }
                                }
-                               
-                               if ((p = (*i)->property ("follow-overlap")) != 0) {
-                                       in_a->set_fade_in_is_short (!string_is_affirmative (p->value()));
-                               } else {
-                                       in_a->set_fade_in_is_short (false);
-                               }
-                               
-                               in_a->set_fade_in_is_xfade (true);
+
                                in_a->set_fade_in_active (true);
                        }
                }