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;
41 AudioPlaylist::State::~State ()
45 AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden)
46 : Playlist (session, node, hidden)
52 save_state (_("initial state"));
55 PlaylistCreated (this); /* EMIT SIGNAL */
59 AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)
60 : Playlist (session, name, hidden)
62 save_state (_("initial state"));
65 PlaylistCreated (this); /* EMIT SIGNAL */
70 AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, string name, bool hidden)
71 : Playlist (other, name, hidden)
73 save_state (_("initial state"));
75 list<Region*>::const_iterator in_o = other.regions.begin();
76 list<Region*>::iterator in_n = regions.begin();
78 while (in_o != other.regions.end()) {
79 AudioRegion *ar = dynamic_cast<AudioRegion *>( (*in_o) );
81 // We look only for crossfades which begin with the current region, so we don't get doubles
82 for (list<Crossfade *>::const_iterator xfades = other._crossfades.begin(); xfades != other._crossfades.end(); ++xfades) {
83 if ( &(*xfades)->in() == ar) {
84 // We found one! Now copy it!
86 list<Region*>::const_iterator out_o = other.regions.begin();
87 list<Region*>::const_iterator out_n = regions.begin();
89 while (out_o != other.regions.end()) {
91 AudioRegion *ar2 = dynamic_cast<AudioRegion *>( (*out_o) );
93 if ( &(*xfades)->out() == ar2) {
94 AudioRegion *in = dynamic_cast<AudioRegion*>( (*in_n) );
95 AudioRegion *out = dynamic_cast<AudioRegion*>( (*out_n) );
96 Crossfade *new_fade = new Crossfade( *(*xfades), in, out);
97 add_crossfade(*new_fade);
104 // cerr << "HUH!? second region in the crossfade not found!" << endl;
113 PlaylistCreated (this); /* EMIT SIGNAL */
117 AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden)
118 : Playlist (other, start, cnt, name, hidden)
120 save_state (_("initial state"));
122 /* this constructor does NOT notify others (session) */
125 AudioPlaylist::~AudioPlaylist ()
127 set<Crossfade*> all_xfades;
128 set<Region*> all_regions;
132 /* find every region we've ever used, and add it to the set of
133 all regions. same for xfades;
136 for (RegionList::iterator x = regions.begin(); x != regions.end(); ++x) {
137 all_regions.insert (*x);
140 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ++x) {
141 all_xfades.insert (*x);
144 for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
146 AudioPlaylist::State* apstate = dynamic_cast<AudioPlaylist::State*> (*i);
148 for (RegionList::iterator r = apstate->regions.begin(); r != apstate->regions.end(); ++r) {
149 all_regions.insert (*r);
151 for (Crossfades::iterator xf = apstate->crossfades.begin(); xf != apstate->crossfades.end(); ++xf) {
152 all_xfades.insert (*xf);
158 /* delete every region */
160 for (set<Region *>::iterator ar = all_regions.begin(); ar != all_regions.end(); ++ar) {
161 (*ar)->unlock_sources ();
165 /* delete every crossfade */
167 for (set<Crossfade *>::iterator axf = all_xfades.begin(); axf != all_xfades.end(); ++axf) {
172 struct RegionSortByLayer {
173 bool operator() (Region *a, Region *b) {
174 return a->layer() < b->layer();
179 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, char * workbuf, jack_nframes_t start,
180 jack_nframes_t cnt, unsigned chan_n)
182 jack_nframes_t ret = cnt;
184 jack_nframes_t read_frames;
185 jack_nframes_t skip_frames;
187 /* optimizing this memset() away involves a lot of conditionals
188 that may well cause more of a hit due to cache misses
189 and related stuff than just doing this here.
191 it would be great if someone could measure this
194 one way or another, parts of the requested area
195 that are not written to by Region::region_at()
196 for all Regions that cover the area need to be
200 memset (buf, 0, sizeof (Sample) * cnt);
202 /* this function is never called from a realtime thread, so
203 its OK to block (for short intervals).
206 LockMonitor rm (region_lock, __LINE__, __FILE__);
208 end = start + cnt - 1;
212 _read_data_count = 0;
214 map<uint32_t,vector<Region*> > relevant_regions;
215 map<uint32_t,vector<Crossfade*> > relevant_xfades;
216 vector<uint32_t> relevant_layers;
218 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
219 if ((*i)->coverage (start, end) != OverlapNone) {
221 relevant_regions[(*i)->layer()].push_back (*i);
222 relevant_layers.push_back ((*i)->layer());
226 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
227 if ((*i)->coverage (start, end) != OverlapNone) {
228 relevant_xfades[(*i)->upper_layer()].push_back (*i);
232 // RegionSortByLayer layer_cmp;
233 // relevant_regions.sort (layer_cmp);
235 /* XXX this whole per-layer approach is a hack that
236 should be removed once Crossfades become
237 CrossfadeRegions and we just grab a list of relevant
238 regions and call read_at() on all of them.
241 sort (relevant_layers.begin(), relevant_layers.end());
243 for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
245 vector<Region*>& r (relevant_regions[*l]);
246 vector<Crossfade*>& x (relevant_xfades[*l]);
248 for (vector<Region*>::iterator i = r.begin(); i != r.end(); ++i) {
249 (*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n, read_frames, skip_frames);
250 _read_data_count += (*i)->read_data_count();
253 for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
255 (*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n);
257 /* don't JACK up _read_data_count, since its the same data as we just
258 read from the regions, and the OS should handle that for us.
268 AudioPlaylist::remove_dependents (Region& region)
270 Crossfades::iterator i, tmp;
271 AudioRegion* r = dynamic_cast<AudioRegion*> (®ion);
274 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
279 for (i = _crossfades.begin(); i != _crossfades.end(); ) {
283 if ((*i)->involves (*r)) {
284 /* do not delete crossfades */
285 _crossfades.erase (i);
294 AudioPlaylist::flush_notifications ()
296 Playlist::flush_notifications();
304 Crossfades::iterator a;
305 for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
306 NewCrossfade (*a); /* EMIT SIGNAL */
309 _pending_xfade_adds.clear ();
315 AudioPlaylist::refresh_dependents (Region& r)
317 AudioRegion* ar = dynamic_cast<AudioRegion*>(&r);
318 set<Crossfade*> updated;
324 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
326 Crossfades::iterator tmp;
331 /* only update them once */
333 if ((*x)->involves (*ar)) {
335 if (find (updated.begin(), updated.end(), *x) == updated.end()) {
336 if ((*x)->refresh ()) {
337 /* not invalidated by the refresh */
348 AudioPlaylist::finalize_split_region (Region *o, Region *l, Region *r)
350 AudioRegion *orig = dynamic_cast<AudioRegion*>(o);
351 AudioRegion *left = dynamic_cast<AudioRegion*>(l);
352 AudioRegion *right = dynamic_cast<AudioRegion*>(r);
354 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ++x) {
355 Crossfades::iterator tmp;
357 if ((*x)->_in == orig) {
361 if ((*x)->_out == orig) {
369 AudioPlaylist::check_dependents (Region& r, bool norefresh)
377 if (in_set_state || in_partition) {
381 if ((region = dynamic_cast<AudioRegion*> (&r)) == 0) {
382 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
388 refresh_dependents (r);
391 if (!Config->get_auto_xfade()) {
395 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
397 other = dynamic_cast<AudioRegion*> (*i);
399 if (other == region) {
403 if (other->muted() || region->muted()) {
407 if (other->layer() < region->layer()) {
417 if (top->coverage (bottom->position(), bottom->last_frame()) != OverlapNone) {
419 /* check if the upper region is within the lower region */
421 if (top->first_frame() > bottom->first_frame() &&
422 top->last_frame() < bottom->last_frame()) {
425 /* [ -------- top ------- ]
426 * {=========== bottom =============}
429 /* to avoid discontinuities at the region boundaries of an internal
430 overlap (this region is completely within another), we create
431 two hidden crossfades at each boundary. this is not dependent
432 on the auto-xfade option, because we require it as basic
436 jack_nframes_t xfade_length = min ((jack_nframes_t) 720, top->length());
439 xfade = new Crossfade (*top, *bottom, xfade_length, top->first_frame(), StartOfIn);
440 add_crossfade (*xfade);
441 xfade = new Crossfade (*bottom, *top, xfade_length, top->last_frame() - xfade_length, EndOfOut);
442 add_crossfade (*xfade);
446 xfade = new Crossfade (*other, *region, _session.get_xfade_model(), _session.get_crossfades_active());
447 add_crossfade (*xfade);
452 catch (failed_constructor& err) {
456 catch (Crossfade::NoCrossfadeHere& err) {
464 AudioPlaylist::add_crossfade (Crossfade& xfade)
466 Crossfades::iterator ci;
468 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
469 if (*(*ci) == xfade) { // Crossfade::operator==()
474 if (ci != _crossfades.end()) {
477 _crossfades.push_back (&xfade);
479 xfade.Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
480 xfade.StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
482 notify_crossfade_added (&xfade);
486 void AudioPlaylist::notify_crossfade_added (Crossfade *x)
488 if (atomic_read(&block_notifications)) {
489 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
491 NewCrossfade (x); /* EMIT SIGNAL */
496 AudioPlaylist::crossfade_invalidated (Crossfade* xfade)
498 Crossfades::iterator i;
500 xfade->in().resume_fade_in ();
501 xfade->out().resume_fade_out ();
503 if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
504 _crossfades.erase (i);
509 AudioPlaylist::set_state (const XMLNode& node)
513 XMLNodeConstIterator niter;
516 Playlist::set_state (node);
519 nlist = node.children();
521 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
525 if (child->name() == "Crossfade") {
530 xfade = new Crossfade (*((const Playlist *)this), *child);
533 catch (failed_constructor& err) {
534 // cout << string_compose (_("could not create crossfade object in playlist %1"),
540 Crossfades::iterator ci;
542 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
543 if (*(*ci) == *xfade) {
548 if (ci == _crossfades.end()) {
549 _crossfades.push_back (xfade);
550 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
551 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
552 /* no need to notify here */
564 AudioPlaylist::drop_all_states ()
566 set<Crossfade*> all_xfades;
567 set<Region*> all_regions;
569 /* find every region we've ever used, and add it to the set of
570 all regions. same for xfades;
573 for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
575 AudioPlaylist::State* apstate = dynamic_cast<AudioPlaylist::State*> (*i);
577 for (RegionList::iterator r = apstate->regions.begin(); r != apstate->regions.end(); ++r) {
578 all_regions.insert (*r);
580 for (Crossfades::iterator xf = apstate->crossfades.begin(); xf != apstate->crossfades.end(); ++xf) {
581 all_xfades.insert (*xf);
585 /* now remove from the "all" lists every region that is in the current list. */
587 for (list<Region*>::iterator i = regions.begin(); i != regions.end(); ++i) {
588 set<Region*>::iterator x = all_regions.find (*i);
589 if (x != all_regions.end()) {
590 all_regions.erase (x);
594 /* ditto for every crossfade */
596 for (list<Crossfade*>::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
597 set<Crossfade*>::iterator x = all_xfades.find (*i);
598 if (x != all_xfades.end()) {
599 all_xfades.erase (x);
603 /* delete every region that is left - these are all things that are part of our "history" */
605 for (set<Region *>::iterator ar = all_regions.begin(); ar != all_regions.end(); ++ar) {
606 (*ar)->unlock_sources ();
610 /* delete every crossfade that is left (ditto as per regions) */
612 for (set<Crossfade *>::iterator axf = all_xfades.begin(); axf != all_xfades.end(); ++axf) {
616 /* Now do the generic thing ... */
618 StateManager::drop_all_states ();
622 AudioPlaylist::state_factory (std::string why) const
624 State* state = new State (why);
626 state->regions = regions;
627 state->region_states.clear ();
628 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
629 state->region_states.push_back ((*i)->get_memento());
632 state->crossfades = _crossfades;
633 state->crossfade_states.clear ();
634 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
635 state->crossfade_states.push_back ((*i)->get_memento());
641 AudioPlaylist::restore_state (StateManager::State& state)
644 RegionLock rlock (this);
645 State* apstate = dynamic_cast<State*> (&state);
649 regions = apstate->regions;
651 for (list<UndoAction>::iterator s = apstate->region_states.begin(); s != apstate->region_states.end(); ++s) {
655 _crossfades = apstate->crossfades;
657 for (list<UndoAction>::iterator s = apstate->crossfade_states.begin(); s != apstate->crossfade_states.end(); ++s) {
661 in_set_state = false;
664 notify_length_changed ();
669 AudioPlaylist::get_memento () const
671 return sigc::bind (mem_fun (*(const_cast<AudioPlaylist*> (this)), &StateManager::use_state), _current_state_id);
675 AudioPlaylist::clear (bool with_delete, bool with_save)
678 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
683 _crossfades.clear ();
685 Playlist::clear (with_delete, with_save);
689 AudioPlaylist::state (bool full_state)
691 XMLNode& node = Playlist::state (full_state);
694 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
695 node.add_child_nocopy ((*i)->get_state());
703 AudioPlaylist::dump () const
708 cerr << "Playlist \"" << _name << "\" " << endl
709 << regions.size() << " regions "
710 << _crossfades.size() << " crossfades"
713 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
715 cerr << " " << r->name() << " @ " << r << " ["
716 << r->start() << "+" << r->length()
724 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
735 << (x->active() ? "yes" : "no")
741 AudioPlaylist::destroy_region (Region* region)
743 AudioRegion* r = dynamic_cast<AudioRegion*> (region);
744 bool changed = false;
745 Crossfades::iterator c, ctmp;
746 set<Crossfade*> unique_xfades;
749 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
756 RegionLock rlock (this);
757 RegionList::iterator i;
758 RegionList::iterator tmp;
760 for (i = regions.begin(); i != regions.end(); ) {
765 if ((*i) == region) {
766 (*i)->unlock_sources ();
775 for (c = _crossfades.begin(); c != _crossfades.end(); ) {
779 if ((*c)->involves (*r)) {
780 unique_xfades.insert (*c);
781 _crossfades.erase (c);
787 for (StateMap::iterator s = states.begin(); s != states.end(); ) {
788 StateMap::iterator tmp;
793 State* astate = dynamic_cast<State*> (*s);
795 for (c = astate->crossfades.begin(); c != astate->crossfades.end(); ) {
800 if ((*c)->involves (*r)) {
801 unique_xfades.insert (*c);
802 _crossfades.erase (c);
808 list<UndoAction>::iterator rsi, rsitmp;
809 RegionList::iterator ri, ritmp;
811 for (ri = astate->regions.begin(), rsi = astate->region_states.begin();
812 ri != astate->regions.end() && rsi != astate->region_states.end();) {
821 if (region == (*ri)) {
822 astate->regions.erase (ri);
823 astate->region_states.erase (rsi);
833 for (set<Crossfade*>::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) {
838 /* overload this, it normally means "removed", not destroyed */
839 notify_region_removed (region);
846 AudioPlaylist::crossfade_changed (Change ignored)
848 if (in_flush || in_set_state) {
852 /* XXX is there a loop here? can an xfade change not happen
853 due to a playlist change? well, sure activation would
854 be an example. maybe we should check the type of change
858 maybe_save_state (_("xfade change"));
864 AudioPlaylist::get_equivalent_regions (const AudioRegion& other, vector<AudioRegion*>& results)
866 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
868 AudioRegion* ar = dynamic_cast<AudioRegion*> (*i);
870 if (ar && ar->equivalent (other)) {
871 results.push_back (ar);
877 AudioPlaylist::get_region_list_equivalent_regions (const AudioRegion& other, vector<AudioRegion*>& results)
879 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
881 AudioRegion* ar = dynamic_cast<AudioRegion*> (*i);
883 if (ar && ar->region_list_equivalent (other)) {
884 results.push_back (ar);
890 AudioPlaylist::region_changed (Change what_changed, Region* region)
892 if (in_flush || in_set_state) {
896 Change our_interests = Change (AudioRegion::FadeInChanged|
897 AudioRegion::FadeOutChanged|
898 AudioRegion::FadeInActiveChanged|
899 AudioRegion::FadeOutActiveChanged|
900 AudioRegion::EnvelopeActiveChanged|
901 AudioRegion::ScaleAmplitudeChanged|
902 AudioRegion::EnvelopeChanged);
903 bool parent_wants_notify;
905 parent_wants_notify = Playlist::region_changed (what_changed, region);
907 maybe_save_state (_("region modified"));
909 if ((parent_wants_notify || (what_changed & our_interests))) {
917 AudioPlaylist::crossfades_at (jack_nframes_t frame, Crossfades& clist)
919 RegionLock rlock (this);
921 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
922 jack_nframes_t start, end;
924 start = (*i)->position();
925 end = start + (*i)->overlap_length(); // not length(), important difference
927 if (frame >= start && frame <= end) {
928 clist.push_back (*i);