maybe fix race condition for peaks; fix % appearing in region names; allow crossfades...
[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                                         xfade = new Crossfade (bottom, top, xfade_length, top->last_frame() - xfade_length, EndOfOut);
429                                         add_crossfade (*xfade);
430                                         
431                                 } else {
432
433                                         xfade = new Crossfade (other, region, Config->get_xfade_model(), Config->get_xfades_active());
434                                         add_crossfade (*xfade);
435                                 }
436                         } 
437                 }
438                 
439                 catch (failed_constructor& err) {
440                         continue;
441                 }
442                 
443                 catch (Crossfade::NoCrossfadeHere& err) {
444                         continue;
445                 }
446                 
447         }
448 }
449
450 void
451 AudioPlaylist::add_crossfade (Crossfade& xfade)
452 {
453         Crossfades::iterator ci;
454
455         for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
456                 if (*(*ci) == xfade) { // Crossfade::operator==()
457                         break;
458                 }
459         }
460         
461         if (ci != _crossfades.end()) {
462                 delete &xfade;
463         } else {
464                 _crossfades.push_back (&xfade);
465
466                 xfade.Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
467                 xfade.StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
468
469                 notify_crossfade_added (&xfade);
470         }
471 }
472         
473 void AudioPlaylist::notify_crossfade_added (Crossfade *x)
474 {
475         if (g_atomic_int_get(&block_notifications)) {
476                 _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
477         } else {
478                 NewCrossfade (x); /* EMIT SIGNAL */
479         }
480 }
481
482 void
483 AudioPlaylist::crossfade_invalidated (Crossfade* xfade)
484 {
485         Crossfades::iterator i;
486
487         xfade->in()->resume_fade_in ();
488         xfade->out()->resume_fade_out ();
489
490         if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
491                 _crossfades.erase (i);
492         }
493 }
494
495 int
496 AudioPlaylist::set_state (const XMLNode& node)
497 {
498         XMLNode *child;
499         XMLNodeList nlist;
500         XMLNodeConstIterator niter;
501
502         in_set_state++;
503         freeze ();
504
505         Playlist::set_state (node);
506
507         nlist = node.children();
508
509         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
510
511                 child = *niter;
512
513                 if (child->name() != "Crossfade") {
514                         continue;
515                 }
516
517                 try {
518                         Crossfade* xfade = new Crossfade (*((const Playlist *)this), *child);
519                         _crossfades.push_back (xfade);
520                         xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
521                         xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
522                         NewCrossfade(xfade);
523                 }
524                 
525                 catch (failed_constructor& err) {
526                         //      cout << string_compose (_("could not create crossfade object in playlist %1"),
527                         //        _name) 
528                         //    << endl;
529                         continue;
530                 }
531         }
532
533         thaw ();
534         in_set_state--;
535
536         return 0;
537 }
538
539 void
540 AudioPlaylist::clear (bool with_signals)
541 {
542         for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ) {
543
544                 Crossfades::iterator tmp;
545                 tmp = i;
546                 ++tmp;
547
548                 delete *i;
549
550                 i = tmp;
551         }
552
553         _crossfades.clear ();
554         
555         Playlist::clear (with_signals);
556 }
557
558 XMLNode&
559 AudioPlaylist::state (bool full_state)
560 {
561         XMLNode& node = Playlist::state (full_state);
562
563         if (full_state) {
564                 for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
565                         node.add_child_nocopy ((*i)->get_state());
566                 }
567         }
568         
569         return node;
570 }
571
572 void
573 AudioPlaylist::dump () const
574 {
575         boost::shared_ptr<Region>r;
576         Crossfade *x;
577
578         cerr << "Playlist \"" << _name << "\" " << endl
579              << regions.size() << " regions "
580              << _crossfades.size() << " crossfades"
581              << endl;
582
583         for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
584                 r = *i;
585                 cerr << "  " << r->name() << " @ " << r << " [" 
586                      << r->start() << "+" << r->length() 
587                      << "] at " 
588                      << r->position()
589                      << " on layer "
590                      << r->layer ()
591                      << endl;
592         }
593
594         for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
595                 x = *i;
596                 cerr << "  xfade [" 
597                      << x->out()->name()
598                      << ','
599                      << x->in()->name()
600                      << " @ "
601                      << x->position()
602                      << " length = " 
603                      << x->length ()
604                      << " active ? "
605                      << (x->active() ? "yes" : "no")
606                      << endl;
607         }
608 }
609
610 bool
611 AudioPlaylist::destroy_region (boost::shared_ptr<Region> region)
612 {
613         boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
614         bool changed = false;
615         Crossfades::iterator c, ctmp;
616         set<Crossfade*> unique_xfades;
617
618         if (r == 0) {
619                 fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
620                       << endmsg;
621                 /*NOTREACHED*/
622                 return false;
623         }
624
625         { 
626                 RegionLock rlock (this);
627                 RegionList::iterator i;
628                 RegionList::iterator tmp;
629
630                 for (i = regions.begin(); i != regions.end(); ) {
631                         
632                         tmp = i;
633                         ++tmp;
634                         
635                         if ((*i) == region) {
636                                 regions.erase (i);
637                                 changed = true;
638                         }
639                         
640                         i = tmp;
641                 }
642         }
643
644         for (c = _crossfades.begin(); c != _crossfades.end(); ) {
645                 ctmp = c;
646                 ++ctmp;
647
648                 if ((*c)->involves (r)) {
649                         unique_xfades.insert (*c);
650                         _crossfades.erase (c);
651                 }
652                 
653                 c = ctmp;
654         }
655
656         for (set<Crossfade*>::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) {
657                 delete *c;
658         }
659
660         if (changed) {
661                 /* overload this, it normally means "removed", not destroyed */
662                 notify_region_removed (region);
663         }
664
665         return changed;
666 }
667
668 void
669 AudioPlaylist::crossfade_changed (Change ignored)
670 {
671         if (in_flush || in_set_state) {
672                 return;
673         }
674
675         /* XXX is there a loop here? can an xfade change not happen
676            due to a playlist change? well, sure activation would
677            be an example. maybe we should check the type of change
678            that occured.
679         */
680
681         notify_modified ();
682 }
683
684 bool
685 AudioPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
686 {
687         if (in_flush || in_set_state) {
688                 return false;
689         }
690
691         Change our_interests = Change (AudioRegion::FadeInChanged|
692                                        AudioRegion::FadeOutChanged|
693                                        AudioRegion::FadeInActiveChanged|
694                                        AudioRegion::FadeOutActiveChanged|
695                                        AudioRegion::EnvelopeActiveChanged|
696                                        AudioRegion::ScaleAmplitudeChanged|
697                                        AudioRegion::EnvelopeChanged);
698         bool parent_wants_notify;
699
700         parent_wants_notify = Playlist::region_changed (what_changed, region);
701
702         if ((parent_wants_notify || (what_changed & our_interests))) {
703                 notify_modified ();
704         }
705
706         return true; 
707 }
708
709 void
710 AudioPlaylist::crossfades_at (nframes_t frame, Crossfades& clist)
711 {
712         RegionLock rlock (this);
713
714         for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
715                 nframes_t start, end;
716
717                 start = (*i)->position();
718                 end = start + (*i)->overlap_length(); // not length(), important difference
719
720                 if (frame >= start && frame <= end) {
721                         clist.push_back (*i);
722                 } 
723         }
724 }
725