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, hidden)
53 save_state (_("initial state"));
56 PlaylistCreated (this); /* EMIT SIGNAL */
60 AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)
61 : Playlist (session, name, hidden)
63 save_state (_("initial state"));
66 PlaylistCreated (this); /* EMIT SIGNAL */
71 AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, string name, bool hidden)
72 : Playlist (other, name, hidden)
74 save_state (_("initial state"));
76 RegionList::const_iterator in_o = other.regions.begin();
77 RegionList::iterator in_n = regions.begin();
79 while (in_o != other.regions.end()) {
80 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*in_o);
82 // We look only for crossfades which begin with the current region, so we don't get doubles
83 for (list<Crossfade *>::const_iterator xfades = other._crossfades.begin(); xfades != other._crossfades.end(); ++xfades) {
84 if ((*xfades)->in() == ar) {
85 // We found one! Now copy it!
87 RegionList::const_iterator out_o = other.regions.begin();
88 RegionList::const_iterator out_n = regions.begin();
90 while (out_o != other.regions.end()) {
92 boost::shared_ptr<AudioRegion>ar2 = boost::dynamic_pointer_cast<AudioRegion>(*out_o);
94 if ((*xfades)->out() == ar2) {
95 boost::shared_ptr<AudioRegion>in = boost::dynamic_pointer_cast<AudioRegion>(*in_n);
96 boost::shared_ptr<AudioRegion>out = boost::dynamic_pointer_cast<AudioRegion>(*out_n);
97 Crossfade *new_fade = new Crossfade (*(*xfades), in, out);
98 add_crossfade(*new_fade);
105 // cerr << "HUH!? second region in the crossfade not found!" << endl;
114 PlaylistCreated (this); /* EMIT SIGNAL */
118 AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden)
119 : Playlist (other, start, cnt, name, hidden)
121 save_state (_("initial state"));
123 /* this constructor does NOT notify others (session) */
126 AudioPlaylist::~AudioPlaylist ()
128 set<Crossfade*> all_xfades;
129 set<Region*> all_regions;
131 GoingAway (); /* EMIT SIGNAL */
133 /* drop connections to signals */
137 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ++x) {
138 all_xfades.insert (*x);
141 for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
143 AudioPlaylist::State* apstate = dynamic_cast<AudioPlaylist::State*> (*i);
145 for (Crossfades::iterator xf = apstate->crossfades.begin(); xf != apstate->crossfades.end(); ++xf) {
146 all_xfades.insert (*xf);
152 /* delete every crossfade */
154 for (set<Crossfade *>::iterator axf = all_xfades.begin(); axf != all_xfades.end(); ++axf) {
159 struct RegionSortByLayer {
160 bool operator() (boost::shared_ptr<Region>a, boost::shared_ptr<Region>b) {
161 return a->layer() < b->layer();
166 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, jack_nframes_t start,
167 jack_nframes_t cnt, unsigned chan_n)
169 jack_nframes_t ret = cnt;
171 jack_nframes_t read_frames;
172 jack_nframes_t skip_frames;
174 /* optimizing this memset() away involves a lot of conditionals
175 that may well cause more of a hit due to cache misses
176 and related stuff than just doing this here.
178 it would be great if someone could measure this
181 one way or another, parts of the requested area
182 that are not written to by Region::region_at()
183 for all Regions that cover the area need to be
187 memset (buf, 0, sizeof (Sample) * cnt);
189 /* this function is never called from a realtime thread, so
190 its OK to block (for short intervals).
193 Glib::Mutex::Lock rm (region_lock);
195 end = start + cnt - 1;
199 _read_data_count = 0;
201 map<uint32_t,vector<boost::shared_ptr<Region> > > relevant_regions;
202 map<uint32_t,vector<Crossfade*> > relevant_xfades;
203 vector<uint32_t> relevant_layers;
205 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
206 if ((*i)->coverage (start, end) != OverlapNone) {
208 relevant_regions[(*i)->layer()].push_back (*i);
209 relevant_layers.push_back ((*i)->layer());
213 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
214 if ((*i)->coverage (start, end) != OverlapNone) {
215 relevant_xfades[(*i)->upper_layer()].push_back (*i);
219 // RegionSortByLayer layer_cmp;
220 // relevant_regions.sort (layer_cmp);
222 /* XXX this whole per-layer approach is a hack that
223 should be removed once Crossfades become
224 CrossfadeRegions and we just grab a list of relevant
225 regions and call read_at() on all of them.
228 sort (relevant_layers.begin(), relevant_layers.end());
230 for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
232 vector<boost::shared_ptr<Region> > r (relevant_regions[*l]);
233 vector<Crossfade*>& x (relevant_xfades[*l]);
235 for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
236 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
238 ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
239 _read_data_count += ar->read_data_count();
242 for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
243 (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
245 /* don't JACK up _read_data_count, since its the same data as we just
246 read from the regions, and the OS should handle that for us.
256 AudioPlaylist::remove_dependents (boost::shared_ptr<Region> region)
258 Crossfades::iterator i, tmp;
259 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
262 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
267 for (i = _crossfades.begin(); i != _crossfades.end(); ) {
271 if ((*i)->involves (r)) {
272 /* do not delete crossfades */
273 _crossfades.erase (i);
282 AudioPlaylist::flush_notifications ()
284 Playlist::flush_notifications();
292 Crossfades::iterator a;
293 for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
294 NewCrossfade (*a); /* EMIT SIGNAL */
297 _pending_xfade_adds.clear ();
303 AudioPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
305 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(r);
306 set<Crossfade*> updated;
312 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
314 Crossfades::iterator tmp;
319 /* only update them once */
321 if ((*x)->involves (ar)) {
323 if (find (updated.begin(), updated.end(), *x) == updated.end()) {
324 if ((*x)->refresh ()) {
325 /* not invalidated by the refresh */
336 AudioPlaylist::finalize_split_region (boost::shared_ptr<Region> o, boost::shared_ptr<Region> l, boost::shared_ptr<Region> r)
338 boost::shared_ptr<AudioRegion> orig = boost::dynamic_pointer_cast<AudioRegion>(o);
339 boost::shared_ptr<AudioRegion> left = boost::dynamic_pointer_cast<AudioRegion>(l);
340 boost::shared_ptr<AudioRegion> right = boost::dynamic_pointer_cast<AudioRegion>(r);
342 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
343 Crossfades::iterator tmp;
349 if ((*x)->_in == orig) {
350 if (! (*x)->covers(right->position())) {
351 fade = new Crossfade (**x, left, (*x)->_out);
353 // Overlap, the crossfade is copied on the left side of the right region instead
354 fade = new Crossfade (**x, right, (*x)->_out);
358 if ((*x)->_out == orig) {
359 if (! (*x)->covers(right->position())) {
360 fade = new Crossfade (**x, (*x)->_in, right);
362 // Overlap, the crossfade is copied on the right side of the left region instead
363 fade = new Crossfade (**x, (*x)->_in, left);
368 _crossfades.remove (*x);
369 add_crossfade (*fade);
376 AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
378 boost::shared_ptr<AudioRegion> other;
379 boost::shared_ptr<AudioRegion> region;
380 boost::shared_ptr<AudioRegion> top;
381 boost::shared_ptr<AudioRegion> bottom;
384 if (in_set_state || in_partition) {
388 if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
389 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
395 refresh_dependents (r);
398 if (!Config->get_auto_xfade()) {
402 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
404 other = boost::dynamic_pointer_cast<AudioRegion> (*i);
406 if (other == region) {
410 if (other->muted() || region->muted()) {
414 if (other->layer() < region->layer()) {
424 if (top->coverage (bottom->position(), bottom->last_frame()) != OverlapNone) {
426 /* check if the upper region is within the lower region */
428 if (top->first_frame() > bottom->first_frame() &&
429 top->last_frame() < bottom->last_frame()) {
432 /* [ -------- top ------- ]
433 * {=========== bottom =============}
436 /* to avoid discontinuities at the region boundaries of an internal
437 overlap (this region is completely within another), we create
438 two hidden crossfades at each boundary. this is not dependent
439 on the auto-xfade option, because we require it as basic
443 jack_nframes_t xfade_length = min ((jack_nframes_t) 720, top->length());
446 xfade = new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn);
447 add_crossfade (*xfade);
448 xfade = new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut);
449 add_crossfade (*xfade);
453 xfade = new Crossfade (other, region, _session.get_xfade_model(), _session.get_crossfades_active());
454 add_crossfade (*xfade);
459 catch (failed_constructor& err) {
463 catch (Crossfade::NoCrossfadeHere& err) {
471 AudioPlaylist::add_crossfade (Crossfade& xfade)
473 Crossfades::iterator ci;
475 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
476 if (*(*ci) == xfade) { // Crossfade::operator==()
481 if (ci != _crossfades.end()) {
484 _crossfades.push_back (&xfade);
486 xfade.Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
487 xfade.StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
489 notify_crossfade_added (&xfade);
493 void AudioPlaylist::notify_crossfade_added (Crossfade *x)
495 if (g_atomic_int_get(&block_notifications)) {
496 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
498 NewCrossfade (x); /* EMIT SIGNAL */
503 AudioPlaylist::crossfade_invalidated (Crossfade* xfade)
505 Crossfades::iterator i;
507 xfade->in()->resume_fade_in ();
508 xfade->out()->resume_fade_out ();
510 if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
511 _crossfades.erase (i);
516 AudioPlaylist::set_state (const XMLNode& node)
520 XMLNodeConstIterator niter;
523 Playlist::set_state (node);
526 nlist = node.children();
528 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
532 if (child->name() == "Crossfade") {
537 xfade = new Crossfade (*((const Playlist *)this), *child);
540 catch (failed_constructor& err) {
541 // cout << string_compose (_("could not create crossfade object in playlist %1"),
547 Crossfades::iterator ci;
549 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
550 if (*(*ci) == *xfade) {
555 if (ci == _crossfades.end()) {
556 _crossfades.push_back (xfade);
557 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
558 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
559 /* no need to notify here */
571 AudioPlaylist::drop_all_states ()
573 set<Crossfade*> all_xfades;
574 set<boost::shared_ptr<Region> > all_regions;
576 /* find every region we've ever used, and add it to the set of
577 all regions. same for xfades;
580 for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
582 AudioPlaylist::State* apstate = dynamic_cast<AudioPlaylist::State*> (*i);
584 for (RegionList::iterator r = apstate->regions.begin(); r != apstate->regions.end(); ++r) {
585 all_regions.insert (*r);
588 for (Crossfades::iterator xf = apstate->crossfades.begin(); xf != apstate->crossfades.end(); ++xf) {
589 all_xfades.insert (*xf);
593 /* now remove from the "all" lists every region that is in the current list. */
595 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
596 set<boost::shared_ptr<Region> >::iterator x = all_regions.find (*i);
597 if (x != all_regions.end()) {
598 all_regions.erase (x);
602 /* ditto for every crossfade */
604 for (list<Crossfade*>::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
605 set<Crossfade*>::iterator x = all_xfades.find (*i);
606 if (x != all_xfades.end()) {
607 all_xfades.erase (x);
611 /* delete every region that is left - these are all things that are part of our "history" */
613 for (set<boost::shared_ptr<Region> >::iterator ar = all_regions.begin(); ar != all_regions.end(); ++ar) {
614 (*ar)->unlock_sources ();
617 /* delete every crossfade that is left (ditto as per regions) */
619 for (set<Crossfade *>::iterator axf = all_xfades.begin(); axf != all_xfades.end(); ++axf) {
623 /* Now do the generic thing ... */
625 StateManager::drop_all_states ();
629 AudioPlaylist::state_factory (std::string why) const
631 State* state = new State (why);
633 state->regions = regions;
634 state->region_states.clear ();
635 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
636 state->region_states.push_back ((*i)->get_memento());
639 state->crossfades = _crossfades;
640 state->crossfade_states.clear ();
641 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
642 state->crossfade_states.push_back ((*i)->get_memento());
648 AudioPlaylist::restore_state (StateManager::State& state)
651 RegionLock rlock (this);
652 State* apstate = dynamic_cast<State*> (&state);
656 regions = apstate->regions;
658 for (list<UndoAction>::iterator s = apstate->region_states.begin(); s != apstate->region_states.end(); ++s) {
662 _crossfades = apstate->crossfades;
664 for (list<UndoAction>::iterator s = apstate->crossfade_states.begin(); s != apstate->crossfade_states.end(); ++s) {
668 in_set_state = false;
671 notify_length_changed ();
676 AudioPlaylist::get_memento () const
678 return sigc::bind (mem_fun (*(const_cast<AudioPlaylist*> (this)), &StateManager::use_state), _current_state_id);
682 AudioPlaylist::clear (bool with_save)
684 _crossfades.clear ();
686 Playlist::clear (with_save);
690 AudioPlaylist::state (bool full_state)
692 XMLNode& node = Playlist::state (full_state);
695 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
696 node.add_child_nocopy ((*i)->get_state());
704 AudioPlaylist::dump () const
706 boost::shared_ptr<Region>r;
709 cerr << "Playlist \"" << _name << "\" " << endl
710 << regions.size() << " regions "
711 << _crossfades.size() << " crossfades"
714 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
716 cerr << " " << r->name() << " @ " << r << " ["
717 << r->start() << "+" << r->length()
725 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
736 << (x->active() ? "yes" : "no")
742 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
744 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
745 bool changed = false;
746 Crossfades::iterator c, ctmp;
747 set<Crossfade*> unique_xfades;
750 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
757 RegionLock rlock (this);
758 RegionList::iterator i;
759 RegionList::iterator tmp;
761 for (i = regions.begin(); i != regions.end(); ) {
766 if ((*i) == region) {
767 (*i)->unlock_sources ();
776 for (c = _crossfades.begin(); c != _crossfades.end(); ) {
780 if ((*c)->involves (r)) {
781 unique_xfades.insert (*c);
782 _crossfades.erase (c);
788 for (StateMap::iterator s = states.begin(); s != states.end(); ) {
789 StateMap::iterator tmp;
794 State* astate = dynamic_cast<State*> (*s);
796 for (c = astate->crossfades.begin(); c != astate->crossfades.end(); ) {
801 if ((*c)->involves (r)) {
802 unique_xfades.insert (*c);
803 _crossfades.erase (c);
809 list<UndoAction>::iterator rsi, rsitmp;
810 RegionList::iterator ri, ritmp;
812 for (ri = astate->regions.begin(), rsi = astate->region_states.begin();
813 ri != astate->regions.end() && rsi != astate->region_states.end();) {
822 if (region == (*ri)) {
823 astate->regions.erase (ri);
824 astate->region_states.erase (rsi);
834 for (set<Crossfade*>::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) {
839 /* overload this, it normally means "removed", not destroyed */
840 notify_region_removed (region);
847 AudioPlaylist::crossfade_changed (Change ignored)
849 if (in_flush || in_set_state) {
853 /* XXX is there a loop here? can an xfade change not happen
854 due to a playlist change? well, sure activation would
855 be an example. maybe we should check the type of change
859 maybe_save_state (_("xfade change"));
865 AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
867 if (in_flush || in_set_state) {
871 Change our_interests = Change (AudioRegion::FadeInChanged|
872 AudioRegion::FadeOutChanged|
873 AudioRegion::FadeInActiveChanged|
874 AudioRegion::FadeOutActiveChanged|
875 AudioRegion::EnvelopeActiveChanged|
876 AudioRegion::ScaleAmplitudeChanged|
877 AudioRegion::EnvelopeChanged);
878 bool parent_wants_notify;
880 parent_wants_notify = Playlist::region_changed (what_changed, region);
882 maybe_save_state (_("region modified"));
884 if ((parent_wants_notify || (what_changed & our_interests))) {
892 AudioPlaylist::crossfades_at (jack_nframes_t frame, Crossfades& clist)
894 RegionLock rlock (this);
896 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
897 jack_nframes_t start, end;
899 start = (*i)->position();
900 end = start + (*i)->overlap_length(); // not length(), important difference
902 if (frame >= start && frame <= end) {
903 clist.push_back (*i);