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