X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudio_playlist.cc;h=d28d88488ed651b853eb7b8d231142ec127a2f32;hb=2177f008411821e7bce9ca3c306ec64c70b1c58e;hp=5118aab68423b4707af9a0a2bb409ec55769b294;hpb=0c4c6e031a3624cfc74c2eef6e79527b7c49eca8;p=ardour.git diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index 5118aab684..d28d88488e 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -15,7 +15,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id$ */ #include @@ -31,6 +30,7 @@ #include #include #include +#include #include "i18n.h" @@ -40,52 +40,47 @@ using namespace std; using namespace PBD; AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden) - : Playlist (session, node, hidden) + : Playlist (session, node, DataType::AUDIO, hidden) { + const XMLProperty* prop = node.property("type"); + assert(!prop || DataType(prop->value()) == DataType::AUDIO); + in_set_state++; set_state (node); in_set_state--; - - if (!hidden) { - PlaylistCreated (this); /* EMIT SIGNAL */ - } } AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden) - : Playlist (session, name, hidden) + : Playlist (session, name, DataType::AUDIO, hidden) { - if (!hidden) { - PlaylistCreated (this); /* EMIT SIGNAL */ - } - } -AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, string name, bool hidden) +AudioPlaylist::AudioPlaylist (boost::shared_ptr other, string name, bool hidden) : Playlist (other, name, hidden) { - RegionList::const_iterator in_o = other.regions.begin(); + RegionList::const_iterator in_o = other->regions.begin(); RegionList::iterator in_n = regions.begin(); - while (in_o != other.regions.end()) { + while (in_o != other->regions.end()) { boost::shared_ptr ar = boost::dynamic_pointer_cast(*in_o); // We look only for crossfades which begin with the current region, so we don't get doubles - for (list::const_iterator xfades = other._crossfades.begin(); xfades != other._crossfades.end(); ++xfades) { + for (Crossfades::const_iterator xfades = other->_crossfades.begin(); xfades != other->_crossfades.end(); ++xfades) { if ((*xfades)->in() == ar) { // We found one! Now copy it! - RegionList::const_iterator out_o = other.regions.begin(); + RegionList::const_iterator out_o = other->regions.begin(); RegionList::const_iterator out_n = regions.begin(); - while (out_o != other.regions.end()) { + while (out_o != other->regions.end()) { boost::shared_ptrar2 = boost::dynamic_pointer_cast(*out_o); if ((*xfades)->out() == ar2) { boost::shared_ptrin = boost::dynamic_pointer_cast(*in_n); boost::shared_ptrout = boost::dynamic_pointer_cast(*out_n); - Crossfade *new_fade = new Crossfade (*(*xfades), in, out); - add_crossfade(*new_fade); + boost::shared_ptr new_fade = boost::shared_ptr (new Crossfade (*xfades, in, out)); + add_crossfade(new_fade); break; } @@ -99,13 +94,9 @@ AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, string name, bool hidd in_o++; in_n++; } - - if (!hidden) { - PlaylistCreated (this); /* EMIT SIGNAL */ - } } -AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, nframes_t start, nframes_t cnt, string name, bool hidden) +AudioPlaylist::AudioPlaylist (boost::shared_ptr other, nframes_t start, nframes_t cnt, string name, bool hidden) : Playlist (other, start, cnt, name, hidden) { /* this constructor does NOT notify others (session) */ @@ -113,40 +104,26 @@ AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, nframes_t start, nfram AudioPlaylist::~AudioPlaylist () { - set all_xfades; - GoingAway (); /* EMIT SIGNAL */ /* drop connections to signals */ notify_callbacks (); - - for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ) { - Crossfades::iterator tmp; - - tmp = x; - ++tmp; - - delete *x; - - x = tmp; - } + + _crossfades.clear (); } struct RegionSortByLayer { - bool operator() (boost::shared_ptra, boost::shared_ptrb) { + bool operator() (boost::shared_ptr a, boost::shared_ptr b) { return a->layer() < b->layer(); } }; -nframes_t +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 @@ -171,12 +148,10 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nf end = start + cnt - 1; - read_frames = 0; - skip_frames = 0; _read_data_count = 0; map > > relevant_regions; - map > relevant_xfades; + map > > relevant_xfades; vector relevant_layers; for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { @@ -206,16 +181,16 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nf for (vector::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) { vector > r (relevant_regions[*l]); - vector& x (relevant_xfades[*l]); + vector >& x (relevant_xfades[*l]); for (vector >::iterator i = r.begin(); i != r.end(); ++i) { boost::shared_ptr ar = boost::dynamic_pointer_cast(*i); assert(ar); - ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames); + ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n); _read_data_count += ar->read_data_count(); } - for (vector::iterator i = x.begin(); i != x.end(); ++i) { + for (vector >::iterator i = x.begin(); i != x.end(); ++i) { (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n); /* don't JACK up _read_data_count, since its the same data as we just @@ -224,14 +199,13 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nf } } - return ret; + return cnt; } void AudioPlaylist::remove_dependents (boost::shared_ptr region) { - Crossfades::iterator i, tmp; boost::shared_ptr r = boost::dynamic_pointer_cast (region); if (in_set_state) { @@ -244,16 +218,13 @@ AudioPlaylist::remove_dependents (boost::shared_ptr region) return; } - for (i = _crossfades.begin(); i != _crossfades.end(); ) { - tmp = i; - tmp++; - + for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ) { if ((*i)->involves (r)) { - delete *i; + i = _crossfades.erase (i); + } else { + ++i; } - - i = tmp; } } @@ -283,7 +254,7 @@ void AudioPlaylist::refresh_dependents (boost::shared_ptr r) { boost::shared_ptr ar = boost::dynamic_pointer_cast(r); - set updated; + set > updated; if (ar == 0) { return; @@ -301,9 +272,14 @@ AudioPlaylist::refresh_dependents (boost::shared_ptr r) if ((*x)->involves (ar)) { if (find (updated.begin(), updated.end(), *x) == updated.end()) { - if ((*x)->refresh ()) { - /* not invalidated by the refresh */ - updated.insert (*x); + try { + if ((*x)->refresh ()) { + updated.insert (*x); + } + } + + catch (Crossfade::NoCrossfadeHere& err) { + // relax, Invalidated during refresh } } } @@ -324,29 +300,29 @@ AudioPlaylist::finalize_split_region (boost::shared_ptr o, boost::shared tmp = x; ++tmp; - Crossfade *fade = 0; + boost::shared_ptr fade; if ((*x)->_in == orig) { if (! (*x)->covers(right->position())) { - fade = new Crossfade (**x, left, (*x)->_out); + fade = boost::shared_ptr (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); + fade = boost::shared_ptr (new Crossfade (*x, right, (*x)->_out)); } } if ((*x)->_out == orig) { if (! (*x)->covers(right->position())) { - fade = new Crossfade (**x, (*x)->_in, right); + fade = boost::shared_ptr (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); + fade = boost::shared_ptr (new Crossfade (*x, (*x)->_in, left)); } } if (fade) { _crossfades.remove (*x); - add_crossfade (*fade); + add_crossfade (fade); } x = tmp; } @@ -359,7 +335,7 @@ AudioPlaylist::check_dependents (boost::shared_ptr r, bool norefresh) boost::shared_ptr region; boost::shared_ptr top; boost::shared_ptr bottom; - Crossfade* xfade; + boost::shared_ptr xfade; if (in_set_state || in_partition) { return; @@ -375,12 +351,15 @@ AudioPlaylist::check_dependents (boost::shared_ptr r, bool norefresh) refresh_dependents (r); } + if (!Config->get_auto_xfade()) { return; } for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + nframes_t xfade_length; + other = boost::dynamic_pointer_cast (*i); if (other == region) { @@ -390,6 +369,7 @@ AudioPlaylist::check_dependents (boost::shared_ptr r, bool norefresh) if (other->muted() || region->muted()) { continue; } + if (other->layer() < region->layer()) { top = region; @@ -399,43 +379,56 @@ AudioPlaylist::check_dependents (boost::shared_ptr r, bool norefresh) bottom = region; } + + + OverlapType c = top->coverage (bottom->position(), bottom->last_frame()); + try { + switch (c) { + case OverlapNone: + break; + + case OverlapInternal: + /* {=============== top =============} + * [ ----- bottom ------- ] + */ + break; + + case OverlapExternal: + + /* [ -------- top ------- ] + * {=========== bottom =============} + */ - if (top->coverage (bottom->position(), bottom->last_frame()) != OverlapNone) { + /* to avoid discontinuities at the region boundaries of an internal + overlap (this region is completely within another), we create + two hidden crossfades at each boundary. this is not dependent + on the auto-xfade option, because we require it as basic + audio engineering. + */ - /* check if the upper region is within the lower region */ + xfade_length = min ((nframes_t) 720, top->length()); - if (top->first_frame() > bottom->first_frame() && - top->last_frame() < bottom->last_frame()) { - - - /* [ -------- top ------- ] - * {=========== bottom =============} - */ - - /* to avoid discontinuities at the region boundaries of an internal - overlap (this region is completely within another), we create - two hidden crossfades at each boundary. this is not dependent - on the auto-xfade option, because we require it as basic - audio engineering. + xfade = boost::shared_ptr (new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn)); + add_crossfade (xfade); + + if (top_region_at (top->last_frame() - 1) == top) { + /* + only add a fade out if there is no region on top of the end of 'top' (which + would cover it). */ - nframes_t xfade_length = min ((nframes_t) 720, top->length()); - - /* in, out */ - xfade = new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn); - add_crossfade (*xfade); - xfade = new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut); - add_crossfade (*xfade); - - } else { - - xfade = new Crossfade (other, region, Config->get_xfade_model(), Config->get_xfades_active()); - add_crossfade (*xfade); + xfade = boost::shared_ptr (new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut)); + add_crossfade (xfade); } - } + break; + + default: + xfade = boost::shared_ptr (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active())); + add_crossfade (xfade); + } } - + catch (failed_constructor& err) { continue; } @@ -448,29 +441,29 @@ AudioPlaylist::check_dependents (boost::shared_ptr r, bool norefresh) } void -AudioPlaylist::add_crossfade (Crossfade& xfade) +AudioPlaylist::add_crossfade (boost::shared_ptr xfade) { Crossfades::iterator ci; for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) { - if (*(*ci) == xfade) { // Crossfade::operator==() + if (*(*ci) == *xfade) { // Crossfade::operator==() break; } } if (ci != _crossfades.end()) { - delete &xfade; + // it will just go away } else { - _crossfades.push_back (&xfade); + _crossfades.push_back (xfade); - xfade.Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated)); - xfade.StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed)); + xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated)); + xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed)); - notify_crossfade_added (&xfade); + notify_crossfade_added (xfade); } } -void AudioPlaylist::notify_crossfade_added (Crossfade *x) +void AudioPlaylist::notify_crossfade_added (boost::shared_ptr x) { if (g_atomic_int_get(&block_notifications)) { _pending_xfade_adds.insert (_pending_xfade_adds.end(), x); @@ -480,9 +473,10 @@ void AudioPlaylist::notify_crossfade_added (Crossfade *x) } void -AudioPlaylist::crossfade_invalidated (Crossfade* xfade) +AudioPlaylist::crossfade_invalidated (boost::shared_ptr r) { Crossfades::iterator i; + boost::shared_ptr xfade = boost::dynamic_pointer_cast (r); xfade->in()->resume_fade_in (); xfade->out()->resume_fade_out (); @@ -515,7 +509,7 @@ AudioPlaylist::set_state (const XMLNode& node) } try { - Crossfade* xfade = new Crossfade (*((const Playlist *)this), *child); + boost::shared_ptr xfade = boost::shared_ptr (new Crossfade (*((const Playlist *)this), *child)); _crossfades.push_back (xfade); xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated)); xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed)); @@ -539,19 +533,7 @@ AudioPlaylist::set_state (const XMLNode& node) void AudioPlaylist::clear (bool with_signals) { - for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ) { - - Crossfades::iterator tmp; - tmp = i; - ++tmp; - - delete *i; - - i = tmp; - } - _crossfades.clear (); - Playlist::clear (with_signals); } @@ -573,7 +555,7 @@ void AudioPlaylist::dump () const { boost::shared_ptrr; - Crossfade *x; + boost::shared_ptr x; cerr << "Playlist \"" << _name << "\" " << endl << regions.size() << " regions " @@ -613,7 +595,7 @@ AudioPlaylist::destroy_region (boost::shared_ptr region) boost::shared_ptr r = boost::dynamic_pointer_cast (region); bool changed = false; Crossfades::iterator c, ctmp; - set unique_xfades; + set > unique_xfades; if (r == 0) { fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist") @@ -651,7 +633,7 @@ AudioPlaylist::destroy_region (boost::shared_ptr region) x = xtmp; } - region->set_playlist (0); + region->set_playlist (boost::shared_ptr()); } for (c = _crossfades.begin(); c != _crossfades.end(); ) { @@ -666,10 +648,6 @@ AudioPlaylist::destroy_region (boost::shared_ptr region) c = ctmp; } - for (set::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) { - delete *c; - } - if (changed) { /* overload this, it normally means "removed", not destroyed */ notify_region_removed (region);