Clean up Region interface, remove Readable stub kludge.
[ardour.git] / libs / ardour / crossfade.cc
1 /*
2     Copyright (C) 2003-2006 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 <sigc++/bind.h>
21
22 #include <pbd/stacktrace.h>
23
24 #include <ardour/types.h>
25 #include <ardour/crossfade.h>
26 #include <ardour/crossfade_compare.h>
27 #include <ardour/audioregion.h>
28 #include <ardour/playlist.h>
29 #include <ardour/utils.h>
30 #include <ardour/session.h>
31 #include <ardour/source.h>
32
33 #include "i18n.h"
34 #include <locale.h>
35
36 using namespace std;
37 using namespace ARDOUR;
38 using namespace PBD;
39
40 nframes_t Crossfade::_short_xfade_length = 0;
41 Change Crossfade::ActiveChanged = new_change();
42 Change Crossfade::FollowOverlapChanged = new_change();
43
44 /* XXX if and when we ever implement parallel processing of the process()
45    callback, these will need to be handled on a per-thread basis.
46 */
47
48 Sample* Crossfade::crossfade_buffer_out = 0;
49 Sample* Crossfade::crossfade_buffer_in = 0;
50
51 void
52 Crossfade::set_buffer_size (nframes_t sz)
53 {
54         delete [] crossfade_buffer_out;
55         crossfade_buffer_out = 0;
56
57         delete [] crossfade_buffer_in;
58         crossfade_buffer_in = 0;
59
60         if (sz) {
61                 crossfade_buffer_out = new Sample[sz];
62                 crossfade_buffer_in = new Sample[sz];
63         }
64 }
65
66 bool
67 Crossfade::operator== (const Crossfade& other)
68 {
69         return (_in == other._in) && (_out == other._out);
70 }
71
72 Crossfade::Crossfade (boost::shared_ptr<AudioRegion> in, boost::shared_ptr<AudioRegion> out, 
73                       nframes_t length,
74                       nframes_t position,
75                       AnchorPoint ap)
76         : AudioRegion (in->session(), position, length, "foobar"),
77           _fade_in (Evoral::Parameter(FadeInAutomation)), // linear (gain coefficient) => -inf..+6dB
78           _fade_out (Evoral::Parameter(FadeOutAutomation)) // linear (gain coefficient) => -inf..+6dB
79
80 {
81         _in = in;
82         _out = out;
83         _anchor_point = ap;
84         _follow_overlap = false;
85
86         _active = Config->get_xfades_active ();
87         _fixed = true;
88
89         initialize ();
90 }
91
92 Crossfade::Crossfade (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioRegion> b, CrossfadeModel model, bool act)
93         : AudioRegion (a->session(), 0, 0, "foobar"),
94           _fade_in (Evoral::Parameter(FadeInAutomation)), // linear (gain coefficient) => -inf..+6dB
95           _fade_out (Evoral::Parameter(FadeOutAutomation)) // linear (gain coefficient) => -inf..+6dB
96 {
97         _in_update = false;
98         _fixed = false;
99
100         if (compute (a, b, model)) {
101                 throw failed_constructor();
102         }
103
104         _active = act;
105
106         initialize ();
107
108
109 }
110
111 Crossfade::Crossfade (const Playlist& playlist, XMLNode& node)
112         : AudioRegion (playlist.session(), 0, 0, "foobar"),
113           _fade_in (Evoral::Parameter(FadeInAutomation)), // linear (gain coefficient) => -inf..+6dB
114           _fade_out (Evoral::Parameter(FadeOutAutomation)) // linear (gain coefficient) => -inf..+6dB
115
116 {
117         boost::shared_ptr<Region> r;
118         XMLProperty* prop;
119         LocaleGuard lg (X_("POSIX"));
120
121         /* we have to find the in/out regions before we can do anything else */
122
123         if ((prop = node.property ("in")) == 0) {
124                 error << _("Crossfade: no \"in\" region in state") << endmsg;
125                 throw failed_constructor();
126         }
127         
128         PBD::ID id (prop->value());
129
130         if ((r = playlist.find_region (id)) == 0) {
131                 error << string_compose (_("Crossfade: no \"in\" region %1 found in playlist %2"), id, playlist.name())
132                       << endmsg;
133                 throw failed_constructor();
134         }
135         
136         if ((_in = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
137                 throw failed_constructor();
138         }
139
140         if ((prop = node.property ("out")) == 0) {
141                 error << _("Crossfade: no \"out\" region in state") << endmsg;
142                 throw failed_constructor();
143         }
144
145         PBD::ID id2 (prop->value());
146
147         if ((r = playlist.find_region (id2)) == 0) {
148                 error << string_compose (_("Crossfade: no \"out\" region %1 found in playlist %2"), id2, playlist.name())
149                       << endmsg;
150                 throw failed_constructor();
151         }
152         
153         if ((_out = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
154                 throw failed_constructor();
155         }
156
157         _length = 0;
158         initialize();
159         _active = true;
160         
161         if (set_state (node)) {
162                 throw failed_constructor();
163         }
164 }
165
166 Crossfade::Crossfade (boost::shared_ptr<Crossfade> orig, boost::shared_ptr<AudioRegion> newin, boost::shared_ptr<AudioRegion> newout)
167         : AudioRegion (boost::dynamic_pointer_cast<const AudioRegion> (orig)),
168           _fade_in (orig->_fade_in),
169           _fade_out (orig->_fade_out)
170 {
171         _active           = orig->_active;
172         _in_update        = orig->_in_update;
173         _anchor_point     = orig->_anchor_point;
174         _follow_overlap   = orig->_follow_overlap;
175         _fixed            = orig->_fixed;
176         
177         _in = newin;
178         _out = newout;
179
180         // copied from Crossfade::initialize()
181         _in_update = false;
182         
183         _out->suspend_fade_out ();
184         _in->suspend_fade_in ();
185
186         overlap_type = _in->coverage (_out->position(), _out->last_frame());
187         layer_relation = (int32_t) (_in->layer() - _out->layer());
188
189         // Let's make sure the fade isn't too long
190         set_length(_length);
191 }
192
193
194 Crossfade::~Crossfade ()
195 {
196         notify_callbacks ();
197 }
198
199 void
200 Crossfade::initialize ()
201 {
202         /* merge source lists from regions */
203
204         _sources = _in->sources();
205         _sources.insert (_sources.end(), _out->sources().begin(), _out->sources().end());
206         _master_sources = _in->master_sources();
207         _master_sources.insert(_master_sources.end(), _out->master_sources().begin(), _out->master_sources().end());
208         
209         _in_update = false;
210         
211         _out->suspend_fade_out ();
212         _in->suspend_fade_in ();
213
214         _fade_out.freeze ();
215         _fade_out.clear ();
216
217 #define EQUAL_POWER_MINUS_3DB
218 #ifdef  EQUAL_POWER_MINUS_3DB
219
220         _fade_out.add ((_length * 0.000000), 1.000000);
221         _fade_out.add ((_length * 0.166667), 0.948859);
222         _fade_out.add ((_length * 0.333333), 0.851507);
223         _fade_out.add ((_length * 0.500000), 0.707946);
224         _fade_out.add ((_length * 0.666667), 0.518174);
225         _fade_out.add ((_length * 0.833333), 0.282192);
226         _fade_out.add ((_length * 1.000000), 0.000000);
227
228 #else // EQUAL_POWER_MINUS_6DB
229
230         _fade_out.add ((_length * 0.000000), 1.000000);
231         _fade_out.add ((_length * 0.166667), 0.833033);
232         _fade_out.add ((_length * 0.333333), 0.666186);
233         _fade_out.add ((_length * 0.500000), 0.499459);
234         _fade_out.add ((_length * 0.666667), 0.332853);
235         _fade_out.add ((_length * 0.833333), 0.166366);
236         _fade_out.add ((_length * 1.000000), 0.000000);
237 #endif
238
239         _fade_out.thaw ();
240         
241         _fade_in.freeze ();
242         _fade_in.clear ();
243
244 #define EQUAL_POWER_MINUS_3DB
245 #ifdef  EQUAL_POWER_MINUS_3DB
246
247         _fade_in.add ((_length * 0.000000), 0.000000);
248         _fade_in.add ((_length * 0.166667), 0.282192);
249         _fade_in.add ((_length * 0.333333), 0.518174);
250         _fade_in.add ((_length * 0.500000), 0.707946);
251         _fade_in.add ((_length * 0.666667), 0.851507);
252         _fade_in.add ((_length * 0.833333), 0.948859);
253         _fade_in.add ((_length * 1.000000), 1.000000);
254
255 #else // EQUAL_POWER_MINUS_SIX_DB
256
257         _fade_in.add ((_length * 0.000000), 0.000000);
258         _fade_in.add ((_length * 0.166667), 0.166366);
259         _fade_in.add ((_length * 0.333333), 0.332853);
260         _fade_in.add ((_length * 0.500000), 0.499459);
261         _fade_in.add ((_length * 0.666667), 0.666186);
262         _fade_in.add ((_length * 0.833333), 0.833033);
263         _fade_in.add ((_length * 1.000000), 1.000000);
264
265 #endif
266
267         _fade_in.thaw ();
268
269         overlap_type = _in->coverage (_out->position(), _out->last_frame());
270         layer_relation = (int32_t) (_in->layer() - _out->layer());
271 }       
272
273 nframes_t 
274 Crossfade::read_raw_internal (Sample* buf, sframes_t start, nframes_t cnt) const
275 {
276         // FIXME: Why is this disabled?
277 #if 0
278         Sample* mixdown = new Sample[cnt];
279         float* gain = new float[cnt];
280         nframes_t ret;
281
282         ret = read_at (buf, mixdown, gain, start, cnt, chan_n, cnt);
283
284         delete [] mixdown;
285         delete [] gain;
286
287         return ret;
288 #endif
289         return cnt;
290 }
291
292 nframes_t 
293 Crossfade::read_at (Sample *buf, Sample *mixdown_buffer, 
294                     float *gain_buffer, sframes_t start, nframes_t cnt, uint32_t chan_n,
295                     nframes_t read_frames, nframes_t skip_frames) const
296 {
297         nframes_t offset;
298         nframes_t to_write;
299
300         if (!_active) {
301                 return 0;
302         }
303
304         if (start < _position) {
305
306                 /* handle an initial section of the read area that we do not
307                    cover.
308                 */
309
310                 offset = _position - start;
311
312                 if (offset < cnt) {
313                         cnt -= offset;
314                 } else {
315                         return 0;
316                 }
317                 
318                 start = _position;
319                 buf += offset;
320                 to_write = min (_length, cnt);
321
322         } else {
323                 
324                 to_write = min (nframes_t(_length - (start - _position)), cnt);
325                 
326         }
327
328         offset = start - _position;
329
330         /* Prevent data from piling up inthe crossfade buffers when reading a transparent region */
331         if (!(_out->opaque())) {
332                 memset (crossfade_buffer_out, 0, sizeof (Sample) * to_write);
333         } else if (!(_in->opaque())) {
334                 memset (crossfade_buffer_in, 0, sizeof (Sample) * to_write);
335         }
336
337         _out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
338         _in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
339
340         float* fiv = new float[to_write];
341         float* fov = new float[to_write];
342
343         _fade_in.curve().get_vector (offset, offset+to_write, fiv, to_write);
344         _fade_out.curve().get_vector (offset, offset+to_write, fov, to_write);
345
346         /* note: although we have not explicitly taken into account the return values
347            from _out->read_at() or _in->read_at(), the length() function does this
348            implicitly. why? because it computes a value based on the in+out regions'
349            position and length, and so we know precisely how much data they could return. 
350         */
351
352         for (nframes_t n = 0; n < to_write; ++n) {
353                 buf[n] = (crossfade_buffer_out[n] * fov[n]) + (crossfade_buffer_in[n] * fiv[n]);
354         }
355
356         delete [] fov;
357         delete [] fiv;
358
359         return to_write;
360 }       
361
362 OverlapType 
363 Crossfade::coverage (nframes_t start, nframes_t end) const
364 {
365         nframes_t my_end = _position + _length;
366
367         if ((start >= _position) && (end <= my_end)) {
368                 return OverlapInternal;
369         }
370         if ((end >= _position) && (end <= my_end)) {
371                 return OverlapStart;
372         }
373         if ((start >= _position) && (start <= my_end)) {
374                 return OverlapEnd;
375         }
376         if ((_position >= start) && (_position <= end) && (my_end <= end)) {
377                 return OverlapExternal;
378         }
379         return OverlapNone;
380 }
381
382 void
383 Crossfade::set_active (bool yn)
384 {
385         if (_active != yn) {
386                 _active = yn;
387                 StateChanged (ActiveChanged);
388         }
389 }
390
391 bool
392 Crossfade::refresh ()
393 {
394         /* crossfades must be between non-muted regions */
395         
396         if (_out->muted() || _in->muted()) {
397                 Invalidated (shared_from_this ());
398                 return false;
399         }
400
401         /* Top layer shouldn't be transparent */
402         
403         if (!((layer_relation > 0 ? _in : _out)->opaque())) {
404                 Invalidated (shared_from_this());
405                 return false;
406         }
407
408         /* layer ordering cannot change */
409
410         int32_t new_layer_relation = (int32_t) (_in->layer() - _out->layer());
411
412         if (new_layer_relation * layer_relation < 0) { // different sign, layers rotated 
413                 Invalidated (shared_from_this ());
414                 return false;
415         }
416
417         OverlapType ot = _in->coverage (_out->first_frame(), _out->last_frame());
418
419         if (ot == OverlapNone) {
420                 Invalidated (shared_from_this ());
421                 return false;
422         } 
423
424         bool send_signal;
425
426         if (ot != overlap_type) {
427
428                 if (_follow_overlap) {
429
430                         try {
431                                 compute (_in, _out, Config->get_xfade_model());
432                         } 
433
434                         catch (NoCrossfadeHere& err) {
435                                 Invalidated (shared_from_this ());
436                                 return false;
437                         }
438
439                         send_signal = true;
440
441                 } else {
442
443                         Invalidated (shared_from_this ());
444                         return false;
445                 }
446
447         } else {
448
449                 send_signal = update ();
450         }
451
452         if (send_signal) {
453                 StateChanged (BoundsChanged); /* EMIT SIGNAL */
454         }
455
456         _in_update = false;
457
458         return true;
459 }
460
461 bool
462 Crossfade::update ()
463 {
464         nframes_t newlen;
465         
466         if (_follow_overlap) {
467                 newlen = _out->first_frame() + _out->length() - _in->first_frame();
468         } else {
469                 newlen = _length;
470         }
471         
472         if (newlen == 0) {
473                 Invalidated (shared_from_this ());
474                 return false;
475         }
476         
477         _in_update = true;
478         
479         if ((_follow_overlap && newlen != _length) || (_length > newlen)) {
480                 
481                 double factor =  newlen / (double) _length;
482                 
483                 _fade_out.x_scale (factor);
484                 _fade_in.x_scale (factor);
485                 
486                 _length = newlen;
487         } 
488                 
489         switch (_anchor_point) {
490         case StartOfIn:
491                 _position = _in->first_frame();
492                 break;
493                 
494         case EndOfIn:
495                 _position = _in->last_frame() - _length;
496                 break;
497                 
498         case EndOfOut:
499                 _position = _out->last_frame() - _length;
500         }
501
502         return true;
503 }
504
505 int
506 Crossfade::compute (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioRegion> b, CrossfadeModel model)
507 {
508         boost::shared_ptr<AudioRegion> top;
509         boost::shared_ptr<AudioRegion> bottom;
510         nframes_t short_xfade_length;
511
512         short_xfade_length = _short_xfade_length; 
513
514         if (a->layer() < b->layer()) {
515                 top = b;
516                 bottom = a;
517         } else {
518                 top = a;
519                 bottom = b;
520         }
521         
522         /* first check for matching ends */
523         
524         if (top->first_frame() == bottom->first_frame()) {
525
526                 /* Both regions start at the same point */
527                 
528                 if (top->last_frame() < bottom->last_frame()) {
529                         
530                         /* top ends before bottom, so put an xfade
531                            in at the end of top.
532                         */
533                         
534                         /* [-------- top ---------- ]
535                          * {====== bottom =====================}
536                          */
537
538                         _in = bottom;
539                         _out = top;
540
541                         if (top->last_frame() < short_xfade_length) {
542                                 _position = 0;
543                         } else {
544                                 _position = top->last_frame() - short_xfade_length;
545                         }
546
547                         _length = min (short_xfade_length, top->length());
548                         _follow_overlap = false;
549                         _anchor_point = EndOfIn;
550                         _active = true;
551                         _fixed = true;
552
553                 } else {
554                         /* top ends after (or same time) as bottom - no xfade
555                          */
556                         
557                         /* [-------- top ------------------------ ]
558                          * {====== bottom =====================}
559                          */
560
561                         throw NoCrossfadeHere();
562                 }
563                 
564         } else if (top->last_frame() == bottom->last_frame()) {
565                 
566                 /* Both regions end at the same point */
567                 
568                 if (top->first_frame() > bottom->first_frame()) {
569                         
570                         /* top starts after bottom, put an xfade in at the
571                            start of top
572                         */
573                         
574                         /*            [-------- top ---------- ]
575                          * {====== bottom =====================}
576                          */
577
578                         _in = top;
579                         _out = bottom;
580                         _position = top->first_frame();
581                         _length = min (short_xfade_length, top->length());
582                         _follow_overlap = false;
583                         _anchor_point = StartOfIn;
584                         _active = true;
585                         _fixed = true;
586                         
587                 } else {
588                         /* top starts before bottom - no xfade
589                          */
590
591                         /* [-------- top ------------------------ ]
592                          *    {====== bottom =====================}
593                          */
594
595                         throw NoCrossfadeHere();
596                 }
597
598         } else {
599         
600                 /* OK, time to do more regular overlapping */
601
602                 OverlapType ot = top->coverage (bottom->first_frame(), bottom->last_frame());
603
604                 switch (ot) {
605                 case OverlapNone:
606                         /* should be NOTREACHED as a precondition of creating
607                            a new crossfade, but we need to handle it here.
608                         */
609                         throw NoCrossfadeHere();
610                         break;
611                         
612                 case OverlapInternal:
613                 case OverlapExternal:
614                         /* should be NOTREACHED because of tests above */
615                         throw NoCrossfadeHere();
616                         break;
617                         
618                 case OverlapEnd: /* top covers start of bottom but ends within it */
619
620                         /* [---- top ------------------------] 
621                          *                { ==== bottom ============ } 
622                          */ 
623
624                         _in = bottom;
625                         _out = top;
626                         _anchor_point = EndOfOut;
627
628                         if (model == FullCrossfade) {
629                                 _position = bottom->first_frame(); // "{"
630                                 _length = _out->first_frame() + _out->length() - _in->first_frame();
631                                 /* leave active alone */
632                                 _follow_overlap = true;
633                         } else {
634                                 _length = min (short_xfade_length, top->length());
635                                 _position = top->last_frame() - _length;  // "]" - length 
636                                 _active = true;
637                                 _follow_overlap = false;
638                                 
639                         }
640                         break;
641                         
642                 case OverlapStart:   /* top starts within bottom but covers bottom's end */
643
644                         /*                   { ==== top ============ } 
645                          *   [---- bottom -------------------] 
646                          */
647
648                         _in = top;
649                         _out = bottom;
650                         _position = top->first_frame();
651                         _anchor_point = StartOfIn;
652
653                         if (model == FullCrossfade) {
654                                 _length = _out->first_frame() + _out->length() - _in->first_frame();
655                                 /* leave active alone */
656                                 _follow_overlap = true;
657                         } else {
658                                 _length = min (short_xfade_length, top->length());
659                                 _active = true;
660                                 _follow_overlap = false;
661                                 
662                         }
663                         
664                         break;
665                 }
666         }
667         
668         return 0;
669 }
670
671 XMLNode&
672 Crossfade::get_state () 
673 {
674         XMLNode* node = new XMLNode (X_("Crossfade"));
675         XMLNode* child;
676         char buf[64];
677         LocaleGuard lg (X_("POSIX"));
678
679         _out->id().print (buf, sizeof (buf));
680         node->add_property ("out", buf);
681         _in->id().print (buf, sizeof (buf));
682         node->add_property ("in", buf);
683         node->add_property ("active", (_active ? "yes" : "no"));
684         node->add_property ("follow-overlap", (_follow_overlap ? "yes" : "no"));
685         node->add_property ("fixed", (_fixed ? "yes" : "no"));
686         snprintf (buf, sizeof(buf), "%" PRIu32, _length);
687         node->add_property ("length", buf);
688         snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _anchor_point);
689         node->add_property ("anchor-point", buf);
690         snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _position);
691         node->add_property ("position", buf);
692
693         child = node->add_child ("FadeIn");
694
695         for (AutomationList::iterator ii = _fade_in.begin(); ii != _fade_in.end(); ++ii) {
696                 XMLNode* pnode;
697
698                 pnode = new XMLNode ("point");
699
700                 snprintf (buf, sizeof (buf), "%" PRIu32, (nframes_t) floor ((*ii)->when));
701                 pnode->add_property ("x", buf);
702                 snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
703                 pnode->add_property ("y", buf);
704                 child->add_child_nocopy (*pnode);
705         }
706
707         child = node->add_child ("FadeOut");
708
709         for (AutomationList::iterator ii = _fade_out.begin(); ii != _fade_out.end(); ++ii) {
710                 XMLNode* pnode;
711
712                 pnode = new XMLNode ("point");
713
714                 snprintf (buf, sizeof (buf), "%" PRIu32, (nframes_t) floor ((*ii)->when));
715                 pnode->add_property ("x", buf);
716                 snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
717                 pnode->add_property ("y", buf);
718                 child->add_child_nocopy (*pnode);
719         }
720
721         return *node;
722 }
723
724 int
725 Crossfade::set_state (const XMLNode& node)
726 {
727         XMLNodeConstIterator i;
728         XMLNodeList children;
729         XMLNode* fi;
730         XMLNode* fo;
731         const XMLProperty* prop;
732         LocaleGuard lg (X_("POSIX"));
733         Change what_changed = Change (0);
734         nframes_t val;
735
736         if ((prop = node.property ("position")) != 0) {
737                 sscanf (prop->value().c_str(), "%" PRIu32, &val);
738                 if (val != _position) {
739                         _position = val;
740                         what_changed = Change (what_changed | PositionChanged);
741                 }
742         } else {
743                 warning << _("old-style crossfade information - no position information") << endmsg;
744                 _position = _in->first_frame();
745         }
746
747         if ((prop = node.property ("active")) != 0) {
748                 bool x = (prop->value() == "yes");
749                 if (x != _active) {
750                         _active = x;
751                         what_changed = Change (what_changed | ActiveChanged);
752                 }
753         } else {
754                 _active = true;
755         }
756
757         if ((prop = node.property ("follow-overlap")) != 0) {
758                 _follow_overlap = (prop->value() == "yes");
759         } else {
760                 _follow_overlap = false;
761         }
762
763         if ((prop = node.property ("fixed")) != 0) {
764                 _fixed = (prop->value() == "yes");
765         } else {
766                 _fixed = false;
767         }
768
769         if ((prop = node.property ("anchor-point")) != 0) {
770                 _anchor_point = AnchorPoint (atoi ((prop->value().c_str())));
771         } else {
772                 _anchor_point = StartOfIn;
773         }
774
775         if ((prop = node.property ("length")) != 0) {
776
777                 sscanf (prop->value().c_str(), "%" PRIu32, &val);
778                 if (val != _length) {
779                         _length = atol (prop->value().c_str());
780                         what_changed = Change (what_changed | LengthChanged);
781                 }
782
783         } else {
784                 
785                 /* XXX this branch is legacy code from before
786                    the point where we stored xfade lengths.
787                 */
788                 
789                 if ((_length = overlap_length()) == 0) {
790                         throw failed_constructor();
791                 }
792         }
793
794         if ((fi = find_named_node (node, "FadeIn")) == 0) {
795                 return -1;
796         }
797         
798         if ((fo = find_named_node (node, "FadeOut")) == 0) {
799                 return -1;
800         }
801
802         /* fade in */
803         
804         _fade_in.freeze ();
805         _fade_in.clear ();
806         
807         children = fi->children();
808         
809         for (i = children.begin(); i != children.end(); ++i) {
810                 if ((*i)->name() == "point") {
811                         nframes_t x;
812                         float y;
813                         
814                         prop = (*i)->property ("x");
815                         sscanf (prop->value().c_str(), "%" PRIu32, &x);
816                         
817                         prop = (*i)->property ("y");
818                         sscanf (prop->value().c_str(), "%f", &y);
819
820                         _fade_in.add (x, y);
821                 }
822         }
823
824         _fade_in.thaw ();
825         
826         /* fade out */
827         
828         _fade_out.freeze ();
829         _fade_out.clear ();
830
831         children = fo->children();
832         
833         for (i = children.begin(); i != children.end(); ++i) {
834                 if ((*i)->name() == "point") {
835                         nframes_t x;
836                         float y;
837                         XMLProperty* prop;
838
839                         prop = (*i)->property ("x");
840                         sscanf (prop->value().c_str(), "%" PRIu32, &x);
841
842                         prop = (*i)->property ("y");
843                         sscanf (prop->value().c_str(), "%f", &y);
844                         
845                         _fade_out.add (x, y);
846                 }
847         }
848
849         _fade_out.thaw ();
850
851         StateChanged (what_changed); /* EMIT SIGNAL */
852
853         return 0;
854 }
855
856 bool
857 Crossfade::can_follow_overlap () const
858 {
859         return !_fixed;
860 }
861
862 void
863 Crossfade::set_follow_overlap (bool yn)
864 {
865         if (yn == _follow_overlap || _fixed) {
866                 return;
867         }
868
869         _follow_overlap = yn;
870
871         if (!yn) {
872                 set_length (_short_xfade_length);
873         } else {
874                 set_length (_out->first_frame() + _out->length() - _in->first_frame());
875         }
876
877         StateChanged (FollowOverlapChanged);
878 }
879
880 nframes_t
881 Crossfade::set_length (nframes_t len)
882 {
883         nframes_t limit = 0;
884
885         switch (_anchor_point) {
886         case StartOfIn:
887                 limit = _in->length();
888                 break;
889
890         case EndOfIn:
891                 limit = _in->length();
892                 break;
893
894         case EndOfOut:
895                 limit = _out->length();
896                 break;
897                 
898         }
899
900         len = min (limit, len);
901
902         double factor = len / (double) _length;
903
904         _in_update = true;
905         _fade_out.x_scale (factor);
906         _fade_in.x_scale (factor);
907         _in_update = false;
908         
909         _length = len;
910
911         StateChanged (LengthChanged);
912
913         return len;
914 }
915
916 nframes_t
917 Crossfade::overlap_length () const
918 {
919         if (_fixed) {
920                 return _length;
921         }
922         return _out->first_frame() + _out->length() - _in->first_frame();
923 }
924
925 void
926 Crossfade::set_short_xfade_length (nframes_t n)
927 {
928         _short_xfade_length = n;
929 }
930
931 void
932 Crossfade::invalidate ()
933 {
934         Invalidated (shared_from_this ()); /* EMIT SIGNAL */
935 }