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 */
124 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ) {
125 Crossfades::iterator tmp;
136 struct RegionSortByLayer {
137 bool operator() (boost::shared_ptr<Region>a, boost::shared_ptr<Region>b) {
138 return a->layer() < b->layer();
143 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t start,
144 nframes_t cnt, unsigned chan_n)
148 nframes_t read_frames;
149 nframes_t skip_frames;
151 /* optimizing this memset() away involves a lot of conditionals
152 that may well cause more of a hit due to cache misses
153 and related stuff than just doing this here.
155 it would be great if someone could measure this
158 one way or another, parts of the requested area
159 that are not written to by Region::region_at()
160 for all Regions that cover the area need to be
164 memset (buf, 0, sizeof (Sample) * cnt);
166 /* this function is never called from a realtime thread, so
167 its OK to block (for short intervals).
170 Glib::Mutex::Lock rm (region_lock);
172 end = start + cnt - 1;
176 _read_data_count = 0;
178 map<uint32_t,vector<boost::shared_ptr<Region> > > relevant_regions;
179 map<uint32_t,vector<Crossfade*> > relevant_xfades;
180 vector<uint32_t> relevant_layers;
182 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
183 if ((*i)->coverage (start, end) != OverlapNone) {
184 relevant_regions[(*i)->layer()].push_back (*i);
185 relevant_layers.push_back ((*i)->layer());
189 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
190 if ((*i)->coverage (start, end) != OverlapNone) {
191 relevant_xfades[(*i)->upper_layer()].push_back (*i);
195 // RegionSortByLayer layer_cmp;
196 // relevant_regions.sort (layer_cmp);
198 /* XXX this whole per-layer approach is a hack that
199 should be removed once Crossfades become
200 CrossfadeRegions and we just grab a list of relevant
201 regions and call read_at() on all of them.
204 sort (relevant_layers.begin(), relevant_layers.end());
206 for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
208 vector<boost::shared_ptr<Region> > r (relevant_regions[*l]);
209 vector<Crossfade*>& x (relevant_xfades[*l]);
211 for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
212 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
214 ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
215 _read_data_count += ar->read_data_count();
218 for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
219 (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
221 /* don't JACK up _read_data_count, since its the same data as we just
222 read from the regions, and the OS should handle that for us.
232 AudioPlaylist::remove_dependents (boost::shared_ptr<Region> region)
234 Crossfades::iterator i, tmp;
235 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
242 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
247 for (i = _crossfades.begin(); i != _crossfades.end(); ) {
252 if ((*i)->involves (r)) {
262 AudioPlaylist::flush_notifications ()
264 Playlist::flush_notifications();
272 Crossfades::iterator a;
273 for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
274 NewCrossfade (*a); /* EMIT SIGNAL */
277 _pending_xfade_adds.clear ();
283 AudioPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
285 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(r);
286 set<Crossfade*> updated;
292 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
294 Crossfades::iterator tmp;
299 /* only update them once */
301 if ((*x)->involves (ar)) {
303 if (find (updated.begin(), updated.end(), *x) == updated.end()) {
304 if ((*x)->refresh ()) {
305 /* not invalidated by the refresh */
316 AudioPlaylist::finalize_split_region (boost::shared_ptr<Region> o, boost::shared_ptr<Region> l, boost::shared_ptr<Region> r)
318 boost::shared_ptr<AudioRegion> orig = boost::dynamic_pointer_cast<AudioRegion>(o);
319 boost::shared_ptr<AudioRegion> left = boost::dynamic_pointer_cast<AudioRegion>(l);
320 boost::shared_ptr<AudioRegion> right = boost::dynamic_pointer_cast<AudioRegion>(r);
322 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
323 Crossfades::iterator tmp;
329 if ((*x)->_in == orig) {
330 if (! (*x)->covers(right->position())) {
331 fade = new Crossfade (**x, left, (*x)->_out);
333 // Overlap, the crossfade is copied on the left side of the right region instead
334 fade = new Crossfade (**x, right, (*x)->_out);
338 if ((*x)->_out == orig) {
339 if (! (*x)->covers(right->position())) {
340 fade = new Crossfade (**x, (*x)->_in, right);
342 // Overlap, the crossfade is copied on the right side of the left region instead
343 fade = new Crossfade (**x, (*x)->_in, left);
348 _crossfades.remove (*x);
349 add_crossfade (*fade);
356 AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
358 boost::shared_ptr<AudioRegion> other;
359 boost::shared_ptr<AudioRegion> region;
360 boost::shared_ptr<AudioRegion> top;
361 boost::shared_ptr<AudioRegion> bottom;
364 if (in_set_state || in_partition) {
368 if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
369 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
375 refresh_dependents (r);
378 if (!Config->get_auto_xfade()) {
382 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
384 other = boost::dynamic_pointer_cast<AudioRegion> (*i);
386 if (other == region) {
390 if (other->muted() || region->muted()) {
394 if (other->layer() < region->layer()) {
404 if (top->coverage (bottom->position(), bottom->last_frame()) != OverlapNone) {
406 /* check if the upper region is within the lower region */
408 if (top->first_frame() > bottom->first_frame() &&
409 top->last_frame() < bottom->last_frame()) {
412 /* [ -------- top ------- ]
413 * {=========== bottom =============}
416 /* to avoid discontinuities at the region boundaries of an internal
417 overlap (this region is completely within another), we create
418 two hidden crossfades at each boundary. this is not dependent
419 on the auto-xfade option, because we require it as basic
423 nframes_t xfade_length = min ((nframes_t) 720, top->length());
426 xfade = new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn);
427 add_crossfade (*xfade);
429 if (top_region_at (top->last_frame() - 1) == top) {
431 only add a fade out if there is no region on top of the end of 'top' (which
434 xfade = new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut);
435 add_crossfade (*xfade);
440 xfade = new Crossfade (other, region, Config->get_xfade_model(), Config->get_xfades_active());
441 add_crossfade (*xfade);
446 catch (failed_constructor& err) {
450 catch (Crossfade::NoCrossfadeHere& err) {
458 AudioPlaylist::add_crossfade (Crossfade& xfade)
460 Crossfades::iterator ci;
462 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
463 if (*(*ci) == xfade) { // Crossfade::operator==()
468 if (ci != _crossfades.end()) {
471 _crossfades.push_back (&xfade);
473 xfade.Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
474 xfade.StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
476 notify_crossfade_added (&xfade);
480 void AudioPlaylist::notify_crossfade_added (Crossfade *x)
482 if (g_atomic_int_get(&block_notifications)) {
483 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
485 NewCrossfade (x); /* EMIT SIGNAL */
490 AudioPlaylist::crossfade_invalidated (Crossfade* xfade)
492 Crossfades::iterator i;
494 xfade->in()->resume_fade_in ();
495 xfade->out()->resume_fade_out ();
497 if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
498 _crossfades.erase (i);
503 AudioPlaylist::set_state (const XMLNode& node)
507 XMLNodeConstIterator niter;
512 Playlist::set_state (node);
514 nlist = node.children();
516 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
520 if (child->name() != "Crossfade") {
525 Crossfade* xfade = new Crossfade (*((const Playlist *)this), *child);
526 _crossfades.push_back (xfade);
527 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
528 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
532 catch (failed_constructor& err) {
533 // cout << string_compose (_("could not create crossfade object in playlist %1"),
547 AudioPlaylist::clear (bool with_signals)
549 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ) {
551 Crossfades::iterator tmp;
560 _crossfades.clear ();
562 Playlist::clear (with_signals);
566 AudioPlaylist::state (bool full_state)
568 XMLNode& node = Playlist::state (full_state);
571 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
572 node.add_child_nocopy ((*i)->get_state());
580 AudioPlaylist::dump () const
582 boost::shared_ptr<Region>r;
585 cerr << "Playlist \"" << _name << "\" " << endl
586 << regions.size() << " regions "
587 << _crossfades.size() << " crossfades"
590 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
592 cerr << " " << r->name() << " @ " << r << " ["
593 << r->start() << "+" << r->length()
601 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
612 << (x->active() ? "yes" : "no")
618 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
620 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
621 bool changed = false;
622 Crossfades::iterator c, ctmp;
623 set<Crossfade*> unique_xfades;
626 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
633 RegionLock rlock (this);
635 for (RegionList::iterator i = regions.begin(); i != regions.end(); ) {
637 RegionList::iterator tmp = i;
640 if ((*i) == region) {
648 for (set<boost::shared_ptr<Region> >::iterator x = all_regions.begin(); x != all_regions.end(); ) {
650 set<boost::shared_ptr<Region> >::iterator xtmp = x;
653 if ((*x) == region) {
654 all_regions.erase (x);
661 region->set_playlist (0);
664 for (c = _crossfades.begin(); c != _crossfades.end(); ) {
668 if ((*c)->involves (r)) {
669 unique_xfades.insert (*c);
670 _crossfades.erase (c);
676 for (set<Crossfade*>::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) {
681 /* overload this, it normally means "removed", not destroyed */
682 notify_region_removed (region);
689 AudioPlaylist::crossfade_changed (Change ignored)
691 if (in_flush || in_set_state) {
695 /* XXX is there a loop here? can an xfade change not happen
696 due to a playlist change? well, sure activation would
697 be an example. maybe we should check the type of change
705 AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
707 if (in_flush || in_set_state) {
711 Change our_interests = Change (AudioRegion::FadeInChanged|
712 AudioRegion::FadeOutChanged|
713 AudioRegion::FadeInActiveChanged|
714 AudioRegion::FadeOutActiveChanged|
715 AudioRegion::EnvelopeActiveChanged|
716 AudioRegion::ScaleAmplitudeChanged|
717 AudioRegion::EnvelopeChanged);
718 bool parent_wants_notify;
720 parent_wants_notify = Playlist::region_changed (what_changed, region);
722 if ((parent_wants_notify || (what_changed & our_interests))) {
730 AudioPlaylist::crossfades_at (nframes_t frame, Crossfades& clist)
732 RegionLock rlock (this);
734 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
735 nframes_t start, end;
737 start = (*i)->position();
738 end = start + (*i)->overlap_length(); // not length(), important difference
740 if (frame >= start && frame <= end) {
741 clist.push_back (*i);