add option to skip guard points when adding new control points to a ControlList;...
[ardour.git] / libs / evoral / evoral / ControlList.hpp
index c6127a4e9b6648590ffec2f1b5cc9aeacc3cb1f0..0774cc528afdfbd2f8b690f50ed57edcfaa06ed6 100644 (file)
 #include <list>
 #include <boost/pool/pool.hpp>
 #include <boost/pool/pool_alloc.hpp>
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
 #include "pbd/signals.h"
+
+#include "evoral/visibility.h"
 #include "evoral/types.hpp"
 #include "evoral/Range.hpp"
 #include "evoral/Parameter.hpp"
@@ -35,7 +37,7 @@ class Curve;
 
 /** A single event (time-stamped value) for a control
  */
-class ControlEvent {
+class LIBEVORAL_API ControlEvent {
 public:
        ControlEvent (double w, double v)
                : when (w), value (v), coeff (0)
@@ -65,27 +67,16 @@ public:
        double* coeff; ///< double[4] allocated by Curve as needed
 };
 
-
-/** Pool allocator for control lists that does not use a lock
- * and allocates 8k blocks of new pointers at a time
- */
-typedef boost::fast_pool_allocator<
-       ControlEvent*,
-       boost::default_user_allocator_new_delete,
-       boost::details::pool::null_mutex,
-       8192>
-ControlEventAllocator;
-
-
 /** A list (sequence) of time-stamped values for a control
  */
-class ControlList
+class LIBEVORAL_API ControlList
 {
 public:
-       typedef std::list<ControlEvent*,ControlEventAllocator> EventList;
+       typedef std::list<ControlEvent*> EventList;
        typedef EventList::iterator iterator;
        typedef EventList::reverse_iterator reverse_iterator;
        typedef EventList::const_iterator const_iterator;
+       typedef EventList::const_reverse_iterator const_reverse_iterator;
 
        ControlList (const Parameter& id);
        ControlList (const ControlList&);
@@ -94,6 +85,8 @@ public:
 
        virtual boost::shared_ptr<ControlList> create(Parameter id);
 
+        void dump (std::ostream&);
+
        ControlList& operator= (const ControlList&);
        bool operator== (const ControlList&);
         void copy_events (const ControlList&);
@@ -107,7 +100,7 @@ public:
 
        EventList::size_type size() const { return _events.size(); }
         double length() const {                
-               Glib::Mutex::Lock lm (_lock);
+               Glib::Threads::Mutex::Lock lm (_lock);
                return _events.empty() ? 0.0 : _events.back()->when;
        }
        bool empty() const { return _events.empty(); }
@@ -124,7 +117,7 @@ public:
 
        virtual bool clamp_value (double& /*when*/, double& /*value*/) const { return true; }
 
-        void add (double when, double value, bool erase_since_last_add = false);
+        virtual void add (double when, double value, bool with_guards=true);
        void fast_simple_add (double when, double value);
 
        void erase_range (double start, double end);
@@ -157,6 +150,10 @@ public:
        const_iterator      begin() const { return _events.begin(); }
        iterator            end()         { return _events.end(); }
        const_iterator      end()   const { return _events.end(); }
+       reverse_iterator            rbegin()       { return _events.rbegin(); }
+       const_reverse_iterator      rbegin() const { return _events.rbegin(); }
+       reverse_iterator            rend()         { return _events.rend(); }
+       const_reverse_iterator      rend()   const { return _events.rend(); }
        ControlEvent*       back()        { return _events.back(); }
        const ControlEvent* back()  const { return _events.back(); }
        ControlEvent*       front()       { return _events.front(); }
@@ -165,18 +162,18 @@ public:
        std::pair<ControlList::iterator,ControlList::iterator> control_points_adjacent (double when);
 
        template<class T> void apply_to_points (T& obj, void (T::*method)(const ControlList&)) {
-               Glib::Mutex::Lock lm (_lock);
+               Glib::Threads::Mutex::Lock lm (_lock);
                (obj.*method)(*this);
        }
 
        double eval (double where) {
-               Glib::Mutex::Lock lm (_lock);
+               Glib::Threads::Mutex::Lock lm (_lock);
                return unlocked_eval (where);
        }
 
        double rt_safe_eval (double where, bool& ok) {
 
-               Glib::Mutex::Lock lm (_lock, Glib::TRY_LOCK);
+               Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
 
                if ((ok = lm.locked())) {
                        return unlocked_eval (where);
@@ -207,7 +204,7 @@ public:
        double default_value() const { return _parameter.normal(); }
 
        // FIXME: const violations for Curve
-       Glib::Mutex& lock()         const { return _lock; }
+       Glib::Threads::Mutex& lock()         const { return _lock; }
        LookupCache& lookup_cache() const { return _lookup_cache; }
        SearchCache& search_cache() const { return _search_cache; }
 
@@ -245,6 +242,8 @@ public:
        virtual bool touch_enabled() const { return false; }
         void start_write_pass (double time);
        void write_pass_finished (double when);
+        void set_in_write_pass (bool, bool add_point = false, double when = 0.0);
+        bool in_write_pass () const;
 
        /** Emitted when mark_dirty() is called on this object */
        mutable PBD::Signal0<void> Dirty;
@@ -278,7 +277,7 @@ protected:
        Parameter             _parameter;
        InterpolationStyle    _interpolation;
        EventList             _events;
-       mutable Glib::Mutex   _lock;
+       mutable Glib::Threads::Mutex   _lock;
        int8_t                _frozen;
        bool                  _changed_when_thawed;
        double                _min_yval;
@@ -291,11 +290,13 @@ protected:
         static double _thinning_factor;
 
   private:
-    iterator   insert_iterator;
+    iterator   most_recent_insert_iterator;
     double     insert_position;
     bool       new_write_pass;
     bool       did_write_during_pass;
+    bool       _in_write_pass;
     void unlocked_invalidate_insert_iterator ();
+    void add_guard_point (double when);
 };
 
 } // namespace Evoral