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