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>
36 using namespace ARDOUR;
41 AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden)
42 : Playlist (session, node, DataType::AUDIO, hidden)
44 const XMLProperty* prop = node.property("type");
45 assert(!prop || DataType(prop->value()) == DataType::AUDIO);
52 AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)
53 : Playlist (session, name, DataType::AUDIO, hidden)
57 AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, string name, bool hidden)
58 : Playlist (other, name, hidden)
60 RegionList::const_iterator in_o = other->regions.begin();
61 RegionList::iterator in_n = regions.begin();
63 while (in_o != other->regions.end()) {
64 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*in_o);
66 // We look only for crossfades which begin with the current region, so we don't get doubles
67 for (Crossfades::const_iterator xfades = other->_crossfades.begin(); xfades != other->_crossfades.end(); ++xfades) {
68 if ((*xfades)->in() == ar) {
69 // We found one! Now copy it!
71 RegionList::const_iterator out_o = other->regions.begin();
72 RegionList::const_iterator out_n = regions.begin();
74 while (out_o != other->regions.end()) {
76 boost::shared_ptr<AudioRegion>ar2 = boost::dynamic_pointer_cast<AudioRegion>(*out_o);
78 if ((*xfades)->out() == ar2) {
79 boost::shared_ptr<AudioRegion>in = boost::dynamic_pointer_cast<AudioRegion>(*in_n);
80 boost::shared_ptr<AudioRegion>out = boost::dynamic_pointer_cast<AudioRegion>(*out_n);
81 boost::shared_ptr<Crossfade> new_fade = boost::shared_ptr<Crossfade> (new Crossfade (*(*xfades), in, out));
82 add_crossfade(new_fade);
89 // cerr << "HUH!? second region in the crossfade not found!" << endl;
98 AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, nframes_t start, nframes_t cnt, string name, bool hidden)
99 : Playlist (other, start, cnt, name, hidden)
101 /* this constructor does NOT notify others (session) */
104 AudioPlaylist::~AudioPlaylist ()
106 GoingAway (); /* EMIT SIGNAL */
108 /* drop connections to signals */
112 _crossfades.clear ();
115 struct RegionSortByLayer {
116 bool operator() (boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
117 return a->layer() < b->layer();
122 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t start,
123 nframes_t cnt, unsigned chan_n)
127 nframes_t read_frames;
128 nframes_t skip_frames;
130 /* optimizing this memset() away involves a lot of conditionals
131 that may well cause more of a hit due to cache misses
132 and related stuff than just doing this here.
134 it would be great if someone could measure this
137 one way or another, parts of the requested area
138 that are not written to by Region::region_at()
139 for all Regions that cover the area need to be
143 memset (buf, 0, sizeof (Sample) * cnt);
145 /* this function is never called from a realtime thread, so
146 its OK to block (for short intervals).
149 Glib::Mutex::Lock rm (region_lock);
151 end = start + cnt - 1;
155 _read_data_count = 0;
157 map<uint32_t,vector<boost::shared_ptr<Region> > > relevant_regions;
158 map<uint32_t,vector<boost::shared_ptr<Crossfade> > > relevant_xfades;
159 vector<uint32_t> relevant_layers;
161 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
162 if ((*i)->coverage (start, end) != OverlapNone) {
163 relevant_regions[(*i)->layer()].push_back (*i);
164 relevant_layers.push_back ((*i)->layer());
168 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
169 if ((*i)->coverage (start, end) != OverlapNone) {
170 relevant_xfades[(*i)->upper_layer()].push_back (*i);
174 // RegionSortByLayer layer_cmp;
175 // relevant_regions.sort (layer_cmp);
177 /* XXX this whole per-layer approach is a hack that
178 should be removed once Crossfades become
179 CrossfadeRegions and we just grab a list of relevant
180 regions and call read_at() on all of them.
183 sort (relevant_layers.begin(), relevant_layers.end());
185 for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
187 vector<boost::shared_ptr<Region> > r (relevant_regions[*l]);
188 vector<boost::shared_ptr<Crossfade> >& x (relevant_xfades[*l]);
190 for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
191 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
193 ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
194 _read_data_count += ar->read_data_count();
197 for (vector<boost::shared_ptr<Crossfade> >::iterator i = x.begin(); i != x.end(); ++i) {
198 (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
200 /* don't JACK up _read_data_count, since its the same data as we just
201 read from the regions, and the OS should handle that for us.
211 AudioPlaylist::remove_dependents (boost::shared_ptr<Region> region)
213 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
220 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
225 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ) {
227 if ((*i)->involves (r)) {
228 i = _crossfades.erase (i);
237 AudioPlaylist::flush_notifications ()
239 Playlist::flush_notifications();
247 Crossfades::iterator a;
248 for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
249 NewCrossfade (*a); /* EMIT SIGNAL */
252 _pending_xfade_adds.clear ();
258 AudioPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
260 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(r);
261 set<boost::shared_ptr<Crossfade> > updated;
267 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
269 Crossfades::iterator tmp;
274 /* only update them once */
276 if ((*x)->involves (ar)) {
278 if (find (updated.begin(), updated.end(), *x) == updated.end()) {
280 if ((*x)->refresh ()) {
285 catch (Crossfade::NoCrossfadeHere& err) {
286 // relax, Invalidated during refresh
296 AudioPlaylist::finalize_split_region (boost::shared_ptr<Region> o, boost::shared_ptr<Region> l, boost::shared_ptr<Region> r)
298 boost::shared_ptr<AudioRegion> orig = boost::dynamic_pointer_cast<AudioRegion>(o);
299 boost::shared_ptr<AudioRegion> left = boost::dynamic_pointer_cast<AudioRegion>(l);
300 boost::shared_ptr<AudioRegion> right = boost::dynamic_pointer_cast<AudioRegion>(r);
302 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
303 Crossfades::iterator tmp;
307 boost::shared_ptr<Crossfade> fade;
309 if ((*x)->_in == orig) {
310 if (! (*x)->covers(right->position())) {
311 fade = boost::shared_ptr<Crossfade> (new Crossfade (**x, left, (*x)->_out));
313 // Overlap, the crossfade is copied on the left side of the right region instead
314 fade = boost::shared_ptr<Crossfade> (new Crossfade (**x, right, (*x)->_out));
318 if ((*x)->_out == orig) {
319 if (! (*x)->covers(right->position())) {
320 fade = boost::shared_ptr<Crossfade> (new Crossfade (**x, (*x)->_in, right));
322 // Overlap, the crossfade is copied on the right side of the left region instead
323 fade = boost::shared_ptr<Crossfade> (new Crossfade (**x, (*x)->_in, left));
328 _crossfades.remove (*x);
329 add_crossfade (fade);
336 AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
338 boost::shared_ptr<AudioRegion> other;
339 boost::shared_ptr<AudioRegion> region;
340 boost::shared_ptr<AudioRegion> top;
341 boost::shared_ptr<AudioRegion> bottom;
342 boost::shared_ptr<Crossfade> xfade;
344 if (in_set_state || in_partition) {
348 cerr << "Check dependents of " << r->name() << endl;
350 if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
351 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
357 refresh_dependents (r);
361 if (!Config->get_auto_xfade()) {
365 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
367 nframes_t xfade_length;
369 other = boost::dynamic_pointer_cast<AudioRegion> (*i);
371 if (other == region) {
375 if (other->muted() || region->muted()) {
380 if (other->layer() < region->layer()) {
389 OverlapType c = top->coverage (bottom->position(), bottom->last_frame());
396 case OverlapInternal:
397 /* {=============== top =============}
398 * [ ----- bottom ------- ]
402 case OverlapExternal:
404 /* [ -------- top ------- ]
405 * {=========== bottom =============}
408 /* to avoid discontinuities at the region boundaries of an internal
409 overlap (this region is completely within another), we create
410 two hidden crossfades at each boundary. this is not dependent
411 on the auto-xfade option, because we require it as basic
415 xfade_length = min ((nframes_t) 720, top->length());
417 xfade = boost::shared_ptr<Crossfade> (new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn));
418 add_crossfade (xfade);
420 if (top_region_at (top->last_frame() - 1) == top) {
422 only add a fade out if there is no region on top of the end of 'top' (which
426 xfade = boost::shared_ptr<Crossfade> (new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut));
427 add_crossfade (xfade);
432 xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
433 add_crossfade (xfade);
437 catch (failed_constructor& err) {
441 catch (Crossfade::NoCrossfadeHere& err) {
449 AudioPlaylist::add_crossfade (boost::shared_ptr<Crossfade> xfade)
451 Crossfades::iterator ci;
453 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
454 if (*(*ci) == *xfade) { // Crossfade::operator==()
459 if (ci != _crossfades.end()) {
460 // it will just go away
462 _crossfades.push_back (xfade);
464 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
465 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
467 notify_crossfade_added (xfade);
471 void AudioPlaylist::notify_crossfade_added (boost::shared_ptr<Crossfade> x)
473 if (g_atomic_int_get(&block_notifications)) {
474 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
476 NewCrossfade (x); /* EMIT SIGNAL */
481 AudioPlaylist::crossfade_invalidated (boost::shared_ptr<Crossfade> xfade)
483 Crossfades::iterator i;
485 xfade->in()->resume_fade_in ();
486 xfade->out()->resume_fade_out ();
488 if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
489 _crossfades.erase (i);
494 AudioPlaylist::set_state (const XMLNode& node)
498 XMLNodeConstIterator niter;
503 Playlist::set_state (node);
505 nlist = node.children();
507 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
511 if (child->name() != "Crossfade") {
516 boost::shared_ptr<Crossfade> xfade = boost::shared_ptr<Crossfade> (new Crossfade (*((const Playlist *)this), *child));
517 _crossfades.push_back (xfade);
518 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
519 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
523 catch (failed_constructor& err) {
524 // cout << string_compose (_("could not create crossfade object in playlist %1"),
538 AudioPlaylist::clear (bool with_signals)
540 _crossfades.clear ();
541 Playlist::clear (with_signals);
545 AudioPlaylist::state (bool full_state)
547 XMLNode& node = Playlist::state (full_state);
550 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
551 node.add_child_nocopy ((*i)->get_state());
559 AudioPlaylist::dump () const
561 boost::shared_ptr<Region>r;
562 boost::shared_ptr<Crossfade> x;
564 cerr << "Playlist \"" << _name << "\" " << endl
565 << regions.size() << " regions "
566 << _crossfades.size() << " crossfades"
569 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
571 cerr << " " << r->name() << " @ " << r << " ["
572 << r->start() << "+" << r->length()
580 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
591 << (x->active() ? "yes" : "no")
597 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
599 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
600 bool changed = false;
601 Crossfades::iterator c, ctmp;
602 set<boost::shared_ptr<Crossfade> > unique_xfades;
605 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
612 RegionLock rlock (this);
614 for (RegionList::iterator i = regions.begin(); i != regions.end(); ) {
616 RegionList::iterator tmp = i;
619 if ((*i) == region) {
627 for (set<boost::shared_ptr<Region> >::iterator x = all_regions.begin(); x != all_regions.end(); ) {
629 set<boost::shared_ptr<Region> >::iterator xtmp = x;
632 if ((*x) == region) {
633 all_regions.erase (x);
640 region->set_playlist (boost::shared_ptr<Playlist>());
643 for (c = _crossfades.begin(); c != _crossfades.end(); ) {
647 if ((*c)->involves (r)) {
648 unique_xfades.insert (*c);
649 _crossfades.erase (c);
656 /* overload this, it normally means "removed", not destroyed */
657 notify_region_removed (region);
664 AudioPlaylist::crossfade_changed (Change ignored)
666 if (in_flush || in_set_state) {
670 /* XXX is there a loop here? can an xfade change not happen
671 due to a playlist change? well, sure activation would
672 be an example. maybe we should check the type of change
680 AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
682 if (in_flush || in_set_state) {
686 Change our_interests = Change (AudioRegion::FadeInChanged|
687 AudioRegion::FadeOutChanged|
688 AudioRegion::FadeInActiveChanged|
689 AudioRegion::FadeOutActiveChanged|
690 AudioRegion::EnvelopeActiveChanged|
691 AudioRegion::ScaleAmplitudeChanged|
692 AudioRegion::EnvelopeChanged);
693 bool parent_wants_notify;
695 parent_wants_notify = Playlist::region_changed (what_changed, region);
697 if ((parent_wants_notify || (what_changed & our_interests))) {
705 AudioPlaylist::crossfades_at (nframes_t frame, Crossfades& clist)
707 RegionLock rlock (this);
709 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
710 nframes_t start, end;
712 start = (*i)->position();
713 end = start + (*i)->overlap_length(); // not length(), important difference
715 if (frame >= start && frame <= end) {
716 clist.push_back (*i);