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 // can be defined by Magick++.h
187 #undef IsNaN
188 #if defined(_MSC_VER)
IsInfinite(double x)189   inline bool IsInfinite(double x) { return _finite(x) == 0 && _isnan(x) == 0; }
IsNaN(double x)190   inline bool IsNaN     (double x) { return _isnan(x) != 0;                    }
191 #else
192 #  if __cplusplus >= 201103L || _GLIBCXX_USE_C99_MATH
193   // These definitions are for the normal Unix suspects.
IsInfinite(double x)194   inline bool IsInfinite(double x) { return (std::isinf)(x);    }
IsNaN(double x)195   inline bool IsNaN     (double x) { return (std::isnan)(x);    }
196 #  else
197 #    ifdef isnan // isnan is defined as a macro
IsInfinite(double x)198   inline bool IsInfinite(double x) { return isinf(x);    }
IsNaN(double x)199   inline bool IsNaN     (double x) { return isnan(x);    }
200 #    else
IsInfinite(double x)201   inline bool IsInfinite(double x) { return ::isinf(x);    }
IsNaN(double x)202   inline bool IsNaN     (double x) { return ::isnan(x);    }
203 #    endif
204 #  endif
205 #endif
206 
207   /** forward class declarations */
208   class PropertySet;
209 
210   /** @brief Enumerates the different types a property can be */
211   enum PropertyTypeEnum {
212     ePointer,
213     eInt,
214     eString,
215     eDouble
216   };
217 
218   /** @brief Enumerates the reasons a plug-in instance may have had one of its values changed */
219   enum InstanceChangeReason {
220     eChangeUserEdit,    /**< @brief A user actively editted something in the plugin, eg: changed the value of an integer param on an interface */
221     eChangePluginEdit,  /**< @brief The plugin's own code changed something in the instance, eg: a callback on on param settting the value of another */
222     eChangeTime         /**< @brief The current value of a parameter has changed because the param animates and the current time has changed */
223   };
224 
225   /** @brief maps a status to a string for debugging purposes, note a c-str for printf */
226   const char * mapStatusToString(OfxStatus stat);
227 
228   /** @brief namespace for OFX support lib exceptions, all derive from std::exception, calling it */
229   namespace Exception {
230 
231     /** @brief thrown when a suite returns a dud status code
232     */
233     class Suite : public std::exception {
234     protected :
235       OfxStatus _status;
236     public :
Suite(OfxStatus s)237       Suite(OfxStatus s) : _status(s) {}
status(void)238       OfxStatus status(void) const {return _status;}
OfxStatus()239       operator OfxStatus() const {return _status;}
240 
241       /** @brief reimplemented from std::exception */
what()242       virtual const char * what () const OFX_NOTHROW {return mapStatusToString(_status);}
243 
244     };
245 
246     /** @brief Exception indicating that a host doesn't know about a property that is should do */
247     class PropertyUnknownToHost : public std::exception {
248     protected :
249       std::string _what;
250     public :
PropertyUnknownToHost(const char * what)251       PropertyUnknownToHost(const char *what) : _what(what) {}
~PropertyUnknownToHost()252       virtual ~PropertyUnknownToHost() OFX_NOTHROW {}
253 
254       /** @brief reimplemented from std::exception */
what()255       virtual const char * what () const OFX_NOTHROW
256       {
257         return _what.c_str();
258       }
259     };
260 
261     /** @brief exception indicating that the host thinks a property has an illegal value */
262     class PropertyValueIllegalToHost : public std::exception {
263     protected :
264       std::string _what;
265     public :
PropertyValueIllegalToHost(const char * what)266       PropertyValueIllegalToHost(const char *what) : _what(what) {}
~PropertyValueIllegalToHost()267       virtual ~PropertyValueIllegalToHost() OFX_NOTHROW {}
268 
269       /** @brief reimplemented from std::exception */
what()270       virtual const char * what () const OFX_NOTHROW
271       {
272         return _what.c_str();
273       }
274     };
275 
276     /** @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
277     indicates a logical error in the code. Asserts are raised in debug code in these situations.
278     */
279     class TypeRequest : public std::exception {
280     protected :
281       std::string _what;
282     public :
TypeRequest(const char * what)283       TypeRequest(const char *what) : _what(what) {}
~TypeRequest()284       virtual ~TypeRequest() OFX_NOTHROW {}
285 
286       /** @brief reimplemented from std::exception */
what()287       virtual const char * what () const OFX_NOTHROW
288       {
289         return _what.c_str();
290       }
291     };
292 
293     ////////////////////////////////////////////////////////////////////////////////
294     // These exceptions are to be thrown by the plugin if it hits a problem, the
295     // code managing the main entry will trap the exception and return a suitable
296     // status code to the host.
297 
298     /** @brief exception indicating a required host feature is missing */
299     class HostInadequate : public std::exception {
300     protected :
301       std::string _what;
302     public :
HostInadequate(const char * what)303       HostInadequate(const char *what) : _what(what) {}
~HostInadequate()304       virtual ~HostInadequate() OFX_NOTHROW {}
305 
306       /** @brief reimplemented from std::exception */
what()307       virtual const char * what () const OFX_NOTHROW
308       {
309         return _what.c_str();
310       }
311     };
312 
313   }; // end of Exception namespace
314 
315   /** @brief Throws an @ref OFX::Exception::Suite depending on the status flag passed in */
316   void
317     throwSuiteStatusException(OfxStatus stat)
318     OFX_THROW2(OFX::Exception::Suite, std::bad_alloc);
319 
320   void
321     throwHostMissingSuiteException(const std::string& name)
322     OFX_THROW(OFX::Exception::Suite);
323 
324   /** @brief This struct is used to return an identifier for the plugin by the function @ref OFX:Plugin::getPlugin.
325   The members correspond to those in the OfxPlugin struct defined in ofxCore.h.
326   */
327 
328   class ImageEffectDescriptor;
329   class ImageEffect;
330 
331   /** @brief This class wraps up an OFX property set */
332   class PropertySet {
333   protected :
334     /** @brief The raw property handle */
335     OfxPropertySetHandle _propHandle;
336 
337     /** @brief Class static, whether we are logging each property action */
338     static int _gPropLogging;
339 
340     /** @brief Do not throw an exception if a host returns 'unsupported' when setting a property */
341     static bool _gThrowOnUnsupported;
342 
343   public :
344     /** @brief turns on logging of property access functions */
propEnableLogging(void)345     static void propEnableLogging(void)  {++_gPropLogging;}
346 
347     /** @brief turns off logging of property access functions */
propDisableLogging(void)348     static void propDisableLogging(void) {--_gPropLogging;}
349 
350     /** @brief Do we throw an exception if a host returns 'unsupported' when setting a property. Default is true */
setThrowOnUnsupportedProperties(bool v)351     static void setThrowOnUnsupportedProperties(bool v) {_gThrowOnUnsupported = v;}
352 
353     /** @brief Do we throw an exception if a host returns 'unsupported' when setting a property. Default is true */
getThrowOnUnsupportedProperties(void)354     static bool getThrowOnUnsupportedProperties(void) {return _gThrowOnUnsupported;}
355 
356     /** @brief construct a property set */
_propHandle(h)357     PropertySet(OfxPropertySetHandle h = NULL) : _propHandle(h) {}
358     virtual ~PropertySet();
359 
360     /** @brief copy constructor */
PropertySet(const PropertySet & p)361     PropertySet(const PropertySet& p) { _propHandle = p.propSetHandle(); }
362     PropertySet& operator=(const PropertySet& p) { _propHandle = p.propSetHandle(); return *this; }
363 
364   public:
365     /** @brief set the handle to use for this set */
propSetHandle(OfxPropertySetHandle h)366     void propSetHandle(OfxPropertySetHandle h) { _propHandle = h;}
367 
368     /** @brief return the handle for this property set */
propSetHandle(void)369     OfxPropertySetHandle propSetHandle(void) const {return _propHandle;}
370 
371     bool  propExists(const char* property, bool throwOnFailure = true) const OFX_THROW3(std::bad_alloc,
372       OFX::Exception::PropertyValueIllegalToHost,
373       OFX::Exception::Suite);
374     int  propGetDimension(const char* property, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
375       OFX::Exception::PropertyUnknownToHost,
376       OFX::Exception::PropertyValueIllegalToHost,
377       OFX::Exception::Suite);
378     void propReset(const char* property) OFX_THROW4(std::bad_alloc,
379       OFX::Exception::PropertyUnknownToHost,
380       OFX::Exception::PropertyValueIllegalToHost,
381       OFX::Exception::Suite);
382 
383     // set single values
384     void propSetPointer(const char* property, void *value, int idx, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
385       OFX::Exception::PropertyUnknownToHost,
386       OFX::Exception::PropertyValueIllegalToHost,
387       OFX::Exception::Suite);
388     void propSetString(const char* property, const std::string &value, int idx, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
389       OFX::Exception::PropertyUnknownToHost,
390       OFX::Exception::PropertyValueIllegalToHost,
391       OFX::Exception::Suite);
392     void propSetDouble(const char* property, double value, int idx, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
393       OFX::Exception::PropertyUnknownToHost,
394       OFX::Exception::PropertyValueIllegalToHost,
395       OFX::Exception::Suite);
396     void propSetInt(const char* property, int value, int idx, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
397       OFX::Exception::PropertyUnknownToHost,
398       OFX::Exception::PropertyValueIllegalToHost,
399       OFX::Exception::Suite);
400 
401     // set multiple values
402     void propSetStringN(const char* property, const std::vector<std::string> &values, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
403       OFX::Exception::PropertyUnknownToHost,
404       OFX::Exception::PropertyValueIllegalToHost,
405       OFX::Exception::Suite);
406 
407     void propSetDoubleN(const char* property, const std::vector<double> &values, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
408       OFX::Exception::PropertyUnknownToHost,
409       OFX::Exception::PropertyValueIllegalToHost,
410       OFX::Exception::Suite);
411 
412     void propSetDoubleN(const char* property, const double *values, int count, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
413       OFX::Exception::PropertyUnknownToHost,
414       OFX::Exception::PropertyValueIllegalToHost,
415       OFX::Exception::Suite);
416 
417     void propSetIntN(const char* property, const std::vector<int> &values, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
418       OFX::Exception::PropertyUnknownToHost,
419       OFX::Exception::PropertyValueIllegalToHost,
420       OFX::Exception::Suite);
421 
422     // values is before count to avoid an easy confusion with propSetInt, whet the pointer to values would be cast to bool
423     void propSetIntN(const char* property, const int *values, int count, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
424       OFX::Exception::PropertyUnknownToHost,
425       OFX::Exception::PropertyValueIllegalToHost,
426       OFX::Exception::Suite);
427 
428 
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)429     void propSetPointer(const char* property, void *value, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
430       OFX::Exception::PropertyUnknownToHost,
431       OFX::Exception::PropertyValueIllegalToHost,
432       OFX::Exception::Suite)
433     {propSetPointer(property, value, 0, throwOnFailure);}
434 
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)435     void propSetString(const char* property, const std::string &value, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
436       OFX::Exception::PropertyUnknownToHost,
437       OFX::Exception::PropertyValueIllegalToHost,
438       OFX::Exception::Suite)
439     {propSetString(property, value, 0, throwOnFailure);}
440 
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)441     void propSetDouble(const char* property, double value, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
442       OFX::Exception::PropertyUnknownToHost,
443       OFX::Exception::PropertyValueIllegalToHost,
444       OFX::Exception::Suite)
445     {propSetDouble(property, value, 0, throwOnFailure);}
446 
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)447     void propSetInt(const char* property, int value, bool throwOnFailure = true) OFX_THROW4(std::bad_alloc,
448       OFX::Exception::PropertyUnknownToHost,
449       OFX::Exception::PropertyValueIllegalToHost,
450       OFX::Exception::Suite)
451     {propSetInt(property, value, 0, throwOnFailure);}
452 
453 
454     /// get a pointer property
455     void       *propGetPointer(const char* property, int idx, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
456       OFX::Exception::PropertyUnknownToHost,
457       OFX::Exception::PropertyValueIllegalToHost,
458       OFX::Exception::Suite);
459 
460     /// get a string property
461     std::string propGetString(const char* property, int idx, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
462       OFX::Exception::PropertyUnknownToHost,
463       OFX::Exception::PropertyValueIllegalToHost,
464       OFX::Exception::Suite);
465 
466     /// get a double property
467     double      propGetDouble(const char* property, int idx, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
468       OFX::Exception::PropertyUnknownToHost,
469       OFX::Exception::PropertyValueIllegalToHost,
470       OFX::Exception::Suite);
471 
472     /// get an int property
473     int propGetInt(const char* property, int idx, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
474       OFX::Exception::PropertyUnknownToHost,
475       OFX::Exception::PropertyValueIllegalToHost,
476       OFX::Exception::Suite);
477 
478     /// get a pointer property with index 0
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)479     void* propGetPointer(const char* property, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
480       OFX::Exception::PropertyUnknownToHost,
481       OFX::Exception::PropertyValueIllegalToHost,
482       OFX::Exception::Suite)
483     {
484       return propGetPointer(property, 0, throwOnFailure);
485     }
486 
487     /// get a string property with index 0
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)488     std::string propGetString(const char* property, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
489       OFX::Exception::PropertyUnknownToHost,
490       OFX::Exception::PropertyValueIllegalToHost,
491       OFX::Exception::Suite)
492     {
493       return propGetString(property, 0, throwOnFailure);
494     }
495 
496     /// get a double property with index 0
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)497     double propGetDouble(const char* property, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
498       OFX::Exception::PropertyUnknownToHost,
499       OFX::Exception::PropertyValueIllegalToHost,
500       OFX::Exception::Suite)
501     {
502       return propGetDouble(property, 0, throwOnFailure);
503     }
504 
505     /// get an int property with index 0
OFX_THROW4(std::bad_alloc,OFX::Exception::PropertyUnknownToHost,OFX::Exception::PropertyValueIllegalToHost,OFX::Exception::Suite)506     int propGetInt(const char* property, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
507       OFX::Exception::PropertyUnknownToHost,
508       OFX::Exception::PropertyValueIllegalToHost,
509       OFX::Exception::Suite)
510     {
511       return propGetInt(property, 0, throwOnFailure);
512     }
513 
514     void propGetStringN(const char* property, std::vector<std::string>* values, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
515       OFX::Exception::PropertyUnknownToHost,
516       OFX::Exception::PropertyValueIllegalToHost,
517       OFX::Exception::Suite);
518 
519     void propGetDoubleN(const char* property, std::vector<double>* values, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
520       OFX::Exception::PropertyUnknownToHost,
521       OFX::Exception::PropertyValueIllegalToHost,
522       OFX::Exception::Suite);
523 
524     // values is before count to avoid an easy confusion with propGetDouble, whet the pointer to values would be cast to bool
525     void propGetDoubleN(const char* property, double* values, int count, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
526       OFX::Exception::PropertyUnknownToHost,
527       OFX::Exception::PropertyValueIllegalToHost,
528       OFX::Exception::Suite);
529 
530     void propGetIntN(const char* property, std::vector<int>* values, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
531       OFX::Exception::PropertyUnknownToHost,
532       OFX::Exception::PropertyValueIllegalToHost,
533       OFX::Exception::Suite);
534 
535     void propGetIntN(const char* property, int* values, int count, bool throwOnFailure = true) const OFX_THROW4(std::bad_alloc,
536       OFX::Exception::PropertyUnknownToHost,
537       OFX::Exception::PropertyValueIllegalToHost,
538       OFX::Exception::Suite);
539 
540   };
541 
542   // forward decl of the image effect
543   class ImageEffect;
544 };
545 
546 // undeclare the protected assign and CC macro
547 #undef mDeclareProtectedAssignAndCC
548 
549 #endif
550