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, nframes_t start, 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, nframes_t start,
167 nframes_t cnt, unsigned chan_n)
171 nframes_t read_frames;
172 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) {
207 relevant_regions[(*i)->layer()].push_back (*i);
208 relevant_layers.push_back ((*i)->layer());
212 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
213 if ((*i)->coverage (start, end) != OverlapNone) {
214 relevant_xfades[(*i)->upper_layer()].push_back (*i);
218 // RegionSortByLayer layer_cmp;
219 // relevant_regions.sort (layer_cmp);
221 /* XXX this whole per-layer approach is a hack that
222 should be removed once Crossfades become
223 CrossfadeRegions and we just grab a list of relevant
224 regions and call read_at() on all of them.
227 sort (relevant_layers.begin(), relevant_layers.end());
229 for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
231 vector<boost::shared_ptr<Region> > r (relevant_regions[*l]);
232 vector<Crossfade*>& x (relevant_xfades[*l]);
234 for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
235 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
237 ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
238 _read_data_count += ar->read_data_count();
241 for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
242 (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
244 /* don't JACK up _read_data_count, since its the same data as we just
245 read from the regions, and the OS should handle that for us.
255 AudioPlaylist::remove_dependents (boost::shared_ptr<Region> region)
257 Crossfades::iterator i, tmp;
258 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
261 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
266 for (i = _crossfades.begin(); i != _crossfades.end(); ) {
270 if ((*i)->involves (r)) {
271 /* do not delete crossfades */
272 _crossfades.erase (i);
281 AudioPlaylist::flush_notifications ()
283 Playlist::flush_notifications();
291 Crossfades::iterator a;
292 for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
293 NewCrossfade (*a); /* EMIT SIGNAL */
296 _pending_xfade_adds.clear ();
302 AudioPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
304 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(r);
305 set<Crossfade*> updated;
311 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
313 Crossfades::iterator tmp;
318 /* only update them once */
320 if ((*x)->involves (ar)) {
322 if (find (updated.begin(), updated.end(), *x) == updated.end()) {
323 if ((*x)->refresh ()) {
324 /* not invalidated by the refresh */
335 AudioPlaylist::finalize_split_region (boost::shared_ptr<Region> o, boost::shared_ptr<Region> l, boost::shared_ptr<Region> r)
337 boost::shared_ptr<AudioRegion> orig = boost::dynamic_pointer_cast<AudioRegion>(o);
338 boost::shared_ptr<AudioRegion> left = boost::dynamic_pointer_cast<AudioRegion>(l);
339 boost::shared_ptr<AudioRegion> right = boost::dynamic_pointer_cast<AudioRegion>(r);
341 for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
342 Crossfades::iterator tmp;
348 if ((*x)->_in == orig) {
349 if (! (*x)->covers(right->position())) {
350 fade = new Crossfade (**x, left, (*x)->_out);
352 // Overlap, the crossfade is copied on the left side of the right region instead
353 fade = new Crossfade (**x, right, (*x)->_out);
357 if ((*x)->_out == orig) {
358 if (! (*x)->covers(right->position())) {
359 fade = new Crossfade (**x, (*x)->_in, right);
361 // Overlap, the crossfade is copied on the right side of the left region instead
362 fade = new Crossfade (**x, (*x)->_in, left);
367 _crossfades.remove (*x);
368 add_crossfade (*fade);
375 AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
377 boost::shared_ptr<AudioRegion> other;
378 boost::shared_ptr<AudioRegion> region;
379 boost::shared_ptr<AudioRegion> top;
380 boost::shared_ptr<AudioRegion> bottom;
383 if (in_set_state || in_partition) {
387 if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
388 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
394 refresh_dependents (r);
397 if (!Config->get_auto_xfade()) {
401 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
403 other = boost::dynamic_pointer_cast<AudioRegion> (*i);
405 if (other == region) {
409 if (other->muted() || region->muted()) {
413 if (other->layer() < region->layer()) {
423 if (top->coverage (bottom->position(), bottom->last_frame()) != OverlapNone) {
425 /* check if the upper region is within the lower region */
427 if (top->first_frame() > bottom->first_frame() &&
428 top->last_frame() < bottom->last_frame()) {
431 /* [ -------- top ------- ]
432 * {=========== bottom =============}
435 /* to avoid discontinuities at the region boundaries of an internal
436 overlap (this region is completely within another), we create
437 two hidden crossfades at each boundary. this is not dependent
438 on the auto-xfade option, because we require it as basic
442 nframes_t xfade_length = min ((nframes_t) 720, top->length());
445 xfade = new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn);
446 add_crossfade (*xfade);
447 xfade = new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut);
448 add_crossfade (*xfade);
452 xfade = new Crossfade (other, region, Config->get_xfade_model(), Config->get_crossfades_active());
453 add_crossfade (*xfade);
458 catch (failed_constructor& err) {
462 catch (Crossfade::NoCrossfadeHere& err) {
470 AudioPlaylist::add_crossfade (Crossfade& xfade)
472 Crossfades::iterator ci;
474 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
475 if (*(*ci) == xfade) { // Crossfade::operator==()
480 if (ci != _crossfades.end()) {
483 _crossfades.push_back (&xfade);
485 xfade.Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
486 xfade.StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
488 notify_crossfade_added (&xfade);
492 void AudioPlaylist::notify_crossfade_added (Crossfade *x)
494 if (g_atomic_int_get(&block_notifications)) {
495 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
497 NewCrossfade (x); /* EMIT SIGNAL */
502 AudioPlaylist::crossfade_invalidated (Crossfade* xfade)
504 Crossfades::iterator i;
506 xfade->in()->resume_fade_in ();
507 xfade->out()->resume_fade_out ();
509 if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
510 _crossfades.erase (i);
515 AudioPlaylist::set_state (const XMLNode& node)
519 XMLNodeConstIterator niter;
522 Playlist::set_state (node);
525 nlist = node.children();
527 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
531 if (child->name() == "Crossfade") {
536 xfade = new Crossfade (*((const Playlist *)this), *child);
539 catch (failed_constructor& err) {
540 // cout << string_compose (_("could not create crossfade object in playlist %1"),
546 Crossfades::iterator ci;
548 for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
549 if (*(*ci) == *xfade) {
554 if (ci == _crossfades.end()) {
555 _crossfades.push_back (xfade);
556 xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
557 xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
570 AudioPlaylist::drop_all_states ()
572 set<Crossfade*> all_xfades;
573 set<boost::shared_ptr<Region> > all_regions;
575 /* find every region we've ever used, and add it to the set of
576 all regions. same for xfades;
579 for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
581 AudioPlaylist::State* apstate = dynamic_cast<AudioPlaylist::State*> (*i);
583 for (RegionList::iterator r = apstate->regions.begin(); r != apstate->regions.end(); ++r) {
584 all_regions.insert (*r);
587 for (Crossfades::iterator xf = apstate->crossfades.begin(); xf != apstate->crossfades.end(); ++xf) {
588 all_xfades.insert (*xf);
592 /* now remove from the "all" lists every region that is in the current list. */
594 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
595 set<boost::shared_ptr<Region> >::iterator x = all_regions.find (*i);
596 if (x != all_regions.end()) {
597 all_regions.erase (x);
601 /* ditto for every crossfade */
603 for (list<Crossfade*>::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
604 set<Crossfade*>::iterator x = all_xfades.find (*i);
605 if (x != all_xfades.end()) {
606 all_xfades.erase (x);
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_save)
677 _crossfades.clear ();
679 Playlist::clear (with_save);
683 AudioPlaylist::state (bool full_state)
685 XMLNode& node = Playlist::state (full_state);
688 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
689 node.add_child_nocopy ((*i)->get_state());
697 AudioPlaylist::dump () const
699 boost::shared_ptr<Region>r;
702 cerr << "Playlist \"" << _name << "\" " << endl
703 << regions.size() << " regions "
704 << _crossfades.size() << " crossfades"
707 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
709 cerr << " " << r->name() << " @ " << r << " ["
710 << r->start() << "+" << r->length()
718 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
729 << (x->active() ? "yes" : "no")
735 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
737 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
738 bool changed = false;
739 Crossfades::iterator c, ctmp;
740 set<Crossfade*> unique_xfades;
743 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
750 RegionLock rlock (this);
751 RegionList::iterator i;
752 RegionList::iterator tmp;
754 for (i = regions.begin(); i != regions.end(); ) {
759 if ((*i) == region) {
768 for (c = _crossfades.begin(); c != _crossfades.end(); ) {
772 if ((*c)->involves (r)) {
773 unique_xfades.insert (*c);
774 _crossfades.erase (c);
780 for (StateMap::iterator s = states.begin(); s != states.end(); ) {
781 StateMap::iterator tmp;
786 State* astate = dynamic_cast<State*> (*s);
788 for (c = astate->crossfades.begin(); c != astate->crossfades.end(); ) {
793 if ((*c)->involves (r)) {
794 unique_xfades.insert (*c);
795 _crossfades.erase (c);
801 list<UndoAction>::iterator rsi, rsitmp;
802 RegionList::iterator ri, ritmp;
804 for (ri = astate->regions.begin(), rsi = astate->region_states.begin();
805 ri != astate->regions.end() && rsi != astate->region_states.end();) {
814 if (region == (*ri)) {
815 astate->regions.erase (ri);
816 astate->region_states.erase (rsi);
826 for (set<Crossfade*>::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) {
831 /* overload this, it normally means "removed", not destroyed */
832 notify_region_removed (region);
839 AudioPlaylist::crossfade_changed (Change ignored)
841 if (in_flush || in_set_state) {
845 /* XXX is there a loop here? can an xfade change not happen
846 due to a playlist change? well, sure activation would
847 be an example. maybe we should check the type of change
851 maybe_save_state (_("xfade change"));
857 AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
859 if (in_flush || in_set_state) {
863 Change our_interests = Change (AudioRegion::FadeInChanged|
864 AudioRegion::FadeOutChanged|
865 AudioRegion::FadeInActiveChanged|
866 AudioRegion::FadeOutActiveChanged|
867 AudioRegion::EnvelopeActiveChanged|
868 AudioRegion::ScaleAmplitudeChanged|
869 AudioRegion::EnvelopeChanged);
870 bool parent_wants_notify;
872 parent_wants_notify = Playlist::region_changed (what_changed, region);
874 maybe_save_state (_("region modified"));
876 if ((parent_wants_notify || (what_changed & our_interests))) {
884 AudioPlaylist::crossfades_at (nframes_t frame, Crossfades& clist)
886 RegionLock rlock (this);
888 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
889 nframes_t start, end;
891 start = (*i)->position();
892 end = start + (*i)->overlap_length(); // not length(), important difference
894 if (frame >= start && frame <= end) {
895 clist.push_back (*i);