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));
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 crossfade that is left (ditto as per regions) */
613 for (set<Crossfade *>::iterator axf = all_xfades.begin(); axf != all_xfades.end(); ++axf) {
617 /* Now do the generic thing ... */
619 StateManager::drop_all_states ();
623 AudioPlaylist::state_factory (std::string why) const
625 State* state = new State (why);
627 state->regions = regions;
628 state->region_states.clear ();
629 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
630 state->region_states.push_back ((*i)->get_memento());
633 state->crossfades = _crossfades;
634 state->crossfade_states.clear ();
635 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
636 state->crossfade_states.push_back ((*i)->get_memento());
642 AudioPlaylist::restore_state (StateManager::State& state)
645 RegionLock rlock (this);
646 State* apstate = dynamic_cast<State*> (&state);
650 regions = apstate->regions;
652 for (list<UndoAction>::iterator s = apstate->region_states.begin(); s != apstate->region_states.end(); ++s) {
656 _crossfades = apstate->crossfades;
658 for (list<UndoAction>::iterator s = apstate->crossfade_states.begin(); s != apstate->crossfade_states.end(); ++s) {
662 in_set_state = false;
665 notify_length_changed ();
670 AudioPlaylist::get_memento () const
672 return sigc::bind (mem_fun (*(const_cast<AudioPlaylist*> (this)), &StateManager::use_state), _current_state_id);
676 AudioPlaylist::clear (bool with_save)
678 _crossfades.clear ();
680 Playlist::clear (with_save);
684 AudioPlaylist::state (bool full_state)
686 XMLNode& node = Playlist::state (full_state);
689 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
690 node.add_child_nocopy ((*i)->get_state());
698 AudioPlaylist::dump () const
700 boost::shared_ptr<Region>r;
703 cerr << "Playlist \"" << _name << "\" " << endl
704 << regions.size() << " regions "
705 << _crossfades.size() << " crossfades"
708 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
710 cerr << " " << r->name() << " @ " << r << " ["
711 << r->start() << "+" << r->length()
719 for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
730 << (x->active() ? "yes" : "no")
736 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
738 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
739 bool changed = false;
740 Crossfades::iterator c, ctmp;
741 set<Crossfade*> unique_xfades;
744 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
751 RegionLock rlock (this);
752 RegionList::iterator i;
753 RegionList::iterator tmp;
755 for (i = regions.begin(); i != regions.end(); ) {
760 if ((*i) == region) {
769 for (c = _crossfades.begin(); c != _crossfades.end(); ) {
773 if ((*c)->involves (r)) {
774 unique_xfades.insert (*c);
775 _crossfades.erase (c);
781 for (StateMap::iterator s = states.begin(); s != states.end(); ) {
782 StateMap::iterator tmp;
787 State* astate = dynamic_cast<State*> (*s);
789 for (c = astate->crossfades.begin(); c != astate->crossfades.end(); ) {
794 if ((*c)->involves (r)) {
795 unique_xfades.insert (*c);
796 _crossfades.erase (c);
802 list<UndoAction>::iterator rsi, rsitmp;
803 RegionList::iterator ri, ritmp;
805 for (ri = astate->regions.begin(), rsi = astate->region_states.begin();
806 ri != astate->regions.end() && rsi != astate->region_states.end();) {
815 if (region == (*ri)) {
816 astate->regions.erase (ri);
817 astate->region_states.erase (rsi);
827 for (set<Crossfade*>::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) {
832 /* overload this, it normally means "removed", not destroyed */
833 notify_region_removed (region);
840 AudioPlaylist::crossfade_changed (Change ignored)
842 if (in_flush || in_set_state) {
846 /* XXX is there a loop here? can an xfade change not happen
847 due to a playlist change? well, sure activation would
848 be an example. maybe we should check the type of change
852 maybe_save_state (_("xfade change"));
858 AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
860 if (in_flush || in_set_state) {
864 Change our_interests = Change (AudioRegion::FadeInChanged|
865 AudioRegion::FadeOutChanged|
866 AudioRegion::FadeInActiveChanged|
867 AudioRegion::FadeOutActiveChanged|
868 AudioRegion::EnvelopeActiveChanged|
869 AudioRegion::ScaleAmplitudeChanged|
870 AudioRegion::EnvelopeChanged);
871 bool parent_wants_notify;
873 parent_wants_notify = Playlist::region_changed (what_changed, region);
875 maybe_save_state (_("region modified"));
877 if ((parent_wants_notify || (what_changed & our_interests))) {
885 AudioPlaylist::crossfades_at (jack_nframes_t frame, Crossfades& clist)
887 RegionLock rlock (this);
889 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
890 jack_nframes_t start, end;
892 start = (*i)->position();
893 end = start + (*i)->overlap_length(); // not length(), important difference
895 if (frame >= start && frame <= end) {
896 clist.push_back (*i);