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