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