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, DataType::AUDIO, hidden)
45 const XMLProperty* prop = node.property("type");
46 assert(!prop || DataType(prop->value()) == DataType::AUDIO);
53 AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)
54 : Playlist (session, name, DataType::AUDIO, hidden)
58 AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, string name, bool hidden)
59 : Playlist (other, name, hidden)
61 RegionList::const_iterator in_o = other->regions.begin();
62 RegionList::iterator in_n = regions.begin();
64 while (in_o != other->regions.end()) {
65 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*in_o);
67 // We look only for crossfades which begin with the current region, so we don't get doubles
68 for (Crossfades::const_iterator xfades = other->_crossfades.begin(); xfades != other->_crossfades.end(); ++xfades) {
69 if ((*xfades)->in() == ar) {
70 // We found one! Now copy it!
72 RegionList::const_iterator out_o = other->regions.begin();
73 RegionList::const_iterator out_n = regions.begin();
75 while (out_o != other->regions.end()) {
77 boost::shared_ptr<AudioRegion>ar2 = boost::dynamic_pointer_cast<AudioRegion>(*out_o);
79 if ((*xfades)->out() == ar2) {
80 boost::shared_ptr<AudioRegion>in = boost::dynamic_pointer_cast<AudioRegion>(*in_n);
81 boost::shared_ptr<AudioRegion>out = boost::dynamic_pointer_cast<AudioRegion>(*out_n);
82 boost::shared_ptr<Crossfade> new_fade = boost::shared_ptr<Crossfade> (new Crossfade (*(*xfades), in, out));
83 add_crossfade(new_fade);
90 // cerr << "HUH!? second region in the crossfade not found!" << endl;
99 AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, nframes_t start, nframes_t cnt, string name, bool hidden)
100 : Playlist (other, start, cnt, name, hidden)
102 /* this constructor does NOT notify others (session) */
105 AudioPlaylist::~AudioPlaylist ()
107 GoingAway (); /* EMIT SIGNAL */
109 /* drop connections to signals */
113 _crossfades.clear ();
116 struct RegionSortByLayer {
117 bool operator() (boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
118 return a->layer() < b->layer();
123 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t start,
124 nframes_t cnt, unsigned chan_n)
128 nframes_t read_frames;
129 nframes_t skip_frames;
131 /* optimizing this memset() away involves a lot of conditionals
132 that may well cause more of a hit due to cache misses
133 and related stuff than just doing this here.
135 it would be great if someone could measure this
138 one way or another, parts of the requested area
139 that are not written to by Region::region_at()
140 for all Regions that cover the area need to be
144 memset (buf, 0, sizeof (Sample) * cnt);
146 /* this function is never called from a realtime thread, so
147 its OK to block (for short intervals).
150 Glib::Mutex::Lock rm (region_lock);
152 end = start + cnt - 1;
156 _read_data_count = 0;
158 map<uint32_t,vector<boost::shared_ptr<Region> > > relevant_regions;
159 map<uint32_t,vector<boost::shared_ptr<Crossfade> > > relevant_xfades;
160 vector<uint32_t> relevant_layers;
162 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
163 if ((*i)->coverage (start, end) != OverlapNone) {
164 relevant_regions[(*i)->layer()].push_back (*i);
165 relevant_layers.push_back ((*i)->layer());
169 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
170 if ((*i)->coverage (start, end) != OverlapNone) {
171 relevant_xfades[(*i)->upper_layer()].push_back (*i);
175 // RegionSortByLayer layer_cmp;
176 // relevant_regions.sort (layer_cmp);
178 /* XXX this whole per-layer approach is a hack that
179 should be removed once Crossfades become
180 CrossfadeRegions and we just grab a list of relevant
181 regions and call read_at() on all of them.
184 sort (relevant_layers.begin(), relevant_layers.end());
186 for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
188 vector<boost::shared_ptr<Region> > r (relevant_regions[*l]);
189 vector<boost::shared_ptr<Crossfade> >& x (relevant_xfades[*l]);
191 for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
192 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
194 ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
195 _read_data_count += ar->read_data_count();
198 for (vector<boost::shared_ptr<Crossfade> >::iterator i = x.begin(); i != x.end(); ++i) {
199 (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
201 /* don't JACK up _read_data_count, since its the same data as we just
202 read from the regions, and the OS should handle that for us.
212 AudioPlaylist::remove_dependents (boost::shared_ptr<Region> region)
214 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
221 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
226 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ) {
228 if ((*i)->involves (r)) {
229 i = _crossfades.erase (i);
238 AudioPlaylist::flush_notifications ()
240 Playlist::flush_notifications();
248 Crossfades::iterator a;
249 for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
250 NewCrossfade (*a); /* EMIT SIGNAL */
253 _pending_xfade_adds.clear ();
259 AudioPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
261 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(r);
262 set<boost::shared_ptr<Crossfade> > updated;
268 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
270 Crossfades::iterator tmp;
275 /* only update them once */
277 if ((*x)->involves (ar)) {
279 if (find (updated.begin(), updated.end(), *x) == updated.end()) {
281 if ((*x)->refresh ()) {
286 catch (Crossfade::NoCrossfadeHere& err) {
287 // relax, Invalidated during refresh
297 AudioPlaylist::finalize_split_region (boost::shared_ptr<Region> o, boost::shared_ptr<Region> l, boost::shared_ptr<Region> r)
299 boost::shared_ptr<AudioRegion> orig = boost::dynamic_pointer_cast<AudioRegion>(o);
300 boost::shared_ptr<AudioRegion> left = boost::dynamic_pointer_cast<AudioRegion>(l);
301 boost::shared_ptr<AudioRegion> right = boost::dynamic_pointer_cast<AudioRegion>(r);
303 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
304 Crossfades::iterator tmp;
308 boost::shared_ptr<Crossfade> fade;
310 if ((*x)->_in == orig) {
311 if (! (*x)->covers(right->position())) {
312 fade = boost::shared_ptr<Crossfade> (new Crossfade (**x, left, (*x)->_out));
314 // Overlap, the crossfade is copied on the left side of the right region instead
315 fade = boost::shared_ptr<Crossfade> (new Crossfade (**x, right, (*x)->_out));
319 if ((*x)->_out == orig) {
320 if (! (*x)->covers(right->position())) {
321 fade = boost::shared_ptr<Crossfade> (new Crossfade (**x, (*x)->_in, right));
323 // Overlap, the crossfade is copied on the right side of the left region instead
324 fade = boost::shared_ptr<Crossfade> (new Crossfade (**x, (*x)->_in, left));
329 _crossfades.remove (*x);
330 add_crossfade (fade);
337 AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
339 boost::shared_ptr<AudioRegion> other;
340 boost::shared_ptr<AudioRegion> region;
341 boost::shared_ptr<AudioRegion> top;
342 boost::shared_ptr<AudioRegion> bottom;
343 boost::shared_ptr<Crossfade> xfade;
345 if (in_set_state || in_partition) {
349 cerr << "Check dependents of " << r->name() << endl;
351 if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
352 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
358 refresh_dependents (r);
362 if (!Config->get_auto_xfade()) {
366 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
368 nframes_t xfade_length;
370 other = boost::dynamic_pointer_cast<AudioRegion> (*i);
372 if (other == region) {
376 if (other->muted() || region->muted()) {
381 if (other->layer() < region->layer()) {
391 OverlapType c = top->coverage (bottom->position(), bottom->last_frame());
398 case OverlapInternal:
399 /* {=============== top =============}
400 * [ ----- bottom ------- ]
404 case OverlapExternal:
406 /* [ -------- top ------- ]
407 * {=========== bottom =============}
410 /* to avoid discontinuities at the region boundaries of an internal
411 overlap (this region is completely within another), we create
412 two hidden crossfades at each boundary. this is not dependent
413 on the auto-xfade option, because we require it as basic
417 xfade_length = min ((nframes_t) 720, top->length());
419 xfade = boost::shared_ptr<Crossfade> (new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn));
420 add_crossfade (xfade);
422 if (top_region_at (top->last_frame() - 1) == top) {
424 only add a fade out if there is no region on top of the end of 'top' (which
428 xfade = boost::shared_ptr<Crossfade> (new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut));
429 add_crossfade (xfade);
434 xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
435 add_crossfade (xfade);
439 catch (failed_constructor& err) {
443 catch (Crossfade::NoCrossfadeHere& err) {
451 AudioPlaylist::add_crossfade (boost::shared_ptr<Crossfade> xfade)
453 Crossfades::iterator ci;
455 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
456 if (*(*ci) == *xfade) { // Crossfade::operator==()
461 if (ci != _crossfades.end()) {
462 // it will just go away
464 _crossfades.push_back (xfade);
466 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
467 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
469 notify_crossfade_added (xfade);
473 void AudioPlaylist::notify_crossfade_added (boost::shared_ptr<Crossfade> x)
475 if (g_atomic_int_get(&block_notifications)) {
476 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
478 NewCrossfade (x); /* EMIT SIGNAL */
483 AudioPlaylist::crossfade_invalidated (boost::shared_ptr<Crossfade> xfade)
485 Crossfades::iterator i;
487 xfade->in()->resume_fade_in ();
488 xfade->out()->resume_fade_out ();
490 if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
491 _crossfades.erase (i);
496 AudioPlaylist::set_state (const XMLNode& node)
500 XMLNodeConstIterator niter;
505 Playlist::set_state (node);
507 nlist = node.children();
509 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
513 if (child->name() != "Crossfade") {
518 boost::shared_ptr<Crossfade> xfade = boost::shared_ptr<Crossfade> (new Crossfade (*((const Playlist *)this), *child));
519 _crossfades.push_back (xfade);
520 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
521 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
525 catch (failed_constructor& err) {
526 // cout << string_compose (_("could not create crossfade object in playlist %1"),
540 AudioPlaylist::clear (bool with_signals)
542 _crossfades.clear ();
543 Playlist::clear (with_signals);
547 AudioPlaylist::state (bool full_state)
549 XMLNode& node = Playlist::state (full_state);
552 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
553 node.add_child_nocopy ((*i)->get_state());
561 AudioPlaylist::dump () const
563 boost::shared_ptr<Region>r;
564 boost::shared_ptr<Crossfade> x;
566 cerr << "Playlist \"" << _name << "\" " << endl
567 << regions.size() << " regions "
568 << _crossfades.size() << " crossfades"
571 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
573 cerr << " " << r->name() << " @ " << r << " ["
574 << r->start() << "+" << r->length()
582 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
593 << (x->active() ? "yes" : "no")
599 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
601 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
602 bool changed = false;
603 Crossfades::iterator c, ctmp;
604 set<boost::shared_ptr<Crossfade> > unique_xfades;
607 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
614 RegionLock rlock (this);
616 for (RegionList::iterator i = regions.begin(); i != regions.end(); ) {
618 RegionList::iterator tmp = i;
621 if ((*i) == region) {
629 for (set<boost::shared_ptr<Region> >::iterator x = all_regions.begin(); x != all_regions.end(); ) {
631 set<boost::shared_ptr<Region> >::iterator xtmp = x;
634 if ((*x) == region) {
635 all_regions.erase (x);
642 region->set_playlist (boost::shared_ptr<Playlist>());
645 for (c = _crossfades.begin(); c != _crossfades.end(); ) {
649 if ((*c)->involves (r)) {
650 unique_xfades.insert (*c);
651 _crossfades.erase (c);
658 /* overload this, it normally means "removed", not destroyed */
659 notify_region_removed (region);
666 AudioPlaylist::crossfade_changed (Change ignored)
668 if (in_flush || in_set_state) {
672 /* XXX is there a loop here? can an xfade change not happen
673 due to a playlist change? well, sure activation would
674 be an example. maybe we should check the type of change
682 AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
684 if (in_flush || in_set_state) {
688 Change our_interests = Change (AudioRegion::FadeInChanged|
689 AudioRegion::FadeOutChanged|
690 AudioRegion::FadeInActiveChanged|
691 AudioRegion::FadeOutActiveChanged|
692 AudioRegion::EnvelopeActiveChanged|
693 AudioRegion::ScaleAmplitudeChanged|
694 AudioRegion::EnvelopeChanged);
695 bool parent_wants_notify;
697 parent_wants_notify = Playlist::region_changed (what_changed, region);
699 if ((parent_wants_notify || (what_changed & our_interests))) {
707 AudioPlaylist::crossfades_at (nframes_t frame, Crossfades& clist)
709 RegionLock rlock (this);
711 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
712 nframes_t start, end;
714 start = (*i)->position();
715 end = start + (*i)->overlap_length(); // not length(), important difference
717 if (frame >= start && frame <= end) {
718 clist.push_back (*i);