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