dd0f313fc4460aaf4bdcb9ee66c87d761c266d4a
[ardour.git] / libs / ardour / audio_playlist.cc
1 /*
2     Copyright (C) 2003 Paul Davis 
3
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.
8
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.
13
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.
17
18     $Id$
19 */
20
21 #include <algorithm>
22
23 #include <cstdlib>
24
25 #include <sigc++/bind.h>
26
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>
34
35 #include "i18n.h"
36
37 using namespace ARDOUR;
38 using namespace sigc;
39 using namespace std;
40 using namespace PBD;
41
42 AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden)
43         : Playlist (session, node, hidden)
44 {
45         in_set_state++;
46         set_state (node);
47         in_set_state--;
48
49         if (!hidden) {
50                 PlaylistCreated (this); /* EMIT SIGNAL */
51         }
52 }
53
54 AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)
55         : Playlist (session, name, hidden)
56 {
57         if (!hidden) {
58                 PlaylistCreated (this); /* EMIT SIGNAL */
59         }
60
61 }
62
63 AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, string name, bool hidden)
64         : Playlist (other, name, hidden)
65 {
66         RegionList::const_iterator in_o  = other.regions.begin();
67         RegionList::iterator in_n = regions.begin();
68
69         while (in_o != other.regions.end()) {
70                 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*in_o);
71
72                 // We look only for crossfades which begin with the current region, so we don't get doubles
73                 for (list<Crossfade *>::const_iterator xfades = other._crossfades.begin(); xfades != other._crossfades.end(); ++xfades) {
74                         if ((*xfades)->in() == ar) {
75                                 // We found one! Now copy it!
76
77                                 RegionList::const_iterator out_o = other.regions.begin();
78                                 RegionList::const_iterator out_n = regions.begin();
79
80                                 while (out_o != other.regions.end()) {
81                                         
82                                         boost::shared_ptr<AudioRegion>ar2 = boost::dynamic_pointer_cast<AudioRegion>(*out_o);
83                                         
84                                         if ((*xfades)->out() == ar2) {
85                                                 boost::shared_ptr<AudioRegion>in  = boost::dynamic_pointer_cast<AudioRegion>(*in_n);
86                                                 boost::shared_ptr<AudioRegion>out = boost::dynamic_pointer_cast<AudioRegion>(*out_n);
87                                                 Crossfade *new_fade = new Crossfade (*(*xfades), in, out);
88                                                 add_crossfade(*new_fade);
89                                                 break;
90                                         }
91                                         
92                                         out_o++;
93                                         out_n++;
94                                 }
95 //                              cerr << "HUH!? second region in the crossfade not found!" << endl;
96                         }
97                 }
98
99                 in_o++;
100                 in_n++;
101         }
102
103         if (!hidden) {
104                 PlaylistCreated (this); /* EMIT SIGNAL */
105         }
106 }
107
108 AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, nframes_t start, nframes_t cnt, string name, bool hidden)
109         : Playlist (other, start, cnt, name, hidden)
110 {
111         /* this constructor does NOT notify others (session) */
112 }
113
114 AudioPlaylist::~AudioPlaylist ()
115 {
116         set<Crossfade*> all_xfades;
117
118         GoingAway (); /* EMIT SIGNAL */
119
120         /* drop connections to signals */
121
122         notify_callbacks ();
123
124         for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ) {
125                 Crossfades::iterator tmp;
126
127                 tmp = x;
128                 ++tmp;
129
130                 delete *x;
131
132                 x = tmp;
133         }
134 }
135
136 struct RegionSortByLayer {
137     bool operator() (boost::shared_ptr<Region>a, boost::shared_ptr<Region>b) {
138             return a->layer() < b->layer();
139     }
140 };
141
142 nframes_t
143 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t start,
144                      nframes_t cnt, unsigned chan_n)
145 {
146         nframes_t ret = cnt;
147         nframes_t end;
148         nframes_t read_frames;
149         nframes_t skip_frames;
150
151         /* optimizing this memset() away involves a lot of conditionals
152            that may well cause more of a hit due to cache misses 
153            and related stuff than just doing this here.
154            
155            it would be great if someone could measure this
156            at some point.
157
158            one way or another, parts of the requested area
159            that are not written to by Region::region_at()
160            for all Regions that cover the area need to be
161            zeroed.
162         */
163
164         memset (buf, 0, sizeof (Sample) * cnt);
165
166         /* this function is never called from a realtime thread, so 
167            its OK to block (for short intervals).
168         */
169
170         Glib::Mutex::Lock rm (region_lock);
171
172         end =  start + cnt - 1;
173
174         read_frames = 0;
175         skip_frames = 0;
176         _read_data_count = 0;
177
178         map<uint32_t,vector<boost::shared_ptr<Region> > > relevant_regions;
179         map<uint32_t,vector<Crossfade*> > relevant_xfades;
180         vector<uint32_t> relevant_layers;
181
182         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
183                 if ((*i)->coverage (start, end) != OverlapNone) {
184                         relevant_regions[(*i)->layer()].push_back (*i);
185                         relevant_layers.push_back ((*i)->layer());
186                 }
187         }
188
189         for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
190                 if ((*i)->coverage (start, end) != OverlapNone) {
191                         relevant_xfades[(*i)->upper_layer()].push_back (*i);
192                 }
193         }
194
195 //      RegionSortByLayer layer_cmp;
196 //      relevant_regions.sort (layer_cmp);
197
198         /* XXX this whole per-layer approach is a hack that
199            should be removed once Crossfades become
200            CrossfadeRegions and we just grab a list of relevant
201            regions and call read_at() on all of them.
202         */
203
204         sort (relevant_layers.begin(), relevant_layers.end());
205
206         for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
207
208                 vector<boost::shared_ptr<Region> > r (relevant_regions[*l]);
209                 vector<Crossfade*>& x (relevant_xfades[*l]);
210
211                 for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
212                         boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
213                         assert(ar);
214                         ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
215                         _read_data_count += ar->read_data_count();
216                 }
217                 
218                 for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
219                         (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
220
221                         /* don't JACK up _read_data_count, since its the same data as we just
222                            read from the regions, and the OS should handle that for us.
223                         */
224                 }
225         }
226
227         return ret;
228 }
229
230
231 void
232 AudioPlaylist::remove_dependents (boost::shared_ptr<Region> region)
233 {
234         Crossfades::iterator i, tmp;
235         boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
236
237         if (in_set_state) {
238                 return;
239         }
240         
241         if (r == 0) {
242                 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
243                       << endmsg;
244                 return;
245         }
246
247         for (i = _crossfades.begin(); i != _crossfades.end(); ) {
248                 tmp = i;
249                 tmp++;
250
251                 
252                 if ((*i)->involves (r)) {
253                         delete *i;
254                 }
255                 
256                 i = tmp;
257         }
258 }
259
260
261 void
262 AudioPlaylist::flush_notifications ()
263 {
264         Playlist::flush_notifications();
265
266         if (in_flush) {
267                 return;
268         }
269
270         in_flush = true;
271
272         Crossfades::iterator a;
273         for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
274                 NewCrossfade (*a); /* EMIT SIGNAL */
275         }
276
277         _pending_xfade_adds.clear ();
278         
279         in_flush = false;
280 }
281
282 void
283 AudioPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
284 {
285         boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(r);
286         set<Crossfade*> updated;
287
288         if (ar == 0) {
289                 return;
290         }
291
292         for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
293
294                 Crossfades::iterator tmp;
295                 
296                 tmp = x;
297                 ++tmp;
298
299                 /* only update them once */
300
301                 if ((*x)->involves (ar)) {
302
303                         if (find (updated.begin(), updated.end(), *x) == updated.end()) {
304                                 if ((*x)->refresh ()) {
305                                         /* not invalidated by the refresh */
306                                         updated.insert (*x);
307                                 }
308                         }
309                 }
310
311                 x = tmp;
312         }
313 }
314
315 void
316 AudioPlaylist::finalize_split_region (boost::shared_ptr<Region> o, boost::shared_ptr<Region> l, boost::shared_ptr<Region> r)
317 {
318         boost::shared_ptr<AudioRegion> orig  = boost::dynamic_pointer_cast<AudioRegion>(o);
319         boost::shared_ptr<AudioRegion> left  = boost::dynamic_pointer_cast<AudioRegion>(l);
320         boost::shared_ptr<AudioRegion> right = boost::dynamic_pointer_cast<AudioRegion>(r);
321
322         for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
323                 Crossfades::iterator tmp;
324                 tmp = x;
325                 ++tmp;
326
327                 Crossfade *fade = 0;
328                 
329                 if ((*x)->_in == orig) {
330                         if (! (*x)->covers(right->position())) {
331                                 fade = new Crossfade (**x, left, (*x)->_out);
332                         } else {
333                                 // Overlap, the crossfade is copied on the left side of the right region instead
334                                 fade = new Crossfade (**x, right, (*x)->_out);
335                         }
336                 }
337                 
338                 if ((*x)->_out == orig) {
339                         if (! (*x)->covers(right->position())) {
340                                 fade = new Crossfade (**x, (*x)->_in, right);
341                         } else {
342                                 // Overlap, the crossfade is copied on the right side of the left region instead
343                                 fade = new Crossfade (**x, (*x)->_in, left);
344                         }
345                 }
346                 
347                 if (fade) {
348                         _crossfades.remove (*x);
349                         add_crossfade (*fade);
350                 }
351                 x = tmp;
352         }
353 }
354
355 void
356 AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
357 {
358         boost::shared_ptr<AudioRegion> other;
359         boost::shared_ptr<AudioRegion> region;
360         boost::shared_ptr<AudioRegion> top;
361         boost::shared_ptr<AudioRegion> bottom;
362         Crossfade*   xfade;
363
364         if (in_set_state || in_partition) {
365                 return;
366         }
367
368         if ((region = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
369                 fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
370                       << endmsg;
371                 return;
372         }
373
374         if (!norefresh) {
375                 refresh_dependents (r);
376         }
377
378         if (!Config->get_auto_xfade()) {
379                 return;
380         }
381
382         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
383
384                 other = boost::dynamic_pointer_cast<AudioRegion> (*i);
385
386                 if (other == region) {
387                         continue;
388                 }
389
390                 if (other->muted() || region->muted()) {
391                         continue;
392                 }
393
394                 if (other->layer() < region->layer()) {
395                         top = region;
396                         bottom = other;
397                 } else {
398                         top = other;
399                         bottom = region;
400                 }
401
402                 try {
403                                 
404                         if (top->coverage (bottom->position(), bottom->last_frame()) != OverlapNone) {
405                                 
406                                 /* check if the upper region is within the lower region */
407                                 
408                                 if (top->first_frame() > bottom->first_frame() &&
409                                     top->last_frame() < bottom->last_frame()) {
410                                         
411                                         
412                                         /*     [ -------- top ------- ]
413                                          * {=========== bottom =============}
414                                          */
415                                         
416                                         /* to avoid discontinuities at the region boundaries of an internal
417                                            overlap (this region is completely within another), we create
418                                            two hidden crossfades at each boundary. this is not dependent
419                                            on the auto-xfade option, because we require it as basic
420                                            audio engineering.
421                                         */
422                                         
423                                         nframes_t xfade_length = min ((nframes_t) 720, top->length());
424                                         
425                                                             /*  in,      out */
426                                         xfade = new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn);
427                                         add_crossfade (*xfade);
428
429                                         if (top_region_at (top->last_frame() - 1) == top) {
430                                           /* 
431                                              only add a fade out if there is no region on top of the end of 'top' (which 
432                                              would cover it).
433                                           */
434                                           xfade = new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut);
435                                           add_crossfade (*xfade);
436                                         }
437                                         
438                                 } else {
439
440                                         xfade = new Crossfade (other, region, Config->get_xfade_model(), Config->get_xfades_active());
441                                         add_crossfade (*xfade);
442                                 }
443                         } 
444                 }
445                 
446                 catch (failed_constructor& err) {
447                         continue;
448                 }
449                 
450                 catch (Crossfade::NoCrossfadeHere& err) {
451                         continue;
452                 }
453                 
454         }
455 }
456
457 void
458 AudioPlaylist::add_crossfade (Crossfade& xfade)
459 {
460         Crossfades::iterator ci;
461
462         for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
463                 if (*(*ci) == xfade) { // Crossfade::operator==()
464                         break;
465                 }
466         }
467         
468         if (ci != _crossfades.end()) {
469                 delete &xfade;
470         } else {
471                 _crossfades.push_back (&xfade);
472
473                 xfade.Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
474                 xfade.StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
475
476                 notify_crossfade_added (&xfade);
477         }
478 }
479         
480 void AudioPlaylist::notify_crossfade_added (Crossfade *x)
481 {
482         if (g_atomic_int_get(&block_notifications)) {
483                 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
484         } else {
485                 NewCrossfade (x); /* EMIT SIGNAL */
486         }
487 }
488
489 void
490 AudioPlaylist::crossfade_invalidated (Crossfade* xfade)
491 {
492         Crossfades::iterator i;
493
494         xfade->in()->resume_fade_in ();
495         xfade->out()->resume_fade_out ();
496
497         if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
498                 _crossfades.erase (i);
499         }
500 }
501
502 int
503 AudioPlaylist::set_state (const XMLNode& node)
504 {
505         XMLNode *child;
506         XMLNodeList nlist;
507         XMLNodeConstIterator niter;
508
509         in_set_state++;
510         freeze ();
511
512         Playlist::set_state (node);
513
514         nlist = node.children();
515
516         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
517
518                 child = *niter;
519
520                 if (child->name() != "Crossfade") {
521                         continue;
522                 }
523
524                 try {
525                         Crossfade* xfade = new Crossfade (*((const Playlist *)this), *child);
526                         _crossfades.push_back (xfade);
527                         xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
528                         xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
529                         NewCrossfade(xfade);
530                 }
531                 
532                 catch (failed_constructor& err) {
533                         //      cout << string_compose (_("could not create crossfade object in playlist %1"),
534                         //        _name) 
535                         //    << endl;
536                         continue;
537                 }
538         }
539
540         thaw ();
541         in_set_state--;
542
543         return 0;
544 }
545
546 void
547 AudioPlaylist::clear (bool with_signals)
548 {
549         for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ) {
550
551                 Crossfades::iterator tmp;
552                 tmp = i;
553                 ++tmp;
554
555                 delete *i;
556
557                 i = tmp;
558         }
559
560         _crossfades.clear ();
561         
562         Playlist::clear (with_signals);
563 }
564
565 XMLNode&
566 AudioPlaylist::state (bool full_state)
567 {
568         XMLNode& node = Playlist::state (full_state);
569
570         if (full_state) {
571                 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
572                         node.add_child_nocopy ((*i)->get_state());
573                 }
574         }
575         
576         return node;
577 }
578
579 void
580 AudioPlaylist::dump () const
581 {
582         boost::shared_ptr<Region>r;
583         Crossfade *x;
584
585         cerr << "Playlist \"" << _name << "\" " << endl
586              << regions.size() << " regions "
587              << _crossfades.size() << " crossfades"
588              << endl;
589
590         for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
591                 r = *i;
592                 cerr << "  " << r->name() << " @ " << r << " [" 
593                      << r->start() << "+" << r->length() 
594                      << "] at " 
595                      << r->position()
596                      << " on layer "
597                      << r->layer ()
598                      << endl;
599         }
600
601         for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
602                 x = *i;
603                 cerr << "  xfade [" 
604                      << x->out()->name()
605                      << ','
606                      << x->in()->name()
607                      << " @ "
608                      << x->position()
609                      << " length = " 
610                      << x->length ()
611                      << " active ? "
612                      << (x->active() ? "yes" : "no")
613                      << endl;
614         }
615 }
616
617 bool
618 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
619 {
620         boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
621         bool changed = false;
622         Crossfades::iterator c, ctmp;
623         set<Crossfade*> unique_xfades;
624
625         if (r == 0) {
626                 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
627                       << endmsg;
628                 /*NOTREACHED*/
629                 return false;
630         }
631
632         { 
633                 RegionLock rlock (this);
634
635                 for (RegionList::iterator i = regions.begin(); i != regions.end(); ) {
636                         
637                         RegionList::iterator tmp = i;
638                         ++tmp;
639                         
640                         if ((*i) == region) {
641                                 regions.erase (i);
642                                 changed = true;
643                         }
644                         
645                         i = tmp;
646                 }
647
648                 for (set<boost::shared_ptr<Region> >::iterator x = all_regions.begin(); x != all_regions.end(); ) {
649
650                         set<boost::shared_ptr<Region> >::iterator xtmp = x;
651                         ++xtmp;
652                         
653                         if ((*x) == region) {
654                                 all_regions.erase (x);
655                                 changed = true;
656                         }
657                         
658                         x = xtmp;
659                 }
660
661                 region->set_playlist (0);
662         }
663
664         for (c = _crossfades.begin(); c != _crossfades.end(); ) {
665                 ctmp = c;
666                 ++ctmp;
667
668                 if ((*c)->involves (r)) {
669                         unique_xfades.insert (*c);
670                         _crossfades.erase (c);
671                 }
672                 
673                 c = ctmp;
674         }
675
676         for (set<Crossfade*>::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) {
677                 delete *c;
678         }
679
680         if (changed) {
681                 /* overload this, it normally means "removed", not destroyed */
682                 notify_region_removed (region);
683         }
684
685         return changed;
686 }
687
688 void
689 AudioPlaylist::crossfade_changed (Change ignored)
690 {
691         if (in_flush || in_set_state) {
692                 return;
693         }
694
695         /* XXX is there a loop here? can an xfade change not happen
696            due to a playlist change? well, sure activation would
697            be an example. maybe we should check the type of change
698            that occured.
699         */
700
701         notify_modified ();
702 }
703
704 bool
705 AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
706 {
707         if (in_flush || in_set_state) {
708                 return false;
709         }
710
711         Change our_interests = Change (AudioRegion::FadeInChanged|
712                                        AudioRegion::FadeOutChanged|
713                                        AudioRegion::FadeInActiveChanged|
714                                        AudioRegion::FadeOutActiveChanged|
715                                        AudioRegion::EnvelopeActiveChanged|
716                                        AudioRegion::ScaleAmplitudeChanged|
717                                        AudioRegion::EnvelopeChanged);
718         bool parent_wants_notify;
719
720         parent_wants_notify = Playlist::region_changed (what_changed, region);
721
722         if ((parent_wants_notify || (what_changed & our_interests))) {
723                 notify_modified ();
724         }
725
726         return true; 
727 }
728
729 void
730 AudioPlaylist::crossfades_at (nframes_t frame, Crossfades& clist)
731 {
732         RegionLock rlock (this);
733
734         for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
735                 nframes_t start, end;
736
737                 start = (*i)->position();
738                 end = start + (*i)->overlap_length(); // not length(), important difference
739
740                 if (frame >= start && frame <= end) {
741                         clist.push_back (*i);
742                 } 
743         }
744 }
745