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 list<Region*>::const_iterator in_o = other.regions.begin();
80 list<Region*>::iterator in_n = regions.begin();
82 while (in_o != other.regions.end()) {
83 AudioRegion *ar = dynamic_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 list<Region*>::const_iterator out_o = other.regions.begin();
91 list<Region*>::const_iterator out_n = regions.begin();
93 while (out_o != other.regions.end()) {
95 AudioRegion *ar2 = dynamic_cast<AudioRegion *>( (*out_o) );
97 if ( &(*xfades)->out() == ar2) {
98 AudioRegion *in = dynamic_cast<AudioRegion*>( (*in_n) );
99 AudioRegion *out = dynamic_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, jack_nframes_t start, jack_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;
132 set<Region*> all_regions;
136 /* find every region we've ever used, and add it to the set of
137 all regions. same for xfades;
140 for (RegionList::iterator x = regions.begin(); x != regions.end(); ++x) {
141 all_regions.insert (*x);
144 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ++x) {
145 all_xfades.insert (*x);
148 for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
150 AudioPlaylist::State* apstate = dynamic_cast<AudioPlaylist::State*> (*i);
152 for (RegionList::iterator r = apstate->regions.begin(); r != apstate->regions.end(); ++r) {
153 all_regions.insert (*r);
155 for (Crossfades::iterator xf = apstate->crossfades.begin(); xf != apstate->crossfades.end(); ++xf) {
156 all_xfades.insert (*xf);
162 /* delete every region */
164 for (set<Region *>::iterator ar = all_regions.begin(); ar != all_regions.end(); ++ar) {
165 (*ar)->unlock_sources ();
169 /* delete every crossfade */
171 for (set<Crossfade *>::iterator axf = all_xfades.begin(); axf != all_xfades.end(); ++axf) {
176 struct RegionSortByLayer {
177 bool operator() (Region *a, Region *b) {
178 return a->layer() < b->layer();
183 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, jack_nframes_t start,
184 jack_nframes_t cnt, unsigned chan_n)
186 jack_nframes_t ret = cnt;
188 jack_nframes_t read_frames;
189 jack_nframes_t skip_frames;
191 /* optimizing this memset() away involves a lot of conditionals
192 that may well cause more of a hit due to cache misses
193 and related stuff than just doing this here.
195 it would be great if someone could measure this
198 one way or another, parts of the requested area
199 that are not written to by Region::region_at()
200 for all Regions that cover the area need to be
204 memset (buf, 0, sizeof (Sample) * cnt);
206 /* this function is never called from a realtime thread, so
207 its OK to block (for short intervals).
210 Glib::Mutex::Lock rm (region_lock);
212 end = start + cnt - 1;
216 _read_data_count = 0;
218 map<uint32_t,vector<Region*> > relevant_regions;
219 map<uint32_t,vector<Crossfade*> > relevant_xfades;
220 vector<uint32_t> relevant_layers;
222 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
223 if ((*i)->coverage (start, end) != OverlapNone) {
225 relevant_regions[(*i)->layer()].push_back (*i);
226 relevant_layers.push_back ((*i)->layer());
230 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
231 if ((*i)->coverage (start, end) != OverlapNone) {
232 relevant_xfades[(*i)->upper_layer()].push_back (*i);
236 // RegionSortByLayer layer_cmp;
237 // relevant_regions.sort (layer_cmp);
239 /* XXX this whole per-layer approach is a hack that
240 should be removed once Crossfades become
241 CrossfadeRegions and we just grab a list of relevant
242 regions and call read_at() on all of them.
245 sort (relevant_layers.begin(), relevant_layers.end());
247 for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
249 // FIXME: Should be vector<AudioRegion*>
250 vector<Region*>& r (relevant_regions[*l]);
251 vector<Crossfade*>& x (relevant_xfades[*l]);
253 for (vector<Region*>::iterator i = r.begin(); i != r.end(); ++i) {
254 AudioRegion* const ar = dynamic_cast<AudioRegion*>(*i);
256 ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
257 _read_data_count += ar->read_data_count();
260 for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
261 (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
263 /* don't JACK up _read_data_count, since its the same data as we just
264 read from the regions, and the OS should handle that for us.
274 AudioPlaylist::remove_dependents (Region& region)
276 Crossfades::iterator i, tmp;
277 AudioRegion* r = dynamic_cast<AudioRegion*> (®ion);
280 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
285 for (i = _crossfades.begin(); i != _crossfades.end(); ) {
289 if ((*i)->involves (*r)) {
290 /* do not delete crossfades */
291 _crossfades.erase (i);
300 AudioPlaylist::flush_notifications ()
302 Playlist::flush_notifications();
310 Crossfades::iterator a;
311 for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
312 NewCrossfade (*a); /* EMIT SIGNAL */
315 _pending_xfade_adds.clear ();
321 AudioPlaylist::refresh_dependents (Region& r)
323 AudioRegion* ar = dynamic_cast<AudioRegion*>(&r);
324 set<Crossfade*> updated;
330 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
332 Crossfades::iterator tmp;
337 /* only update them once */
339 if ((*x)->involves (*ar)) {
341 if (find (updated.begin(), updated.end(), *x) == updated.end()) {
342 if ((*x)->refresh ()) {
343 /* not invalidated by the refresh */
354 AudioPlaylist::finalize_split_region (Region *o, Region *l, Region *r)
356 AudioRegion *orig = dynamic_cast<AudioRegion*>(o);
357 AudioRegion *left = dynamic_cast<AudioRegion*>(l);
358 AudioRegion *right = dynamic_cast<AudioRegion*>(r);
360 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
361 Crossfades::iterator tmp;
367 if ((*x)->_in == orig) {
368 if (! (*x)->covers(right->position())) {
369 fade = new Crossfade( *(*x), left, (*x)->_out);
371 // Overlap, the crossfade is copied on the left side of the right region instead
372 fade = new Crossfade( *(*x), right, (*x)->_out);
376 if ((*x)->_out == orig) {
377 if (! (*x)->covers(right->position())) {
378 fade = new Crossfade( *(*x), (*x)->_in, right);
380 // Overlap, the crossfade is copied on the right side of the left region instead
381 fade = new Crossfade( *(*x), (*x)->_in, left);
386 _crossfades.remove( (*x) );
387 add_crossfade (*fade);
394 AudioPlaylist::check_dependents (Region& r, bool norefresh)
402 if (in_set_state || in_partition) {
406 if ((region = dynamic_cast<AudioRegion*> (&r)) == 0) {
407 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
413 refresh_dependents (r);
416 if (!Config->get_auto_xfade()) {
420 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
422 other = dynamic_cast<AudioRegion*> (*i);
424 if (other == region) {
428 if (other->muted() || region->muted()) {
432 if (other->layer() < region->layer()) {
442 if (top->coverage (bottom->position(), bottom->last_frame()) != OverlapNone) {
444 /* check if the upper region is within the lower region */
446 if (top->first_frame() > bottom->first_frame() &&
447 top->last_frame() < bottom->last_frame()) {
450 /* [ -------- top ------- ]
451 * {=========== bottom =============}
454 /* to avoid discontinuities at the region boundaries of an internal
455 overlap (this region is completely within another), we create
456 two hidden crossfades at each boundary. this is not dependent
457 on the auto-xfade option, because we require it as basic
461 jack_nframes_t xfade_length = min ((jack_nframes_t) 720, top->length());
464 xfade = new Crossfade (*top, *bottom, xfade_length, top->first_frame(), StartOfIn);
465 add_crossfade (*xfade);
466 xfade = new Crossfade (*bottom, *top, xfade_length, top->last_frame() - xfade_length, EndOfOut);
467 add_crossfade (*xfade);
471 xfade = new Crossfade (*other, *region, _session.get_xfade_model(), _session.get_crossfades_active());
472 add_crossfade (*xfade);
477 catch (failed_constructor& err) {
481 catch (Crossfade::NoCrossfadeHere& err) {
489 AudioPlaylist::add_crossfade (Crossfade& xfade)
491 Crossfades::iterator ci;
493 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
494 if (*(*ci) == xfade) { // Crossfade::operator==()
499 if (ci != _crossfades.end()) {
502 _crossfades.push_back (&xfade);
504 xfade.Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
505 xfade.StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
507 notify_crossfade_added (&xfade);
511 void AudioPlaylist::notify_crossfade_added (Crossfade *x)
513 if (g_atomic_int_get(&block_notifications)) {
514 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
516 NewCrossfade (x); /* EMIT SIGNAL */
521 AudioPlaylist::crossfade_invalidated (Crossfade* xfade)
523 Crossfades::iterator i;
525 xfade->in().resume_fade_in ();
526 xfade->out().resume_fade_out ();
528 if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
529 _crossfades.erase (i);
534 AudioPlaylist::set_state (const XMLNode& node)
538 XMLNodeConstIterator niter;
541 Playlist::set_state (node);
544 nlist = node.children();
546 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
550 if (child->name() == "Crossfade") {
555 xfade = new Crossfade (*((const Playlist *)this), *child);
558 catch (failed_constructor& err) {
559 // cout << string_compose (_("could not create crossfade object in playlist %1"),
565 Crossfades::iterator ci;
567 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
568 if (*(*ci) == *xfade) {
573 if (ci == _crossfades.end()) {
574 _crossfades.push_back (xfade);
575 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
576 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
577 /* no need to notify here */
589 AudioPlaylist::drop_all_states ()
591 set<Crossfade*> all_xfades;
592 set<Region*> all_regions;
594 /* find every region we've ever used, and add it to the set of
595 all regions. same for xfades;
598 for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
600 AudioPlaylist::State* apstate = dynamic_cast<AudioPlaylist::State*> (*i);
602 for (RegionList::iterator r = apstate->regions.begin(); r != apstate->regions.end(); ++r) {
603 all_regions.insert (*r);
605 for (Crossfades::iterator xf = apstate->crossfades.begin(); xf != apstate->crossfades.end(); ++xf) {
606 all_xfades.insert (*xf);
610 /* now remove from the "all" lists every region that is in the current list. */
612 for (list<Region*>::iterator i = regions.begin(); i != regions.end(); ++i) {
613 set<Region*>::iterator x = all_regions.find (*i);
614 if (x != all_regions.end()) {
615 all_regions.erase (x);
619 /* ditto for every crossfade */
621 for (list<Crossfade*>::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
622 set<Crossfade*>::iterator x = all_xfades.find (*i);
623 if (x != all_xfades.end()) {
624 all_xfades.erase (x);
628 /* delete every region that is left - these are all things that are part of our "history" */
630 for (set<Region *>::iterator ar = all_regions.begin(); ar != all_regions.end(); ++ar) {
631 (*ar)->unlock_sources ();
635 /* delete every crossfade that is left (ditto as per regions) */
637 for (set<Crossfade *>::iterator axf = all_xfades.begin(); axf != all_xfades.end(); ++axf) {
641 /* Now do the generic thing ... */
643 StateManager::drop_all_states ();
647 AudioPlaylist::state_factory (std::string why) const
649 State* state = new State (why);
651 state->regions = regions;
652 state->region_states.clear ();
653 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
654 state->region_states.push_back ((*i)->get_memento());
657 state->crossfades = _crossfades;
658 state->crossfade_states.clear ();
659 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
660 state->crossfade_states.push_back ((*i)->get_memento());
666 AudioPlaylist::restore_state (StateManager::State& state)
669 RegionLock rlock (this);
670 State* apstate = dynamic_cast<State*> (&state);
674 regions = apstate->regions;
676 for (list<UndoAction>::iterator s = apstate->region_states.begin(); s != apstate->region_states.end(); ++s) {
680 _crossfades = apstate->crossfades;
682 for (list<UndoAction>::iterator s = apstate->crossfade_states.begin(); s != apstate->crossfade_states.end(); ++s) {
686 in_set_state = false;
689 notify_length_changed ();
694 AudioPlaylist::get_memento () const
696 return sigc::bind (mem_fun (*(const_cast<AudioPlaylist*> (this)), &StateManager::use_state), _current_state_id);
700 AudioPlaylist::clear (bool with_delete, bool with_save)
703 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
708 _crossfades.clear ();
710 Playlist::clear (with_delete, with_save);
714 AudioPlaylist::state (bool full_state)
716 XMLNode& node = Playlist::state (full_state);
719 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
720 node.add_child_nocopy ((*i)->get_state());
728 AudioPlaylist::dump () const
733 cerr << "Playlist \"" << _name << "\" " << endl
734 << regions.size() << " regions "
735 << _crossfades.size() << " crossfades"
738 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
740 cerr << " " << r->name() << " @ " << r << " ["
741 << r->start() << "+" << r->length()
749 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
760 << (x->active() ? "yes" : "no")
766 AudioPlaylist::destroy_region (Region* region)
768 AudioRegion* r = dynamic_cast<AudioRegion*> (region);
769 bool changed = false;
770 Crossfades::iterator c, ctmp;
771 set<Crossfade*> unique_xfades;
774 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
781 RegionLock rlock (this);
782 RegionList::iterator i;
783 RegionList::iterator tmp;
785 for (i = regions.begin(); i != regions.end(); ) {
790 if ((*i) == region) {
791 (*i)->unlock_sources ();
800 for (c = _crossfades.begin(); c != _crossfades.end(); ) {
804 if ((*c)->involves (*r)) {
805 unique_xfades.insert (*c);
806 _crossfades.erase (c);
812 for (StateMap::iterator s = states.begin(); s != states.end(); ) {
813 StateMap::iterator tmp;
818 State* astate = dynamic_cast<State*> (*s);
820 for (c = astate->crossfades.begin(); c != astate->crossfades.end(); ) {
825 if ((*c)->involves (*r)) {
826 unique_xfades.insert (*c);
827 _crossfades.erase (c);
833 list<UndoAction>::iterator rsi, rsitmp;
834 RegionList::iterator ri, ritmp;
836 for (ri = astate->regions.begin(), rsi = astate->region_states.begin();
837 ri != astate->regions.end() && rsi != astate->region_states.end();) {
846 if (region == (*ri)) {
847 astate->regions.erase (ri);
848 astate->region_states.erase (rsi);
858 for (set<Crossfade*>::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) {
863 /* overload this, it normally means "removed", not destroyed */
864 notify_region_removed (region);
871 AudioPlaylist::crossfade_changed (Change ignored)
873 if (in_flush || in_set_state) {
877 /* XXX is there a loop here? can an xfade change not happen
878 due to a playlist change? well, sure activation would
879 be an example. maybe we should check the type of change
883 maybe_save_state (_("xfade change"));
889 AudioPlaylist::region_changed (Change what_changed, Region* region)
891 if (in_flush || in_set_state) {
895 Change our_interests = Change (AudioRegion::FadeInChanged|
896 AudioRegion::FadeOutChanged|
897 AudioRegion::FadeInActiveChanged|
898 AudioRegion::FadeOutActiveChanged|
899 AudioRegion::EnvelopeActiveChanged|
900 AudioRegion::ScaleAmplitudeChanged|
901 AudioRegion::EnvelopeChanged);
902 bool parent_wants_notify;
904 parent_wants_notify = Playlist::region_changed (what_changed, region);
906 maybe_save_state (_("region modified"));
908 if ((parent_wants_notify || (what_changed & our_interests))) {
916 AudioPlaylist::crossfades_at (jack_nframes_t frame, Crossfades& clist)
918 RegionLock rlock (this);
920 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
921 jack_nframes_t start, end;
923 start = (*i)->position();
924 end = start + (*i)->overlap_length(); // not length(), important difference
926 if (frame >= start && frame <= end) {
927 clist.push_back (*i);