Fix crash on clear option for automation tracks (#3195). Also fix state change signa...
[ardour.git] / libs / evoral / src / ControlList.cpp
1 /* This file is part of Evoral.
2  * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
3  * Copyright (C) 2000-2008 Paul Davis
4  *
5  * Evoral is free software; you can redistribute it and/or modify it under the
6  * terms of the GNU General Public License as published by the Free Software
7  * Foundation; either version 2 of the License, or (at your option) any later
8  * version.
9  *
10  * Evoral is distributed in the hope that it will be useful, but WITHOUT ANY
11  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include <cmath>
20 #include <cassert>
21 #include <utility>
22 #include <iostream>
23 #include "evoral/ControlList.hpp"
24 #include "evoral/Curve.hpp"
25
26 using namespace std;
27
28 namespace Evoral {
29
30
31 inline bool event_time_less_than (ControlEvent* a, ControlEvent* b)
32 {
33         return a->when < b->when;
34 }
35
36
37 ControlList::ControlList (const Parameter& id)
38         : _parameter(id)
39         , _interpolation(Linear)
40         , _curve(0)
41 {
42         _frozen = 0;
43         _changed_when_thawed = false;
44         _min_yval = id.min();
45         _max_yval = id.max();
46         _max_xval = 0; // means "no limit"
47         _default_value = 0;
48         _rt_insertion_point = _events.end();
49         _lookup_cache.left = -1;
50         _lookup_cache.range.first = _events.end();
51         _search_cache.left = -1;
52         _search_cache.range.first = _events.end();
53         _sort_pending = false;
54 }
55
56 ControlList::ControlList (const ControlList& other)
57         : _parameter(other._parameter)
58         , _interpolation(Linear)
59         , _curve(0)
60 {
61         _frozen = 0;
62         _changed_when_thawed = false;
63         _min_yval = other._min_yval;
64         _max_yval = other._max_yval;
65         _max_xval = other._max_xval;
66         _default_value = other._default_value;
67         _rt_insertion_point = _events.end();
68         _lookup_cache.range.first = _events.end();
69         _search_cache.range.first = _events.end();
70         _sort_pending = false;
71
72         for (const_iterator i = other._events.begin(); i != other._events.end(); ++i) {
73                 _events.push_back (new ControlEvent (**i));
74         }
75
76         mark_dirty ();
77 }
78
79 ControlList::ControlList (const ControlList& other, double start, double end)
80         : _parameter(other._parameter)
81         , _interpolation(Linear)
82         , _curve(0)
83 {
84         _frozen = 0;
85         _changed_when_thawed = false;
86         _min_yval = other._min_yval;
87         _max_yval = other._max_yval;
88         _max_xval = other._max_xval;
89         _default_value = other._default_value;
90         _rt_insertion_point = _events.end();
91         _lookup_cache.range.first = _events.end();
92         _search_cache.range.first = _events.end();
93         _sort_pending = false;
94
95         /* now grab the relevant points, and shift them back if necessary */
96
97         boost::shared_ptr<ControlList> section = const_cast<ControlList*>(&other)->copy (start, end);
98
99         if (!section->empty()) {
100                 for (iterator i = section->begin(); i != section->end(); ++i) {
101                         _events.push_back (new ControlEvent ((*i)->when, (*i)->value));
102                 }
103         }
104
105         mark_dirty ();
106 }
107
108 ControlList::~ControlList()
109 {
110         for (EventList::iterator x = _events.begin(); x != _events.end(); ++x) {
111                 delete (*x);
112         }
113
114         delete _curve;
115 }
116
117 boost::shared_ptr<ControlList>
118 ControlList::create(Parameter id)
119 {
120         return boost::shared_ptr<ControlList>(new ControlList(id));
121 }
122
123 bool
124 ControlList::operator== (const ControlList& other)
125 {
126         return _events == other._events;
127 }
128
129 ControlList&
130 ControlList::operator= (const ControlList& other)
131 {
132         if (this != &other) {
133
134                 _events.clear ();
135
136                 for (const_iterator i = other._events.begin(); i != other._events.end(); ++i) {
137                         _events.push_back (new ControlEvent (**i));
138                 }
139
140                 _min_yval = other._min_yval;
141                 _max_yval = other._max_yval;
142                 _max_xval = other._max_xval;
143                 _default_value = other._default_value;
144
145                 mark_dirty ();
146                 maybe_signal_changed ();
147         }
148
149         return *this;
150 }
151
152 void
153 ControlList::create_curve()
154 {
155         _curve = new Curve(*this);
156 }
157
158 void
159 ControlList::destroy_curve()
160 {
161         delete _curve;
162         _curve = NULL;
163 }
164
165 void
166 ControlList::maybe_signal_changed ()
167 {
168         mark_dirty ();
169
170         if (_frozen) {
171                 _changed_when_thawed = true;
172         }
173 }
174
175 void
176 ControlList::clear ()
177 {
178         {
179                 Glib::Mutex::Lock lm (_lock);
180                 _events.clear ();
181                 mark_dirty ();
182         }
183
184         maybe_signal_changed ();
185 }
186
187 void
188 ControlList::x_scale (double factor)
189 {
190         Glib::Mutex::Lock lm (_lock);
191         _x_scale (factor);
192 }
193
194 bool
195 ControlList::extend_to (double when)
196 {
197         Glib::Mutex::Lock lm (_lock);
198         if (_events.empty() || _events.back()->when == when) {
199                 return false;
200         }
201         double factor = when / _events.back()->when;
202         _x_scale (factor);
203         return true;
204 }
205
206 void ControlList::_x_scale (double factor)
207 {
208         for (iterator i = _events.begin(); i != _events.end(); ++i) {
209                 (*i)->when = floor ((*i)->when * factor);
210         }
211
212         mark_dirty ();
213 }
214
215 void
216 ControlList::reposition_for_rt_add (double /*when*/)
217 {
218         _rt_insertion_point = _events.end();
219 }
220
221 void
222 ControlList::rt_add (double when, double value)
223 {
224         //cerr << "RT: alist " << this << " add " << value << " @ " << when << endl;
225
226         {
227                 Glib::Mutex::Lock lm (_lock);
228
229                 iterator where;
230                 ControlEvent cp (when, 0.0);
231                 bool done = false;
232
233                 if ((_rt_insertion_point != _events.end()) && ((*_rt_insertion_point)->when < when) ) {
234
235                         /* we have a previous insertion point, so we should delete
236                            everything between it and the position where we are going
237                            to insert this point.
238                         */
239
240                         iterator after = _rt_insertion_point;
241
242                         if (++after != _events.end()) {
243                                 iterator far = after;
244
245                                 while (far != _events.end()) {
246                                         if ((*far)->when > when) {
247                                                 break;
248                                         }
249                                         ++far;
250                                 }
251
252                                 if (_new_value) {
253                                         where = far;
254                                         _rt_insertion_point = where;
255
256                                         if ((*where)->when == when) {
257                                                 (*where)->value = value;
258                                                 done = true;
259                                         }
260                                 } else {
261                                         where = _events.erase (after, far);
262                                 }
263
264                         } else {
265
266                                 where = after;
267
268                         }
269
270                         iterator previous = _rt_insertion_point;
271                         --previous;
272
273                         if (_rt_insertion_point != _events.begin() && (*_rt_insertion_point)->value == value && (*previous)->value == value) {
274                                 (*_rt_insertion_point)->when = when;
275                                 done = true;
276
277                         }
278
279                 } else {
280
281                         where = lower_bound (_events.begin(), _events.end(), &cp, time_comparator);
282
283                         if (where != _events.end()) {
284                                 if ((*where)->when == when) {
285                                         (*where)->value = value;
286                                         done = true;
287                                 }
288                         }
289                 }
290
291                 if (!done) {
292                         _rt_insertion_point = _events.insert (where, new ControlEvent (when, value));
293                 }
294
295                 _new_value = false;
296                 mark_dirty ();
297         }
298
299         maybe_signal_changed ();
300 }
301
302 void
303 ControlList::fast_simple_add (double when, double value)
304 {
305         /* to be used only for loading pre-sorted data from saved state */
306         _events.insert (_events.end(), new ControlEvent (when, value));
307         assert(_events.back());
308 }
309
310 void
311 ControlList::add (double when, double value)
312 {
313         /* this is for graphical editing */
314
315         {
316                 Glib::Mutex::Lock lm (_lock);
317                 ControlEvent cp (when, 0.0f);
318                 bool insert = true;
319                 iterator insertion_point;
320
321                 for (insertion_point = lower_bound (_events.begin(), _events.end(), &cp, time_comparator); insertion_point != _events.end(); ++insertion_point) {
322
323                         /* only one point allowed per time point */
324
325                         if ((*insertion_point)->when == when) {
326                                 (*insertion_point)->value = value;
327                                 insert = false;
328                                 break;
329                         }
330
331                         if ((*insertion_point)->when >= when) {
332                                 break;
333                         }
334                 }
335
336                 if (insert) {
337
338                         _events.insert (insertion_point, new ControlEvent (when, value));
339                         reposition_for_rt_add (0);
340
341                 }
342
343                 mark_dirty ();
344         }
345
346         maybe_signal_changed ();
347 }
348
349 void
350 ControlList::erase (iterator i)
351 {
352         {
353                 Glib::Mutex::Lock lm (_lock);
354                 _events.erase (i);
355                 reposition_for_rt_add (0);
356                 mark_dirty ();
357         }
358         maybe_signal_changed ();
359 }
360
361 void
362 ControlList::erase (iterator start, iterator end)
363 {
364         {
365                 Glib::Mutex::Lock lm (_lock);
366                 _events.erase (start, end);
367                 reposition_for_rt_add (0);
368                 mark_dirty ();
369         }
370         maybe_signal_changed ();
371 }
372
373 void
374 ControlList::reset_range (double start, double endt)
375 {
376         bool reset = false;
377
378         {
379                 Glib::Mutex::Lock lm (_lock);
380                 ControlEvent cp (start, 0.0f);
381                 iterator s;
382                 iterator e;
383
384                 if ((s = lower_bound (_events.begin(), _events.end(), &cp, time_comparator)) != _events.end()) {
385
386                         cp.when = endt;
387                         e = upper_bound (_events.begin(), _events.end(), &cp, time_comparator);
388
389                         for (iterator i = s; i != e; ++i) {
390                                 (*i)->value = _default_value;
391                         }
392
393                         reset = true;
394
395                         mark_dirty ();
396                 }
397         }
398
399         if (reset) {
400                 maybe_signal_changed ();
401         }
402 }
403
404 void
405 ControlList::erase_range (double start, double endt)
406 {
407         bool erased = false;
408
409         {
410                 Glib::Mutex::Lock lm (_lock);
411                 erased = erase_range_internal (start, endt, _events);
412
413                 if (erased) {
414                         reposition_for_rt_add (0);
415                         mark_dirty ();
416                 }
417
418         }
419
420         if (erased) {
421                 maybe_signal_changed ();
422         }
423 }
424
425 bool
426 ControlList::erase_range_internal (double start, double endt, EventList & events)
427 {
428         bool erased = false;
429         ControlEvent cp (start, 0.0f);
430         iterator s;
431         iterator e;
432
433         if ((s = lower_bound (events.begin(), events.end(), &cp, time_comparator)) != events.end()) {
434                 cp.when = endt;
435                 e = upper_bound (events.begin(), events.end(), &cp, time_comparator);
436                 events.erase (s, e);
437                 erased = true;
438         }
439
440         return erased;
441 }
442
443 void
444 ControlList::slide (iterator before, double distance)
445 {
446         {
447                 Glib::Mutex::Lock lm (_lock);
448
449                 if (before == _events.end()) {
450                         return;
451                 }
452
453                 while (before != _events.end()) {
454                         (*before)->when += distance;
455                         ++before;
456                 }
457         }
458
459         maybe_signal_changed ();
460 }
461
462 void
463 ControlList::modify (iterator iter, double when, double val)
464 {
465         /* note: we assume higher level logic is in place to avoid this
466            reordering the time-order of control events in the list. ie. all
467            points after *iter are later than when.
468         */
469
470         {
471                 Glib::Mutex::Lock lm (_lock);
472
473                 (*iter)->when = when;
474                 (*iter)->value = val;
475
476                 if (isnan (val)) {
477                         abort ();
478                 }
479
480                 if (!_frozen) {
481                         _events.sort (event_time_less_than);
482                 } else {
483                         _sort_pending = true;
484                 }
485
486                 mark_dirty ();
487         }
488
489         maybe_signal_changed ();
490 }
491
492 std::pair<ControlList::iterator,ControlList::iterator>
493 ControlList::control_points_adjacent (double xval)
494 {
495         Glib::Mutex::Lock lm (_lock);
496         iterator i;
497         ControlEvent cp (xval, 0.0f);
498         std::pair<iterator,iterator> ret;
499
500         ret.first = _events.end();
501         ret.second = _events.end();
502
503         for (i = lower_bound (_events.begin(), _events.end(), &cp, time_comparator); i != _events.end(); ++i) {
504
505                 if (ret.first == _events.end()) {
506                         if ((*i)->when >= xval) {
507                                 if (i != _events.begin()) {
508                                         ret.first = i;
509                                         --ret.first;
510                                 } else {
511                                         return ret;
512                                 }
513                         }
514                 }
515
516                 if ((*i)->when > xval) {
517                         ret.second = i;
518                         break;
519                 }
520         }
521
522         return ret;
523 }
524
525 void
526 ControlList::set_max_xval (double x)
527 {
528         _max_xval = x;
529 }
530
531 void
532 ControlList::freeze ()
533 {
534         _frozen++;
535 }
536
537 void
538 ControlList::thaw ()
539 {
540         assert(_frozen > 0);
541
542         if (--_frozen > 0) {
543                 return;
544         }
545
546         {
547                 Glib::Mutex::Lock lm (_lock);
548
549                 if (_sort_pending) {
550                         _events.sort (event_time_less_than);
551                         _sort_pending = false;
552                 }
553         }
554 }
555
556 void
557 ControlList::mark_dirty () const
558 {
559         _lookup_cache.left = -1;
560         _search_cache.left = -1;
561         if (_curve)
562                 _curve->mark_dirty();
563 }
564
565 void
566 ControlList::truncate_end (double last_coordinate)
567 {
568         {
569                 Glib::Mutex::Lock lm (_lock);
570                 ControlEvent cp (last_coordinate, 0);
571                 ControlList::reverse_iterator i;
572                 double last_val;
573
574                 if (_events.empty()) {
575                         return;
576                 }
577
578                 if (last_coordinate == _events.back()->when) {
579                         return;
580                 }
581
582                 if (last_coordinate > _events.back()->when) {
583
584                         /* extending end:
585                         */
586
587                         iterator foo = _events.begin();
588                         bool lessthantwo;
589
590                         if (foo == _events.end()) {
591                                 lessthantwo = true;
592                         } else if (++foo == _events.end()) {
593                                 lessthantwo = true;
594                         } else {
595                                 lessthantwo = false;
596                         }
597
598                         if (lessthantwo) {
599                                 /* less than 2 points: add a new point */
600                                 _events.push_back (new ControlEvent (last_coordinate, _events.back()->value));
601                         } else {
602
603                                 /* more than 2 points: check to see if the last 2 values
604                                    are equal. if so, just move the position of the
605                                    last point. otherwise, add a new point.
606                                 */
607
608                                 iterator penultimate = _events.end();
609                                 --penultimate; /* points at last point */
610                                 --penultimate; /* points at the penultimate point */
611
612                                 if (_events.back()->value == (*penultimate)->value) {
613                                         _events.back()->when = last_coordinate;
614                                 } else {
615                                         _events.push_back (new ControlEvent (last_coordinate, _events.back()->value));
616                                 }
617                         }
618
619                 } else {
620
621                         /* shortening end */
622
623                         last_val = unlocked_eval (last_coordinate);
624                         last_val = max ((double) _min_yval, last_val);
625                         last_val = min ((double) _max_yval, last_val);
626
627                         i = _events.rbegin();
628
629                         /* make i point to the last control point */
630
631                         ++i;
632
633                         /* now go backwards, removing control points that are
634                            beyond the new last coordinate.
635                         */
636
637                         // FIXME: SLOW! (size() == O(n))
638
639                         uint32_t sz = _events.size();
640
641                         while (i != _events.rend() && sz > 2) {
642                                 ControlList::reverse_iterator tmp;
643
644                                 tmp = i;
645                                 ++tmp;
646
647                                 if ((*i)->when < last_coordinate) {
648                                         break;
649                                 }
650
651                                 _events.erase (i.base());
652                                 --sz;
653
654                                 i = tmp;
655                         }
656
657                         _events.back()->when = last_coordinate;
658                         _events.back()->value = last_val;
659                 }
660
661                 reposition_for_rt_add (0);
662                 mark_dirty();
663         }
664
665         maybe_signal_changed ();
666 }
667
668 void
669 ControlList::truncate_start (double overall_length)
670 {
671         {
672                 Glib::Mutex::Lock lm (_lock);
673                 iterator i;
674                 double first_legal_value;
675                 double first_legal_coordinate;
676
677                 assert(!_events.empty());
678
679                 if (overall_length == _events.back()->when) {
680                         /* no change in overall length */
681                         return;
682                 }
683
684                 if (overall_length > _events.back()->when) {
685
686                         /* growing at front: duplicate first point. shift all others */
687
688                         double shift = overall_length - _events.back()->when;
689                         uint32_t np;
690
691                         for (np = 0, i = _events.begin(); i != _events.end(); ++i, ++np) {
692                                 (*i)->when += shift;
693                         }
694
695                         if (np < 2) {
696
697                                 /* less than 2 points: add a new point */
698                                 _events.push_front (new ControlEvent (0, _events.front()->value));
699
700                         } else {
701
702                                 /* more than 2 points: check to see if the first 2 values
703                                    are equal. if so, just move the position of the
704                                    first point. otherwise, add a new point.
705                                 */
706
707                                 iterator second = _events.begin();
708                                 ++second; /* points at the second point */
709
710                                 if (_events.front()->value == (*second)->value) {
711                                         /* first segment is flat, just move start point back to zero */
712                                         _events.front()->when = 0;
713                                 } else {
714                                         /* leave non-flat segment in place, add a new leading point. */
715                                         _events.push_front (new ControlEvent (0, _events.front()->value));
716                                 }
717                         }
718
719                 } else {
720
721                         /* shrinking at front */
722
723                         first_legal_coordinate = _events.back()->when - overall_length;
724                         first_legal_value = unlocked_eval (first_legal_coordinate);
725                         first_legal_value = max (_min_yval, first_legal_value);
726                         first_legal_value = min (_max_yval, first_legal_value);
727
728                         /* remove all events earlier than the new "front" */
729
730                         i = _events.begin();
731
732                         while (i != _events.end() && !_events.empty()) {
733                                 ControlList::iterator tmp;
734
735                                 tmp = i;
736                                 ++tmp;
737
738                                 if ((*i)->when > first_legal_coordinate) {
739                                         break;
740                                 }
741
742                                 _events.erase (i);
743
744                                 i = tmp;
745                         }
746
747
748                         /* shift all remaining points left to keep their same
749                            relative position
750                         */
751
752                         for (i = _events.begin(); i != _events.end(); ++i) {
753                                 (*i)->when -= first_legal_coordinate;
754                         }
755
756                         /* add a new point for the interpolated new value */
757
758                         _events.push_front (new ControlEvent (0, first_legal_value));
759                 }
760
761                 reposition_for_rt_add (0);
762
763                 mark_dirty();
764         }
765
766         maybe_signal_changed ();
767 }
768
769 double
770 ControlList::unlocked_eval (double x) const
771 {
772         pair<EventList::iterator,EventList::iterator> range;
773         int32_t npoints;
774         double lpos, upos;
775         double lval, uval;
776         double fraction;
777
778         const_iterator length_check_iter = _events.begin();
779         for (npoints = 0; npoints < 4; ++npoints, ++length_check_iter) {
780                 if (length_check_iter == _events.end()) {
781                         break;
782                 }
783         }
784
785         switch (npoints) {
786         case 0:
787                 return _default_value;
788
789         case 1:
790                 return _events.front()->value;
791
792         case 2:
793                 if (x >= _events.back()->when) {
794                         return _events.back()->value;
795                 } else if (x <= _events.front()->when) {
796                         return _events.front()->value;
797                 }
798
799                 lpos = _events.front()->when;
800                 lval = _events.front()->value;
801                 upos = _events.back()->when;
802                 uval = _events.back()->value;
803
804                 if (_interpolation == Discrete) {
805                         return lval;
806                 }
807
808                 /* linear interpolation betweeen the two points */
809                 fraction = (double) (x - lpos) / (double) (upos - lpos);
810                 return lval + (fraction * (uval - lval));
811
812         default:
813                 if (x >= _events.back()->when) {
814                         return _events.back()->value;
815                 } else if (x <= _events.front()->when) {
816                         return _events.front()->value;
817                 }
818
819                 return multipoint_eval (x);
820         }
821
822         /*NOTREACHED*/ /* stupid gcc */
823         return _default_value;
824 }
825
826 double
827 ControlList::multipoint_eval (double x) const
828 {
829         double upos, lpos;
830         double uval, lval;
831         double fraction;
832
833         /* "Stepped" lookup (no interpolation) */
834         /* FIXME: no cache.  significant? */
835         if (_interpolation == Discrete) {
836                 const ControlEvent cp (x, 0);
837                 EventList::const_iterator i = lower_bound (_events.begin(), _events.end(), &cp, time_comparator);
838
839                 // shouldn't have made it to multipoint_eval
840                 assert(i != _events.end());
841
842                 if (i == _events.begin() || (*i)->when == x)
843                         return (*i)->value;
844                 else
845                         return (*(--i))->value;
846         }
847
848         /* Only do the range lookup if x is in a different range than last time
849          * this was called (or if the lookup cache has been marked "dirty" (left<0) */
850         if ((_lookup_cache.left < 0) ||
851             ((_lookup_cache.left > x) ||
852              (_lookup_cache.range.first == _events.end()) ||
853              ((*_lookup_cache.range.second)->when < x))) {
854
855                 const ControlEvent cp (x, 0);
856
857                 _lookup_cache.range = equal_range (_events.begin(), _events.end(), &cp, time_comparator);
858         }
859
860         pair<const_iterator,const_iterator> range = _lookup_cache.range;
861
862         if (range.first == range.second) {
863
864                 /* x does not exist within the list as a control point */
865
866                 _lookup_cache.left = x;
867
868                 if (range.first != _events.begin()) {
869                         --range.first;
870                         lpos = (*range.first)->when;
871                         lval = (*range.first)->value;
872                 }  else {
873                         /* we're before the first point */
874                         // return _default_value;
875                         return _events.front()->value;
876                 }
877
878                 if (range.second == _events.end()) {
879                         /* we're after the last point */
880                         return _events.back()->value;
881                 }
882
883                 upos = (*range.second)->when;
884                 uval = (*range.second)->value;
885
886                 /* linear interpolation betweeen the two points
887                    on either side of x
888                 */
889
890                 fraction = (double) (x - lpos) / (double) (upos - lpos);
891                 return lval + (fraction * (uval - lval));
892
893         }
894
895         /* x is a control point in the data */
896         _lookup_cache.left = -1;
897         return (*range.first)->value;
898 }
899
900 void
901 ControlList::build_search_cache_if_necessary(double start, double end) const
902 {
903         /* Only do the range lookup if x is in a different range than last time
904          * this was called (or if the search cache has been marked "dirty" (left<0) */
905         if (!_events.empty() && ((_search_cache.left < 0) ||
906                         ((_search_cache.left > start) ||
907                          (_search_cache.right < end)))) {
908
909                 const ControlEvent start_point (start, 0);
910                 const ControlEvent end_point (end, 0);
911
912                 //cerr << "REBUILD: (" << _search_cache.left << ".." << _search_cache.right << ") := ("
913                 //      << start << ".." << end << ")" << endl;
914
915                 _search_cache.range.first = lower_bound (_events.begin(), _events.end(), &start_point, time_comparator);
916                 _search_cache.range.second = upper_bound (_events.begin(), _events.end(), &end_point, time_comparator);
917
918                 _search_cache.left = start;
919                 _search_cache.right = end;
920         }
921 }
922
923 /** Get the earliest event between \a start and \a end, using the current interpolation style.
924  *
925  * If an event is found, \a x and \a y are set to its coordinates.
926  *
927  * \param inclusive Include events with timestamp exactly equal to \a start
928  * \return true if event is found (and \a x and \a y are valid).
929  */
930 bool
931 ControlList::rt_safe_earliest_event(double start, double end, double& x, double& y, bool inclusive) const
932 {
933         // FIXME: It would be nice if this was unnecessary..
934         Glib::Mutex::Lock lm(_lock, Glib::TRY_LOCK);
935         if (!lm.locked()) {
936                 return false;
937         }
938
939         return rt_safe_earliest_event_unlocked(start, end, x, y, inclusive);
940 }
941
942
943 /** Get the earliest event between \a start and \a end, using the current interpolation style.
944  *
945  * If an event is found, \a x and \a y are set to its coordinates.
946  *
947  * \param inclusive Include events with timestamp exactly equal to \a start
948  * \return true if event is found (and \a x and \a y are valid).
949  */
950 bool
951 ControlList::rt_safe_earliest_event_unlocked(double start, double end, double& x, double& y, bool inclusive) const
952 {
953         if (_interpolation == Discrete)
954                 return rt_safe_earliest_event_discrete_unlocked(start, end, x, y, inclusive);
955         else
956                 return rt_safe_earliest_event_linear_unlocked(start, end, x, y, inclusive);
957 }
958
959
960 /** Get the earliest event between \a start and \a end (Discrete (lack of) interpolation)
961  *
962  * If an event is found, \a x and \a y are set to its coordinates.
963  *
964  * \param inclusive Include events with timestamp exactly equal to \a start
965  * \return true if event is found (and \a x and \a y are valid).
966  */
967 bool
968 ControlList::rt_safe_earliest_event_discrete_unlocked (double start, double end, double& x, double& y, bool inclusive) const
969 {
970         build_search_cache_if_necessary(start, end);
971
972         const pair<const_iterator,const_iterator>& range = _search_cache.range;
973
974         if (range.first != _events.end()) {
975                 const ControlEvent* const first = *range.first;
976
977                 const bool past_start = (inclusive ? first->when >= start : first->when > start);
978
979                 /* Earliest points is in range, return it */
980                 if (past_start && first->when < end) {
981
982                         x = first->when;
983                         y = first->value;
984
985                         /* Move left of cache to this point
986                          * (Optimize for immediate call this cycle within range) */
987                         _search_cache.left = x;
988                         ++_search_cache.range.first;
989
990                         assert(x >= start);
991                         assert(x < end);
992                         return true;
993
994                 } else {
995                         return false;
996                 }
997
998         /* No points in range */
999         } else {
1000                 return false;
1001         }
1002 }
1003
1004 /** Get the earliest time the line crosses an integer (Linear interpolation).
1005  *
1006  * If an event is found, \a x and \a y are set to its coordinates.
1007  *
1008  * \param inclusive Include events with timestamp exactly equal to \a start
1009  * \return true if event is found (and \a x and \a y are valid).
1010  */
1011 bool
1012 ControlList::rt_safe_earliest_event_linear_unlocked (double start, double end, double& x, double& y, bool inclusive) const
1013 {
1014         //cerr << "earliest_event(start: " << start << ", end: " << end
1015         //<< ", x: " << x << ", y: " << y << ", inclusive: " << inclusive <<  ")" << endl;
1016
1017         const_iterator length_check_iter = _events.begin();
1018         if (_events.empty()) // 0 events
1019                 return false;
1020         else if (_events.end() == ++length_check_iter) // 1 event
1021                 return rt_safe_earliest_event_discrete_unlocked(start, end, x, y, inclusive);
1022
1023         // Hack to avoid infinitely repeating the same event
1024         build_search_cache_if_necessary(start, end);
1025
1026         pair<const_iterator,const_iterator> range = _search_cache.range;
1027
1028         if (range.first != _events.end()) {
1029
1030                 const ControlEvent* first = NULL;
1031                 const ControlEvent* next = NULL;
1032
1033                 /* No events past start (maybe?) */
1034                 if (next && next->when < start)
1035                         return false;
1036
1037                 /* Step is after first */
1038                 if (range.first == _events.begin() || (*range.first)->when == start) {
1039                         first = *range.first;
1040                         next = *(++range.first);
1041                         ++_search_cache.range.first;
1042
1043                 /* Step is before first */
1044                 } else {
1045                         const_iterator prev = range.first;
1046                         --prev;
1047                         first = *prev;
1048                         next = *range.first;
1049                 }
1050
1051                 if (inclusive && first->when == start) {
1052                         x = first->when;
1053                         y = first->value;
1054                         /* Move left of cache to this point
1055                          * (Optimize for immediate call this cycle within range) */
1056                         _search_cache.left = x;
1057                         //++_search_cache.range.first;
1058                         assert(x >= start);
1059                         return true;
1060                 }
1061
1062                 if (fabs(first->value - next->value) <= 1) {
1063                         if (next->when <= end && (next->when > start)) {
1064                                 x = next->when;
1065                                 y = next->value;
1066                                 /* Move left of cache to this point
1067                                  * (Optimize for immediate call this cycle within range) */
1068                                 _search_cache.left = x;
1069                                 //++_search_cache.range.first;
1070                                 assert(inclusive ? x >= start : x > start);
1071                                 return true;
1072                         } else {
1073                                 return false;
1074                         }
1075                 }
1076
1077                 const double slope = (next->value - first->value) / (double)(next->when - first->when);
1078                 //cerr << "start y: " << start_y << endl;
1079
1080                 //y = first->value + (slope * fabs(start - first->when));
1081                 y = first->value;
1082
1083                 if (first->value < next->value) // ramping up
1084                         y = ceil(y);
1085                 else // ramping down
1086                         y = floor(y);
1087
1088                 x = first->when + (y - first->value) / (double)slope;
1089
1090                 while ((inclusive && x < start) || (x <= start && y != next->value)) {
1091
1092                         if (first->value < next->value) // ramping up
1093                                 y += 1.0;
1094                         else // ramping down
1095                                 y -= 1.0;
1096
1097                         x = first->when + (y - first->value) / (double)slope;
1098                 }
1099
1100                 /*cerr << first->value << " @ " << first->when << " ... "
1101                                 << next->value << " @ " << next->when
1102                                 << " = " << y << " @ " << x << endl;*/
1103
1104                 assert(    (y >= first->value && y <= next->value)
1105                                 || (y <= first->value && y >= next->value) );
1106
1107
1108                 const bool past_start = (inclusive ? x >= start : x > start);
1109                 if (past_start && x < end) {
1110                         /* Move left of cache to this point
1111                          * (Optimize for immediate call this cycle within range) */
1112                         _search_cache.left = x;
1113                         assert(inclusive ? x >= start : x > start);
1114                         return true;
1115                 } else {
1116                         return false;
1117                 }
1118
1119         /* No points in the future, so no steps (towards them) in the future */
1120         } else {
1121                 return false;
1122         }
1123 }
1124
1125 boost::shared_ptr<ControlList>
1126 ControlList::cut (iterator start, iterator end)
1127 {
1128         boost::shared_ptr<ControlList> nal = create (_parameter);
1129
1130         {
1131                 Glib::Mutex::Lock lm (_lock);
1132
1133                 for (iterator x = start; x != end; ) {
1134                         iterator tmp;
1135
1136                         tmp = x;
1137                         ++tmp;
1138
1139                         nal->_events.push_back (new ControlEvent (**x));
1140                         _events.erase (x);
1141
1142                         reposition_for_rt_add (0);
1143
1144                         x = tmp;
1145                 }
1146
1147                 mark_dirty ();
1148         }
1149
1150         maybe_signal_changed ();
1151
1152         return nal;
1153 }
1154
1155 /** @param op 0 = cut, 1 = copy, 2 = clear */
1156 boost::shared_ptr<ControlList>
1157 ControlList::cut_copy_clear (double start, double end, int op)
1158 {
1159         boost::shared_ptr<ControlList> nal = create (_parameter);
1160         
1161         iterator s, e;
1162         bool changed = false;
1163
1164         {
1165                 Glib::Mutex::Lock lm (_lock);
1166
1167                 /* find the first event in our list that is at or before `start' in time */
1168                 ControlEvent cp (start, 0.0);
1169                 if ((s = lower_bound (_events.begin(), _events.end(), &cp, time_comparator)) == _events.end()) {
1170                         return nal;
1171                 }
1172
1173                 /* and the last that is at or after `end' */
1174                 cp.when = end;
1175                 e = upper_bound (_events.begin(), _events.end(), &cp, time_comparator);
1176
1177                 if (op != 2 && (*s)->when != start) {
1178                         nal->_events.push_back (new ControlEvent (0, unlocked_eval (start)));
1179                 }
1180
1181                 for (iterator x = s; x != e; ) {
1182                         iterator tmp = x;
1183                         ++tmp;
1184
1185                         changed = true;
1186
1187                         /* adjust new points to be relative to start, which
1188                            has been set to zero.
1189                         */
1190
1191                         if (op != 2) {
1192                                 nal->_events.push_back (new ControlEvent ((*x)->when - start, (*x)->value));
1193                         }
1194
1195                         if (op != 1) {
1196                                 _events.erase (x);
1197                         }
1198
1199                         x = tmp;
1200                 }
1201
1202                 if (op != 2 && nal->_events.back()->when != end - start) {
1203                         nal->_events.push_back (new ControlEvent (end - start, unlocked_eval (end)));
1204                 }
1205
1206                 if (changed) {
1207                         reposition_for_rt_add (0);
1208                 }
1209
1210                 mark_dirty ();
1211         }
1212
1213         maybe_signal_changed ();
1214
1215         return nal;
1216
1217 }
1218
1219 boost::shared_ptr<ControlList>
1220 ControlList::copy (iterator start, iterator end)
1221 {
1222         boost::shared_ptr<ControlList> nal = create (_parameter);
1223
1224         {
1225                 Glib::Mutex::Lock lm (_lock);
1226
1227                 for (iterator x = start; x != end; ) {
1228                         iterator tmp;
1229
1230                         tmp = x;
1231                         ++tmp;
1232
1233                         nal->_events.push_back (new ControlEvent (**x));
1234
1235                         x = tmp;
1236                 }
1237         }
1238
1239         return nal;
1240 }
1241
1242 boost::shared_ptr<ControlList>
1243 ControlList::cut (double start, double end)
1244 {
1245         return cut_copy_clear (start, end, 0);
1246 }
1247
1248 boost::shared_ptr<ControlList>
1249 ControlList::copy (double start, double end)
1250 {
1251         return cut_copy_clear (start, end, 1);
1252 }
1253
1254 void
1255 ControlList::clear (double start, double end)
1256 {
1257         (void) cut_copy_clear (start, end, 2);
1258 }
1259
1260 bool
1261 ControlList::paste (ControlList& alist, double pos, float /*times*/)
1262 {
1263         if (alist._events.empty()) {
1264                 return false;
1265         }
1266
1267         {
1268                 Glib::Mutex::Lock lm (_lock);
1269                 iterator where;
1270                 iterator prev;
1271                 double end = 0;
1272                 ControlEvent cp (pos, 0.0);
1273
1274                 where = upper_bound (_events.begin(), _events.end(), &cp, time_comparator);
1275
1276                 for (iterator i = alist.begin();i != alist.end(); ++i) {
1277                         _events.insert (where, new ControlEvent( (*i)->when+pos,( *i)->value));
1278                         end = (*i)->when + pos;
1279                 }
1280
1281
1282                 /* move all  points after the insertion along the timeline by
1283                    the correct amount.
1284                 */
1285
1286                 while (where != _events.end()) {
1287                         iterator tmp;
1288                         if ((*where)->when <= end) {
1289                                 tmp = where;
1290                                 ++tmp;
1291                                 _events.erase(where);
1292                                 where = tmp;
1293
1294                         } else {
1295                                 break;
1296                         }
1297                 }
1298
1299                 reposition_for_rt_add (0);
1300                 mark_dirty ();
1301         }
1302
1303         maybe_signal_changed ();
1304         return true;
1305 }
1306
1307 /** Move automation around according to a list of region movements */
1308 void
1309 ControlList::move_ranges (const list< RangeMove<double> >& movements)
1310 {
1311         typedef list< RangeMove<double> > RangeMoveList;
1312
1313         {
1314                 Glib::Mutex::Lock lm (_lock);
1315
1316                 /* a copy of the events list before we started moving stuff around */
1317                 EventList old_events = _events;
1318
1319                 /* clear the source and destination ranges in the new list */
1320                 for (RangeMoveList::const_iterator i = movements.begin (); i != movements.end (); ++i) {
1321
1322                         erase_range_internal (i->from, i->from + i->length, _events);
1323                         erase_range_internal (i->to, i->to + i->length, _events);
1324
1325                 }
1326
1327                 /* copy the events into the new list */
1328                 for (RangeMoveList::const_iterator i = movements.begin (); i != movements.end (); ++i) {
1329                         iterator j = old_events.begin ();
1330                         const double limit = i->from + i->length;
1331                         const double dx    = i->to - i->from;
1332                         while (j != old_events.end () && (*j)->when <= limit) {
1333                                 if ((*j)->when >= i->from) {
1334                                         ControlEvent* ev = new ControlEvent (**j);
1335                                         ev->when += dx;
1336                                         _events.push_back (ev);
1337                                 }
1338                                 ++j;
1339                         }
1340                 }
1341
1342                 if (!_frozen) {
1343                         _events.sort (event_time_less_than);
1344                 } else {
1345                         _sort_pending = true;
1346                 }
1347
1348                 reposition_for_rt_add (0);
1349                 mark_dirty ();
1350         }
1351
1352         maybe_signal_changed ();
1353 }
1354
1355 } // namespace Evoral
1356