2 Copyright (C) 2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <sigc++/bind.h>
26 #include <ardour/types.h>
27 #include <ardour/configuration.h>
28 #include <ardour/audioplaylist.h>
29 #include <ardour/audioregion.h>
30 #include <ardour/crossfade.h>
31 #include <ardour/crossfade_compare.h>
32 #include <ardour/session.h>
33 #include <pbd/enumwriter.h>
37 using namespace ARDOUR;
42 AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden)
43 : Playlist (session, node, hidden)
50 AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)
51 : Playlist (session, name, hidden)
55 AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, string name, bool hidden)
56 : Playlist (other, name, hidden)
58 RegionList::const_iterator in_o = other->regions.begin();
59 RegionList::iterator in_n = regions.begin();
61 while (in_o != other->regions.end()) {
62 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*in_o);
64 // We look only for crossfades which begin with the current region, so we don't get doubles
65 for (Crossfades::const_iterator xfades = other->_crossfades.begin(); xfades != other->_crossfades.end(); ++xfades) {
66 if ((*xfades)->in() == ar) {
67 // We found one! Now copy it!
69 RegionList::const_iterator out_o = other->regions.begin();
70 RegionList::const_iterator out_n = regions.begin();
72 while (out_o != other->regions.end()) {
74 boost::shared_ptr<AudioRegion>ar2 = boost::dynamic_pointer_cast<AudioRegion>(*out_o);
76 if ((*xfades)->out() == ar2) {
77 boost::shared_ptr<AudioRegion>in = boost::dynamic_pointer_cast<AudioRegion>(*in_n);
78 boost::shared_ptr<AudioRegion>out = boost::dynamic_pointer_cast<AudioRegion>(*out_n);
79 boost::shared_ptr<Crossfade> new_fade = boost::shared_ptr<Crossfade> (new Crossfade (*(*xfades), in, out));
80 add_crossfade(new_fade);
87 // cerr << "HUH!? second region in the crossfade not found!" << endl;
96 AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, nframes_t start, nframes_t cnt, string name, bool hidden)
97 : Playlist (other, start, cnt, name, hidden)
99 /* this constructor does NOT notify others (session) */
102 AudioPlaylist::~AudioPlaylist ()
104 GoingAway (); /* EMIT SIGNAL */
106 /* drop connections to signals */
110 _crossfades.clear ();
113 struct RegionSortByLayer {
114 bool operator() (boost::shared_ptr<Region>a, boost::shared_ptr<Region>b) {
115 return a->layer() < b->layer();
120 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t start,
121 nframes_t cnt, unsigned chan_n)
125 nframes_t read_frames;
126 nframes_t skip_frames;
128 /* optimizing this memset() away involves a lot of conditionals
129 that may well cause more of a hit due to cache misses
130 and related stuff than just doing this here.
132 it would be great if someone could measure this
135 one way or another, parts of the requested area
136 that are not written to by Region::region_at()
137 for all Regions that cover the area need to be
141 memset (buf, 0, sizeof (Sample) * cnt);
143 /* this function is never called from a realtime thread, so
144 its OK to block (for short intervals).
147 Glib::Mutex::Lock rm (region_lock);
149 end = start + cnt - 1;
153 _read_data_count = 0;
155 RegionList* rlist = regions_to_read (start, start+cnt);
157 if (rlist->empty()) {
162 map<uint32_t,vector<boost::shared_ptr<Region> > > relevant_regions;
163 map<uint32_t,vector<boost::shared_ptr<Crossfade> > > relevant_xfades;
164 vector<uint32_t> relevant_layers;
166 for (RegionList::iterator i = rlist->begin(); i != rlist->end(); ++i) {
167 if ((*i)->coverage (start, end) != OverlapNone) {
168 relevant_regions[(*i)->layer()].push_back (*i);
169 relevant_layers.push_back ((*i)->layer());
173 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
174 if ((*i)->coverage (start, end) != OverlapNone) {
175 relevant_xfades[(*i)->upper_layer()].push_back (*i);
179 // RegionSortByLayer layer_cmp;
180 // relevant_regions.sort (layer_cmp);
182 /* XXX this whole per-layer approach is a hack that
183 should be removed once Crossfades become
184 CrossfadeRegions and we just grab a list of relevant
185 regions and call read_at() on all of them.
188 sort (relevant_layers.begin(), relevant_layers.end());
190 for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
192 vector<boost::shared_ptr<Region> > r (relevant_regions[*l]);
193 vector<boost::shared_ptr<Crossfade> >& x (relevant_xfades[*l]);
195 for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
196 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
198 ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
199 _read_data_count += ar->read_data_count();
202 for (vector<boost::shared_ptr<Crossfade> >::iterator i = x.begin(); i != x.end(); ++i) {
203 (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
205 /* don't JACK up _read_data_count, since its the same data as we just
206 read from the regions, and the OS should handle that for us.
217 AudioPlaylist::remove_dependents (boost::shared_ptr<Region> region)
219 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
226 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
231 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ) {
233 if ((*i)->involves (r)) {
234 i = _crossfades.erase (i);
243 AudioPlaylist::flush_notifications ()
245 Playlist::flush_notifications();
253 Crossfades::iterator a;
254 for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
255 NewCrossfade (*a); /* EMIT SIGNAL */
258 _pending_xfade_adds.clear ();
264 AudioPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
266 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(r);
267 set<boost::shared_ptr<Crossfade> > updated;
273 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
275 Crossfades::iterator tmp;
280 /* only update them once */
282 if ((*x)->involves (ar)) {
284 pair<set<boost::shared_ptr<Crossfade> >::iterator, bool> const u = updated.insert (*x);
287 /* x was succesfully inserted into the set, so it has not already been updated */
292 catch (Crossfade::NoCrossfadeHere& err) {
293 // relax, Invalidated during refresh
303 AudioPlaylist::finalize_split_region (boost::shared_ptr<Region> o, boost::shared_ptr<Region> l, boost::shared_ptr<Region> r)
305 boost::shared_ptr<AudioRegion> orig = boost::dynamic_pointer_cast<AudioRegion>(o);
306 boost::shared_ptr<AudioRegion> left = boost::dynamic_pointer_cast<AudioRegion>(l);
307 boost::shared_ptr<AudioRegion> right = boost::dynamic_pointer_cast<AudioRegion>(r);
309 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
310 Crossfades::iterator tmp;
314 boost::shared_ptr<Crossfade> fade;
316 if ((*x)->_in == orig) {
317 if (! (*x)->covers(right->position())) {
318 fade = boost::shared_ptr<Crossfade> (new Crossfade (**x, left, (*x)->_out));
320 // Overlap, the crossfade is copied on the left side of the right region instead
321 fade = boost::shared_ptr<Crossfade> (new Crossfade (**x, right, (*x)->_out));
325 if ((*x)->_out == orig) {
326 if (! (*x)->covers(right->position())) {
327 fade = boost::shared_ptr<Crossfade> (new Crossfade (**x, (*x)->_in, right));
329 // Overlap, the crossfade is copied on the right side of the left region instead
330 fade = boost::shared_ptr<Crossfade> (new Crossfade (**x, (*x)->_in, left));
335 _crossfades.remove (*x);
336 add_crossfade (fade);
343 AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
345 boost::shared_ptr<AudioRegion> other;
346 boost::shared_ptr<AudioRegion> region;
347 boost::shared_ptr<AudioRegion> top;
348 boost::shared_ptr<AudioRegion> bottom;
349 boost::shared_ptr<Crossfade> xfade;
351 if (in_set_state || in_partition) {
355 if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
356 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
362 refresh_dependents (r);
366 if (!Config->get_auto_xfade()) {
370 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
372 nframes_t xfade_length;
374 other = boost::dynamic_pointer_cast<AudioRegion> (*i);
376 if (other == region) {
380 if (other->muted() || region->muted()) {
385 if (other->layer() < region->layer()) {
393 if (!(top->opaque())) {
399 OverlapType c = top->coverage (bottom->position(), bottom->last_frame());
406 case OverlapInternal:
407 /* {=============== top =============}
408 * [ ----- bottom ------- ]
412 case OverlapExternal:
414 /* [ -------- top ------- ]
415 * {=========== bottom =============}
418 /* to avoid discontinuities at the region boundaries of an internal
419 overlap (this region is completely within another), we create
420 two hidden crossfades at each boundary. this is not dependent
421 on the auto-xfade option, because we require it as basic
425 xfade_length = min ((nframes_t) 720, top->length());
427 xfade = boost::shared_ptr<Crossfade> (new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn));
428 add_crossfade (xfade);
430 if (top_region_at (top->last_frame() - 1) == top) {
432 only add a fade out if there is no region on top of the end of 'top' (which
436 xfade = boost::shared_ptr<Crossfade> (new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut));
437 add_crossfade (xfade);
442 xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
443 add_crossfade (xfade);
447 catch (failed_constructor& err) {
451 catch (Crossfade::NoCrossfadeHere& err) {
459 AudioPlaylist::add_crossfade (boost::shared_ptr<Crossfade> xfade)
461 Crossfades::iterator ci;
463 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
464 if (*(*ci) == *xfade) { // Crossfade::operator==()
469 if (ci != _crossfades.end()) {
470 // it will just go away
472 _crossfades.push_back (xfade);
474 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
475 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
477 notify_crossfade_added (xfade);
481 void AudioPlaylist::notify_crossfade_added (boost::shared_ptr<Crossfade> x)
483 if (g_atomic_int_get(&block_notifications)) {
484 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
486 NewCrossfade (x); /* EMIT SIGNAL */
491 AudioPlaylist::crossfade_invalidated (boost::shared_ptr<Crossfade> xfade)
493 Crossfades::iterator i;
495 xfade->in()->resume_fade_in ();
496 xfade->out()->resume_fade_out ();
498 if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
499 _crossfades.erase (i);
504 AudioPlaylist::set_state (const XMLNode& node)
508 XMLNodeConstIterator niter;
513 Playlist::set_state (node);
515 nlist = node.children();
517 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
521 if (child->name() != "Crossfade") {
526 boost::shared_ptr<Crossfade> xfade = boost::shared_ptr<Crossfade> (new Crossfade (*((const Playlist *)this), *child));
527 _crossfades.push_back (xfade);
528 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
529 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
533 catch (failed_constructor& err) {
534 // cout << string_compose (_("could not create crossfade object in playlist %1"),
548 AudioPlaylist::clear (bool with_signals)
550 _crossfades.clear ();
551 Playlist::clear (with_signals);
555 AudioPlaylist::state (bool full_state)
557 XMLNode& node = Playlist::state (full_state);
560 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
561 node.add_child_nocopy ((*i)->get_state());
569 AudioPlaylist::dump () const
571 boost::shared_ptr<Region>r;
572 boost::shared_ptr<Crossfade> x;
574 cerr << "Playlist \"" << _name << "\" " << endl
575 << regions.size() << " regions "
576 << _crossfades.size() << " crossfades"
579 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
581 cerr << " " << r->name() << " @ " << r << " ["
582 << r->start() << "+" << r->length()
590 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
601 << (x->active() ? "yes" : "no")
607 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
609 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
610 bool changed = false;
611 Crossfades::iterator c, ctmp;
612 set<boost::shared_ptr<Crossfade> > unique_xfades;
615 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
622 RegionLock rlock (this);
624 for (RegionList::iterator i = regions.begin(); i != regions.end(); ) {
626 RegionList::iterator tmp = i;
629 if ((*i) == region) {
637 for (set<boost::shared_ptr<Region> >::iterator x = all_regions.begin(); x != all_regions.end(); ) {
639 set<boost::shared_ptr<Region> >::iterator xtmp = x;
642 if ((*x) == region) {
643 all_regions.erase (x);
650 region->set_playlist (boost::shared_ptr<Playlist>());
653 for (c = _crossfades.begin(); c != _crossfades.end(); ) {
657 if ((*c)->involves (r)) {
658 unique_xfades.insert (*c);
659 _crossfades.erase (c);
666 /* overload this, it normally means "removed", not destroyed */
667 notify_region_removed (region);
674 AudioPlaylist::crossfade_changed (Change ignored)
676 if (in_flush || in_set_state) {
680 /* XXX is there a loop here? can an xfade change not happen
681 due to a playlist change? well, sure activation would
682 be an example. maybe we should check the type of change
690 AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
692 if (in_flush || in_set_state) {
696 Change our_interests = Change (AudioRegion::FadeInChanged|
697 AudioRegion::FadeOutChanged|
698 AudioRegion::FadeInActiveChanged|
699 AudioRegion::FadeOutActiveChanged|
700 AudioRegion::EnvelopeActiveChanged|
701 AudioRegion::ScaleAmplitudeChanged|
702 AudioRegion::EnvelopeChanged);
703 bool parent_wants_notify;
705 parent_wants_notify = Playlist::region_changed (what_changed, region);
707 if ((parent_wants_notify || (what_changed & our_interests))) {
715 AudioPlaylist::crossfades_at (nframes_t frame, Crossfades& clist)
717 RegionLock rlock (this);
719 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
720 nframes_t start, end;
722 start = (*i)->position();
723 end = start + (*i)->overlap_length(); // not length(), important difference
725 if (frame >= start && frame <= end) {
726 clist.push_back (*i);