fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / ardour / variant.h
index 8fd9c829f7d024230ff9ec59b6e019d247410643..4cf1df5556490946c857c14bcdd0a52ae7b57ef5 100644 (file)
@@ -27,6 +27,7 @@
 #include <stdexcept>
 
 #include "ardour/libardour_visibility.h"
+#include "evoral/Beats.hpp"
 #include "pbd/compose.h"
 
 namespace ARDOUR {
@@ -37,6 +38,7 @@ class LIBARDOUR_API Variant
 public:
        enum Type {
                NOTHING, ///< Nothing (void)
+               BEATS,   ///< Beats+ticks
                BOOL,    ///< Boolean
                DOUBLE,  ///< C double (64-bit IEEE-754)
                FLOAT,   ///< C float (32-bit IEEE-754)
@@ -47,13 +49,19 @@ public:
                URI      ///< URI string
        };
 
-       explicit Variant()              : _type(NOTHING) { _long   = 0;     }
+       Variant() : _type(NOTHING) { _long = 0; }
+
        explicit Variant(bool    value) : _type(BOOL)    { _bool   = value; }
        explicit Variant(double  value) : _type(DOUBLE)  { _double = value; }
        explicit Variant(float   value) : _type(FLOAT)   { _float  = value; }
        explicit Variant(int32_t value) : _type(INT)     { _int    = value; }
        explicit Variant(int64_t value) : _type(LONG)    { _long   = value; }
 
+       explicit Variant(const Evoral::Beats& beats)
+               : _type(BEATS)
+               , _beats(beats)
+       {}
+
        /** Make a variant of a specific string type (string types only) */
        Variant(Type type, const std::string& value)
                : _type(type)
@@ -85,6 +93,9 @@ public:
                        _long = (int64_t)lrint(std::max((double)INT64_MIN,
                                                        std::min(value, (double)INT64_MAX)));
                        break;
+               case BEATS:
+                       _beats = Evoral::Beats(value);
+                       break;
                default:
                        _type = NOTHING;
                        _long = 0;
@@ -99,6 +110,7 @@ public:
                case FLOAT:  return _float;
                case INT:    return _int;
                case LONG:   return _long;
+               case BEATS:  return _beats.to_double();
                default:     return 0.0;
                }
        }
@@ -109,15 +121,64 @@ public:
        int    get_int()    const { ensure_type(INT);    return _int;    }
        long   get_long()   const { ensure_type(LONG);   return _long;   }
 
+       bool   operator==(bool v)   const { return _type == BOOL   && _bool == v; }
+       double operator==(double v) const { return _type == DOUBLE && _double == v; }
+       float  operator==(float v)  const { return _type == FLOAT  && _float == v; }
+       int    operator==(int v)    const { return _type == INT    && _int == v; }
+       long   operator==(long v)   const { return _type == LONG   && _long == v; }
+
+       Variant& operator=(bool v)   { _type = BOOL;   _bool = v;   return *this; }
+       Variant& operator=(double v) { _type = DOUBLE; _double = v; return *this; }
+       Variant& operator=(float v)  { _type = FLOAT;  _float = v;  return *this; }
+       Variant& operator=(int v)    { _type = INT;    _int = v;    return *this; }
+       Variant& operator=(long v)   { _type = LONG;   _long = v;   return *this; }
+
        const std::string& get_path()   const { ensure_type(PATH);   return _string; }
        const std::string& get_string() const { ensure_type(STRING); return _string; }
        const std::string& get_uri()    const { ensure_type(URI);    return _string; }
 
+       bool operator==(const Variant& v) const {
+               if (_type != v._type) {
+                       return false;
+               }
+
+               switch (_type) {
+               case NOTHING: return true;
+               case BEATS:   return _beats  == v._beats;
+               case BOOL:    return _bool   == v._bool;
+               case DOUBLE:  return _double == v._double;
+               case FLOAT:   return _float  == v._float;
+               case INT:     return _int    == v._int;
+               case LONG:    return _long   == v._long;
+               case PATH:
+               case STRING:
+               case URI:     return _string == v._string;
+               }
+
+               return false;
+       }
+
+       bool operator==(const Evoral::Beats& v) const {
+               return _type == BEATS && _beats == v;
+       }
+
+       bool operator!() const { return _type == NOTHING; }
+
+       Variant& operator=(Evoral::Beats v) {
+               _type  = BEATS;
+               _beats = v;
+               return *this;
+       }
+
+       const Evoral::Beats& get_beats() const {
+               ensure_type(BEATS); return _beats;
+       }
+
        Type type() const { return _type; }
 
        static bool type_is_numeric(Type type) {
                switch (type) {
-               case BOOL: case DOUBLE: case FLOAT: case INT: case LONG:
+               case BOOL: case DOUBLE: case FLOAT: case INT: case LONG: case BEATS:
                        return true;
                default:
                        return false;
@@ -141,8 +202,9 @@ private:
                }
        }
 
-       Type        _type;    ///< Type tag
-       std::string _string;  ///< For all string types (PATH, STRING, URI)
+       Type          _type;    ///< Type tag
+       std::string   _string;  ///< PATH, STRING, URI
+       Evoral::Beats _beats;   ///< BEATS
 
        // Union of all primitive numeric types
        union {