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::State::~State ()
46 AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden)
47 : Playlist (session, node, DataType::AUDIO, hidden)
49 const XMLProperty* prop = node.property("type");
50 assert(!prop || DataType(prop->value()) == DataType::AUDIO);
56 save_state (_("initial state"));
59 PlaylistCreated (this); /* EMIT SIGNAL */
63 AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)
64 : Playlist (session, name, DataType::AUDIO, hidden)
66 save_state (_("initial state"));
69 PlaylistCreated (this); /* EMIT SIGNAL */
74 AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, string name, bool hidden)
75 : Playlist (other, name, hidden)
77 save_state (_("initial state"));
79 RegionList::const_iterator in_o = other.regions.begin();
80 RegionList::iterator in_n = regions.begin();
82 while (in_o != other.regions.end()) {
83 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*in_o);
85 // We look only for crossfades which begin with the current region, so we don't get doubles
86 for (list<Crossfade *>::const_iterator xfades = other._crossfades.begin(); xfades != other._crossfades.end(); ++xfades) {
87 if ((*xfades)->in() == ar) {
88 // We found one! Now copy it!
90 RegionList::const_iterator out_o = other.regions.begin();
91 RegionList::const_iterator out_n = regions.begin();
93 while (out_o != other.regions.end()) {
95 boost::shared_ptr<AudioRegion>ar2 = boost::dynamic_pointer_cast<AudioRegion>(*out_o);
97 if ((*xfades)->out() == ar2) {
98 boost::shared_ptr<AudioRegion>in = boost::dynamic_pointer_cast<AudioRegion>(*in_n);
99 boost::shared_ptr<AudioRegion>out = boost::dynamic_pointer_cast<AudioRegion>(*out_n);
100 Crossfade *new_fade = new Crossfade (*(*xfades), in, out);
101 add_crossfade(*new_fade);
108 // cerr << "HUH!? second region in the crossfade not found!" << endl;
117 PlaylistCreated (this); /* EMIT SIGNAL */
121 AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, nframes_t start, nframes_t cnt, string name, bool hidden)
122 : Playlist (other, start, cnt, name, hidden)
124 save_state (_("initial state"));
126 /* this constructor does NOT notify others (session) */
129 AudioPlaylist::~AudioPlaylist ()
131 set<Crossfade*> all_xfades;
133 GoingAway (); /* EMIT SIGNAL */
135 /* drop connections to signals */
139 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ++x) {
140 all_xfades.insert (*x);
143 for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
145 AudioPlaylist::State* apstate = dynamic_cast<AudioPlaylist::State*> (*i);
147 for (Crossfades::iterator xf = apstate->crossfades.begin(); xf != apstate->crossfades.end(); ++xf) {
148 all_xfades.insert (*xf);
154 /* delete every crossfade */
156 for (set<Crossfade *>::iterator axf = all_xfades.begin(); axf != all_xfades.end(); ++axf) {
161 struct RegionSortByLayer {
162 bool operator() (boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
163 return a->layer() < b->layer();
168 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t start,
169 nframes_t cnt, unsigned chan_n)
173 nframes_t read_frames;
174 nframes_t skip_frames;
176 /* optimizing this memset() away involves a lot of conditionals
177 that may well cause more of a hit due to cache misses
178 and related stuff than just doing this here.
180 it would be great if someone could measure this
183 one way or another, parts of the requested area
184 that are not written to by Region::region_at()
185 for all Regions that cover the area need to be
189 memset (buf, 0, sizeof (Sample) * cnt);
191 /* this function is never called from a realtime thread, so
192 its OK to block (for short intervals).
195 Glib::Mutex::Lock rm (region_lock);
197 end = start + cnt - 1;
201 _read_data_count = 0;
203 map<uint32_t,vector<boost::shared_ptr<Region> > > relevant_regions;
204 map<uint32_t,vector<Crossfade*> > relevant_xfades;
205 vector<uint32_t> relevant_layers;
207 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
208 if ((*i)->coverage (start, end) != OverlapNone) {
209 relevant_regions[(*i)->layer()].push_back (*i);
210 relevant_layers.push_back ((*i)->layer());
214 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
215 if ((*i)->coverage (start, end) != OverlapNone) {
216 relevant_xfades[(*i)->upper_layer()].push_back (*i);
220 // RegionSortByLayer layer_cmp;
221 // relevant_regions.sort (layer_cmp);
223 /* XXX this whole per-layer approach is a hack that
224 should be removed once Crossfades become
225 CrossfadeRegions and we just grab a list of relevant
226 regions and call read_at() on all of them.
229 sort (relevant_layers.begin(), relevant_layers.end());
231 for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
233 vector<boost::shared_ptr<Region> > r (relevant_regions[*l]);
234 vector<Crossfade*>& x (relevant_xfades[*l]);
236 for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
237 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
239 ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
240 _read_data_count += ar->read_data_count();
243 for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
244 (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
246 /* don't JACK up _read_data_count, since its the same data as we just
247 read from the regions, and the OS should handle that for us.
257 AudioPlaylist::remove_dependents (boost::shared_ptr<Region> region)
259 Crossfades::iterator i, tmp;
260 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
263 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
268 for (i = _crossfades.begin(); i != _crossfades.end(); ) {
272 if ((*i)->involves (r)) {
273 /* do not delete crossfades */
274 _crossfades.erase (i);
283 AudioPlaylist::flush_notifications ()
285 Playlist::flush_notifications();
293 Crossfades::iterator a;
294 for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
295 NewCrossfade (*a); /* EMIT SIGNAL */
298 _pending_xfade_adds.clear ();
304 AudioPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
306 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(r);
307 set<Crossfade*> updated;
313 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
315 Crossfades::iterator tmp;
320 /* only update them once */
322 if ((*x)->involves (ar)) {
324 if (find (updated.begin(), updated.end(), *x) == updated.end()) {
325 if ((*x)->refresh ()) {
326 /* not invalidated by the refresh */
337 AudioPlaylist::finalize_split_region (boost::shared_ptr<Region> o, boost::shared_ptr<Region> l, boost::shared_ptr<Region> r)
339 boost::shared_ptr<AudioRegion> orig = boost::dynamic_pointer_cast<AudioRegion>(o);
340 boost::shared_ptr<AudioRegion> left = boost::dynamic_pointer_cast<AudioRegion>(l);
341 boost::shared_ptr<AudioRegion> right = boost::dynamic_pointer_cast<AudioRegion>(r);
343 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
344 Crossfades::iterator tmp;
350 if ((*x)->_in == orig) {
351 if (! (*x)->covers(right->position())) {
352 fade = new Crossfade (**x, left, (*x)->_out);
354 // Overlap, the crossfade is copied on the left side of the right region instead
355 fade = new Crossfade (**x, right, (*x)->_out);
359 if ((*x)->_out == orig) {
360 if (! (*x)->covers(right->position())) {
361 fade = new Crossfade (**x, (*x)->_in, right);
363 // Overlap, the crossfade is copied on the right side of the left region instead
364 fade = new Crossfade (**x, (*x)->_in, left);
369 _crossfades.remove (*x);
370 add_crossfade (*fade);
377 AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
379 boost::shared_ptr<AudioRegion> other;
380 boost::shared_ptr<AudioRegion> region;
381 boost::shared_ptr<AudioRegion> top;
382 boost::shared_ptr<AudioRegion> bottom;
385 if (in_set_state || in_partition) {
389 if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
390 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
396 refresh_dependents (r);
399 if (!Config->get_auto_xfade()) {
403 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
405 other = boost::dynamic_pointer_cast<AudioRegion> (*i);
407 if (other == region) {
411 if (other->muted() || region->muted()) {
415 if (other->layer() < region->layer()) {
425 if (top->coverage (bottom->position(), bottom->last_frame()) != OverlapNone) {
427 /* check if the upper region is within the lower region */
429 if (top->first_frame() > bottom->first_frame() &&
430 top->last_frame() < bottom->last_frame()) {
433 /* [ -------- top ------- ]
434 * {=========== bottom =============}
437 /* to avoid discontinuities at the region boundaries of an internal
438 overlap (this region is completely within another), we create
439 two hidden crossfades at each boundary. this is not dependent
440 on the auto-xfade option, because we require it as basic
444 nframes_t xfade_length = min ((nframes_t) 720, top->length());
447 xfade = new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn);
448 add_crossfade (*xfade);
449 xfade = new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut);
450 add_crossfade (*xfade);
454 xfade = new Crossfade (other, region, Config->get_xfade_model(), Config->get_crossfades_active());
455 add_crossfade (*xfade);
460 catch (failed_constructor& err) {
464 catch (Crossfade::NoCrossfadeHere& err) {
472 AudioPlaylist::add_crossfade (Crossfade& xfade)
474 Crossfades::iterator ci;
476 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
477 if (*(*ci) == xfade) { // Crossfade::operator==()
482 if (ci != _crossfades.end()) {
485 _crossfades.push_back (&xfade);
487 xfade.Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
488 xfade.StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
490 notify_crossfade_added (&xfade);
494 void AudioPlaylist::notify_crossfade_added (Crossfade *x)
496 if (g_atomic_int_get(&block_notifications)) {
497 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
499 NewCrossfade (x); /* EMIT SIGNAL */
504 AudioPlaylist::crossfade_invalidated (Crossfade* xfade)
506 Crossfades::iterator i;
508 xfade->in()->resume_fade_in ();
509 xfade->out()->resume_fade_out ();
511 if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
512 _crossfades.erase (i);
517 AudioPlaylist::set_state (const XMLNode& node)
521 XMLNodeConstIterator niter;
524 Playlist::set_state (node);
527 nlist = node.children();
529 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
533 if (child->name() == "Crossfade") {
538 xfade = new Crossfade (*((const Playlist *)this), *child);
541 catch (failed_constructor& err) {
542 // cout << string_compose (_("could not create crossfade object in playlist %1"),
548 Crossfades::iterator ci;
550 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
551 if (*(*ci) == *xfade) {
556 if (ci == _crossfades.end()) {
557 _crossfades.push_back (xfade);
558 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
559 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
572 AudioPlaylist::drop_all_states ()
574 set<Crossfade*> all_xfades;
575 set<boost::shared_ptr<Region> > all_regions;
577 /* find every region we've ever used, and add it to the set of
578 all regions. same for xfades;
581 for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
583 AudioPlaylist::State* apstate = dynamic_cast<AudioPlaylist::State*> (*i);
585 for (RegionList::iterator r = apstate->regions.begin(); r != apstate->regions.end(); ++r) {
586 all_regions.insert (*r);
589 for (Crossfades::iterator xf = apstate->crossfades.begin(); xf != apstate->crossfades.end(); ++xf) {
590 all_xfades.insert (*xf);
594 /* now remove from the "all" lists every region that is in the current list. */
596 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
597 set<boost::shared_ptr<Region> >::iterator x = all_regions.find (*i);
598 if (x != all_regions.end()) {
599 all_regions.erase (x);
603 /* ditto for every crossfade */
605 for (list<Crossfade*>::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
606 set<Crossfade*>::iterator x = all_xfades.find (*i);
607 if (x != all_xfades.end()) {
608 all_xfades.erase (x);
612 /* delete every crossfade that is left (ditto as per regions) */
614 for (set<Crossfade *>::iterator axf = all_xfades.begin(); axf != all_xfades.end(); ++axf) {
618 /* Now do the generic thing ... */
620 StateManager::drop_all_states ();
624 AudioPlaylist::state_factory (std::string why) const
626 State* state = new State (why);
628 state->regions = regions;
629 state->region_states.clear ();
630 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
631 state->region_states.push_back ((*i)->get_memento());
634 state->crossfades = _crossfades;
635 state->crossfade_states.clear ();
636 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
637 state->crossfade_states.push_back ((*i)->get_memento());
643 AudioPlaylist::restore_state (StateManager::State& state)
646 RegionLock rlock (this);
647 State* apstate = dynamic_cast<State*> (&state);
651 regions = apstate->regions;
653 for (list<UndoAction>::iterator s = apstate->region_states.begin(); s != apstate->region_states.end(); ++s) {
657 _crossfades = apstate->crossfades;
659 for (list<UndoAction>::iterator s = apstate->crossfade_states.begin(); s != apstate->crossfade_states.end(); ++s) {
663 in_set_state = false;
666 notify_length_changed ();
671 AudioPlaylist::get_memento () const
673 return sigc::bind (mem_fun (*(const_cast<AudioPlaylist*> (this)), &StateManager::use_state), _current_state_id);
677 AudioPlaylist::clear (bool with_save)
679 _crossfades.clear ();
681 Playlist::clear (with_save);
685 AudioPlaylist::state (bool full_state)
687 XMLNode& node = Playlist::state (full_state);
690 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
691 node.add_child_nocopy ((*i)->get_state());
699 AudioPlaylist::dump () const
701 boost::shared_ptr<Region>r;
704 cerr << "Playlist \"" << _name << "\" " << endl
705 << regions.size() << " regions "
706 << _crossfades.size() << " crossfades"
709 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
711 cerr << " " << r->name() << " @ " << r << " ["
712 << r->start() << "+" << r->length()
720 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
731 << (x->active() ? "yes" : "no")
737 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
739 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
740 bool changed = false;
741 Crossfades::iterator c, ctmp;
742 set<Crossfade*> unique_xfades;
745 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
752 RegionLock rlock (this);
753 RegionList::iterator i;
754 RegionList::iterator tmp;
756 for (i = regions.begin(); i != regions.end(); ) {
761 if ((*i) == region) {
770 for (c = _crossfades.begin(); c != _crossfades.end(); ) {
774 if ((*c)->involves (r)) {
775 unique_xfades.insert (*c);
776 _crossfades.erase (c);
782 for (StateMap::iterator s = states.begin(); s != states.end(); ) {
783 StateMap::iterator tmp;
788 State* astate = dynamic_cast<State*> (*s);
790 for (c = astate->crossfades.begin(); c != astate->crossfades.end(); ) {
795 if ((*c)->involves (r)) {
796 unique_xfades.insert (*c);
797 _crossfades.erase (c);
803 list<UndoAction>::iterator rsi, rsitmp;
804 RegionList::iterator ri, ritmp;
806 for (ri = astate->regions.begin(), rsi = astate->region_states.begin();
807 ri != astate->regions.end() && rsi != astate->region_states.end();) {
816 if (region == (*ri)) {
817 astate->regions.erase (ri);
818 astate->region_states.erase (rsi);
828 for (set<Crossfade*>::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) {
833 /* overload this, it normally means "removed", not destroyed */
834 notify_region_removed (region);
841 AudioPlaylist::crossfade_changed (Change ignored)
843 if (in_flush || in_set_state) {
847 /* XXX is there a loop here? can an xfade change not happen
848 due to a playlist change? well, sure activation would
849 be an example. maybe we should check the type of change
853 maybe_save_state (_("xfade change"));
859 AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
861 if (in_flush || in_set_state) {
865 Change our_interests = Change (AudioRegion::FadeInChanged|
866 AudioRegion::FadeOutChanged|
867 AudioRegion::FadeInActiveChanged|
868 AudioRegion::FadeOutActiveChanged|
869 AudioRegion::EnvelopeActiveChanged|
870 AudioRegion::ScaleAmplitudeChanged|
871 AudioRegion::EnvelopeChanged);
872 bool parent_wants_notify;
874 parent_wants_notify = Playlist::region_changed (what_changed, region);
876 maybe_save_state (_("region modified"));
878 if ((parent_wants_notify || (what_changed & our_interests))) {
886 AudioPlaylist::crossfades_at (nframes_t frame, Crossfades& clist)
888 RegionLock rlock (this);
890 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
891 nframes_t start, end;
893 start = (*i)->position();
894 end = start + (*i)->overlap_length(); // not length(), important difference
896 if (frame >= start && frame <= end) {
897 clist.push_back (*i);