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