Trim include dependency tree (particularly on evoral/Sequence.hpp).
[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, nframes_t start, nframes_t cnt) const
275 {
276 #if 0
277         Sample* mixdown = new Sample[cnt];
278         float* gain = new float[cnt];
279         nframes_t ret;
280
281         ret = read_at (buf, mixdown, gain, start, cnt, chan_n, cnt);
282
283         delete [] mixdown;
284         delete [] gain;
285
286         return ret;
287 #endif
288         return cnt;
289 }
290
291 nframes_t 
292 Crossfade::read_at (Sample *buf, Sample *mixdown_buffer, 
293                     float *gain_buffer, nframes_t start, nframes_t cnt, uint32_t chan_n,
294                     nframes_t read_frames, nframes_t skip_frames) const
295 {
296         nframes_t offset;
297         nframes_t to_write;
298
299         if (!_active) {
300                 return 0;
301         }
302
303         if (start < _position) {
304
305                 /* handle an initial section of the read area that we do not
306                    cover.
307                 */
308
309                 offset = _position - start;
310
311                 if (offset < cnt) {
312                         cnt -= offset;
313                 } else {
314                         return 0;
315                 }
316                 
317                 start = _position;
318                 buf += offset;
319                 to_write = min (_length, cnt);
320
321         } else {
322                 
323                 to_write = min (_length - (start - _position), cnt);
324                 
325         }
326
327         offset = start - _position;
328
329         /* Prevent data from piling up inthe crossfade buffers when reading a transparent region */
330         if (!(_out->opaque())) {
331                 memset (crossfade_buffer_out, 0, sizeof (Sample) * to_write);
332         } else if (!(_in->opaque())) {
333                 memset (crossfade_buffer_in, 0, sizeof (Sample) * to_write);
334         }
335
336         _out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
337         _in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
338
339         float* fiv = new float[to_write];
340         float* fov = new float[to_write];
341
342         _fade_in.curve().get_vector (offset, offset+to_write, fiv, to_write);
343         _fade_out.curve().get_vector (offset, offset+to_write, fov, to_write);
344
345         /* note: although we have not explicitly taken into account the return values
346            from _out->read_at() or _in->read_at(), the length() function does this
347            implicitly. why? because it computes a value based on the in+out regions'
348            position and length, and so we know precisely how much data they could return. 
349         */
350
351         for (nframes_t n = 0; n < to_write; ++n) {
352                 buf[n] = (crossfade_buffer_out[n] * fov[n]) + (crossfade_buffer_in[n] * fiv[n]);
353         }
354
355         delete [] fov;
356         delete [] fiv;
357
358         return to_write;
359 }       
360
361 OverlapType 
362 Crossfade::coverage (nframes_t start, nframes_t end) const
363 {
364         nframes_t my_end = _position + _length;
365
366         if ((start >= _position) && (end <= my_end)) {
367                 return OverlapInternal;
368         }
369         if ((end >= _position) && (end <= my_end)) {
370                 return OverlapStart;
371         }
372         if ((start >= _position) && (start <= my_end)) {
373                 return OverlapEnd;
374         }
375         if ((_position >= start) && (_position <= end) && (my_end <= end)) {
376                 return OverlapExternal;
377         }
378         return OverlapNone;
379 }
380
381 void
382 Crossfade::set_active (bool yn)
383 {
384         if (_active != yn) {
385                 _active = yn;
386                 StateChanged (ActiveChanged);
387         }
388 }
389
390 bool
391 Crossfade::refresh ()
392 {
393         /* crossfades must be between non-muted regions */
394         
395         if (_out->muted() || _in->muted()) {
396                 Invalidated (shared_from_this ());
397                 return false;
398         }
399
400         /* Top layer shouldn't be transparent */
401         
402         if (!((layer_relation > 0 ? _in : _out)->opaque())) {
403                 Invalidated (shared_from_this());
404                 return false;
405         }
406
407         /* layer ordering cannot change */
408
409         int32_t new_layer_relation = (int32_t) (_in->layer() - _out->layer());
410
411         if (new_layer_relation * layer_relation < 0) { // different sign, layers rotated 
412                 Invalidated (shared_from_this ());
413                 return false;
414         }
415
416         OverlapType ot = _in->coverage (_out->first_frame(), _out->last_frame());
417
418         if (ot == OverlapNone) {
419                 Invalidated (shared_from_this ());
420                 return false;
421         } 
422
423         bool send_signal;
424
425         if (ot != overlap_type) {
426
427                 if (_follow_overlap) {
428
429                         try {
430                                 compute (_in, _out, Config->get_xfade_model());
431                         } 
432
433                         catch (NoCrossfadeHere& err) {
434                                 Invalidated (shared_from_this ());
435                                 return false;
436                         }
437
438                         send_signal = true;
439
440                 } else {
441
442                         Invalidated (shared_from_this ());
443                         return false;
444                 }
445
446         } else {
447
448                 send_signal = update ();
449         }
450
451         if (send_signal) {
452                 StateChanged (BoundsChanged); /* EMIT SIGNAL */
453         }
454
455         _in_update = false;
456
457         return true;
458 }
459
460 bool
461 Crossfade::update ()
462 {
463         nframes_t newlen;
464         
465         if (_follow_overlap) {
466                 newlen = _out->first_frame() + _out->length() - _in->first_frame();
467         } else {
468                 newlen = _length;
469         }
470         
471         if (newlen == 0) {
472                 Invalidated (shared_from_this ());
473                 return false;
474         }
475         
476         _in_update = true;
477         
478         if ((_follow_overlap && newlen != _length) || (_length > newlen)) {
479                 
480                 double factor =  newlen / (double) _length;
481                 
482                 _fade_out.x_scale (factor);
483                 _fade_in.x_scale (factor);
484                 
485                 _length = newlen;
486         } 
487                 
488         switch (_anchor_point) {
489         case StartOfIn:
490                 _position = _in->first_frame();
491                 break;
492                 
493         case EndOfIn:
494                 _position = _in->last_frame() - _length;
495                 break;
496                 
497         case EndOfOut:
498                 _position = _out->last_frame() - _length;
499         }
500
501         return true;
502 }
503
504 int
505 Crossfade::compute (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioRegion> b, CrossfadeModel model)
506 {
507         boost::shared_ptr<AudioRegion> top;
508         boost::shared_ptr<AudioRegion> bottom;
509         nframes_t short_xfade_length;
510
511         short_xfade_length = _short_xfade_length; 
512
513         if (a->layer() < b->layer()) {
514                 top = b;
515                 bottom = a;
516         } else {
517                 top = a;
518                 bottom = b;
519         }
520         
521         /* first check for matching ends */
522         
523         if (top->first_frame() == bottom->first_frame()) {
524
525                 /* Both regions start at the same point */
526                 
527                 if (top->last_frame() < bottom->last_frame()) {
528                         
529                         /* top ends before bottom, so put an xfade
530                            in at the end of top.
531                         */
532                         
533                         /* [-------- top ---------- ]
534                          * {====== bottom =====================}
535                          */
536
537                         _in = bottom;
538                         _out = top;
539
540                         if (top->last_frame() < short_xfade_length) {
541                                 _position = 0;
542                         } else {
543                                 _position = top->last_frame() - short_xfade_length;
544                         }
545
546                         _length = min (short_xfade_length, top->length());
547                         _follow_overlap = false;
548                         _anchor_point = EndOfIn;
549                         _active = true;
550                         _fixed = true;
551
552                 } else {
553                         /* top ends after (or same time) as bottom - no xfade
554                          */
555                         
556                         /* [-------- top ------------------------ ]
557                          * {====== bottom =====================}
558                          */
559
560                         throw NoCrossfadeHere();
561                 }
562                 
563         } else if (top->last_frame() == bottom->last_frame()) {
564                 
565                 /* Both regions end at the same point */
566                 
567                 if (top->first_frame() > bottom->first_frame()) {
568                         
569                         /* top starts after bottom, put an xfade in at the
570                            start of top
571                         */
572                         
573                         /*            [-------- top ---------- ]
574                          * {====== bottom =====================}
575                          */
576
577                         _in = top;
578                         _out = bottom;
579                         _position = top->first_frame();
580                         _length = min (short_xfade_length, top->length());
581                         _follow_overlap = false;
582                         _anchor_point = StartOfIn;
583                         _active = true;
584                         _fixed = true;
585                         
586                 } else {
587                         /* top starts before bottom - no xfade
588                          */
589
590                         /* [-------- top ------------------------ ]
591                          *    {====== bottom =====================}
592                          */
593
594                         throw NoCrossfadeHere();
595                 }
596
597         } else {
598         
599                 /* OK, time to do more regular overlapping */
600
601                 OverlapType ot = top->coverage (bottom->first_frame(), bottom->last_frame());
602
603                 switch (ot) {
604                 case OverlapNone:
605                         /* should be NOTREACHED as a precondition of creating
606                            a new crossfade, but we need to handle it here.
607                         */
608                         throw NoCrossfadeHere();
609                         break;
610                         
611                 case OverlapInternal:
612                 case OverlapExternal:
613                         /* should be NOTREACHED because of tests above */
614                         throw NoCrossfadeHere();
615                         break;
616                         
617                 case OverlapEnd: /* top covers start of bottom but ends within it */
618
619                         /* [---- top ------------------------] 
620                          *                { ==== bottom ============ } 
621                          */ 
622
623                         _in = bottom;
624                         _out = top;
625                         _anchor_point = EndOfOut;
626
627                         if (model == FullCrossfade) {
628                                 _position = bottom->first_frame(); // "{"
629                                 _length = _out->first_frame() + _out->length() - _in->first_frame();
630                                 /* leave active alone */
631                                 _follow_overlap = true;
632                         } else {
633                                 _length = min (short_xfade_length, top->length());
634                                 _position = top->last_frame() - _length;  // "]" - length 
635                                 _active = true;
636                                 _follow_overlap = false;
637                                 
638                         }
639                         break;
640                         
641                 case OverlapStart:   /* top starts within bottom but covers bottom's end */
642
643                         /*                   { ==== top ============ } 
644                          *   [---- bottom -------------------] 
645                          */
646
647                         _in = top;
648                         _out = bottom;
649                         _position = top->first_frame();
650                         _anchor_point = StartOfIn;
651
652                         if (model == FullCrossfade) {
653                                 _length = _out->first_frame() + _out->length() - _in->first_frame();
654                                 /* leave active alone */
655                                 _follow_overlap = true;
656                         } else {
657                                 _length = min (short_xfade_length, top->length());
658                                 _active = true;
659                                 _follow_overlap = false;
660                                 
661                         }
662                         
663                         break;
664                 }
665         }
666         
667         return 0;
668 }
669
670 XMLNode&
671 Crossfade::get_state () 
672 {
673         XMLNode* node = new XMLNode (X_("Crossfade"));
674         XMLNode* child;
675         char buf[64];
676         LocaleGuard lg (X_("POSIX"));
677
678         _out->id().print (buf, sizeof (buf));
679         node->add_property ("out", buf);
680         _in->id().print (buf, sizeof (buf));
681         node->add_property ("in", buf);
682         node->add_property ("active", (_active ? "yes" : "no"));
683         node->add_property ("follow-overlap", (_follow_overlap ? "yes" : "no"));
684         node->add_property ("fixed", (_fixed ? "yes" : "no"));
685         snprintf (buf, sizeof(buf), "%" PRIu32, _length);
686         node->add_property ("length", buf);
687         snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _anchor_point);
688         node->add_property ("anchor-point", buf);
689         snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _position);
690         node->add_property ("position", buf);
691
692         child = node->add_child ("FadeIn");
693
694         for (AutomationList::iterator ii = _fade_in.begin(); ii != _fade_in.end(); ++ii) {
695                 XMLNode* pnode;
696
697                 pnode = new XMLNode ("point");
698
699                 snprintf (buf, sizeof (buf), "%" PRIu32, (nframes_t) floor ((*ii)->when));
700                 pnode->add_property ("x", buf);
701                 snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
702                 pnode->add_property ("y", buf);
703                 child->add_child_nocopy (*pnode);
704         }
705
706         child = node->add_child ("FadeOut");
707
708         for (AutomationList::iterator ii = _fade_out.begin(); ii != _fade_out.end(); ++ii) {
709                 XMLNode* pnode;
710
711                 pnode = new XMLNode ("point");
712
713                 snprintf (buf, sizeof (buf), "%" PRIu32, (nframes_t) floor ((*ii)->when));
714                 pnode->add_property ("x", buf);
715                 snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
716                 pnode->add_property ("y", buf);
717                 child->add_child_nocopy (*pnode);
718         }
719
720         return *node;
721 }
722
723 int
724 Crossfade::set_state (const XMLNode& node)
725 {
726         XMLNodeConstIterator i;
727         XMLNodeList children;
728         XMLNode* fi;
729         XMLNode* fo;
730         const XMLProperty* prop;
731         LocaleGuard lg (X_("POSIX"));
732         Change what_changed = Change (0);
733         nframes_t val;
734
735         if ((prop = node.property ("position")) != 0) {
736                 sscanf (prop->value().c_str(), "%" PRIu32, &val);
737                 if (val != _position) {
738                         _position = val;
739                         what_changed = Change (what_changed | PositionChanged);
740                 }
741         } else {
742                 warning << _("old-style crossfade information - no position information") << endmsg;
743                 _position = _in->first_frame();
744         }
745
746         if ((prop = node.property ("active")) != 0) {
747                 bool x = (prop->value() == "yes");
748                 if (x != _active) {
749                         _active = x;
750                         what_changed = Change (what_changed | ActiveChanged);
751                 }
752         } else {
753                 _active = true;
754         }
755
756         if ((prop = node.property ("follow-overlap")) != 0) {
757                 _follow_overlap = (prop->value() == "yes");
758         } else {
759                 _follow_overlap = false;
760         }
761
762         if ((prop = node.property ("fixed")) != 0) {
763                 _fixed = (prop->value() == "yes");
764         } else {
765                 _fixed = false;
766         }
767
768         if ((prop = node.property ("anchor-point")) != 0) {
769                 _anchor_point = AnchorPoint (atoi ((prop->value().c_str())));
770         } else {
771                 _anchor_point = StartOfIn;
772         }
773
774         if ((prop = node.property ("length")) != 0) {
775
776                 sscanf (prop->value().c_str(), "%" PRIu32, &val);
777                 if (val != _length) {
778                         _length = atol (prop->value().c_str());
779                         what_changed = Change (what_changed | LengthChanged);
780                 }
781
782         } else {
783                 
784                 /* XXX this branch is legacy code from before
785                    the point where we stored xfade lengths.
786                 */
787                 
788                 if ((_length = overlap_length()) == 0) {
789                         throw failed_constructor();
790                 }
791         }
792
793         if ((fi = find_named_node (node, "FadeIn")) == 0) {
794                 return -1;
795         }
796         
797         if ((fo = find_named_node (node, "FadeOut")) == 0) {
798                 return -1;
799         }
800
801         /* fade in */
802         
803         _fade_in.freeze ();
804         _fade_in.clear ();
805         
806         children = fi->children();
807         
808         for (i = children.begin(); i != children.end(); ++i) {
809                 if ((*i)->name() == "point") {
810                         nframes_t x;
811                         float y;
812                         
813                         prop = (*i)->property ("x");
814                         sscanf (prop->value().c_str(), "%" PRIu32, &x);
815                         
816                         prop = (*i)->property ("y");
817                         sscanf (prop->value().c_str(), "%f", &y);
818
819                         _fade_in.add (x, y);
820                 }
821         }
822
823         _fade_in.thaw ();
824         
825         /* fade out */
826         
827         _fade_out.freeze ();
828         _fade_out.clear ();
829
830         children = fo->children();
831         
832         for (i = children.begin(); i != children.end(); ++i) {
833                 if ((*i)->name() == "point") {
834                         nframes_t x;
835                         float y;
836                         XMLProperty* prop;
837
838                         prop = (*i)->property ("x");
839                         sscanf (prop->value().c_str(), "%" PRIu32, &x);
840
841                         prop = (*i)->property ("y");
842                         sscanf (prop->value().c_str(), "%f", &y);
843                         
844                         _fade_out.add (x, y);
845                 }
846         }
847
848         _fade_out.thaw ();
849
850         StateChanged (what_changed); /* EMIT SIGNAL */
851
852         return 0;
853 }
854
855 bool
856 Crossfade::can_follow_overlap () const
857 {
858         return !_fixed;
859 }
860
861 void
862 Crossfade::set_follow_overlap (bool yn)
863 {
864         if (yn == _follow_overlap || _fixed) {
865                 return;
866         }
867
868         _follow_overlap = yn;
869
870         if (!yn) {
871                 set_length (_short_xfade_length);
872         } else {
873                 set_length (_out->first_frame() + _out->length() - _in->first_frame());
874         }
875
876         StateChanged (FollowOverlapChanged);
877 }
878
879 nframes_t
880 Crossfade::set_length (nframes_t len)
881 {
882         nframes_t limit = 0;
883
884         switch (_anchor_point) {
885         case StartOfIn:
886                 limit = _in->length();
887                 break;
888
889         case EndOfIn:
890                 limit = _in->length();
891                 break;
892
893         case EndOfOut:
894                 limit = _out->length();
895                 break;
896                 
897         }
898
899         len = min (limit, len);
900
901         double factor = len / (double) _length;
902
903         _in_update = true;
904         _fade_out.x_scale (factor);
905         _fade_in.x_scale (factor);
906         _in_update = false;
907         
908         _length = len;
909
910         StateChanged (LengthChanged);
911
912         return len;
913 }
914
915 nframes_t
916 Crossfade::overlap_length () const
917 {
918         if (_fixed) {
919                 return _length;
920         }
921         return _out->first_frame() + _out->length() - _in->first_frame();
922 }
923
924 void
925 Crossfade::set_short_xfade_length (nframes_t n)
926 {
927         _short_xfade_length = n;
928 }
929
930 void
931 Crossfade::invalidate ()
932 {
933         Invalidated (shared_from_this ()); /* EMIT SIGNAL */
934 }