vestige-based VST support, back-ported from 2.0-ongoing
[ardour.git] / libs / evoral / evoral / ControlList.hpp
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 #ifndef EVORAL_CONTROL_LIST_HPP
20 #define EVORAL_CONTROL_LIST_HPP
21
22 #include <cassert>
23 #include <list>
24 #include <boost/pool/pool.hpp>
25 #include <boost/pool/pool_alloc.hpp>
26 #include <glibmm/thread.h>
27 #include "evoral/types.hpp"
28 #include "evoral/Parameter.hpp"
29
30 namespace Evoral {
31
32 class Curve;
33
34 /** A single event (time-stamped value) for a control
35  */
36 struct ControlEvent {
37     ControlEvent (double w, double v)
38             : when (w), value (v), coeff (0)
39         {}
40
41     ControlEvent (const ControlEvent& other) 
42             : when (other.when), value (other.value), coeff (0)
43         {
44                 if (other.coeff) {
45                         create_coeffs();
46                         for (size_t i = 0; i < 4; ++i)
47                                 coeff[i] = other.coeff[i];
48                 }
49         }
50
51         ~ControlEvent() { if (coeff) delete[] coeff; }
52         
53         void create_coeffs() {
54                 if (!coeff)
55                         coeff = new double[4];
56             
57                 coeff[0] = coeff[1] = coeff[2] = coeff[3] = 0.0;
58         }
59
60     double  when;
61     double  value;
62     double* coeff; ///< double[4] allocated by Curve as needed
63 };
64
65
66 /** Pool allocator for control lists that does not use a lock
67  * and allocates 8k blocks of new pointers at a time
68  */
69 typedef boost::fast_pool_allocator<
70                 ControlEvent*,
71                 boost::default_user_allocator_new_delete,
72                 boost::details::pool::null_mutex,
73                 8192>
74         ControlEventAllocator;
75
76
77 /** A list (sequence) of time-stamped values for a control
78  */
79 class ControlList
80 {
81 public:
82         typedef std::list<ControlEvent*,ControlEventAllocator> EventList;
83         typedef EventList::iterator iterator;
84         typedef EventList::reverse_iterator reverse_iterator;
85         typedef EventList::const_iterator const_iterator;
86
87         ControlList (const Parameter& id);
88         ControlList (const ControlList&);
89         ControlList (const ControlList&, double start, double end);
90         virtual ~ControlList();
91         
92         virtual boost::shared_ptr<ControlList> create(Parameter id);
93         
94         ControlList& operator= (const ControlList&);
95         bool operator== (const ControlList&);
96         
97         void freeze();
98         void thaw ();
99
100         const Parameter& parameter() const                 { return _parameter; }
101         void             set_parameter(const Parameter& p) { _parameter = p; }
102
103         EventList::size_type size() const { return _events.size(); }
104         bool empty() const { return _events.empty(); }
105
106         void reset_default (double val) {
107                 _default_value = val;
108         }
109
110         void clear ();
111         void x_scale (double factor);
112         bool extend_to (double);
113         void slide (iterator before, double distance);
114
115         void reposition_for_rt_add (double when);
116         void rt_add (double when, double value);
117         void add (double when, double value);
118         void fast_simple_add (double when, double value);
119
120         void reset_range (double start, double end);
121         void erase_range (double start, double end);
122         void erase (iterator);
123         void erase (iterator, iterator);
124         void move_ranges (std::list< RangeMove<double> > const &);
125         void modify (iterator, double, double);
126
127         boost::shared_ptr<ControlList> cut (double, double);
128         boost::shared_ptr<ControlList> copy (double, double);
129         void clear (double, double);
130
131         boost::shared_ptr<ControlList> cut (iterator, iterator);
132         boost::shared_ptr<ControlList> copy (iterator, iterator);
133         void clear (iterator, iterator);
134
135         bool paste (ControlList&, double position, float times);
136         
137         void set_yrange (double min, double max) {
138                 _min_yval = min;
139                 _max_yval = max;
140         }
141
142         double get_max_y() const { return _max_yval; }
143         double get_min_y() const { return _min_yval; }
144
145         void truncate_end (double length);
146         void truncate_start (double length);
147
148         iterator            begin()       { return _events.begin(); }
149         const_iterator      begin() const { return _events.begin(); }
150         iterator            end()         { return _events.end(); }
151         const_iterator      end()   const { return _events.end(); }
152         ControlEvent*       back()        { return _events.back(); }
153         const ControlEvent* back()  const { return _events.back(); }
154         ControlEvent*       front()       { return _events.front(); }
155         const ControlEvent* front() const { return _events.front(); }
156
157         std::pair<ControlList::iterator,ControlList::iterator> control_points_adjacent (double when);
158
159         template<class T> void apply_to_points (T& obj, void (T::*method)(const ControlList&)) {
160                 Glib::Mutex::Lock lm (_lock);
161                 (obj.*method)(*this);
162         }
163
164         void set_max_xval (double);
165         double get_max_xval() const { return _max_xval; }
166
167         double eval (double where) {
168                 Glib::Mutex::Lock lm (_lock);
169                 return unlocked_eval (where);
170         }
171
172         double rt_safe_eval (double where, bool& ok) {
173
174                 Glib::Mutex::Lock lm (_lock, Glib::TRY_LOCK);
175
176                 if ((ok = lm.locked())) {
177                         return unlocked_eval (where);
178                 } else {
179                         return 0.0;
180                 }
181         }
182
183         static inline bool time_comparator (const ControlEvent* a, const ControlEvent* b) { 
184                 return a->when < b->when;
185         }
186
187         /** Lookup cache for eval functions, range contains equivalent values */
188         struct LookupCache {
189                 LookupCache() : left(-1) {}
190                 double left;  /* leftmost x coordinate used when finding "range" */
191                 std::pair<ControlList::const_iterator,ControlList::const_iterator> range;
192         };
193
194         /** Lookup cache for point finding, range contains points between left and right */
195         struct SearchCache {
196                 SearchCache() : left(-1), right(-1) {}
197                 double left;  /* leftmost x coordinate used when finding "range" */
198                 double right; /* rightmost x coordinate used when finding "range" */
199                 std::pair<ControlList::const_iterator,ControlList::const_iterator> range;
200         };
201
202         const EventList& events() const { return _events; }
203         double default_value() const { return _parameter.normal(); }
204
205         // FIXME: const violations for Curve
206         Glib::Mutex& lock()         const { return _lock; }
207         LookupCache& lookup_cache() const { return _lookup_cache; }
208         SearchCache& search_cache() const { return _search_cache; }
209
210         /** Called by locked entry point and various private
211          * locations where we already hold the lock.
212          * 
213          * FIXME: Should this be private?  Curve needs it..
214          */
215         double unlocked_eval (double x) const;
216
217         bool rt_safe_earliest_event (double start, double end, double& x, double& y, bool start_inclusive=false) const;
218         bool rt_safe_earliest_event_unlocked (double start, double end, double& x, double& y, bool start_inclusive=false) const;
219
220         void create_curve();
221         void destroy_curve();
222
223         Curve&       curve()       { assert(_curve); return *_curve; }
224         const Curve& curve() const { assert(_curve); return *_curve; }
225         
226         virtual void mark_dirty () const;
227
228         enum InterpolationStyle {
229                 Discrete,
230                 Linear,
231                 Curved
232         };
233
234         InterpolationStyle interpolation() const { return _interpolation; }
235         void set_interpolation(InterpolationStyle style) { _interpolation = style; }
236
237 protected:
238
239         /** Called by unlocked_eval() to handle cases of 3 or more control points. */
240         double multipoint_eval (double x) const; 
241
242         void build_search_cache_if_necessary(double start, double end) const;
243
244         bool rt_safe_earliest_event_discrete_unlocked (double start, double end, double& x, double& y, bool inclusive) const;
245         bool rt_safe_earliest_event_linear_unlocked (double start, double end, double& x, double& y, bool inclusive) const;
246
247         boost::shared_ptr<ControlList> cut_copy_clear (double, double, int op);
248         bool erase_range_internal (double start, double end, EventList &);
249
250         virtual void maybe_signal_changed ();
251         
252         void _x_scale (double factor);
253
254         mutable LookupCache _lookup_cache;
255         mutable SearchCache _search_cache;
256
257         Parameter           _parameter;
258         InterpolationStyle  _interpolation;
259         EventList           _events;
260         mutable Glib::Mutex _lock;
261         int8_t              _frozen;
262         bool                _changed_when_thawed;
263         bool                _new_value;
264         double              _max_xval;
265         double              _min_yval;
266         double              _max_yval;
267         double              _default_value;
268         bool                _sort_pending;
269         iterator            _rt_insertion_point;
270         double              _rt_pos;
271
272         Curve* _curve;
273 };
274
275 } // namespace Evoral
276
277 #endif // EVORAL_CONTROL_LIST_HPP
278