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.
25 #include <sigc++/bind.h>
27 #include <ardour/types.h>
28 #include <ardour/configuration.h>
29 #include <ardour/audioplaylist.h>
30 #include <ardour/audioregion.h>
31 #include <ardour/crossfade.h>
32 #include <ardour/crossfade_compare.h>
33 #include <ardour/session.h>
37 using namespace ARDOUR;
42 AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden)
43 : Playlist (session, node, hidden)
50 PlaylistCreated (this); /* EMIT SIGNAL */
54 AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)
55 : Playlist (session, name, hidden)
58 PlaylistCreated (this); /* EMIT SIGNAL */
63 AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, string name, bool hidden)
64 : Playlist (other, name, hidden)
66 RegionList::const_iterator in_o = other.regions.begin();
67 RegionList::iterator in_n = regions.begin();
69 while (in_o != other.regions.end()) {
70 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*in_o);
72 // We look only for crossfades which begin with the current region, so we don't get doubles
73 for (list<Crossfade *>::const_iterator xfades = other._crossfades.begin(); xfades != other._crossfades.end(); ++xfades) {
74 if ((*xfades)->in() == ar) {
75 // We found one! Now copy it!
77 RegionList::const_iterator out_o = other.regions.begin();
78 RegionList::const_iterator out_n = regions.begin();
80 while (out_o != other.regions.end()) {
82 boost::shared_ptr<AudioRegion>ar2 = boost::dynamic_pointer_cast<AudioRegion>(*out_o);
84 if ((*xfades)->out() == ar2) {
85 boost::shared_ptr<AudioRegion>in = boost::dynamic_pointer_cast<AudioRegion>(*in_n);
86 boost::shared_ptr<AudioRegion>out = boost::dynamic_pointer_cast<AudioRegion>(*out_n);
87 Crossfade *new_fade = new Crossfade (*(*xfades), in, out);
88 add_crossfade(*new_fade);
95 // cerr << "HUH!? second region in the crossfade not found!" << endl;
104 PlaylistCreated (this); /* EMIT SIGNAL */
108 AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, nframes_t start, nframes_t cnt, string name, bool hidden)
109 : Playlist (other, start, cnt, name, hidden)
111 /* this constructor does NOT notify others (session) */
114 AudioPlaylist::~AudioPlaylist ()
116 set<Crossfade*> all_xfades;
118 GoingAway (); /* EMIT SIGNAL */
120 /* drop connections to signals */
125 cerr << "deleting crossfades " << _crossfades.size() << endl;
127 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ) {
128 Crossfades::iterator tmp;
135 cerr << _crossfades.size() << " to go\n";
143 struct RegionSortByLayer {
144 bool operator() (boost::shared_ptr<Region>a, boost::shared_ptr<Region>b) {
145 return a->layer() < b->layer();
150 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t start,
151 nframes_t cnt, unsigned chan_n)
155 nframes_t read_frames;
156 nframes_t skip_frames;
158 /* optimizing this memset() away involves a lot of conditionals
159 that may well cause more of a hit due to cache misses
160 and related stuff than just doing this here.
162 it would be great if someone could measure this
165 one way or another, parts of the requested area
166 that are not written to by Region::region_at()
167 for all Regions that cover the area need to be
171 memset (buf, 0, sizeof (Sample) * cnt);
173 /* this function is never called from a realtime thread, so
174 its OK to block (for short intervals).
177 Glib::Mutex::Lock rm (region_lock);
179 end = start + cnt - 1;
183 _read_data_count = 0;
185 map<uint32_t,vector<boost::shared_ptr<Region> > > relevant_regions;
186 map<uint32_t,vector<Crossfade*> > relevant_xfades;
187 vector<uint32_t> relevant_layers;
189 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
190 if ((*i)->coverage (start, end) != OverlapNone) {
191 relevant_regions[(*i)->layer()].push_back (*i);
192 relevant_layers.push_back ((*i)->layer());
196 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
197 if ((*i)->coverage (start, end) != OverlapNone) {
198 relevant_xfades[(*i)->upper_layer()].push_back (*i);
202 // RegionSortByLayer layer_cmp;
203 // relevant_regions.sort (layer_cmp);
205 /* XXX this whole per-layer approach is a hack that
206 should be removed once Crossfades become
207 CrossfadeRegions and we just grab a list of relevant
208 regions and call read_at() on all of them.
211 sort (relevant_layers.begin(), relevant_layers.end());
213 for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
215 vector<boost::shared_ptr<Region> > r (relevant_regions[*l]);
216 vector<Crossfade*>& x (relevant_xfades[*l]);
218 for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
219 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
221 ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
222 _read_data_count += ar->read_data_count();
225 for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
226 (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
228 /* don't JACK up _read_data_count, since its the same data as we just
229 read from the regions, and the OS should handle that for us.
239 AudioPlaylist::remove_dependents (boost::shared_ptr<Region> region)
241 Crossfades::iterator i, tmp;
242 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
249 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
254 for (i = _crossfades.begin(); i != _crossfades.end(); ) {
259 if ((*i)->involves (r)) {
269 AudioPlaylist::flush_notifications ()
271 Playlist::flush_notifications();
279 Crossfades::iterator a;
280 for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
281 NewCrossfade (*a); /* EMIT SIGNAL */
284 _pending_xfade_adds.clear ();
290 AudioPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
292 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(r);
293 set<Crossfade*> updated;
299 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
301 Crossfades::iterator tmp;
306 /* only update them once */
308 if ((*x)->involves (ar)) {
310 if (find (updated.begin(), updated.end(), *x) == updated.end()) {
311 if ((*x)->refresh ()) {
312 /* not invalidated by the refresh */
323 AudioPlaylist::finalize_split_region (boost::shared_ptr<Region> o, boost::shared_ptr<Region> l, boost::shared_ptr<Region> r)
325 boost::shared_ptr<AudioRegion> orig = boost::dynamic_pointer_cast<AudioRegion>(o);
326 boost::shared_ptr<AudioRegion> left = boost::dynamic_pointer_cast<AudioRegion>(l);
327 boost::shared_ptr<AudioRegion> right = boost::dynamic_pointer_cast<AudioRegion>(r);
329 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
330 Crossfades::iterator tmp;
336 if ((*x)->_in == orig) {
337 if (! (*x)->covers(right->position())) {
338 fade = new Crossfade (**x, left, (*x)->_out);
340 // Overlap, the crossfade is copied on the left side of the right region instead
341 fade = new Crossfade (**x, right, (*x)->_out);
345 if ((*x)->_out == orig) {
346 if (! (*x)->covers(right->position())) {
347 fade = new Crossfade (**x, (*x)->_in, right);
349 // Overlap, the crossfade is copied on the right side of the left region instead
350 fade = new Crossfade (**x, (*x)->_in, left);
355 _crossfades.remove (*x);
356 add_crossfade (*fade);
363 AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
365 boost::shared_ptr<AudioRegion> other;
366 boost::shared_ptr<AudioRegion> region;
367 boost::shared_ptr<AudioRegion> top;
368 boost::shared_ptr<AudioRegion> bottom;
371 if (in_set_state || in_partition) {
375 cerr << "Check dependents of " << r->name() << endl;
377 if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
378 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
384 refresh_dependents (r);
387 if (!Config->get_auto_xfade()) {
391 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
393 other = boost::dynamic_pointer_cast<AudioRegion> (*i);
395 if (other == region) {
399 if (other->muted() || region->muted()) {
403 if (other->layer() < region->layer()) {
413 if (top->coverage (bottom->position(), bottom->last_frame()) != OverlapNone) {
415 /* check if the upper region is within the lower region */
417 if (top->first_frame() > bottom->first_frame() &&
418 top->last_frame() < bottom->last_frame()) {
421 /* [ -------- top ------- ]
422 * {=========== bottom =============}
425 /* to avoid discontinuities at the region boundaries of an internal
426 overlap (this region is completely within another), we create
427 two hidden crossfades at each boundary. this is not dependent
428 on the auto-xfade option, because we require it as basic
432 nframes_t xfade_length = min ((nframes_t) 720, top->length());
435 xfade = new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn);
436 add_crossfade (*xfade);
437 xfade = new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut);
438 add_crossfade (*xfade);
442 xfade = new Crossfade (other, region, Config->get_xfade_model(), Config->get_xfades_active());
443 add_crossfade (*xfade);
448 catch (failed_constructor& err) {
452 catch (Crossfade::NoCrossfadeHere& err) {
460 AudioPlaylist::add_crossfade (Crossfade& xfade)
462 Crossfades::iterator ci;
464 cerr << "adding xfade involving " << xfade.in()->name() << " and " << xfade.out()->name() << endl;
466 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
467 cerr << "\tcompare to " << (*ci)->in()->name() << " and " << (*ci)->out()->name() << endl;
468 if (*(*ci) == xfade) { // Crossfade::operator==()
473 if (ci != _crossfades.end()) {
476 _crossfades.push_back (&xfade);
478 xfade.Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
479 xfade.StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
481 notify_crossfade_added (&xfade);
485 void AudioPlaylist::notify_crossfade_added (Crossfade *x)
487 if (g_atomic_int_get(&block_notifications)) {
488 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
490 NewCrossfade (x); /* EMIT SIGNAL */
495 AudioPlaylist::crossfade_invalidated (Crossfade* xfade)
497 Crossfades::iterator i;
499 xfade->in()->resume_fade_in ();
500 xfade->out()->resume_fade_out ();
502 if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
503 _crossfades.erase (i);
508 AudioPlaylist::set_state (const XMLNode& node)
512 XMLNodeConstIterator niter;
517 Playlist::set_state (node);
519 nlist = node.children();
521 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
525 if (child->name() != "Crossfade") {
530 Crossfade* xfade = new Crossfade (*((const Playlist *)this), *child);
531 _crossfades.push_back (xfade);
532 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
533 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
537 catch (failed_constructor& err) {
538 // cout << string_compose (_("could not create crossfade object in playlist %1"),
552 AudioPlaylist::clear (bool with_signals)
554 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ) {
556 Crossfades::iterator tmp;
565 _crossfades.clear ();
567 Playlist::clear (with_signals);
571 AudioPlaylist::state (bool full_state)
573 XMLNode& node = Playlist::state (full_state);
576 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
577 node.add_child_nocopy ((*i)->get_state());
585 AudioPlaylist::dump () const
587 boost::shared_ptr<Region>r;
590 cerr << "Playlist \"" << _name << "\" " << endl
591 << regions.size() << " regions "
592 << _crossfades.size() << " crossfades"
595 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
597 cerr << " " << r->name() << " @ " << r << " ["
598 << r->start() << "+" << r->length()
606 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
617 << (x->active() ? "yes" : "no")
623 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
625 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
626 bool changed = false;
627 Crossfades::iterator c, ctmp;
628 set<Crossfade*> unique_xfades;
631 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
638 RegionLock rlock (this);
639 RegionList::iterator i;
640 RegionList::iterator tmp;
642 for (i = regions.begin(); i != regions.end(); ) {
647 if ((*i) == region) {
656 for (c = _crossfades.begin(); c != _crossfades.end(); ) {
660 if ((*c)->involves (r)) {
661 unique_xfades.insert (*c);
662 _crossfades.erase (c);
668 for (set<Crossfade*>::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) {
673 /* overload this, it normally means "removed", not destroyed */
674 notify_region_removed (region);
681 AudioPlaylist::crossfade_changed (Change ignored)
683 if (in_flush || in_set_state) {
687 /* XXX is there a loop here? can an xfade change not happen
688 due to a playlist change? well, sure activation would
689 be an example. maybe we should check the type of change
697 AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
699 if (in_flush || in_set_state) {
703 Change our_interests = Change (AudioRegion::FadeInChanged|
704 AudioRegion::FadeOutChanged|
705 AudioRegion::FadeInActiveChanged|
706 AudioRegion::FadeOutActiveChanged|
707 AudioRegion::EnvelopeActiveChanged|
708 AudioRegion::ScaleAmplitudeChanged|
709 AudioRegion::EnvelopeChanged);
710 bool parent_wants_notify;
712 parent_wants_notify = Playlist::region_changed (what_changed, region);
714 if ((parent_wants_notify || (what_changed & our_interests))) {
722 AudioPlaylist::crossfades_at (nframes_t frame, Crossfades& clist)
724 RegionLock rlock (this);
726 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
727 nframes_t start, end;
729 start = (*i)->position();
730 end = start + (*i)->overlap_length(); // not length(), important difference
732 if (frame >= start && frame <= end) {
733 clist.push_back (*i);