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