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