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