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