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::check_dependents (Region& r, bool norefresh)
356 if (in_set_state || in_partition) {
360 if ((region = dynamic_cast<AudioRegion*> (&r)) == 0) {
361 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
367 refresh_dependents (r);
370 if (!Config->get_auto_xfade()) {
374 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
376 other = dynamic_cast<AudioRegion*> (*i);
378 if (other == region) {
382 if (other->muted() || region->muted()) {
386 if (other->layer() < region->layer()) {
396 if (top->coverage (bottom->position(), bottom->last_frame()) != OverlapNone) {
398 /* check if the upper region is within the lower region */
400 if (top->first_frame() > bottom->first_frame() &&
401 top->last_frame() < bottom->last_frame()) {
404 /* [ -------- top ------- ]
405 * {=========== bottom =============}
408 /* to avoid discontinuities at the region boundaries of an internal
409 overlap (this region is completely within another), we create
410 two hidden crossfades at each boundary. this is not dependent
411 on the auto-xfade option, because we require it as basic
415 jack_nframes_t xfade_length = min ((jack_nframes_t) 720, top->length());
418 xfade = new Crossfade (*top, *bottom, xfade_length, top->first_frame(), StartOfIn);
419 add_crossfade (*xfade);
420 xfade = new Crossfade (*bottom, *top, xfade_length, top->last_frame() - xfade_length, EndOfOut);
421 add_crossfade (*xfade);
425 xfade = new Crossfade (*other, *region, _session.get_xfade_model(), _session.get_crossfades_active());
426 add_crossfade (*xfade);
431 catch (failed_constructor& err) {
435 catch (Crossfade::NoCrossfadeHere& err) {
443 AudioPlaylist::add_crossfade (Crossfade& xfade)
445 Crossfades::iterator ci;
447 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
448 if (*(*ci) == xfade) { // Crossfade::operator==()
453 if (ci != _crossfades.end()) {
456 _crossfades.push_back (&xfade);
458 xfade.Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
459 xfade.StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
461 notify_crossfade_added (&xfade);
465 void AudioPlaylist::notify_crossfade_added (Crossfade *x)
467 if (atomic_read(&block_notifications)) {
468 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
470 NewCrossfade (x); /* EMIT SIGNAL */
475 AudioPlaylist::crossfade_invalidated (Crossfade* xfade)
477 Crossfades::iterator i;
479 xfade->in().resume_fade_in ();
480 xfade->out().resume_fade_out ();
482 if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
483 _crossfades.erase (i);
488 AudioPlaylist::set_state (const XMLNode& node)
492 XMLNodeConstIterator niter;
495 Playlist::set_state (node);
498 nlist = node.children();
500 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
504 if (child->name() == "Crossfade") {
509 xfade = new Crossfade (*((const Playlist *)this), *child);
512 catch (failed_constructor& err) {
513 // cout << string_compose (_("could not create crossfade object in playlist %1"),
519 Crossfades::iterator ci;
521 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
522 if (*(*ci) == *xfade) {
527 if (ci == _crossfades.end()) {
528 _crossfades.push_back (xfade);
529 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
530 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
531 /* no need to notify here */
543 AudioPlaylist::drop_all_states ()
545 set<Crossfade*> all_xfades;
546 set<Region*> all_regions;
548 /* find every region we've ever used, and add it to the set of
549 all regions. same for xfades;
552 for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
554 AudioPlaylist::State* apstate = dynamic_cast<AudioPlaylist::State*> (*i);
556 for (RegionList::iterator r = apstate->regions.begin(); r != apstate->regions.end(); ++r) {
557 all_regions.insert (*r);
559 for (Crossfades::iterator xf = apstate->crossfades.begin(); xf != apstate->crossfades.end(); ++xf) {
560 all_xfades.insert (*xf);
564 /* now remove from the "all" lists every region that is in the current list. */
566 for (list<Region*>::iterator i = regions.begin(); i != regions.end(); ++i) {
567 set<Region*>::iterator x = all_regions.find (*i);
568 if (x != all_regions.end()) {
569 all_regions.erase (x);
573 /* ditto for every crossfade */
575 for (list<Crossfade*>::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
576 set<Crossfade*>::iterator x = all_xfades.find (*i);
577 if (x != all_xfades.end()) {
578 all_xfades.erase (x);
582 /* delete every region that is left - these are all things that are part of our "history" */
584 for (set<Region *>::iterator ar = all_regions.begin(); ar != all_regions.end(); ++ar) {
585 (*ar)->unlock_sources ();
589 /* delete every crossfade that is left (ditto as per regions) */
591 for (set<Crossfade *>::iterator axf = all_xfades.begin(); axf != all_xfades.end(); ++axf) {
595 /* Now do the generic thing ... */
597 StateManager::drop_all_states ();
601 AudioPlaylist::state_factory (std::string why) const
603 State* state = new State (why);
605 state->regions = regions;
606 state->region_states.clear ();
607 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
608 state->region_states.push_back ((*i)->get_memento());
611 state->crossfades = _crossfades;
612 state->crossfade_states.clear ();
613 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
614 state->crossfade_states.push_back ((*i)->get_memento());
620 AudioPlaylist::restore_state (StateManager::State& state)
623 RegionLock rlock (this);
624 State* apstate = dynamic_cast<State*> (&state);
628 regions = apstate->regions;
630 for (list<UndoAction>::iterator s = apstate->region_states.begin(); s != apstate->region_states.end(); ++s) {
634 _crossfades = apstate->crossfades;
636 for (list<UndoAction>::iterator s = apstate->crossfade_states.begin(); s != apstate->crossfade_states.end(); ++s) {
640 in_set_state = false;
643 notify_length_changed ();
648 AudioPlaylist::get_memento () const
650 return sigc::bind (mem_fun (*(const_cast<AudioPlaylist*> (this)), &StateManager::use_state), _current_state_id);
654 AudioPlaylist::clear (bool with_delete, bool with_save)
657 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
662 _crossfades.clear ();
664 Playlist::clear (with_delete, with_save);
668 AudioPlaylist::state (bool full_state)
670 XMLNode& node = Playlist::state (full_state);
673 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
674 node.add_child_nocopy ((*i)->get_state());
682 AudioPlaylist::dump () const
687 cerr << "Playlist \"" << _name << "\" " << endl
688 << regions.size() << " regions "
689 << _crossfades.size() << " crossfades"
692 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
694 cerr << " " << r->name() << " @ " << r << " ["
695 << r->start() << "+" << r->length()
703 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
714 << (x->active() ? "yes" : "no")
720 AudioPlaylist::destroy_region (Region* region)
722 AudioRegion* r = dynamic_cast<AudioRegion*> (region);
723 bool changed = false;
724 Crossfades::iterator c, ctmp;
725 set<Crossfade*> unique_xfades;
728 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
735 RegionLock rlock (this);
736 RegionList::iterator i;
737 RegionList::iterator tmp;
739 for (i = regions.begin(); i != regions.end(); ) {
744 if ((*i) == region) {
745 (*i)->unlock_sources ();
754 for (c = _crossfades.begin(); c != _crossfades.end(); ) {
758 if ((*c)->involves (*r)) {
759 unique_xfades.insert (*c);
760 _crossfades.erase (c);
766 for (StateMap::iterator s = states.begin(); s != states.end(); ) {
767 StateMap::iterator tmp;
772 State* astate = dynamic_cast<State*> (*s);
774 for (c = astate->crossfades.begin(); c != astate->crossfades.end(); ) {
779 if ((*c)->involves (*r)) {
780 unique_xfades.insert (*c);
781 _crossfades.erase (c);
787 list<UndoAction>::iterator rsi, rsitmp;
788 RegionList::iterator ri, ritmp;
790 for (ri = astate->regions.begin(), rsi = astate->region_states.begin();
791 ri != astate->regions.end() && rsi != astate->region_states.end();) {
800 if (region == (*ri)) {
801 astate->regions.erase (ri);
802 astate->region_states.erase (rsi);
812 for (set<Crossfade*>::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) {
817 /* overload this, it normally means "removed", not destroyed */
818 notify_region_removed (region);
825 AudioPlaylist::crossfade_changed (Change ignored)
827 if (in_flush || in_set_state) {
831 /* XXX is there a loop here? can an xfade change not happen
832 due to a playlist change? well, sure activation would
833 be an example. maybe we should check the type of change
837 maybe_save_state (_("xfade change"));
843 AudioPlaylist::get_equivalent_regions (const AudioRegion& other, vector<AudioRegion*>& results)
845 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
847 AudioRegion* ar = dynamic_cast<AudioRegion*> (*i);
849 if (ar && ar->equivalent (other)) {
850 results.push_back (ar);
856 AudioPlaylist::get_region_list_equivalent_regions (const AudioRegion& other, vector<AudioRegion*>& results)
858 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
860 AudioRegion* ar = dynamic_cast<AudioRegion*> (*i);
862 if (ar && ar->region_list_equivalent (other)) {
863 results.push_back (ar);
869 AudioPlaylist::region_changed (Change what_changed, Region* region)
871 if (in_flush || in_set_state) {
875 Change our_interests = Change (AudioRegion::FadeInChanged|
876 AudioRegion::FadeOutChanged|
877 AudioRegion::FadeInActiveChanged|
878 AudioRegion::FadeOutActiveChanged|
879 AudioRegion::EnvelopeActiveChanged|
880 AudioRegion::ScaleAmplitudeChanged|
881 AudioRegion::EnvelopeChanged);
882 bool parent_wants_notify;
884 parent_wants_notify = Playlist::region_changed (what_changed, region);
886 maybe_save_state (_("region modified"));
888 if ((parent_wants_notify || (what_changed & our_interests))) {
896 AudioPlaylist::crossfades_at (jack_nframes_t frame, Crossfades& clist)
898 RegionLock rlock (this);
900 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
901 jack_nframes_t start, end;
903 start = (*i)->position();
904 end = start + (*i)->overlap_length(); // not length(), important difference
906 if (frame >= start && frame <= end) {
907 clist.push_back (*i);