rethink how to load legacy crossfades as new-style xfades
[ardour.git] / libs / ardour / audio_playlist.cc
index 9b433d160bcfdb787faedc3ca4895e8f5d47d9d8..0054b6a1777c5430ce43f5b8fcc4d41d6fef4ef0 100644 (file)
 
 #include "ardour/types.h"
 #include "ardour/debug.h"
-#include "ardour/configuration.h"
 #include "ardour/audioplaylist.h"
 #include "ardour/audioregion.h"
 #include "ardour/region_sorters.h"
 #include "ardour/session.h"
-#include "pbd/enumwriter.h"
 
 #include "i18n.h"
 
@@ -66,7 +64,7 @@ AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, stri
 AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, framepos_t start, framecnt_t cnt, string name, bool hidden)
        : Playlist (other, start, cnt, name, hidden)
 {
-       RegionLock rlock2 (const_cast<AudioPlaylist*> (other.get()));
+       RegionReadLock rlock2 (const_cast<AudioPlaylist*> (other.get()));
        in_set_state++;
 
        framepos_t const end = start + cnt - 1;
@@ -186,7 +184,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr
           its OK to block (for short intervals).
        */
 
-       Playlist::RegionLock rl (this, false);
+       Playlist::RegionReadLock rl (this);
 
        /* Find all the regions that are involved in the bit we are reading,
           and sort them by descending layer and ascending position.
@@ -315,35 +313,51 @@ AudioPlaylist::check_crossfades (Evoral::Range<framepos_t> range)
 
                                        /* Top's fade-in will cause an implicit fade-out of bottom */
                                        
-                                       framecnt_t len = 0;
-                                       switch (_session.config.get_xfade_model()) {
-                                       case FullCrossfade:
-                                               len = bottom->last_frame () - top->first_frame ();
-                                               break;
-                                       case ShortCrossfade:
-                                               len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
-                                               break;
+                                       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;
+                                               }
                                        }
-                                       
-                                       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);
                                }
 
@@ -358,29 +372,44 @@ AudioPlaylist::check_crossfades (Evoral::Range<framepos_t> range)
                                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 */
                                        
-                                       framecnt_t len = 0;
-                                       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;
+                                       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);
@@ -392,14 +421,18 @@ AudioPlaylist::check_crossfades (Evoral::Range<framepos_t> range)
        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);
-                       r->set_default_fade_in ();
+                       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);
-                       r->set_default_fade_out ();
+                       if (r->fade_out_is_xfade()) {
+                               r->set_default_fade_out ();
+                       }
                }
        }
 }
@@ -437,7 +470,7 @@ AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
        bool changed = false;
 
        {
-               RegionLock rlock (this);
+               RegionWriteLock rlock (this);
 
                for (RegionList::iterator i = regions.begin(); i != regions.end(); ) {
 
@@ -636,34 +669,46 @@ AudioPlaylist::set_state (const XMLNode& node, int version)
 
                        XMLProperty* p = (*i)->property (X_("active"));
                        assert (p);
+
                        if (!string_is_affirmative (p->value())) {
                                continue;
                        }
+                       
+                       if ((p = (*i)->property (X_("in"))) == 0) {
+                               continue;
+                       }
 
-                       p = (*i)->property (X_("in"));
-                       assert (p);
                        boost::shared_ptr<Region> in = region_by_id (PBD::ID (p->value ()));
-                       assert (in);
+
+                       if (!in) {
+                               warning << string_compose (_("Legacy crossfade involved an incoming region not present in playlist \"%1\" - crossfade discarded"),
+                                                          name()) 
+                                       << endmsg;
+                               continue;
+                       }
+
                        boost::shared_ptr<AudioRegion> in_a = boost::dynamic_pointer_cast<AudioRegion> (in);
                        assert (in_a);
+                       
+                       const XMLNodeList c = (*i)->children ();
 
-                       p = (*i)->property (X_("out"));
-                       assert (p);
-                       boost::shared_ptr<Region> out = region_by_id (PBD::ID (p->value ()));
-                       assert (out);
-                       boost::shared_ptr<AudioRegion> out_a = boost::dynamic_pointer_cast<AudioRegion> (out);
-                       assert (out_a);
-
-                       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);
-                                       in_a->set_fade_in_active (true);
                                } else if ((*j)->name() == X_("FadeOut")) {
-                                       out_a->fade_out()->set_state (**j, version);
-                                       out_a->set_fade_out_active (true);
+                                       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);
+                       cerr << in_a->name() << " from playlist fade in  = xfade false\n";
                }
        }