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