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
69 for (Crossfades::const_iterator xfades = other->_crossfades.begin(); xfades != other->_crossfades.end(); ++xfades) {
70 if ((*xfades)->in() == ar) {
71 // We found one! Now copy it!
73 RegionList::const_iterator out_o = other->regions.begin();
74 RegionList::const_iterator out_n = regions.begin();
76 while (out_o != other->regions.end()) {
78 boost::shared_ptr<AudioRegion>ar2 = boost::dynamic_pointer_cast<AudioRegion>(*out_o);
80 if ((*xfades)->out() == ar2) {
81 boost::shared_ptr<AudioRegion>in = boost::dynamic_pointer_cast<AudioRegion>(*in_n);
82 boost::shared_ptr<AudioRegion>out = boost::dynamic_pointer_cast<AudioRegion>(*out_n);
83 boost::shared_ptr<Crossfade> new_fade = boost::shared_ptr<Crossfade> (new Crossfade (*xfades, in, out));
84 add_crossfade(new_fade);
91 // cerr << "HUH!? second region in the crossfade not found!" << endl;
100 AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, nframes_t start, nframes_t cnt, string name, bool hidden)
101 : Playlist (other, start, cnt, name, hidden)
103 /* this constructor does NOT notify others (session) */
106 AudioPlaylist::~AudioPlaylist ()
108 GoingAway (); /* EMIT SIGNAL */
110 /* drop connections to signals */
114 _crossfades.clear ();
118 AudioPlaylist::copy_regions (RegionList& newlist) const
120 RegionLock rlock (const_cast<Playlist *> (this));
122 Playlist::copy_regions (newlist, false);
124 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
125 if (!(*i)->is_dependent()) {
126 newlist.push_back (RegionFactory::RegionFactory::create (*i));
132 struct RegionSortByLayer {
133 bool operator() (boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
134 return a->layer() < b->layer();
139 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t start,
140 nframes_t cnt, unsigned chan_n)
145 /* optimizing this memset() away involves a lot of conditionals
146 that may well cause more of a hit due to cache misses
147 and related stuff than just doing this here.
149 it would be great if someone could measure this
152 one way or another, parts of the requested area
153 that are not written to by Region::region_at()
154 for all Regions that cover the area need to be
158 memset (buf, 0, sizeof (Sample) * cnt);
160 /* this function is never called from a realtime thread, so
161 its OK to block (for short intervals).
164 Glib::Mutex::Lock rm (region_lock);
166 end = start + cnt - 1;
168 _read_data_count = 0;
170 map<uint32_t,vector<boost::shared_ptr<Region> > > relevant_regions;
171 map<uint32_t,vector<boost::shared_ptr<Crossfade> > > relevant_xfades;
172 vector<uint32_t> relevant_layers;
174 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
175 if ((*i)->coverage (start, end) != OverlapNone) {
176 relevant_regions[(*i)->layer()].push_back (*i);
177 relevant_layers.push_back ((*i)->layer());
181 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
182 if ((*i)->coverage (start, end) != OverlapNone) {
183 relevant_xfades[(*i)->upper_layer()].push_back (*i);
187 // RegionSortByLayer layer_cmp;
188 // relevant_regions.sort (layer_cmp);
190 /* XXX this whole per-layer approach is a hack that
191 should be removed once Crossfades become
192 CrossfadeRegions and we just grab a list of relevant
193 regions and call read_at() on all of them.
196 sort (relevant_layers.begin(), relevant_layers.end());
198 for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
200 vector<boost::shared_ptr<Region> > r (relevant_regions[*l]);
201 vector<boost::shared_ptr<Crossfade> >& x (relevant_xfades[*l]);
203 for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
204 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
206 ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
207 _read_data_count += ar->read_data_count();
210 for (vector<boost::shared_ptr<Crossfade> >::iterator i = x.begin(); i != x.end(); ++i) {
211 (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
213 /* don't JACK up _read_data_count, since its the same data as we just
214 read from the regions, and the OS should handle that for us.
224 AudioPlaylist::remove_dependents (boost::shared_ptr<Region> region)
226 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
233 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
238 for (RegionList::iterator i = regions.begin(); i != regions.end(); ) {
240 if ((*i)->depends_on (r)) {
241 i = regions.erase (i);
250 AudioPlaylist::flush_notifications ()
252 Playlist::flush_notifications();
260 Crossfades::iterator a;
261 for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
262 NewCrossfade (*a); /* EMIT SIGNAL */
265 _pending_xfade_adds.clear ();
271 AudioPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
273 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(r);
274 set<boost::shared_ptr<Crossfade> > updated;
280 for (RegionList::iterator x = regions.begin(); x != regions.end();) {
282 RegionList::iterator tmp;
287 /* only update them once */
289 if ((*x)->depends_on (ar)) {
291 if (find (updated.begin(), updated.end(), *x) == updated.end()) {
293 if ((*x)->refresh ()) {
298 catch (Crossfade::NoCrossfadeHere& err) {
299 // relax, Invalidated during refresh
309 AudioPlaylist::finalize_split_region (boost::shared_ptr<Region> o, boost::shared_ptr<Region> l, boost::shared_ptr<Region> r)
311 boost::shared_ptr<AudioRegion> orig = boost::dynamic_pointer_cast<AudioRegion>(o);
312 boost::shared_ptr<AudioRegion> left = boost::dynamic_pointer_cast<AudioRegion>(l);
313 boost::shared_ptr<AudioRegion> right = boost::dynamic_pointer_cast<AudioRegion>(r);
315 for (RegionList::iterator x = regions.begin(); x !=regions.end();) {
316 Crossfades::iterator tmp;
317 boost::shared_ptr<Crossfade> xfade = boost::dynamic_pointer_cast<Crossfade>(*x);
327 boost::shared_ptr<Crossfade> fade;
329 if (xfade->_in == orig) {
330 if (! xfade->covers(right->position())) {
331 fade = boost::shared_ptr<Crossfade> (new Crossfade (*xfade, left, xfade->_out));
333 // Overlap, the crossfade is copied on the left side of the right region instead
334 fade = boost::shared_ptr<Crossfade> (new Crossfade (*xfade, right, xfade->_out));
338 if (xfade->_out == orig) {
339 if (! xfade->covers(right->position())) {
340 fade = boost::shared_ptr<Crossfade> (new Crossfade (*xfade, xfade->_in, right));
342 // Overlap, the crossfade is copied on the right side of the left region instead
343 fade = boost::shared_ptr<Crossfade> (new Crossfade (*xfade, xfade->_in, left));
349 add_crossfade (fade);
357 AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
359 boost::shared_ptr<AudioRegion> other;
360 boost::shared_ptr<AudioRegion> region;
361 boost::shared_ptr<AudioRegion> top;
362 boost::shared_ptr<AudioRegion> bottom;
363 boost::shared_ptr<Crossfade> xfade;
365 if (in_set_state || in_partition) {
369 if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
370 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
376 refresh_dependents (r);
380 if (!Config->get_auto_xfade()) {
384 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
386 nframes_t xfade_length;
388 other = boost::dynamic_pointer_cast<AudioRegion> (*i);
390 if (other == region) {
394 if (other->muted() || region->muted()) {
399 if (other->layer() < region->layer()) {
409 OverlapType c = top->coverage (bottom->position(), bottom->last_frame());
416 case OverlapInternal:
417 /* {=============== top =============}
418 * [ ----- bottom ------- ]
422 case OverlapExternal:
424 /* [ -------- top ------- ]
425 * {=========== bottom =============}
428 /* to avoid discontinuities at the region boundaries of an internal
429 overlap (this region is completely within another), we create
430 two hidden crossfades at each boundary. this is not dependent
431 on the auto-xfade option, because we require it as basic
435 xfade_length = min ((nframes_t) 720, top->length());
437 xfade = boost::shared_ptr<Crossfade> (new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn));
438 add_crossfade (xfade);
440 if (top_region_at (top->last_frame() - 1) == top) {
442 only add a fade out if there is no region on top of the end of 'top' (which
446 xfade = boost::shared_ptr<Crossfade> (new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut));
447 add_crossfade (xfade);
452 xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
453 add_crossfade (xfade);
457 catch (failed_constructor& err) {
461 catch (Crossfade::NoCrossfadeHere& err) {
469 AudioPlaylist::add_crossfade (boost::shared_ptr<Crossfade> new_xfade)
471 RegionList::iterator r;
472 boost::shared_ptr<Crossfade> xfade;
474 for (r = regions.begin(); r != regions.end(); ++r) {
476 if ((xfade = boost::dynamic_pointer_cast<Crossfade>(*r))) {
477 if (*xfade == *new_xfade) { // Crossfade::operator==()
483 if (r != regions.end()) {
484 // it will just go away
486 add_region_internal (new_xfade);
488 new_xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
489 new_xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
491 notify_crossfade_added (new_xfade);
495 void AudioPlaylist::notify_crossfade_added (boost::shared_ptr<Crossfade> x)
497 if (g_atomic_int_get(&block_notifications)) {
498 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
500 NewCrossfade (x); /* EMIT SIGNAL */
505 AudioPlaylist::crossfade_invalidated (boost::shared_ptr<Region> r)
507 boost::shared_ptr<Crossfade> xfade = boost::dynamic_pointer_cast<Crossfade> (r);
509 xfade->in()->resume_fade_in ();
510 xfade->out()->resume_fade_out ();
512 remove_region_internal (r);
516 AudioPlaylist::set_state (const XMLNode& node)
520 XMLNodeConstIterator niter;
525 Playlist::set_state (node);
527 nlist = node.children();
529 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
533 if (child->name() != Crossfade::node_name()) {
538 boost::shared_ptr<Crossfade> xfade = boost::dynamic_pointer_cast<Crossfade> (RegionFactory::create (*((const Playlist *) this), *child));
540 add_region_internal (xfade);
541 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
542 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
546 catch (failed_constructor& err) {
547 // cout << string_compose (_("could not create crossfade object in playlist %1"),
561 AudioPlaylist::clear (bool with_signals)
563 Playlist::clear (with_signals);
567 AudioPlaylist::dump () const
569 boost::shared_ptr<Region>r;
570 boost::shared_ptr<Crossfade> x;
572 cerr << "Playlist \"" << _name << "\" " << endl
573 << regions.size() << " regions "
576 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
579 if ((x = boost::dynamic_pointer_cast<Crossfade> (r))) {
589 << (x->active() ? "yes" : "no")
592 cerr << " " << r->name() << " @ " << r << " ["
593 << r->start() << "+" << r->length()
604 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
606 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
607 bool changed = false;
610 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
617 RegionLock rlock (this);
619 for (RegionList::iterator i = regions.begin(); i != regions.end(); ) {
621 RegionList::iterator tmp = i;
624 if ((*i) == region) {
627 } else if ((*i)->depends_on (region)) {
635 for (set<boost::shared_ptr<Region> >::iterator x = all_regions.begin(); x != all_regions.end(); ) {
637 set<boost::shared_ptr<Region> >::iterator xtmp = x;
640 if ((*x) == region) {
641 all_regions.erase (x);
643 } else if ((*x)->depends_on (region)) {
644 all_regions.erase (x);
651 region->set_playlist (boost::shared_ptr<Playlist>());
655 /* overload this, it normally means "removed", not destroyed */
656 notify_region_removed (region);
663 AudioPlaylist::crossfade_changed (Change ignored)
665 if (in_flush || in_set_state) {
669 /* XXX is there a loop here? can an xfade change not happen
670 due to a playlist change? well, sure activation would
671 be an example. maybe we should check the type of change
679 AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
681 if (in_flush || in_set_state) {
685 Change our_interests = Change (AudioRegion::FadeInChanged|
686 AudioRegion::FadeOutChanged|
687 AudioRegion::FadeInActiveChanged|
688 AudioRegion::FadeOutActiveChanged|
689 AudioRegion::EnvelopeActiveChanged|
690 AudioRegion::ScaleAmplitudeChanged|
691 AudioRegion::EnvelopeChanged);
692 bool parent_wants_notify;
694 parent_wants_notify = Playlist::region_changed (what_changed, region);
696 if ((parent_wants_notify || (what_changed & our_interests))) {