1 #ifndef _ofxsCore_H_
2 #define _ofxsCore_H_
3 /*
4 OFX Support Library, a library that skins the OFX plug-in API with C++ classes.
5 Copyright (C) 2004-2005 The Open Effects Association Ltd
6 Author Bruno Nicoletti bruno@thefoundry.co.uk
7 
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10 
11 * Redistributions of source code must retain the above copyright notice,
12 this list of conditions and the following disclaimer.
13 * Redistributions in binary form must reproduce the above copyright notice,
14 this list of conditions and the following disclaimer in the documentation
15 and/or other materials provided with the distribution.
16 * Neither the name The Open Effects Association Ltd, nor the names of its
17 contributors may be used to endorse or promote products derived from this
18 software without specific prior written permission.
19 
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
24 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 The Open Effects Association Ltd
32 1 Wardour St
33 London W1D 6PA
34 England
35 
36 
37 
38 */
39 
40 
41 /** @mainpage OFX Support Library
42 
43 @section mainpageIntro Introduction
44 
45 This support library skins the raw OFX C API with a set of C++ classes and functions that makes it easier to understand and write plug-ins to the API. Look at the examples to see how it is done.
46 
47 <HR>
48 
49 @section fifteenLineGuide Fifteen Line Plugin Writing Guide
50 
51 - work from the examples
52 - you need to write the following functions....
53 - void OFX::Plugin::getPluginID(OFX::PluginID &id)
54 - gives the unique name and version numbers of the plug-in
55 - void OFX::Plugin::loadAction(void)
56 - called after the plug-in is first loaded, and before any instance has been made,
57 - void OFX::Plugin::unloadAction(void)
58 - called before the plug-in is unloaded, and all instances have been destroyed,
59 - void OFX::Plugin::describe(OFX::ImageEffectDescriptor &desc)
60 - called to describe the plugin to the host
61 - void OFX::Plugin::describeInContext(OFX::ImageEffectDescriptor &desc, OFX::ContextEnum context)
62 - called to describe the plugin to the host for a context reported in OFX::Plugin::describe
63 -  OFX::ImageEffect * OFX::Plugin::createInstance(OfxImageEffectHandle handle, OFX::ContextEnum context)
64 - called when a new instance of a plug-in needs to be created. You need to derive a class from ImageEffect, new it and return it.
65 
66 The OFX::ImageEffect class has a set of members you can override to do various things, like rendering an effect. Again, look at the examples.
67 
68 <HR>
69 
70 @section license Copyright and License
71 
72 The library is copyright 2004-2005, The Open Effects Association Ltd, and was
73 written by Bruno Nicoletti (bruno@thefoundry.co.uk).
74 
75 It has been released under the GNU Lesser General Public License, see the
76 top of any source file for details.
77 
78 */
79 
80 /** @file This file contains core code that wraps OFX 'objects' with C++ classes.
81 
82 This file only holds code that is visible to a plugin implementation, and so hides much
83 of the direct OFX objects and any library side only functions.
84 */
85 
86 #ifdef _MSC_VER
87 #pragma warning( disable : 4290 )
88 #endif
89 
90 #include "ofxCore.h"
91 #include "ofxImageEffect.h"
92 #include "ofxInteract.h"
93 #include "ofxKeySyms.h"
94 #include "ofxMemory.h"
95 #include "ofxMessage.h"
96 #include "ofxMultiThread.h"
97 #include "ofxParam.h"
98 #include "ofxProperty.h"
99 #include "ofxPixels.h"
100 #ifdef OFX_SUPPORTS_DIALOG
101 #include "ofxDialog.h"
102 #endif
103 
104 #include <assert.h>
105 #include <vector>
106 #include <list>
107 #include <string>
108 #include <map>
109 #include <exception>
110 #include <stdexcept>
111 #include <sstream>
112 #include <memory>
113 #if defined(_MSC_VER)
114 #include <float.h> // _isnan
115 #endif
116 #include <cmath> // isnan, std::isnan
117 
118 #ifdef OFX_CLIENT_EXCEPTION_HEADER
119 #include OFX_CLIENT_EXCEPTION_HEADER
120 #endif
121 
122 #if __cplusplus >= 201103L
123 #  define OFX_THROW(x) noexcept(false)
124 #  define OFX_THROW2(x,y) noexcept(false)
125 #  define OFX_THROW3(x,y,z) noexcept(false)
126 #  define OFX_THROW4(x,y,z,w) noexcept(false)
127 #else
128 #  define OFX_THROW(x) throw(x)
129 #  define OFX_THROW2(x,y) throw(x,y)
130 #  define OFX_THROW3(x,y,z) throw(x,y,z)
131 #  define OFX_THROW4(x,y,z,w) throw(x,y,z,w)
132 #endif
133 
134 // Is noexcept supported?
135 // "noexcept" is only supported since the Visual Studio 2015, as stated here: https://msdn.microsoft.com/en-us/library/wfa0edys.aspx
136 #if defined(__clang__)
137 #if __has_feature(cxx_noexcept)
138 #define OFX_NOTHROW noexcept(true)
139 #else
140 #define OFX_NOTHROW throw()
141 #endif
142 #else
143 #if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \
144     defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026
145 #define OFX_NOTHROW noexcept(true)
146 #else
147 #if defined(_NOEXCEPT)
148 #define OFX_NOTHROW _NOEXCEPT
149 #else
150 #define OFX_NOTHROW throw()
151 #endif
152 #endif
153 #endif
154 
155 /** @brief Defines an integer 3D point
156 
157 Should migrate this to the ofxCore.h in a v1.1
158 */
159 struct Ofx3DPointI {
160   int x, y, z;
161 };
162 
163 /** @brief Defines a double precision 3D point
164 
165 Should migrate this to the ofxCore.h in a v1.1
166 */
167 struct Ofx3DPointD {
168   double x, y, z;
169 };
170 
171 /** @brief Nasty macro used to define empty protected copy ctors and assign ops */
172 #define mDeclareProtectedAssignAndCC(CLASS) \
173   CLASS &operator=(const CLASS &) {assert(false); return *this;}	\
174   CLASS(const CLASS &) {assert(false); }
175 
176 /** @brief The core 'OFX Support' namespace, used by plugin implementations. All code for these are defined in the common support libraries.
177 */
178 namespace OFX {
179 #if __cplusplus >= 201103L
180   template <typename T>
181   using auto_ptr = std::unique_ptr<T>;
182 #else
183   using std::auto_ptr;
184 #endif
185 
186 #if defined(_MSC_VER)
IsInfinite(double x)187   inline bool IsInfinite(double x) { return _finite(x) == 0 && _isnan(x) == 0; }
IsNaN(double x)188   inline bool IsNaN     (double x) { return _isnan(x) != 0;                    }
189 #else
190 #  if __cplusplus >= 201103L || _GLIBCXX_USE_C99_MATH
191   // These definitions are for the normal Unix suspects.
IsInfinite(double x)192   inline bool IsInfinite(double x) { return (std::isinf)(x);    }
IsNaN(double x)193   inline bool IsNaN     (double x) { return (std::isnan)(x);    }
194 #  else
195 #    ifdef isnan // isnan is defined as a macro
IsInfinite(double x)196   inline bool IsInfinite(double x) { return isinf(x);    }
IsNaN(double x)197   inline bool IsNaN     (double x) { return isnan(x);    }
198 #    else
IsInfinite(double x)199   inline bool IsInfinite(double x) { return ::isinf(x);    }
IsNaN(double x)200   inline bool IsNaN     (double x) { return ::isnan(x);    }
201 #    endif
202 #  endif
203 #endif
204 
205   /** forward class declarations */
206   class PropertySet;
207 
208   /** @brief Enumerates the different types a property can be */
209   enum PropertyTypeEnum {
210     ePointer,
211     eInt,
212     eString,
213     eDouble
214   };
215 
216   /** @brief Enumerates the reasons a plug-in instance may have had one of its values changed */
217   enum InstanceChangeReason {
218     eChangeUserEdit,    /**< @brief A user actively editted something in the plugin, eg: changed the value of an integer param on an interface */
219     eChangePluginEdit,  /**< @brief The plugin's own code changed something in the instance, eg: a callback on on param settting the value of another */
220     eChangeTime         /**< @brief The current value of a parameter has changed because the param animates and the current time has changed */
221   };
222 
223   /** @brief maps a status to a string for debugging purposes, note a c-str for printf */
224   const char * mapStatusToString(OfxStatus stat);
225 
226   /** @brief namespace for OFX support lib exceptions, all derive from std::exception, calling it */
227   namespace Exception {
228 
229     /** @brief thrown when a suite returns a dud status code
230     */
231     class Suite : public std::exception {
232     protected :
233       OfxStatus _status;
234     public :
Suite(OfxStatus s)235       Suite(OfxStatus s) : _status(s) {}
status(void)236       OfxStatus status(void) const {return _status;}
OfxStatus()237       operator OfxStatus() const {return _status;}
238 
239       /** @brief reimplemented from std::exception */
what()240       virtual const char * what () const OFX_NOTHROW {return mapStatusToString(_status);}
241 
242     };
243 
244     /** @brief Exception indicating that a host doesn't know about a property that is should do */
245     class PropertyUnknownToHost : public std::exception {
246     protected :
247       std::string _what;
248     public :
PropertyUnknownToHost(const char * what)249       PropertyUnknownToHost(const char *what) : _what(what) {}
~PropertyUnknownToHost()250       virtual ~PropertyUnknownToHost() OFX_NOTHROW {}
251 
252       /** @brief reimplemented from std::exception */
what()253       virtual const char * what () const OFX_NOTHROW
254       {
255         return _what.c_str();
256       }
257     };
258 
259     /** @brief exception indicating that the host thinks a property has an illegal value */
260     class PropertyValueIllegalToHost : public std::exception {
261     protected :
262       std::string _what;
263     public :
PropertyValueIllegalToHost(const char * what)264       PropertyValueIllegalToHost(const char *what) : _what(what) {}
~PropertyValueIllegalToHost()265       virtual ~PropertyValueIllegalToHost() OFX_NOTHROW {}
266 
267       /** @brief reimplemented from std::exception */
what()268       virtual const char * what () const OFX_NOTHROW
269       {
270         return _what.c_str();
271       }
272     };
273 
274     /** @brief exception indicating a request for a named thing exists (eg: a param), but is of the wrong type, should never make it back to the main entry
275     indicates a logical error in the code. Asserts are raised in debug code in these situations.
276     */
277     class TypeRequest : public std::exception {
278     protected :
279       std::string _what;
280     public :
TypeRequest(const char * what)281       TypeRequest(const char *what) : _what(what) {}
~TypeRequest()282       virtual ~TypeRequest() OFX_NOTHROW {}
283 
284       /** @brief reimplemented from std::exception */
what()285       virtual const char * what () const OFX_NOTHROW
286       {
287         return _what.c_str();
288       }
289     };
290 
291     ////////////////////////////////////////////////////////////////////////////////
292     // These exceptions are to be thrown by the plugin if it hits a problem, the
293     // code managing the main entry will trap the exception and return a suitable
294     // status code to the host.
295 
296     /** @brief exception indicating a required host feature is missing */
297     class HostInadequate : public std::exception {
298     protected :
299       std::string _what;
300     public :
HostInadequate(const char * what)301       HostInadequate(const char *what) : _what(what) {}
~HostInadequate()302       virtual ~HostInadequate() OFX_NOTHROW {}
303 
304       /** @brief reimplemented from std::exception */
what()305       virtual const char * what () const OFX_NOTHROW
306       {
307         return _what.c_str();
308       }
309     };
310 
311   }; // end of Exception namespace
312 
313   /** @brief Throws an @ref OFX::Exception::Suite depending on the status flag passed in */
314   void
315     throwSuiteStatusException(OfxStatus stat)
316     OFX_THROW2(OFX::Exception::Suite, std::bad_alloc);
317 
318   void
319     throwHostMissingSuiteException(const std::string& name)
320     OFX_THROW(OFX::Exception::Suite);
321 
322   /** @brief This struct is used to return an identifier for the plugin by the function @ref OFX:Plugin::getPlugin.
323   The members correspond to those in the OfxPlugin struct defined in ofxCore.h.
324   */
325 
326   class ImageEffectDescriptor;
327   class ImageEffect;
328 
329   /** @brief This class wraps up an OFX property set */
330   class PropertySet {
331   protected :
332     /** @brief The raw property handle */
333     OfxPropertySetHandle _propHandle;
334 
335     /** @brief Class static, whether we are logging each property action */
336     static int _gPropLogging;
337 
338     /** @brief Do not throw an exception if a host returns 'unsupported' when setting a property */
339     static bool _gThrowOnUnsupported;
340 
341   public :
342     /** @brief turns on logging of property access functions */
propEnableLogging(void)343     static void propEnableLogging(void)  {++_gPropLogging;}
344 
345     /** @brief turns off logging of property access functions */
propDisableLogging(void)346     static void propDisableLogging(void) {--_gPropLogging;}
347 
348     /** @brief Do we throw an exception if a host returns 'unsupported' when setting a property. Default is true */
setThrowOnUnsupportedProperties(bool v)349     static void setThrowOnUnsupportedProperties(bool v) {_gThrowOnUnsupported = v;}
350 
351     /** @brief Do we throw an exception if a host returns 'unsupported' when setting a property. Default is true */
getThrowOnUnsupportedProperties(void)352     static bool getThrowOnUnsupportedProperties(void) {return _gThrowOnUnsupported;}
353 
354     /** @brief construct a property set */
_propHandle(h)355     PropertySet(OfxPropertySetHandle h = NULL) : _propHandle(h) {}
356     virtual ~PropertySet();
357 
358     /** @brief copy constructor */
PropertySet(const PropertySet & p)359     PropertySet(const PropertySet& p) { _propHandle = p.propSetHandle(); }
360     PropertySet& operator=(const PropertySet& p) { _propHandle = p.propSetHandle(); return *this; }
361 
362   public:
363     /** @brief set the handle to use for this set */
propSetHandle(OfxPropertySetHandle h)364     void propSetHandle(OfxPropertySetHandle h) { _propHandle = h;}
365 
366     /** @brief return the handle for this property set */
propSetHandle(void)367     OfxPropertySetHandle propSetHandle(void) const {return _propHandle;}
368 
369     bool  propExists(const char* property, bool throwOnFailure = true) const OFX_THROW3(std::bad_alloc,
370       OFX::Exception::PropertyValueIllegalToHost,
371       OFX::Exception::Suite);
372     int  propGetDimension(const char* property, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
373       OFX::Exception::PropertyUnknownToHost,
374       OFX::Exception::PropertyValueIllegalToHost,
375       OFX::Exception::Suite);
376     void propReset(const char* property) OFX_THROW4(std::bad_alloc,
377       OFX::Exception::PropertyUnknownToHost,
378       OFX::Exception::PropertyValueIllegalToHost,
379       OFX::Exception::Suite);
380 
381     // set single values
382     void propSetPointer(const char* property, void *value, int idx, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
383       OFX::Exception::PropertyUnknownToHost,
384       OFX::Exception::PropertyValueIllegalToHost,
385       OFX::Exception::Suite);
386     void propSetString(const char* property, const std::string &value, int idx, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
387       OFX::Exception::PropertyUnknownToHost,
388       OFX::Exception::PropertyValueIllegalToHost,
389       OFX::Exception::Suite);
390     void propSetDouble(const char* property, double value, int idx, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
391       OFX::Exception::PropertyUnknownToHost,
392       OFX::Exception::PropertyValueIllegalToHost,
393       OFX::Exception::Suite);
394     void propSetInt(const char* property, int value, int idx, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
395       OFX::Exception::PropertyUnknownToHost,
396       OFX::Exception::PropertyValueIllegalToHost,
397       OFX::Exception::Suite);
398 
399     // set multiple values
400     void propSetStringN(const char* property, const std::vector<std::string> &values, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
401       OFX::Exception::PropertyUnknownToHost,
402       OFX::Exception::PropertyValueIllegalToHost,
403       OFX::Exception::Suite);
404 
405     void propSetDoubleN(const char* property, const std::vector<double> &values, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
406       OFX::Exception::PropertyUnknownToHost,
407       OFX::Exception::PropertyValueIllegalToHost,
408       OFX::Exception::Suite);
409 
410     void propSetDoubleN(const char* property, const double *values, int count, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
411       OFX::Exception::PropertyUnknownToHost,
412       OFX::Exception::PropertyValueIllegalToHost,
413       OFX::Exception::Suite);
414 
415     void propSetIntN(const char* property, const std::vector<int> &values, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
416       OFX::Exception::PropertyUnknownToHost,
417       OFX::Exception::PropertyValueIllegalToHost,
418       OFX::Exception::Suite);
419 
420     // values is before count to avoid an easy confusion with propSetInt, whet the pointer to values would be cast to bool
421     void propSetIntN(const char* property, const int *values, int count, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
422       OFX::Exception::PropertyUnknownToHost,
423       OFX::Exception::PropertyValueIllegalToHost,
424       OFX::Exception::Suite);
425 
426 
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)427     void propSetPointer(const char* property, void *value, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
428       OFX::Exception::PropertyUnknownToHost,
429       OFX::Exception::PropertyValueIllegalToHost,
430       OFX::Exception::Suite)
431     {propSetPointer(property, value, 0, throwOnFailure);}
432 
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)433     void propSetString(const char* property, const std::string &value, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
434       OFX::Exception::PropertyUnknownToHost,
435       OFX::Exception::PropertyValueIllegalToHost,
436       OFX::Exception::Suite)
437     {propSetString(property, value, 0, throwOnFailure);}
438 
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)439     void propSetDouble(const char* property, double value, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
440       OFX::Exception::PropertyUnknownToHost,
441       OFX::Exception::PropertyValueIllegalToHost,
442       OFX::Exception::Suite)
443     {propSetDouble(property, value, 0, throwOnFailure);}
444 
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)445     void propSetInt(const char* property, int value, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
446       OFX::Exception::PropertyUnknownToHost,
447       OFX::Exception::PropertyValueIllegalToHost,
448       OFX::Exception::Suite)
449     {propSetInt(property, value, 0, throwOnFailure);}
450 
451 
452     /// get a pointer property
453     void       *propGetPointer(const char* property, int idx, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
454       OFX::Exception::PropertyUnknownToHost,
455       OFX::Exception::PropertyValueIllegalToHost,
456       OFX::Exception::Suite);
457 
458     /// get a string property
459     std::string propGetString(const char* property, int idx, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
460       OFX::Exception::PropertyUnknownToHost,
461       OFX::Exception::PropertyValueIllegalToHost,
462       OFX::Exception::Suite);
463 
464     /// get a double property
465     double      propGetDouble(const char* property, int idx, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
466       OFX::Exception::PropertyUnknownToHost,
467       OFX::Exception::PropertyValueIllegalToHost,
468       OFX::Exception::Suite);
469 
470     /// get an int property
471     int propGetInt(const char* property, int idx, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
472       OFX::Exception::PropertyUnknownToHost,
473       OFX::Exception::PropertyValueIllegalToHost,
474       OFX::Exception::Suite);
475 
476     /// get a pointer property with index 0
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)477     void* propGetPointer(const char* property, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
478       OFX::Exception::PropertyUnknownToHost,
479       OFX::Exception::PropertyValueIllegalToHost,
480       OFX::Exception::Suite)
481     {
482       return propGetPointer(property, 0, throwOnFailure);
483     }
484 
485     /// get a string property with index 0
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)486     std::string propGetString(const char* property, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
487       OFX::Exception::PropertyUnknownToHost,
488       OFX::Exception::PropertyValueIllegalToHost,
489       OFX::Exception::Suite)
490     {
491       return propGetString(property, 0, throwOnFailure);
492     }
493 
494     /// get a double property with index 0
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)495     double propGetDouble(const char* property, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
496       OFX::Exception::PropertyUnknownToHost,
497       OFX::Exception::PropertyValueIllegalToHost,
498       OFX::Exception::Suite)
499     {
500       return propGetDouble(property, 0, throwOnFailure);
501     }
502 
503     /// get an int property with index 0
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)504     int propGetInt(const char* property, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
505       OFX::Exception::PropertyUnknownToHost,
506       OFX::Exception::PropertyValueIllegalToHost,
507       OFX::Exception::Suite)
508     {
509       return propGetInt(property, 0, throwOnFailure);
510     }
511 
512     void propGetStringN(const char* property, std::vector<std::string>* values, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
513       OFX::Exception::PropertyUnknownToHost,
514       OFX::Exception::PropertyValueIllegalToHost,
515       OFX::Exception::Suite);
516 
517     void propGetDoubleN(const char* property, std::vector<double>* values, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
518       OFX::Exception::PropertyUnknownToHost,
519       OFX::Exception::PropertyValueIllegalToHost,
520       OFX::Exception::Suite);
521 
522     // values is before count to avoid an easy confusion with propGetDouble, whet the pointer to values would be cast to bool
523     void propGetDoubleN(const char* property, double* values, int count, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
524       OFX::Exception::PropertyUnknownToHost,
525       OFX::Exception::PropertyValueIllegalToHost,
526       OFX::Exception::Suite);
527 
528     void propGetIntN(const char* property, std::vector<int>* values, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
529       OFX::Exception::PropertyUnknownToHost,
530       OFX::Exception::PropertyValueIllegalToHost,
531       OFX::Exception::Suite);
532 
533     void propGetIntN(const char* property, int* values, int count, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
534       OFX::Exception::PropertyUnknownToHost,
535       OFX::Exception::PropertyValueIllegalToHost,
536       OFX::Exception::Suite);
537 
538   };
539 
540   // forward decl of the image effect
541   class ImageEffect;
542 };
543 
544 // undeclare the protected assign and CC macro
545 #undef mDeclareProtectedAssignAndCC
546 
547 #endif
548