change: Switch to offical OpenFX Support. Still can't compile.
This commit is contained in:
+37
@@ -0,0 +1,37 @@
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Dependent upon the following
|
||||
|
||||
*the expat library (expat.h) - to parse XML
|
||||
*ofx header files
|
||||
|
||||
How to build the library
|
||||
------------------------
|
||||
|
||||
UNIX
|
||||
- simply type 'make' in this directory, it will create 'libofxHost.a' in directory ./lib
|
||||
- the Makefile assumes expat is installed in a standard system location, if it is not,
|
||||
you need to do the following
|
||||
|
||||
make EXPAT_INCLUDE=-IDIRECTORY_WITH_EXPAT
|
||||
|
||||
WINDOWS
|
||||
- use the vc8 projects
|
||||
|
||||
|
||||
How to build the examples
|
||||
------------------------
|
||||
|
||||
UNIX
|
||||
- make the ofxHostLib.a library
|
||||
- in the examples directory type 'make',
|
||||
- the Makefile assumes expat is installed in a standard system location, if it is not,
|
||||
you need to do the following
|
||||
|
||||
make EXPAT_INCLUDE=-IDIRECTORY_WITH_EXPAT EXPAT_LIB=SOMEWHERE/libexpat.a
|
||||
|
||||
WINDOWS
|
||||
- use the vc8 projects
|
||||
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
set(OFX_HOSTSUPPORT_HEADER_DIR "include")
|
||||
set(OFX_HOSTSUPPORT_LIBRARY_DIR "src")
|
||||
set(OFX_HEADER_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../include")
|
||||
aux_source_directory(OFX_HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/../include")
|
||||
file(GLOB_RECURSE OFX_HOSTSUPPORT_HEADER_FILES "${OFX_HOSTSUPPORT_HEADER_DIR}/*.h")
|
||||
file(GLOB_RECURSE OFX_HOSTSUPPORT_LIBRARY_FILES "${OFX_HOSTSUPPORT_LIBRARY_DIR}/*.cpp")
|
||||
add_library(OfxHost STATIC
|
||||
${OFX_HEADER_FILES}
|
||||
${OFX_HOSTSUPPORT_HEADER_FILES}
|
||||
${OFX_HOSTSUPPORT_LIBRARY_FILES})
|
||||
|
||||
set_target_properties(OfxHost PROPERTIES LINKER_LANGUAGE CXX)
|
||||
if(NOT MSVC)
|
||||
set_target_properties(OfxHost PROPERTIES COMPILE_FLAGS "-fPIC")
|
||||
endif()
|
||||
|
||||
target_link_libraries(OfxHost PUBLIC expat::expat)
|
||||
|
||||
target_include_directories(OfxHost PUBLIC
|
||||
${OFX_HEADER_DIR}
|
||||
${OFX_HOSTSUPPORT_HEADER_DIR}
|
||||
${expat_INCLUDE_DIR})
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
This directory contains source to an implementation of an OFX host C++ support library.
|
||||
This library skins the raw C API with a C++ layer, which is easy to program and abstracts
|
||||
the base API.
|
||||
|
||||
It does several things,
|
||||
- skins the C API with C++ classes, the host application 'only' needs to
|
||||
- derive several classes
|
||||
- implement a bunch of virtual methods
|
||||
- set some OFX properties
|
||||
- does most of the complicated logic in OFX,
|
||||
- regions of interest calls
|
||||
- clip preferences calls
|
||||
- provides a persistent plug-in caching mechanism so that
|
||||
- newly installed plug-ins are described into a cache file,
|
||||
- the cache persists as an XML file with enough information
|
||||
to construct simple menus etc..
|
||||
- once cached, plug-ins need only be loaded on demand.
|
||||
- is extensible beyond the base API,
|
||||
- allows hosts to provide extra suites and properties fairly easily.
|
||||
- it is generic beyond ImageEffects APIs, so other APIs can be implemented
|
||||
on the core sections of it.
|
||||
|
||||
Apart from standard C and C++ libraries it is dependent on the expat XML library.
|
||||
|
||||
You'll still need to understand what the API actually does, its just that the implementation details that become easier.
|
||||
|
||||
The layer could do with some improvement, specifically,
|
||||
- support for the external XML resource file,
|
||||
- a degree more tidying up,
|
||||
- parameter interacts
|
||||
- more documentation.
|
||||
|
||||
Released under a BSD-style licence: see source.
|
||||
|
||||
Authors:
|
||||
Abigail Brady <abigail@thefoundry.co.uk>
|
||||
Andrew Whitmore <andy@thefoundry.co.uk>
|
||||
Bruno Nicoletti <bruno@thefoundry.co.uk>
|
||||
|
||||
Release Notes
|
||||
-------------
|
||||
|
||||
26/03/2007
|
||||
|
||||
Minimum implementation, which allows plugin descriptions to be cached. Includes property sets and
|
||||
property suite and implementation of plugin description. Support for describing in context and
|
||||
parameters not fully enabled.
|
||||
|
||||
29/03/2007
|
||||
|
||||
Support for describing in contexts and parameters. These are cached as well.
|
||||
|
||||
25/06/2007
|
||||
|
||||
Major overhaul of the thing,
|
||||
- propertys made simpler to use
|
||||
- re-namespaced several classes so that anything to do with image effects are
|
||||
in the ImageEffect namespace
|
||||
- made the host layer do the logic for several Image Effect actions
|
||||
- clip preferences
|
||||
- regions of interest
|
||||
- simplified the function signatures of the actions
|
||||
- the 'Host' class now acts as,
|
||||
- a factory,
|
||||
- a filter for constructed objects,
|
||||
- a description of the host application to the plugin.
|
||||
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
Things to do. This is a wish list of features to add to the host layer...
|
||||
|
||||
Common Base Class for All Plugin Instances
|
||||
- currently using a void * to pass instance pointers to components that do not
|
||||
need to know about image effects (eg: interact base classes).
|
||||
- Should have a base 'Plugin::Instance' class that ImageEffect::Instance and any
|
||||
other kind of plugin instance should derive from.
|
||||
|
||||
XML Resource Support
|
||||
- have the host layer manage the external XML resource file and relabel things appropriately.
|
||||
|
||||
Support for Custom Params
|
||||
- not there yet
|
||||
- should have the host layer manage most of the custom param animation stuff as well.
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
|
||||
|
||||
#ifndef OFX_BINARY_H
|
||||
#define OFX_BINARY_H
|
||||
|
||||
// Copyright OpenFX and contributors to the OpenFX project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
#define I386
|
||||
#elif defined(__linux__) || defined(__FreeBSD__)
|
||||
#define UNIX
|
||||
#ifdef __i386__
|
||||
#define I386
|
||||
#elif defined(__amd64__)
|
||||
#define AMD64
|
||||
#else
|
||||
#error cannot detect architecture
|
||||
#endif
|
||||
#elif defined( __APPLE__)
|
||||
#define UNIX
|
||||
#else
|
||||
#error cannot detect operating system
|
||||
#endif
|
||||
|
||||
#if defined(UNIX)
|
||||
#include <dlfcn.h>
|
||||
#elif defined (WINDOWS)
|
||||
#include "windows.h"
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace OFX
|
||||
{
|
||||
|
||||
/// class representing a DLL/Shared Object/etc
|
||||
class Binary {
|
||||
/// destruction will close the library and invalidate
|
||||
/// any function pointers returned by lookupSymbol()
|
||||
protected :
|
||||
std::string _binaryPath;
|
||||
bool _invalid;
|
||||
#if defined(UNIX)
|
||||
void *_dlHandle;
|
||||
#elif defined (WINDOWS)
|
||||
HINSTANCE _dlHandle;
|
||||
#endif
|
||||
time_t _time;
|
||||
off_t _size;
|
||||
int _users;
|
||||
public :
|
||||
|
||||
/// create object representing the binary. will stat() it,
|
||||
/// and this fails, will set binary to be invalid.
|
||||
Binary(const std::string &binaryPath);
|
||||
|
||||
~Binary() { unload(); }
|
||||
|
||||
bool isLoaded() const { return _dlHandle != 0; }
|
||||
|
||||
/// is this binary invalid? (did the a stat() or load() on the file fail,
|
||||
/// or are we missing a some of the symbols?
|
||||
bool isInvalid() const { return _invalid; }
|
||||
|
||||
/// set invalid status (e.g. called by user if a mandatory symbol was missing)
|
||||
void setInvalid(bool invalid) { _invalid = invalid; }
|
||||
|
||||
/// Last modification time of the file.
|
||||
time_t getTime() const { return _time; }
|
||||
|
||||
/// Current size of the file.
|
||||
off_t getSize() const { return _size; }
|
||||
|
||||
/// Path to the file.
|
||||
const std::string &getBinaryPath() const { return _binaryPath; }
|
||||
|
||||
void ref();
|
||||
void unref();
|
||||
|
||||
/// open the binary.
|
||||
void load();
|
||||
|
||||
/// close the binary
|
||||
void unload();
|
||||
|
||||
/// look up a symbol in the binary file and return it as a pointer.
|
||||
/// returns null pointer if not found, or if the library is not loaded.
|
||||
void *findSymbol(const std::string &symbol);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
+499
@@ -0,0 +1,499 @@
|
||||
|
||||
// Copyright OpenFX and contributors to the OpenFX project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#ifndef OFX_CLIP_H
|
||||
#define OFX_CLIP_H
|
||||
|
||||
#include "ofxImageEffect.h"
|
||||
#include "ofxhPropertySuite.h"
|
||||
#include "ofxhUtilities.h"
|
||||
|
||||
namespace OFX {
|
||||
|
||||
namespace Host {
|
||||
|
||||
namespace ImageEffect {
|
||||
// forward declarations
|
||||
class Image;
|
||||
class Instance;
|
||||
# ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
class Texture;
|
||||
# endif
|
||||
|
||||
/// Base to both descriptor and instance it
|
||||
/// is used to basically fetch common properties
|
||||
/// by function name
|
||||
class ClipBase {
|
||||
protected :
|
||||
Property::Set _properties;
|
||||
|
||||
public :
|
||||
/// base ctor, for a descriptor
|
||||
ClipBase();
|
||||
|
||||
virtual ~ClipBase() { }
|
||||
|
||||
/// ctor, when copy constructing an instance from a descripto
|
||||
explicit ClipBase(const ClipBase &other);
|
||||
|
||||
/// name of the clip
|
||||
const std::string &getName() const
|
||||
{
|
||||
return _properties.getStringProperty(kOfxPropName);
|
||||
}
|
||||
|
||||
/// name of the clip
|
||||
const std::string &getShortLabel() const;
|
||||
|
||||
/// name of the clip
|
||||
const std::string &getLabel() const;
|
||||
|
||||
/// name of the clip
|
||||
const std::string &getLongLabel() const;
|
||||
|
||||
/// return a std::vector of supported comp
|
||||
const std::vector<std::string> &getSupportedComponents() const;
|
||||
|
||||
/// is the given component supported
|
||||
bool isSupportedComponent(const std::string &comp) const;
|
||||
|
||||
/// does the clip do random temporal access
|
||||
bool temporalAccess() const;
|
||||
|
||||
/// is the clip optional
|
||||
bool isOptional() const;
|
||||
|
||||
/// is the clip a nominal 'mask' clip
|
||||
bool isMask() const;
|
||||
|
||||
/// how does this clip like fielded images to be presented to it
|
||||
const std::string &getFieldExtraction() const;
|
||||
|
||||
/// is the clip a nominal 'mask' clip
|
||||
bool supportsTiles() const;
|
||||
|
||||
/// get property set, const version
|
||||
const Property::Set &getProps() const;
|
||||
|
||||
/// get property set , non const version
|
||||
Property::Set &getProps();
|
||||
|
||||
/// get a handle on the properties of the clip descriptor for the C api
|
||||
OfxPropertySetHandle getPropHandle() const;
|
||||
|
||||
/// get a handle on the clip descriptor/instance for the C api
|
||||
OfxImageClipHandle getHandle() const;
|
||||
|
||||
virtual bool verifyMagic() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/// a clip descriptor
|
||||
class ClipDescriptor : public ClipBase {
|
||||
public:
|
||||
/// constructor
|
||||
ClipDescriptor(const std::string &name);
|
||||
|
||||
/// is the clip an output clip
|
||||
bool isOutput() const {return getName() == kOfxImageEffectOutputClipName; }
|
||||
};
|
||||
|
||||
/// a clip instance
|
||||
class ClipInstance : public ClipBase
|
||||
, protected Property::GetHook
|
||||
, protected Property::NotifyHook {
|
||||
protected:
|
||||
ImageEffect::Instance* _effectInstance; ///< image effect instance
|
||||
bool _isOutput; ///< are we the output clip
|
||||
std::string _pixelDepth; ///< what is the bit depth we is at. Set during the clip prefernces action.
|
||||
std::string _components; ///< what components do we have. Set during the clip prefernces action.
|
||||
|
||||
public:
|
||||
ClipInstance(ImageEffect::Instance* effectInstance, ClipDescriptor& desc);
|
||||
|
||||
/// is the clip an output clip
|
||||
bool isOutput() const {return _isOutput;}
|
||||
|
||||
/// notify override properties
|
||||
virtual void notify(const std::string &name, bool isSingle, int indexOrN);
|
||||
|
||||
/// get hook override
|
||||
virtual void reset(const std::string &name);
|
||||
|
||||
// get the virtuals for viewport size, pixel scale, background colour
|
||||
virtual double getDoubleProperty(const std::string &name, int index) const;
|
||||
|
||||
// get the virtuals for viewport size, pixel scale, background colour
|
||||
virtual void getDoublePropertyN(const std::string &name, double *values, int count) const;
|
||||
|
||||
// get the virtuals for viewport size, pixel scale, background colour
|
||||
virtual int getIntProperty(const std::string &name, int index) const;
|
||||
|
||||
// get the virtuals for viewport size, pixel scale, background colour
|
||||
virtual void getIntPropertyN(const std::string &name, int *values, int count) const;
|
||||
|
||||
// get the virtuals for viewport size, pixel scale, background colour
|
||||
virtual const std::string &getStringProperty(const std::string &name, int index) const;
|
||||
|
||||
// fetch multiple values in a multi-dimension property
|
||||
virtual void getStringPropertyN(const std::string &name, const char** values, int count) const;
|
||||
|
||||
// get hook virtuals
|
||||
virtual int getDimension(const std::string &name) const;
|
||||
|
||||
// instance changed action
|
||||
OfxStatus instanceChangedAction(const std::string &why,
|
||||
OfxTime time,
|
||||
OfxPointD renderScale);
|
||||
|
||||
// properties of an instance that are live
|
||||
|
||||
/// Pixel Depth - fetch depth of all chromatic component in this clip
|
||||
///
|
||||
/// kOfxBitDepthNone (implying a clip is unconnected, not valid for an image)
|
||||
/// kOfxBitDepthByte
|
||||
/// kOfxBitDepthShort
|
||||
/// kOfxBitDepthHalf
|
||||
/// kOfxBitDepthFloat
|
||||
const std::string &getPixelDepth() const
|
||||
{
|
||||
return _pixelDepth;
|
||||
}
|
||||
|
||||
/// set the current pixel depth
|
||||
/// called by clip preferences action
|
||||
void setPixelDepth(const std::string &s)
|
||||
{
|
||||
_pixelDepth = s;
|
||||
}
|
||||
|
||||
/// Components that can be fetched from this clip -
|
||||
///
|
||||
/// kOfxImageComponentNone (implying a clip is unconnected, not valid for an image)
|
||||
/// kOfxImageComponentRGBA
|
||||
/// kOfxImageComponentRGB
|
||||
/// kOfxImageComponentAlpha
|
||||
/// and any custom ones you may think of
|
||||
virtual const std::string &getComponents() const;
|
||||
|
||||
/// set the current set of components
|
||||
/// called by clip preferences action
|
||||
virtual void setComponents(const std::string &s);
|
||||
|
||||
/// Get the Raw Unmapped Pixel Depth from the host for chromatic planes
|
||||
///
|
||||
/// \returns
|
||||
/// - kOfxBitDepthNone (implying a clip is unconnected image)
|
||||
/// - kOfxBitDepthByte
|
||||
/// - kOfxBitDepthShort
|
||||
/// - kOfxBitDepthHalf
|
||||
/// - kOfxBitDepthFloat
|
||||
virtual const std::string &getUnmappedBitDepth() const = 0;
|
||||
|
||||
/// Get the Raw Unmapped Components from the host
|
||||
///
|
||||
/// \returns
|
||||
/// - kOfxImageComponentNone (implying a clip is unconnected, not valid for an image)
|
||||
/// - kOfxImageComponentRGBA
|
||||
/// - kOfxImageComponentAlpha
|
||||
virtual const std::string &getUnmappedComponents() const = 0;
|
||||
|
||||
// PreMultiplication -
|
||||
//
|
||||
// kOfxImageOpaque - the image is opaque and so has no premultiplication state
|
||||
// kOfxImagePreMultiplied - the image is premultiplied by it's alpha
|
||||
// kOfxImageUnPreMultiplied - the image is unpremultiplied
|
||||
virtual const std::string &getPremult() const = 0;
|
||||
|
||||
// Pixel Aspect Ratio -
|
||||
//
|
||||
// The pixel aspect ratio of a clip or image.
|
||||
virtual double getAspectRatio() const = 0;
|
||||
|
||||
// Frame Rate -
|
||||
//
|
||||
// The frame rate of a clip or instance's project.
|
||||
virtual double getFrameRate() const = 0;
|
||||
|
||||
// Frame Range (startFrame, endFrame) -
|
||||
//
|
||||
// The frame range over which a clip has images.
|
||||
virtual void getFrameRange(double &startFrame, double &endFrame) const = 0;
|
||||
|
||||
/// Field Order - Which spatial field occurs temporally first in a frame.
|
||||
/// \returns
|
||||
/// - kOfxImageFieldNone - the clip material is unfielded
|
||||
/// - kOfxImageFieldLower - the clip material is fielded, with image rows 0,2,4.... occuring first in a frame
|
||||
/// - kOfxImageFieldUpper - the clip material is fielded, with image rows line 1,3,5.... occuring first in a frame
|
||||
virtual const std::string &getFieldOrder() const = 0;
|
||||
|
||||
// Connected -
|
||||
//
|
||||
// Says whether the clip is actually connected at the moment.
|
||||
virtual bool getConnected() const = 0;
|
||||
|
||||
// Unmapped Frame Rate -
|
||||
//
|
||||
// The unmapped frame rate.
|
||||
virtual double getUnmappedFrameRate() const = 0;
|
||||
|
||||
// Unmapped Frame Range -
|
||||
//
|
||||
// The unmapped frame range over which an output clip has images.
|
||||
virtual void getUnmappedFrameRange(double &unmappedStartFrame, double &unmappedEndFrame) const = 0;
|
||||
|
||||
// Continuous Samples -
|
||||
//
|
||||
// 0 if the images can only be sampled at discreet times (eg: the clip is a sequence of frames),
|
||||
// 1 if the images can only be sampled continuously (eg: the clip is infact an animating roto spline and can be rendered anywhen).
|
||||
virtual bool getContinuousSamples() const = 0;
|
||||
|
||||
/// override this to fill in the image at the given time.
|
||||
/// The bounds of the image on the image plane should be
|
||||
/// 'appropriate', typically the value returned in getRegionsOfInterest
|
||||
/// on the effect instance. Outside a render call, the optionalBounds should
|
||||
/// be 'appropriate' for the.
|
||||
/// If bounds is not null, fetch the indicated section of the canonical image plane.
|
||||
virtual ImageEffect::Image* getImage(OfxTime time, const OfxRectD *optionalBounds) = 0;
|
||||
|
||||
# ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
/// override this to fill in the OpenGL texture at the given time.
|
||||
/// The bounds of the image on the image plane should be
|
||||
/// 'appropriate', typically the value returned in getRegionsOfInterest
|
||||
/// on the effect instance. Outside a render call, the optionalBounds should
|
||||
/// be 'appropriate' for the.
|
||||
/// If bounds is not null, fetch the indicated section of the canonical image plane.
|
||||
virtual ImageEffect::Texture* loadTexture(OfxTime time, const char *format, const OfxRectD *optionalBounds) = 0;
|
||||
# endif
|
||||
|
||||
/// override this to return the rod on the clip
|
||||
virtual OfxRectD getRegionOfDefinition(OfxTime time) const = 0;
|
||||
|
||||
/// given the colour component, find the nearest set of supported colour components
|
||||
/// override this for extra wierd custom component depths
|
||||
virtual const std::string &findSupportedComp(const std::string &s) const;
|
||||
};
|
||||
|
||||
|
||||
/// instance of an image inside an image effect
|
||||
class ImageBase : public Property::Set {
|
||||
protected :
|
||||
/// called during ctors to get bits from the clip props into ours
|
||||
void getClipBits(ClipInstance& instance);
|
||||
int _referenceCount; ///< reference count on this image
|
||||
|
||||
public:
|
||||
// default constructor
|
||||
virtual ~ImageBase();
|
||||
|
||||
/// basic ctor, makes empty property set but sets not value
|
||||
ImageBase();
|
||||
|
||||
/// construct from a clip instance, but leave the
|
||||
/// filling it to the calling code via the propery set
|
||||
explicit ImageBase(ClipInstance& instance);
|
||||
|
||||
// Render Scale (renderScaleX,renderScaleY) -
|
||||
//
|
||||
// The proxy render scale currently being applied.
|
||||
// ------
|
||||
// Bounds (bx1,by1,bx2,by2) -
|
||||
//
|
||||
// The bounds of an image's pixels. The bounds, in PixelCoordinates, are of the
|
||||
// addressable pixels in an image's data pointer. The order of the values is
|
||||
// x1, y1, x2, y2. X values are x1 <= X < x2 Y values are y1 <= Y < y2
|
||||
// ------
|
||||
// ROD (rodx1,rody1,rodx2,rody2) -
|
||||
//
|
||||
// The full region of definition. The ROD, in PixelCoordinates, are of the
|
||||
// addressable pixels in an image's data pointer. The order of the values is
|
||||
// x1, y1, x2, y2. X values are x1 <= X < x2 Y values are y1 <= Y < y2
|
||||
// ------
|
||||
// Row Bytes -
|
||||
//
|
||||
// The number of bytes in a row of an image.
|
||||
// ------
|
||||
// Field -
|
||||
//
|
||||
// kOfxImageFieldNone - the image is an unfielded frame
|
||||
// kOfxImageFieldBoth - the image is fielded and contains both interlaced fields
|
||||
// kOfxImageFieldLower - the image is fielded and contains a single field, being the lower field (rows 0,2,4...)
|
||||
// kOfxImageFieldUpper - the image is fielded and contains a single field, being the upper field (rows 1,3,5...)
|
||||
// ------
|
||||
// Unique Identifier -
|
||||
//
|
||||
// Uniquely labels an image. This is host set and allows a plug-in to differentiate between images. This is
|
||||
// especially useful if a plugin caches analysed information about the image (for example motion vectors). The
|
||||
// plugin can label the cached information with this identifier. If a user connects a different clip to the
|
||||
// analysed input, or the image has changed in some way then the plugin can detect this via an identifier change
|
||||
// and re-evaluate the cached information.
|
||||
|
||||
// construction based on clip instance
|
||||
ImageBase(ClipInstance& instance, // construct from clip instance taking pixel depth, components, pre mult and aspect ratio
|
||||
double renderScaleX,
|
||||
double renderScaleY,
|
||||
const OfxRectI &bounds,
|
||||
const OfxRectI &rod,
|
||||
int rowBytes,
|
||||
std::string field,
|
||||
std::string uniqueIdentifier);
|
||||
|
||||
// OfxImageClipHandle getHandle();
|
||||
OfxPropertySetHandle getPropHandle() const { return Property::Set::getHandle(); }
|
||||
|
||||
/// get the bounds of the pixels in memory
|
||||
OfxRectI getBounds() const;
|
||||
|
||||
/// get the full region of this image
|
||||
OfxRectI getROD() const;
|
||||
|
||||
/// release the reference count, which, if zero, deletes this
|
||||
void releaseReference();
|
||||
|
||||
/// add a reference to this image
|
||||
void addReference() {_referenceCount++;}
|
||||
};
|
||||
|
||||
/// instance of an image inside an image effect
|
||||
class Image : public ImageBase {
|
||||
public:
|
||||
// default constructor
|
||||
virtual ~Image();
|
||||
|
||||
/// basic ctor, makes empty property set but sets not value
|
||||
Image();
|
||||
|
||||
/// construct from a clip instance, but leave the
|
||||
/// filling it to the calling code via the propery set
|
||||
explicit Image(ClipInstance& instance);
|
||||
|
||||
// Render Scale (renderScaleX,renderScaleY) -
|
||||
//
|
||||
// The proxy render scale currently being applied.
|
||||
// ------
|
||||
// Data -
|
||||
//
|
||||
// The pixel data pointer of an image.
|
||||
// ------
|
||||
// Bounds (bx1,by1,bx2,by2) -
|
||||
//
|
||||
// The bounds of an image's pixels. The bounds, in PixelCoordinates, are of the
|
||||
// addressable pixels in an image's data pointer. The order of the values is
|
||||
// x1, y1, x2, y2. X values are x1 <= X < x2 Y values are y1 <= Y < y2
|
||||
// ------
|
||||
// ROD (rodx1,rody1,rodx2,rody2) -
|
||||
//
|
||||
// The full region of definition. The ROD, in PixelCoordinates, are of the
|
||||
// addressable pixels in an image's data pointer. The order of the values is
|
||||
// x1, y1, x2, y2. X values are x1 <= X < x2 Y values are y1 <= Y < y2
|
||||
// ------
|
||||
// Row Bytes -
|
||||
//
|
||||
// The number of bytes in a row of an image.
|
||||
// ------
|
||||
// Field -
|
||||
//
|
||||
// kOfxImageFieldNone - the image is an unfielded frame
|
||||
// kOfxImageFieldBoth - the image is fielded and contains both interlaced fields
|
||||
// kOfxImageFieldLower - the image is fielded and contains a single field, being the lower field (rows 0,2,4...)
|
||||
// kOfxImageFieldUpper - the image is fielded and contains a single field, being the upper field (rows 1,3,5...)
|
||||
// ------
|
||||
// Unique Identifier -
|
||||
//
|
||||
// Uniquely labels an image. This is host set and allows a plug-in to differentiate between images. This is
|
||||
// especially useful if a plugin caches analysed information about the image (for example motion vectors). The
|
||||
// plugin can label the cached information with this identifier. If a user connects a different clip to the
|
||||
// analysed input, or the image has changed in some way then the plugin can detect this via an identifier change
|
||||
// and re-evaluate the cached information.
|
||||
|
||||
// construction based on clip instance
|
||||
Image(ClipInstance& instance, // construct from clip instance taking pixel depth, components, pre mult and aspect ratio
|
||||
double renderScaleX,
|
||||
double renderScaleY,
|
||||
void* data,
|
||||
const OfxRectI &bounds,
|
||||
const OfxRectI &rod,
|
||||
int rowBytes,
|
||||
std::string field,
|
||||
std::string uniqueIdentifier);
|
||||
};
|
||||
|
||||
# ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
/// instance of an OpenGL texture inside an image effect
|
||||
class Texture : public ImageBase {
|
||||
public:
|
||||
// default constructor
|
||||
virtual ~Texture();
|
||||
|
||||
/// basic ctor, makes empty property set but sets not value
|
||||
Texture();
|
||||
|
||||
/// construct from a clip instance, but leave the
|
||||
/// filling it to the calling code via the propery set
|
||||
explicit Texture(ClipInstance& instance);
|
||||
|
||||
// Render Scale (renderScaleX,renderScaleY) -
|
||||
//
|
||||
// The proxy render scale currently being applied.
|
||||
// ------
|
||||
// Index -
|
||||
//
|
||||
// The texture id (cast to GLuint).
|
||||
// ------
|
||||
// Target -
|
||||
//
|
||||
// The texture target (cast to GLenum).
|
||||
// ------
|
||||
// Bounds (bx1,by1,bx2,by2) -
|
||||
//
|
||||
// The bounds of an image's pixels. The bounds, in PixelCoordinates, are of the
|
||||
// addressable pixels in an image's data pointer. The order of the values is
|
||||
// x1, y1, x2, y2. X values are x1 <= X < x2 Y values are y1 <= Y < y2
|
||||
// ------
|
||||
// ROD (rodx1,rody1,rodx2,rody2) -
|
||||
//
|
||||
// The full region of definition. The ROD, in PixelCoordinates, are of the
|
||||
// addressable pixels in an image's data pointer. The order of the values is
|
||||
// x1, y1, x2, y2. X values are x1 <= X < x2 Y values are y1 <= Y < y2
|
||||
// ------
|
||||
// Row Bytes -
|
||||
//
|
||||
// The number of bytes in a row of an image.
|
||||
// ------
|
||||
// Field -
|
||||
//
|
||||
// kOfxImageFieldNone - the image is an unfielded frame
|
||||
// kOfxImageFieldBoth - the image is fielded and contains both interlaced fields
|
||||
// kOfxImageFieldLower - the image is fielded and contains a single field, being the lower field (rows 0,2,4...)
|
||||
// kOfxImageFieldUpper - the image is fielded and contains a single field, being the upper field (rows 1,3,5...)
|
||||
// ------
|
||||
// Unique Identifier -
|
||||
//
|
||||
// Uniquely labels an image. This is host set and allows a plug-in to differentiate between images. This is
|
||||
// especially useful if a plugin caches analysed information about the image (for example motion vectors). The
|
||||
// plugin can label the cached information with this identifier. If a user connects a different clip to the
|
||||
// analysed input, or the image has changed in some way then the plugin can detect this via an identifier change
|
||||
// and re-evaluate the cached information.
|
||||
|
||||
// construction based on clip instance
|
||||
Texture(ClipInstance& instance, // construct from clip instance taking pixel depth, components, pre mult and aspect ratio
|
||||
double renderScaleX,
|
||||
double renderScaleY,
|
||||
int index,
|
||||
int target,
|
||||
const OfxRectI &bounds,
|
||||
const OfxRectI &rod,
|
||||
int rowBytes,
|
||||
std::string field,
|
||||
std::string uniqueIdentifier);
|
||||
};
|
||||
# endif
|
||||
} // Memory
|
||||
|
||||
} // Host
|
||||
|
||||
} // OFX
|
||||
|
||||
#endif // OFX_CLIP_H
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
#ifndef OFX_HOST_H
|
||||
#define OFX_HOST_H
|
||||
|
||||
// Copyright OpenFX and contributors to the OpenFX project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <cstdarg>
|
||||
|
||||
#include "ofxCore.h"
|
||||
#include "ofxImageEffect.h"
|
||||
#include "ofxTimeLine.h"
|
||||
#include "ofxhPropertySuite.h"
|
||||
|
||||
namespace OFX {
|
||||
|
||||
namespace Host {
|
||||
|
||||
/// a plugin what we use
|
||||
class Plugin;
|
||||
|
||||
/// a param descriptor
|
||||
namespace Param {
|
||||
class Descriptor;
|
||||
}
|
||||
|
||||
/// Base class for all objects passed to a plugin by the 'setHost' function
|
||||
/// passed back by any plug-in.
|
||||
class Host {
|
||||
protected :
|
||||
OfxHost _host;
|
||||
Property::Set _properties;
|
||||
|
||||
public:
|
||||
Host();
|
||||
virtual ~Host() {}
|
||||
|
||||
|
||||
/// get the props on this host
|
||||
Property::Set &getProperties() {return _properties; }
|
||||
|
||||
/// fetch a suite
|
||||
/// The base class returns the following suites
|
||||
/// PropertySuite
|
||||
/// MemorySuite
|
||||
virtual const void *fetchSuite(const char *suiteName, int suiteVersion);
|
||||
|
||||
/// get the C API handle that is passed across the API to represent this host
|
||||
OfxHost *getHandle();
|
||||
|
||||
/// override this to handle do post-construction initialisation on a Param::Descriptor
|
||||
virtual void initParamDescriptor(Param::Descriptor *) { }
|
||||
|
||||
/// is my magic number valid?
|
||||
bool verifyMagic() { return true; }
|
||||
|
||||
/// message (called when an exception occurs, calls vmessage)
|
||||
OfxStatus message(const char* type,
|
||||
const char* id,
|
||||
const char* format,
|
||||
...);
|
||||
|
||||
/// vmessage
|
||||
virtual OfxStatus vmessage(const char* type,
|
||||
const char* id,
|
||||
const char* format,
|
||||
va_list args) = 0;
|
||||
|
||||
/// setPersistentMessage
|
||||
virtual OfxStatus setPersistentMessage(const char* type,
|
||||
const char* id,
|
||||
const char* format,
|
||||
va_list args) = 0;
|
||||
/// clearPersistentMessage
|
||||
virtual OfxStatus clearPersistentMessage() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+679
@@ -0,0 +1,679 @@
|
||||
|
||||
|
||||
|
||||
#ifndef OFX_IMAGE_EFFECT_H
|
||||
#define OFX_IMAGE_EFFECT_H
|
||||
|
||||
#include "ofxCore.h"
|
||||
#include "ofxImageEffect.h"
|
||||
|
||||
#include "ofxhHost.h"
|
||||
#include "ofxhClip.h"
|
||||
#include "ofxhProgress.h"
|
||||
#include "ofxhTimeLine.h"
|
||||
#include "ofxhParam.h"
|
||||
#include "ofxhMemory.h"
|
||||
#include "ofxhInteract.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
//Use visual studio extension
|
||||
#define __PRETTY_FUNCTION__ __FUNCSIG__
|
||||
#endif
|
||||
|
||||
namespace OFX {
|
||||
|
||||
namespace Host {
|
||||
|
||||
// forward declare
|
||||
class Plugin;
|
||||
|
||||
namespace Memory {
|
||||
class Instance;
|
||||
}
|
||||
|
||||
namespace ImageEffect {
|
||||
|
||||
// forward declare
|
||||
class ImageEffectPlugin;
|
||||
class OverlayInstance;
|
||||
class Instance;
|
||||
class Descriptor;
|
||||
|
||||
/// An image effect host, passed to the setHost function of all image effect plugins
|
||||
class Host : public OFX::Host::Host {
|
||||
public :
|
||||
Host();
|
||||
|
||||
/// fetch a suite
|
||||
virtual const void *fetchSuite(const char *suiteName, int suiteVersion);
|
||||
|
||||
/// Create a new instance of an image effect plug-in.
|
||||
///
|
||||
/// It is called by ImageEffectPlugin::createInstance which the
|
||||
/// client code calls when it wants to make a new instance.
|
||||
///
|
||||
/// \arg clientData - the clientData passed into the ImageEffectPlugin::createInstance
|
||||
/// \arg plugin - the plugin being created
|
||||
/// \arg desc - the descriptor for that plugin
|
||||
/// \arg context - the context to be created in
|
||||
virtual Instance* newInstance(void* clientData,
|
||||
ImageEffectPlugin* plugin,
|
||||
Descriptor& desc,
|
||||
const std::string& context) = 0;
|
||||
|
||||
/// Function called as each plugin binary is found and loaded from disk
|
||||
///
|
||||
/// Use this in any dialogue etc... showing progress
|
||||
virtual void loadingStatus(const std::string &);
|
||||
|
||||
/// Override this to filter out plugins which the host can't support for whatever reason
|
||||
///
|
||||
/// \arg plugin - the plugin to examine
|
||||
/// \arg reason - set this to report the reason the plugin was not loaded
|
||||
virtual bool pluginSupported(ImageEffectPlugin *plugin, std::string &reason) const;
|
||||
|
||||
/// Override this to create a descriptor, this makes the 'root' descriptor
|
||||
virtual Descriptor *makeDescriptor(ImageEffectPlugin* plugin) = 0;
|
||||
|
||||
/// used to construct a context description, rootContext is the main context
|
||||
virtual Descriptor *makeDescriptor(const Descriptor &rootContext, ImageEffectPlugin *plug) = 0;
|
||||
|
||||
/// used to construct populate the cache
|
||||
virtual Descriptor *makeDescriptor(const std::string &bundlePath, ImageEffectPlugin *plug) = 0;
|
||||
|
||||
/// Override this to initialise an image effect descriptor after it has been
|
||||
/// created.
|
||||
virtual void initDescriptor(Descriptor* desc);
|
||||
|
||||
#ifdef OFX_SUPPORTS_MULTITHREAD
|
||||
// these functions must be implemented if the host supports OfxMultiThreadSuiteV1
|
||||
// all the following functions are described in ofxMultiThread.h
|
||||
//
|
||||
|
||||
/// @see OfxMultiThreadSuiteV1.multiThread()
|
||||
virtual OfxStatus multiThread(OfxThreadFunctionV1 func,unsigned int nThreads, void *customArg) = 0;
|
||||
|
||||
/// @see OfxMultiThreadSuiteV1.multiThreadNumCPUS()
|
||||
virtual OfxStatus multiThreadNumCPUS(unsigned int *nCPUs) const = 0;
|
||||
|
||||
/// @see OfxMultiThreadSuiteV1.multiThreadIndex()
|
||||
virtual OfxStatus multiThreadIndex(unsigned int *threadIndex) const = 0;
|
||||
|
||||
/// @see OfxMultiThreadSuiteV1.multiThreadIsSpawnedThread()
|
||||
virtual int multiThreadIsSpawnedThread() const = 0;
|
||||
|
||||
/// @see OfxMultiThreadSuiteV1.mutexCreate()
|
||||
virtual OfxStatus mutexCreate(OfxMutexHandle *mutex, int lockCount) = 0;
|
||||
|
||||
/// @see OfxMultiThreadSuiteV1.mutexDestroy()
|
||||
virtual OfxStatus mutexDestroy(const OfxMutexHandle mutex) = 0;
|
||||
|
||||
/// @see OfxMultiThreadSuiteV1.mutexLock()
|
||||
virtual OfxStatus mutexLock(const OfxMutexHandle mutex) = 0;
|
||||
|
||||
/// @see OfxMultiThreadSuiteV1.mutexUnLock()
|
||||
virtual OfxStatus mutexUnLock(const OfxMutexHandle mutex) = 0;
|
||||
|
||||
/// @see OfxMultiThreadSuiteV1.mutexTryLock()
|
||||
virtual OfxStatus mutexTryLock(const OfxMutexHandle mutex) = 0;
|
||||
#endif // OFX_SUPPORTS_MULTITHREAD
|
||||
|
||||
# ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
/// @see OfxImageEffectOpenGLRenderSuiteV1.flushResources()
|
||||
virtual OfxStatus flushOpenGLResources() const = 0;
|
||||
# endif
|
||||
|
||||
/// override this to use your own memory instance - must inherrit from memory::instance
|
||||
virtual Memory::Instance* newMemoryInstance(size_t nBytes);
|
||||
|
||||
// return an memory::instance calls makeMemoryInstance that can be overriden
|
||||
Memory::Instance* imageMemoryAlloc(size_t nBytes);
|
||||
};
|
||||
|
||||
/// our global host object, set when the plugin cache is created
|
||||
extern Host *gImageEffectHost;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// base class to both effect descriptors and instances
|
||||
class Base {
|
||||
protected:
|
||||
Property::Set _properties;
|
||||
|
||||
public:
|
||||
Base(const Property::Set &set);
|
||||
Base(const Property::PropSpec * propSpec);
|
||||
virtual ~Base();
|
||||
|
||||
/// is my magic number valid?
|
||||
virtual bool verifyMagic() { return true; }
|
||||
|
||||
/// obtain a handle on this for passing to the C api
|
||||
OfxImageEffectHandle getHandle() const;
|
||||
|
||||
/// get the properties set
|
||||
Property::Set &getProps();
|
||||
|
||||
/// get the properties set, const version
|
||||
const Property::Set &getProps() const;
|
||||
|
||||
/// name of the clip
|
||||
const std::string &getShortLabel() const;
|
||||
|
||||
/// name of the clip
|
||||
const std::string &getLabel() const;
|
||||
|
||||
/// name of the clip
|
||||
const std::string &getLongLabel() const;
|
||||
|
||||
/// is the given context supported
|
||||
bool isContextSupported(const std::string &s) const;
|
||||
|
||||
/// what is the name of the group the plug-in belongs to
|
||||
const std::string &getPluginGrouping() const;
|
||||
|
||||
/// is the effect single instance
|
||||
bool isSingleInstance() const;
|
||||
|
||||
/// what is the thread safety on this effect
|
||||
const std::string &getRenderThreadSafety() const;
|
||||
|
||||
/// should the host attempt to managed multi-threaded rendering if it can
|
||||
/// via tiling or some such
|
||||
bool getHostFrameThreading() const;
|
||||
|
||||
/// get the overlay interact main entry if it exists
|
||||
OfxPluginEntryPoint *getOverlayInteractMainEntry() const;
|
||||
|
||||
/// does the effect support images of differing sizes
|
||||
bool supportsMultiResolution() const;
|
||||
|
||||
/// does the effect support tiled rendering
|
||||
bool supportsTiles() const;
|
||||
|
||||
/// does this effect need random temporal access
|
||||
bool temporalAccess() const;
|
||||
|
||||
/// is the given RGBA/A pixel depth supported by the effect
|
||||
bool isPixelDepthSupported(const std::string &s) const;
|
||||
|
||||
/// when field rendering, does the effect need to be called
|
||||
/// twice to render a frame in all circumstances (with different fields)
|
||||
bool fieldRenderTwiceAlways() const;
|
||||
|
||||
/// does the effect support multiple clip depths
|
||||
bool supportsMultipleClipDepths() const;
|
||||
|
||||
/// does the effect support multiple clip pixel aspect ratios
|
||||
bool supportsMultipleClipPARs() const;
|
||||
|
||||
/// does changing the named param re-tigger a clip preferences action
|
||||
bool isClipPreferencesSlaveParam(const std::string &s) const;
|
||||
|
||||
};
|
||||
|
||||
/// an image effect plugin descriptor
|
||||
class Descriptor
|
||||
: public Base
|
||||
, public Param::SetDescriptor {
|
||||
private :
|
||||
// private CC
|
||||
Descriptor(const Descriptor &other)
|
||||
: Base(other._properties)
|
||||
, Param::SetDescriptor()
|
||||
, _plugin(other._plugin)
|
||||
{}
|
||||
|
||||
protected:
|
||||
Plugin *_plugin; ///< the plugin I belong to
|
||||
std::map<std::string, ClipDescriptor*> _clips; ///< clips descriptors by name
|
||||
std::vector<ClipDescriptor*> _clipsByOrder; ///< clip descriptors in order of declaration
|
||||
mutable Interact::Descriptor _overlayDescriptor; ///< descriptor to use for overlays, it has delayed description
|
||||
|
||||
public:
|
||||
/// used to construct the global description
|
||||
Descriptor(Plugin *plug);
|
||||
|
||||
/// used to construct a context description, 'other' is the main context
|
||||
Descriptor(const Descriptor &rootContext, Plugin *plug);
|
||||
|
||||
/// used to construct populate the cache
|
||||
Descriptor(const std::string &bundlePath, Plugin *plug);
|
||||
|
||||
/// dtor
|
||||
virtual ~Descriptor();
|
||||
|
||||
/// implemented for Param::SetDescriptor
|
||||
virtual Property::Set &getParamSetProps();
|
||||
|
||||
/// get the plugin I belong to
|
||||
Plugin *getPlugin() const {return _plugin;}
|
||||
|
||||
/// create a new clip and add this to the clip map
|
||||
virtual ClipDescriptor *defineClip(const std::string &name);
|
||||
|
||||
/// get the clips
|
||||
const std::map<std::string, ClipDescriptor*> &getClips() const;
|
||||
|
||||
/// add a new clip
|
||||
void addClip(const std::string &name, ClipDescriptor *clip);
|
||||
|
||||
/// get the clips in order of construction
|
||||
const std::vector<ClipDescriptor*> &getClipsByOrder() const
|
||||
{
|
||||
return _clipsByOrder;
|
||||
}
|
||||
|
||||
/// Get the interact description, this will also call describe on the interact
|
||||
/// This will return NULL if there is not main entry point or if the description failed
|
||||
/// otherwise it will return the described overlay
|
||||
Interact::Descriptor &getOverlayDescriptor(int bitDepthPerComponent = 8, bool hasAlpha = false);
|
||||
};
|
||||
|
||||
/// a map used to specify needed frame ranges on set of clips
|
||||
typedef std::map<ClipInstance *, std::vector<OfxRangeD> > RangeMap;
|
||||
|
||||
/// an image effect plugin instance.
|
||||
///
|
||||
/// Client code needs to filling the pure virtuals in this.
|
||||
class Instance : public Base,
|
||||
public Param::SetInstance,
|
||||
public Progress::ProgressI,
|
||||
public TimeLine::TimeLineI,
|
||||
private Property::NotifyHook,
|
||||
private Property::GetHook
|
||||
{
|
||||
protected:
|
||||
OFX::Host::ImageEffect::ImageEffectPlugin *_plugin;
|
||||
std::string _context;
|
||||
Descriptor *_descriptor;
|
||||
std::map<std::string, ClipInstance*> _clips;
|
||||
bool _interactive;
|
||||
bool _created;
|
||||
|
||||
bool _clipPrefsDirty; ///< do we need to re-run the clip prefs action
|
||||
bool _continuousSamples; ///< set by clip prefs
|
||||
bool _frameVarying; ///< set by clip prefs
|
||||
std::string _outputPreMultiplication; ///< set by clip prefs
|
||||
std::string _outputFielding; ///< set by clip prefs
|
||||
double _outputFrameRate; ///< set by clip prefs
|
||||
|
||||
public:
|
||||
/// constructor based on clip descriptor
|
||||
Instance(ImageEffectPlugin* plugin,
|
||||
Descriptor &other,
|
||||
const std::string &context,
|
||||
bool interactive);
|
||||
|
||||
virtual ~Instance();
|
||||
|
||||
/// implemented for Param::SetInstance
|
||||
virtual Property::Set &getParamSetProps();
|
||||
|
||||
/// implemented for Param::SetInstance
|
||||
virtual void paramChangedByPlugin(Param::Instance *param);
|
||||
|
||||
/// get the descriptor for this instance
|
||||
const Descriptor &getDescriptor() const {return *_descriptor;}
|
||||
|
||||
/// return the plugin this instance was created with
|
||||
OFX::Host::ImageEffect::ImageEffectPlugin*getPlugin() const { return _plugin; }
|
||||
|
||||
/// return the context this instance was created with
|
||||
const std::string &getContext() const { return _context; }
|
||||
|
||||
/// get the descriptor for this instance
|
||||
Descriptor &getDescriptor() {return *_descriptor;}
|
||||
|
||||
/// get default output fielding. This is passed into the clip prefs action
|
||||
/// and might be mapped (if the host allows such a thing)
|
||||
virtual const std::string &getDefaultOutputFielding() const = 0;
|
||||
|
||||
/// get output fielding as set in the clip preferences action.
|
||||
const std::string &getOutputFielding() const {return _outputFielding; }
|
||||
|
||||
/// get output fielding as set in the clip preferences action.
|
||||
const std::string &getOutputPreMultiplication() const {return _outputPreMultiplication; }
|
||||
|
||||
/// get the output frame rate, as set in the clip prefences action.
|
||||
double getOutputFrameRate() const {return _outputFrameRate;}
|
||||
|
||||
|
||||
/// called after construction to populate the various members
|
||||
/// ideally should be called in the ctor, but it relies on
|
||||
/// virtuals so has to be delayed until after the effect is
|
||||
/// constructed
|
||||
OfxStatus populate();
|
||||
|
||||
/// get the nth clip, in order of declaration
|
||||
ClipInstance* getNthClip(int index);
|
||||
|
||||
/// get the nth clip, in order of declaration
|
||||
int getNClips() const
|
||||
{
|
||||
return int(_clips.size());
|
||||
}
|
||||
|
||||
/// are the clip preferences currently dirty
|
||||
bool areClipPrefsDirty() const {return _clipPrefsDirty;}
|
||||
|
||||
/// are all the non optional clips connected
|
||||
bool checkClipConnectionStatus() const;
|
||||
|
||||
/// can this this instance render images at arbitrary times, not just frame boundaries
|
||||
/// set by getClipPreferenceAction()
|
||||
bool continuousSamples() const {return _continuousSamples;}
|
||||
|
||||
/// does this instance generate a different picture on a frame change, even if the
|
||||
/// params and input images are exactly the same. eg: random noise generator
|
||||
bool isFrameVarying() const {return _frameVarying;}
|
||||
|
||||
/// pure virtuals that must be overriden
|
||||
virtual ClipInstance* getClip(const std::string& name) const;
|
||||
|
||||
/// override this to make processing abort, return 1 to abort processing
|
||||
virtual int abort();
|
||||
|
||||
/// override this to use your own memory instance - must inherrit from memory::instance
|
||||
virtual Memory::Instance* newMemoryInstance(size_t nBytes);
|
||||
|
||||
// return an memory::instance calls makeMemoryInstance that can be overriden
|
||||
Memory::Instance* imageMemoryAlloc(size_t nBytes);
|
||||
|
||||
/// make a clip
|
||||
virtual ClipInstance* newClipInstance(ImageEffect::Instance* plugin,
|
||||
ClipDescriptor* descriptor,
|
||||
int index) = 0;
|
||||
|
||||
/// message suite
|
||||
virtual OfxStatus vmessage(const char* type,
|
||||
const char* id,
|
||||
const char* format,
|
||||
va_list args) = 0;
|
||||
|
||||
virtual OfxStatus setPersistentMessage(const char* type,
|
||||
const char* id,
|
||||
const char* format,
|
||||
va_list args) = 0;
|
||||
|
||||
virtual OfxStatus clearPersistentMessage() = 0;
|
||||
|
||||
|
||||
/// call the effect entry point
|
||||
virtual OfxStatus mainEntry(const char *action,
|
||||
const void *handle,
|
||||
Property::Set *inArgs,
|
||||
Property::Set *outArgs);
|
||||
|
||||
int upperGetDimension(const std::string &name);
|
||||
|
||||
/// overridden from Property::Notify
|
||||
virtual void notify(const std::string &name, bool singleValue, int indexOrN);
|
||||
|
||||
/// overridden from gethook, get the virutals for viewport size, pixel scale, background colour
|
||||
virtual double getDoubleProperty(const std::string &name, int index) const;
|
||||
|
||||
/// overridden from gethook, get the virutals for viewport size, pixel scale, background colour
|
||||
virtual void getDoublePropertyN(const std::string &name, double *values, int count) const;
|
||||
|
||||
/// overridden from gethook, don't know what to do
|
||||
virtual void reset(const std::string &name);
|
||||
|
||||
//// overridden from gethook
|
||||
virtual int getDimension(const std::string &name) const;
|
||||
|
||||
//
|
||||
// live parameters
|
||||
//
|
||||
|
||||
// The size of the current project in canonical coordinates.
|
||||
// The size of a project is a sub set of the kOfxImageEffectPropProjectExtent. For example a
|
||||
// project may be a PAL SD project, but only be a letter-box within that. The project size is
|
||||
// the size of this sub window.
|
||||
virtual void getProjectSize(double& xSize, double& ySize) const = 0;
|
||||
|
||||
// The offset of the current project in canonical coordinates.
|
||||
// The offset is related to the kOfxImageEffectPropProjectSize and is the offset from the origin
|
||||
// of the project 'subwindow'. For example for a PAL SD project that is in letterbox form, the
|
||||
// project offset is the offset to the bottom left hand corner of the letter box. The project
|
||||
// offset is in canonical coordinates.
|
||||
virtual void getProjectOffset(double& xOffset, double& yOffset) const = 0;
|
||||
|
||||
// The extent of the current project in canonical coordinates.
|
||||
// The extent is the size of the 'output' for the current project. See ProjectCoordinateSystems
|
||||
// for more infomation on the project extent. The extent is in canonical coordinates and only
|
||||
// returns the top right position, as the extent is always rooted at 0,0. For example a PAL SD
|
||||
// project would have an extent of 768, 576.
|
||||
virtual void getProjectExtent(double& xSize, double& ySize) const = 0;
|
||||
|
||||
// The pixel aspect ratio of the current project
|
||||
virtual double getProjectPixelAspectRatio() const = 0;
|
||||
|
||||
// The duration of the effect
|
||||
// This contains the duration of the plug-in effect, in frames.
|
||||
virtual double getEffectDuration() const = 0;
|
||||
|
||||
// For an instance, this is the frame rate of the project the effect is in.
|
||||
virtual double getFrameRate() const = 0;
|
||||
|
||||
/// This is called whenever a param is changed by the plugin so that
|
||||
/// the recursive instanceChangedAction will be fed the correct frame
|
||||
virtual double getFrameRecursive() const = 0;
|
||||
|
||||
/// This is called whenever a param is changed by the plugin so that
|
||||
/// the recursive instanceChangedAction will be fed the correct
|
||||
/// renderScale
|
||||
virtual void getRenderScaleRecursive(double &x, double &y) const = 0;
|
||||
|
||||
/// Get whether the component is a supported 'chromatic' component (RGBA or alpha) in
|
||||
/// the base API.
|
||||
/// Override this if you have extended your chromatic colour types (eg RGB) and want
|
||||
/// the clip preferences logic to still work
|
||||
virtual bool isChromaticComponent(const std::string &str) const;
|
||||
|
||||
/// function to check for multiple bit depth support
|
||||
/// The answer will depend on host, plugin and context
|
||||
virtual bool canCurrentlyHandleMultipleClipDepths() const;
|
||||
|
||||
/// calculate the default rod for this effect instance
|
||||
virtual OfxRectD calcDefaultRegionOfDefinition(OfxTime time,
|
||||
OfxPointD renderScale) const;
|
||||
|
||||
//
|
||||
// actions
|
||||
//
|
||||
|
||||
/// this is used to populate with any extra action in argumnents that may be needed
|
||||
virtual void setCustomInArgs(const std::string &action, Property::Set &inArgs);
|
||||
|
||||
/// this is used to populate with any extra action out argumnents that may be needed
|
||||
virtual void setCustomOutArgs(const std::string &action, Property::Set &outArgs);
|
||||
|
||||
/// this is used retrieve any out args after the action was called in mainEntry
|
||||
virtual void examineOutArgs(const std::string &action, OfxStatus stat, const Property::Set &outArgs);
|
||||
|
||||
/// create an instance. This needs to be called _after_ construction and
|
||||
/// _after_ the host populates it's params and clips with the 'correct'
|
||||
/// values (either persisted ones or the defaults)
|
||||
virtual OfxStatus createInstanceAction();
|
||||
|
||||
// begin/change/end instance changed
|
||||
|
||||
//
|
||||
// why -
|
||||
//
|
||||
// kOfxChangeUserEdited - the user or host changed the instance somehow and
|
||||
// caused a change to something, this includes undo/redos,
|
||||
// resets and loading values from files or presets,
|
||||
// kOfxChangePluginEdited - the plugin itself has changed the value of the instance
|
||||
// in some action
|
||||
// kOfxChangeTime - the time has changed and this has affected the value
|
||||
// of the object because it varies over time
|
||||
//
|
||||
virtual OfxStatus beginInstanceChangedAction(const std::string &why);
|
||||
|
||||
virtual OfxStatus paramInstanceChangedAction(const std::string ¶mName,
|
||||
const std::string & why,
|
||||
OfxTime time,
|
||||
OfxPointD renderScale);
|
||||
|
||||
virtual OfxStatus clipInstanceChangedAction(const std::string &clipName,
|
||||
const std::string & why,
|
||||
OfxTime time,
|
||||
OfxPointD renderScale);
|
||||
|
||||
virtual OfxStatus endInstanceChangedAction(const std::string &why);
|
||||
|
||||
// purge your caches
|
||||
virtual OfxStatus purgeCachesAction();
|
||||
|
||||
// sync your private data
|
||||
virtual OfxStatus syncPrivateDataAction();
|
||||
|
||||
// begin/end edit instance
|
||||
virtual OfxStatus beginInstanceEditAction();
|
||||
virtual OfxStatus endInstanceEditAction();
|
||||
|
||||
# ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
// attach/detach OpenGL context
|
||||
virtual OfxStatus contextAttachedAction();
|
||||
virtual OfxStatus contextDetachedAction();
|
||||
# endif
|
||||
|
||||
// render action
|
||||
virtual OfxStatus beginRenderAction(OfxTime startFrame,
|
||||
OfxTime endFrame,
|
||||
OfxTime step,
|
||||
bool interactive,
|
||||
OfxPointD renderScale,
|
||||
bool sequentialRender,
|
||||
bool interactiveRender
|
||||
);
|
||||
|
||||
virtual OfxStatus renderAction(OfxTime time,
|
||||
const std::string & field,
|
||||
const OfxRectI &renderRoI,
|
||||
OfxPointD renderScale,
|
||||
bool sequentialRender,
|
||||
bool interactiveRender,
|
||||
bool draftRender
|
||||
);
|
||||
|
||||
virtual OfxStatus endRenderAction(OfxTime startFrame,
|
||||
OfxTime endFrame,
|
||||
OfxTime step,
|
||||
bool interactive,
|
||||
OfxPointD renderScale,
|
||||
bool sequentialRender,
|
||||
bool interactiveRender
|
||||
);
|
||||
|
||||
/// Call the region of definition action the plugin at the given time
|
||||
/// and with the given render scales. The value is returned in rod.
|
||||
/// Note that if the plugin does not trap the action the default
|
||||
/// RoD is calculated and returned.
|
||||
virtual OfxStatus getRegionOfDefinitionAction(OfxTime time,
|
||||
OfxPointD renderScale,
|
||||
OfxRectD &rod);
|
||||
|
||||
/// call the get region of interest action on the plugin for the
|
||||
/// given frame and renderscale. The render RoI is passed in in
|
||||
/// roi, the std::map will contain the requested rois. Note
|
||||
/// That this call will check for tiling support and for
|
||||
/// default replies and set up the correct rois in these cases
|
||||
/// as well
|
||||
virtual OfxStatus getRegionOfInterestAction(OfxTime time,
|
||||
OfxPointD renderScale,
|
||||
const OfxRectD &roi,
|
||||
std::map<ClipInstance *, OfxRectD> &rois);
|
||||
|
||||
// get frames needed to render the given frame
|
||||
virtual OfxStatus getFrameNeededAction(OfxTime time,
|
||||
RangeMap &rangeMap);
|
||||
|
||||
// is identity
|
||||
virtual OfxStatus isIdentityAction(OfxTime &time,
|
||||
const std::string & field,
|
||||
const OfxRectI &renderRoI,
|
||||
OfxPointD renderScale,
|
||||
std::string &clip);
|
||||
|
||||
// time domain
|
||||
virtual OfxStatus getTimeDomainAction(OfxRangeD& range);
|
||||
|
||||
/// Get the interact description, this will also call describe on the interact
|
||||
/// This will return NULL if there is not main entry point or if the description failed
|
||||
/// otherwise it will return the described overlay
|
||||
/// This is called by the CTOR of OverlayInteract to get the descriptor to do things with
|
||||
Interact::Descriptor &getOverlayDescriptor(int bitDepthPerComponent = 8, bool hasAlpha = false);
|
||||
|
||||
/// Setup the default clip preferences on the clips
|
||||
virtual void setDefaultClipPreferences();
|
||||
|
||||
/// Initialise the clip preferences arguments, override this to do
|
||||
/// stuff with wierd components etc... Calls setDefaultClipPreferences
|
||||
virtual void setupClipPreferencesArgs(Property::Set &args);
|
||||
|
||||
/// Run the clip preferences action from the effect.
|
||||
///
|
||||
/// This will look into the input clips and output clip
|
||||
/// and set the following properties that the effect should
|
||||
/// fetch the image at.
|
||||
/// - pixel depth
|
||||
/// - components
|
||||
/// - pixel aspect ratio
|
||||
/// It will also set on the effect itselff
|
||||
/// - whether it is continuously samplable
|
||||
/// - the premult state of the output
|
||||
/// - whether the effect is frame varying
|
||||
/// - the fielding of the output clip
|
||||
///
|
||||
/// This will be run automatically by the effect in the following situations...
|
||||
/// - an input clip is changed
|
||||
/// - a clip preferences slave param is changed
|
||||
///
|
||||
/// The host still needs to call this explicitly just after the effect is wired
|
||||
/// up.
|
||||
virtual bool getClipPreferences();
|
||||
|
||||
/// calls getClipPreferences only if the prefs are dirty
|
||||
///
|
||||
/// returns whether the clips prefs were dirty or not
|
||||
bool runGetClipPrefsConditionally()
|
||||
{
|
||||
if(areClipPrefsDirty()) {
|
||||
getClipPreferences();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// find the best supported bit depth for the given one. Override this if you define
|
||||
/// more depths
|
||||
virtual const std::string &bestSupportedDepth(const std::string &depth) const;
|
||||
|
||||
/// find the most chromatic components out of the two. Override this if you define
|
||||
/// more chromatic components
|
||||
virtual const std::string &findMostChromaticComponents(const std::string &a, const std::string &b) const;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// An overlay interact for image effects, derived from one of these to
|
||||
/// be an overlay interact
|
||||
class OverlayInteract : public Interact::Instance {
|
||||
protected :
|
||||
/// our image effect instance
|
||||
ImageEffect::Instance &_instance;
|
||||
|
||||
public :
|
||||
/// ctor this calls Instance->getOverlayDescriptor to get the descriptor
|
||||
OverlayInteract(ImageEffect::Instance &v, int bitDepthPerComponent = 8, bool hasAlpha = false);
|
||||
};
|
||||
|
||||
|
||||
} // namespace ImageEffect
|
||||
|
||||
} // namespace Host
|
||||
|
||||
} // namespace OFX
|
||||
|
||||
#endif // OFX_IMAGE_EFFECT_H
|
||||
@@ -0,0 +1,221 @@
|
||||
|
||||
|
||||
|
||||
#ifndef OFXH_IMAGE_EFFECT_API_H
|
||||
#define OFXH_IMAGE_EFFECT_API_H
|
||||
|
||||
#include "ofxhPluginAPICache.h"
|
||||
#include "ofxhPluginCache.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "ofxCore.h"
|
||||
#include "ofxImageEffect.h"
|
||||
#include "ofxhImageEffect.h"
|
||||
#include "ofxhHost.h"
|
||||
|
||||
|
||||
|
||||
|
||||
namespace OFX::Host::ImageEffect {
|
||||
|
||||
class PluginCache;
|
||||
|
||||
/// subclass of Plugin representing an ImageEffect plugin. used to store API-specific
|
||||
/// data
|
||||
class ImageEffectPlugin : public Plugin {
|
||||
|
||||
PluginCache &_pc;
|
||||
|
||||
// this comes off Descriptor's property set after a describe
|
||||
// context independent
|
||||
Descriptor *_baseDescriptor; /// NEEDS TO BE MADE WITH A FACTORY FUNCTION ON THE HOST!!!!!!
|
||||
|
||||
/// map to store contexts in
|
||||
std::map<std::string, std::unique_ptr<Descriptor>> _contexts;
|
||||
|
||||
mutable std::set<std::string> _knownContexts;
|
||||
mutable bool _madeKnownContexts;
|
||||
|
||||
std::unique_ptr<PluginHandle> _pluginHandle;
|
||||
|
||||
void addContextInternal(const std::string &context) const;
|
||||
|
||||
public:
|
||||
ImageEffectPlugin(PluginCache &pc, PluginBinary *pb, int pi, OfxPlugin *pl);
|
||||
|
||||
ImageEffectPlugin(PluginCache &pc,
|
||||
PluginBinary *pb,
|
||||
int pi,
|
||||
const std::string &api,
|
||||
int apiVersion,
|
||||
const std::string &pluginId,
|
||||
const std::string &rawId,
|
||||
int pluginMajorVersion,
|
||||
int pluginMinorVersion);
|
||||
|
||||
~ImageEffectPlugin() override;
|
||||
|
||||
/// return the API handler this plugin was constructed by
|
||||
APICache::PluginAPICacheI &getApiHandler() override;
|
||||
|
||||
|
||||
/// get the base image effect descriptor
|
||||
Descriptor &getDescriptor();
|
||||
|
||||
/// get the base image effect descriptor, const version
|
||||
const Descriptor &getDescriptor() const;
|
||||
|
||||
/// get the image effect descriptor for the context
|
||||
Descriptor *getContext(const std::string &context);
|
||||
|
||||
void addContext(const std::string &context);
|
||||
void addContext(const std::string &context, std::unique_ptr<Descriptor> ied);
|
||||
|
||||
virtual void saveXML(std::ostream &os);
|
||||
|
||||
const std::set<std::string>& getContexts() const;
|
||||
|
||||
PluginHandle *getPluginHandle();
|
||||
|
||||
void unload();
|
||||
|
||||
/// this is called to make an instance of the effect
|
||||
/// the client data ptr is what is passed back to the client creation function
|
||||
ImageEffect::Instance* createInstance(const std::string &context, void *clientDataPtr);
|
||||
|
||||
};
|
||||
|
||||
class MajorPlugin {
|
||||
std::string _id;
|
||||
int _major;
|
||||
|
||||
public:
|
||||
MajorPlugin(std::string id, int major) : _id(std::move(id)), _major(major) {
|
||||
}
|
||||
|
||||
explicit MajorPlugin(ImageEffectPlugin *iep) : _id(iep->getIdentifier()), _major(iep->getVersionMajor()) {
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::string &getId() const {
|
||||
return _id;
|
||||
}
|
||||
|
||||
[[nodiscard]] int getMajor() const {
|
||||
return _major;
|
||||
}
|
||||
|
||||
bool operator<(const MajorPlugin &other) const {
|
||||
if (_id < other._id)
|
||||
return true;
|
||||
|
||||
if (_id > other._id)
|
||||
return false;
|
||||
|
||||
if (_major < other._major)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/// implementation of the specific Image Effect handler API cache.
|
||||
class PluginCache : public APICache::PluginAPICacheI {
|
||||
public:
|
||||
|
||||
private:
|
||||
/// all plugins
|
||||
std::vector<ImageEffectPlugin *> _plugins;
|
||||
|
||||
/// latest version of each plugin by ID
|
||||
std::map<std::string, ImageEffectPlugin *> _pluginsByID;
|
||||
|
||||
/// latest minor version of each plugin by (ID,major)
|
||||
std::map<MajorPlugin, ImageEffectPlugin *> _pluginsByIDMajor;
|
||||
|
||||
/// xml parsing state
|
||||
ImageEffectPlugin *_currentPlugin;
|
||||
/// xml parsing state
|
||||
Property::Property *_currentProp;
|
||||
|
||||
Descriptor *_currentContext;
|
||||
Param::Descriptor *_currentParam;
|
||||
ClipDescriptor *_currentClip;
|
||||
|
||||
/// pointer to our image effect host
|
||||
OFX::Host::ImageEffect::Host* _host;
|
||||
|
||||
public:
|
||||
|
||||
explicit PluginCache(OFX::Host::ImageEffect::Host &host);
|
||||
|
||||
~PluginCache() override;
|
||||
|
||||
/// get the plugin by id. vermaj and vermin can be specified. if they are not it will
|
||||
/// pick the highest found version.
|
||||
ImageEffectPlugin *getPluginById(const std::string &id, int vermaj=-1, int vermin=-1);
|
||||
|
||||
/// get the plugin by label. vermaj and vermin can be specified. if they are not it will
|
||||
/// pick the highest found version.
|
||||
ImageEffectPlugin *getPluginByLabel(const std::string &label, int vermaj=-1, int vermin=-1);
|
||||
|
||||
OFX::Host::ImageEffect::Host *getHost() {
|
||||
return _host;
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::vector<ImageEffectPlugin *>& getPlugins() const;
|
||||
|
||||
[[nodiscard]] const std::map<std::string, ImageEffectPlugin *>& getPluginsByID() const;
|
||||
|
||||
[[nodiscard]] const std::map<MajorPlugin, ImageEffectPlugin *>& getPluginsByIDMajor() const
|
||||
{
|
||||
return _pluginsByIDMajor;
|
||||
}
|
||||
|
||||
/// handle the case where the info needs filling in from the file. runs the "describe" action on the plugin.
|
||||
void loadFromPlugin(Plugin *p) const override;
|
||||
|
||||
/// handler for preparing to read in a chunk of XML from the cache, set up context to do this
|
||||
void beginXmlParsing(Plugin *p) override;
|
||||
|
||||
/// XML handler : element begins (everything is stored in elements and attributes)
|
||||
void xmlElementBegin(const std::string &el, std::map<std::string, std::string> map) override;
|
||||
|
||||
void xmlCharacterHandler(const std::string &) override;
|
||||
|
||||
void xmlElementEnd(const std::string &el) override;
|
||||
|
||||
void endXmlParsing() override;
|
||||
|
||||
void saveXML(Plugin *ip, std::ostream &os) const override;
|
||||
|
||||
void confirmPlugin(Plugin *p) override;
|
||||
|
||||
bool pluginSupported(Plugin *p, std::string &reason) const override;
|
||||
|
||||
Plugin *newPlugin(PluginBinary *pb,
|
||||
int pi,
|
||||
OfxPlugin *pl) override;
|
||||
|
||||
Plugin *newPlugin(PluginBinary *pb,
|
||||
int pi,
|
||||
const std::string &api,
|
||||
int apiVersion,
|
||||
const std::string &pluginId,
|
||||
const std::string &rawId,
|
||||
int pluginMajorVersion,
|
||||
int pluginMinorVersion) override;
|
||||
|
||||
void dumpToStdOut();
|
||||
};
|
||||
|
||||
} // ImageEffect
|
||||
|
||||
// Host
|
||||
|
||||
// OFX
|
||||
|
||||
#endif
|
||||
+278
@@ -0,0 +1,278 @@
|
||||
|
||||
|
||||
|
||||
#ifndef OFX_INTERACT_H
|
||||
#define OFX_INTERACT_H
|
||||
|
||||
#include "ofxInteract.h"
|
||||
#include "ofxOld.h" // old plugins may rely on deprecated properties being present
|
||||
#include "ofxhPropertySuite.h"
|
||||
|
||||
namespace OFX {
|
||||
|
||||
namespace Host {
|
||||
|
||||
namespace Interact {
|
||||
|
||||
/// fetch a versioned suite for our interact
|
||||
const void *GetSuite(int version);
|
||||
|
||||
class Base {
|
||||
public:
|
||||
virtual ~Base() {
|
||||
}
|
||||
|
||||
/// grab a handle on the parameter for passing to the C API
|
||||
OfxInteractHandle getHandle() {return (OfxInteractHandle)this;}
|
||||
|
||||
/// get the property handle for this instance/descriptor
|
||||
virtual OfxPropertySetHandle getPropHandle() = 0;
|
||||
};
|
||||
|
||||
/// state the interact can be in
|
||||
enum State {
|
||||
eUninitialised,
|
||||
eDescribed,
|
||||
eCreated,
|
||||
eFailed
|
||||
};
|
||||
|
||||
/// Descriptor for an interact. Interacts all share a single description
|
||||
class Descriptor : public Base {
|
||||
protected:
|
||||
Property::Set _properties; ///< its props
|
||||
State _state; ///< how is it feeling today
|
||||
OfxPluginEntryPoint *_entryPoint; ///< the entry point for this overlay
|
||||
|
||||
public:
|
||||
/// CTOR
|
||||
Descriptor();
|
||||
|
||||
/// dtor
|
||||
virtual ~Descriptor();
|
||||
|
||||
/// set the main entry points
|
||||
void setEntryPoint(OfxPluginEntryPoint *entryPoint) {_entryPoint = entryPoint;}
|
||||
|
||||
/// call describe on this descriptor, returns true if all went well
|
||||
bool describe(int bitDepthPerComponent, bool hasAlpha);
|
||||
|
||||
/// grab a handle on the properties of this parameter for the C api
|
||||
OfxPropertySetHandle getPropHandle() {return _properties.getHandle();}
|
||||
|
||||
/// get prop set
|
||||
const Property::Set &getProperties() const {return _properties;}
|
||||
|
||||
/// get a non const prop set
|
||||
Property::Set &getProperties() {return _properties;}
|
||||
|
||||
/// call the entry point with action and the given args
|
||||
OfxStatus callEntry(const char *action,
|
||||
void *handle,
|
||||
OfxPropertySetHandle inArgs,
|
||||
OfxPropertySetHandle outArgs);
|
||||
|
||||
/// what is it's state?
|
||||
State getState() const {return _state;}
|
||||
};
|
||||
|
||||
/// a generic interact, it doesn't belong to anything in particular
|
||||
/// we need to generify this slighty more and remove the renderscale args
|
||||
/// into a derived class, as they only belong to image effect plugins
|
||||
class Instance : public Base, protected Property::GetHook {
|
||||
protected:
|
||||
Descriptor &_descriptor; ///< who we are
|
||||
Property::Set _properties; ///< its props
|
||||
State _state; ///< how is it feeling today
|
||||
void *_effectInstance; ///< this is ugly, we need a base class to all plugin instances at some point.
|
||||
Property::Set _argProperties;
|
||||
|
||||
/// initialise the argument properties
|
||||
void initArgProp(OfxTime time,
|
||||
const OfxPointD &renderScale);
|
||||
|
||||
/// set pen props in the args
|
||||
void setPenArgProps(const OfxPointD &penPos,
|
||||
const OfxPointI &penPosViewport,
|
||||
double pressure);
|
||||
|
||||
/// set key args in the props
|
||||
void setKeyArgProps(int key,
|
||||
char* keyString);
|
||||
|
||||
public:
|
||||
Instance(Descriptor &desc, void *effectInstance);
|
||||
|
||||
virtual ~Instance();
|
||||
|
||||
/// what is it's state?
|
||||
State getState() const {return _state;}
|
||||
|
||||
/// grab a handle on the properties of this parameter for the C api
|
||||
OfxPropertySetHandle getPropHandle() {return _properties.getHandle();}
|
||||
|
||||
/// get prop set
|
||||
const Property::Set &getProperties() const {return _properties;}
|
||||
|
||||
/// call the entry point in the descriptor with action and the given args
|
||||
virtual OfxStatus callEntry(const char *action,
|
||||
Property::Set *inArgs);
|
||||
|
||||
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
|
||||
/// hooks to kOfxInteractPropViewportSize in the property set
|
||||
/// this is actually redundant and is to be deprecated
|
||||
virtual void getViewportSize(double &width, double &height) const = 0;
|
||||
#endif
|
||||
|
||||
// hooks to live kOfxInteractPropPixelScale in the property set
|
||||
virtual void getPixelScale(double& xScale, double& yScale) const = 0;
|
||||
|
||||
// hooks to kOfxInteractPropBackgroundColour in the property set
|
||||
virtual void getBackgroundColour(double &r, double &g, double &b) const = 0;
|
||||
|
||||
// hooks to kOfxInteractPropSuggestedColour and kOfxPropOverlayColour in the property set
|
||||
// return false if there is no color suggestion by the host.
|
||||
virtual bool getSuggestedColour(double &r, double &g, double &b) const = 0;
|
||||
|
||||
/// implement
|
||||
virtual OfxStatus swapBuffers() = 0;
|
||||
|
||||
/// implement this
|
||||
virtual OfxStatus redraw() = 0;
|
||||
|
||||
/// returns the params the interact uses
|
||||
virtual void getSlaveToParam(std::vector<std::string>& params) const;
|
||||
|
||||
// do nothing
|
||||
virtual int getDimension(const std::string &name) const;
|
||||
|
||||
// don't know what to do
|
||||
virtual void reset(const std::string &name);
|
||||
|
||||
/// the gethook virutals for pixel scale, background colour
|
||||
virtual double getDoubleProperty(const std::string &name, int index) const;
|
||||
|
||||
/// for pixel scale and background colour
|
||||
virtual void getDoublePropertyN(const std::string &name, double *first, int n) const;
|
||||
|
||||
/// call create instance
|
||||
virtual OfxStatus createInstanceAction();
|
||||
|
||||
// interact action - kOfxInteractActionDraw
|
||||
//
|
||||
// Params -
|
||||
//
|
||||
// time - the effect time at which changed occured
|
||||
// renderScale - the render scale
|
||||
virtual OfxStatus drawAction(OfxTime time, const OfxPointD &renderScale);
|
||||
|
||||
// interact action - kOfxInteractActionPenMotion
|
||||
//
|
||||
// Params -
|
||||
//
|
||||
// time - the effect time at which changed occured
|
||||
// renderScale - the render scale
|
||||
// penX - the X position
|
||||
// penY - the Y position
|
||||
// pressure - the pen pressue 0 to 1
|
||||
virtual OfxStatus penMotionAction(OfxTime time,
|
||||
const OfxPointD &renderScale,
|
||||
const OfxPointD &penPos,
|
||||
const OfxPointI &penPosViewport,
|
||||
double pressure);
|
||||
|
||||
// interact action - kOfxInteractActionPenUp
|
||||
//
|
||||
// Params -
|
||||
//
|
||||
// time - the effect time at which changed occured
|
||||
// renderScale - the render scale
|
||||
// penX - the X position
|
||||
// penY - the Y position
|
||||
// pressure - the pen pressue 0 to 1
|
||||
virtual OfxStatus penUpAction(OfxTime time,
|
||||
const OfxPointD &renderScale,
|
||||
const OfxPointD &penPos,
|
||||
const OfxPointI &penPosViewport,
|
||||
double pressure);
|
||||
|
||||
// interact action - kOfxInteractActionPenDown
|
||||
//
|
||||
// Params -
|
||||
//
|
||||
// time - the effect time at which changed occured
|
||||
// renderScale - the render scale
|
||||
// penX - the X position
|
||||
// penY - the Y position
|
||||
// pressure - the pen pressue 0 to 1
|
||||
virtual OfxStatus penDownAction(OfxTime time,
|
||||
const OfxPointD &renderScale,
|
||||
const OfxPointD &penPos,
|
||||
const OfxPointI &penPosViewport,
|
||||
double pressure);
|
||||
|
||||
// interact action - kOfxInteractActionkeyDown
|
||||
//
|
||||
// Params -
|
||||
//
|
||||
// time - the effect time at which changed occured
|
||||
// renderScale - the render scale
|
||||
// key - the pressed key
|
||||
// keyString - the pressed key string
|
||||
virtual OfxStatus keyDownAction(OfxTime time,
|
||||
const OfxPointD &renderScale,
|
||||
int key,
|
||||
char* keyString);
|
||||
|
||||
// interact action - kOfxInteractActionkeyUp
|
||||
//
|
||||
// Params -
|
||||
//
|
||||
// time - the effect time at which changed occured
|
||||
// renderScale - the render scale
|
||||
// key - the pressed key
|
||||
// keyString - the pressed key string
|
||||
virtual OfxStatus keyUpAction(OfxTime time,
|
||||
const OfxPointD &renderScale,
|
||||
int key,
|
||||
char* keyString);
|
||||
|
||||
// interact action - kOfxInteractActionkeyRepeat
|
||||
//
|
||||
// Params -
|
||||
//
|
||||
// time - the effect time at which changed occured
|
||||
// renderScale - the render scale
|
||||
// key - the pressed key
|
||||
// keyString - the pressed key string
|
||||
virtual OfxStatus keyRepeatAction(OfxTime time,
|
||||
const OfxPointD &renderScale,
|
||||
int key,
|
||||
char* keyString);
|
||||
|
||||
// interact action - kOfxInteractActionLoseFocus
|
||||
//
|
||||
// Params -
|
||||
//
|
||||
// time - the effect time at which changed occured
|
||||
// renderScale - the render scale
|
||||
virtual OfxStatus gainFocusAction(OfxTime time,
|
||||
const OfxPointD &renderScale);
|
||||
|
||||
// interact action - kOfxInteractActionLoseFocus
|
||||
//
|
||||
// Params -
|
||||
//
|
||||
// time - the effect time at which changed occured
|
||||
// renderScale - the render scale
|
||||
virtual OfxStatus loseFocusAction(OfxTime time,
|
||||
const OfxPointD &renderScale);
|
||||
};
|
||||
|
||||
} // Interact
|
||||
|
||||
} // Host
|
||||
|
||||
} // OFX
|
||||
|
||||
#endif // OFX_INTERACT_H
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
|
||||
|
||||
|
||||
#ifndef OFX_MEMORY_H
|
||||
#define OFX_MEMORY_H
|
||||
|
||||
#include "ofxImageEffect.h"
|
||||
namespace OFX {
|
||||
|
||||
namespace Host {
|
||||
|
||||
namespace Memory {
|
||||
|
||||
class Instance {
|
||||
public:
|
||||
Instance();
|
||||
|
||||
virtual ~Instance();
|
||||
virtual bool alloc(size_t nBytes);
|
||||
virtual OfxImageMemoryHandle getHandle();
|
||||
virtual void freeMem();
|
||||
virtual void* getPtr();
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
|
||||
virtual bool verifyMagic() { return true; }
|
||||
|
||||
protected:
|
||||
char* _ptr;
|
||||
int _locked;
|
||||
};
|
||||
|
||||
} // Memory
|
||||
|
||||
} // Host
|
||||
|
||||
} // OFX
|
||||
|
||||
#endif // OFX_MEMORY_H
|
||||
+678
@@ -0,0 +1,678 @@
|
||||
|
||||
|
||||
|
||||
#ifndef OFXH_PARAM_H
|
||||
#define OFXH_PARAM_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <cstdarg>
|
||||
|
||||
//ofx
|
||||
#include "ofxParam.h"
|
||||
|
||||
//ofxh
|
||||
#include "ofxhPropertySuite.h"
|
||||
|
||||
|
||||
namespace OFX {
|
||||
|
||||
namespace Host {
|
||||
|
||||
namespace Param {
|
||||
|
||||
/// fetch the param suite
|
||||
const void *GetSuite(int version);
|
||||
|
||||
bool isColourParam(const std::string ¶mType);
|
||||
|
||||
bool isIntParam(const std::string ¶mType);
|
||||
|
||||
/// is this a standard type
|
||||
bool isStandardType(const std::string &type);
|
||||
|
||||
/// base class for all params
|
||||
class Base {
|
||||
|
||||
private:
|
||||
Base();
|
||||
protected:
|
||||
std::string _paramName;
|
||||
std::string _paramType;
|
||||
Property::Set _properties;
|
||||
public:
|
||||
Base(const std::string &name, const std::string &type);
|
||||
Base(const std::string &name, const std::string &type, const Property::Set &properties);
|
||||
virtual ~Base();
|
||||
|
||||
/// grab a handle on the parameter for passing to the C API
|
||||
OfxParamHandle getHandle() const;
|
||||
|
||||
virtual bool verifyMagic() { return true; }
|
||||
|
||||
/// grab a handle on the properties of this parameter for the C api
|
||||
OfxPropertySetHandle getPropHandle() const;
|
||||
|
||||
const Property::Set &getProperties() const;
|
||||
|
||||
Property::Set &getProperties();
|
||||
|
||||
const std::string &getType() const;
|
||||
|
||||
const std::string &getName() const;
|
||||
|
||||
const std::string &getParentName() const;
|
||||
|
||||
const std::string &getLabel() const;
|
||||
|
||||
const std::string &getShortLabel() const;
|
||||
|
||||
const std::string &getLongLabel() const;
|
||||
|
||||
const std::string &getScriptName() const;
|
||||
|
||||
const std::string &getDoubleType() const;
|
||||
|
||||
const std::string &getDefaultCoordinateSystem() const;
|
||||
|
||||
const std::string &getCacheInvalidation() const;
|
||||
|
||||
const std::string &getHint() const;
|
||||
|
||||
bool getEnabled() const;
|
||||
|
||||
bool getCanUndo() const;
|
||||
|
||||
bool getSecret() const;
|
||||
|
||||
bool getIsPersistant() const;
|
||||
|
||||
bool getEvaluateOnChange() const;
|
||||
|
||||
bool getCanAnimate() const;
|
||||
};
|
||||
|
||||
/// the Descriptor of a plugin parameter
|
||||
class Descriptor : public Base {
|
||||
Descriptor();
|
||||
|
||||
public:
|
||||
/// make a parameter, with the given type and name
|
||||
Descriptor(const std::string &type, const std::string &name);
|
||||
|
||||
/// add standard param props, will call the below
|
||||
void addStandardParamProps(const std::string &type);
|
||||
|
||||
/// add standard properties to a params that can take an interact
|
||||
void addInteractParamProps(const std::string &type);
|
||||
|
||||
/// add standard properties to a value holding param
|
||||
void addValueParamProps(const std::string &type, Property::TypeEnum valueType, int dim);
|
||||
|
||||
/// add standard properties to a value holding param
|
||||
void addNumericParamProps(const std::string &type, Property::TypeEnum valueType, int dim);
|
||||
};
|
||||
|
||||
/// base class to the param set instance and param set descriptor
|
||||
class BaseSet {
|
||||
public:
|
||||
virtual ~BaseSet();
|
||||
|
||||
/// obtain a handle on this set for passing to the C api
|
||||
OfxParamSetHandle getParamSetHandle() const;
|
||||
|
||||
/// get the property handle that lives with the set
|
||||
/// The plugin descriptor/instance that derives from
|
||||
/// this will provide this.
|
||||
virtual Property::Set &getParamSetProps() = 0;
|
||||
};
|
||||
|
||||
/// a set of parameters
|
||||
class SetDescriptor : public BaseSet {
|
||||
std::map<std::string, Descriptor*> _paramMap;
|
||||
std::list<Descriptor *> _paramList;
|
||||
|
||||
/// CC doesn't exist
|
||||
SetDescriptor(const SetDescriptor &);
|
||||
|
||||
public:
|
||||
/// default ctor
|
||||
SetDescriptor();
|
||||
|
||||
/// dtor
|
||||
virtual ~SetDescriptor();
|
||||
|
||||
/// get the map of params
|
||||
const std::map<std::string, Descriptor*> &getParams() const;
|
||||
|
||||
/// get the list of params
|
||||
const std::list<Descriptor *> &getParamList() const;
|
||||
|
||||
/// define a param
|
||||
virtual Descriptor *paramDefine(const char *paramType,
|
||||
const char *name);
|
||||
|
||||
/// add a param in
|
||||
virtual void addParam(const std::string &name, Descriptor *p);
|
||||
};
|
||||
|
||||
// forward declare
|
||||
class SetInstance;
|
||||
|
||||
/// the description of a plugin parameter
|
||||
class Instance : public Base, protected Property::NotifyHook {
|
||||
Instance();
|
||||
protected:
|
||||
SetInstance* _paramSetInstance;
|
||||
Instance* _parentInstance;
|
||||
public:
|
||||
virtual ~Instance();
|
||||
|
||||
/// make a parameter, with the given type and name
|
||||
explicit Instance(Descriptor& descriptor, Param::SetInstance* instance = 0);
|
||||
|
||||
// OfxStatus instanceChangedAction(const std::string &why,
|
||||
// OfxTime time,
|
||||
// double renderScaleX,
|
||||
// double renderScaleY);
|
||||
|
||||
// get the param instance
|
||||
OFX::Host::Param::SetInstance* getParamSetInstance() { return _paramSetInstance; }
|
||||
|
||||
// set/get parent instance
|
||||
void setParentInstance(Instance* instance);
|
||||
Instance* getParentInstance();
|
||||
|
||||
// copy one parameter to another, with a range (NULL means to copy all animation)
|
||||
virtual OfxStatus copyFrom(const Instance &instance, OfxTime offset, const OfxRangeD* range);
|
||||
|
||||
// callback which should set enabled state as appropriate
|
||||
virtual void setEnabled();
|
||||
|
||||
// callback which should set secret state as appropriate
|
||||
virtual void setSecret();
|
||||
|
||||
/// callback which should update label
|
||||
virtual void setLabel();
|
||||
|
||||
/// callback which should set range
|
||||
virtual void setRange();
|
||||
|
||||
/// callback which should set display range
|
||||
virtual void setDisplayRange();
|
||||
|
||||
/// callback which should set evaluate on change
|
||||
virtual void setEvaluateOnChange();
|
||||
|
||||
// va list calls below turn the var args (oh what a mistake)
|
||||
// suite functions into virtual function calls on instances
|
||||
// they are not to be overridden by host implementors by
|
||||
// by the various typeed param instances so that they can
|
||||
// deconstruct the var args lists
|
||||
|
||||
/// get a value, implemented by instances to deconstruct var args
|
||||
virtual OfxStatus getV(va_list arg);
|
||||
|
||||
/// get a value, implemented by instances to deconstruct var args
|
||||
virtual OfxStatus getV(OfxTime time, va_list arg);
|
||||
|
||||
/// set a value, implemented by instances to deconstruct var args
|
||||
virtual OfxStatus setV(va_list arg);
|
||||
|
||||
/// key a value, implemented by instances to deconstruct var args
|
||||
virtual OfxStatus setV(OfxTime time, va_list arg);
|
||||
|
||||
/// derive a value, implemented by instances to deconstruct var args
|
||||
virtual OfxStatus deriveV(OfxTime time, va_list arg);
|
||||
|
||||
/// integrate a value, implemented by instances to deconstruct var args
|
||||
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
|
||||
|
||||
/// overridden from Property::NotifyHook
|
||||
virtual void notify(const std::string &name, bool single, int num);
|
||||
};
|
||||
|
||||
class KeyframeParam {
|
||||
public:
|
||||
virtual OfxStatus getNumKeys(unsigned int &nKeys) const ;
|
||||
virtual OfxStatus getKeyTime(int nth, OfxTime& time) const ;
|
||||
virtual OfxStatus getKeyIndex(OfxTime time, int direction, int & index) const ;
|
||||
virtual OfxStatus deleteKey(OfxTime time) ;
|
||||
virtual OfxStatus deleteAllKeys() ;
|
||||
|
||||
virtual ~KeyframeParam() {
|
||||
}
|
||||
};
|
||||
|
||||
class GroupInstance : public Instance {
|
||||
protected:
|
||||
std::vector<Param::Instance*> _children;
|
||||
public:
|
||||
GroupInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
|
||||
void setChildren(std::vector<Param::Instance*> children);
|
||||
const std::vector<Param::Instance*> &getChildren() const;
|
||||
};
|
||||
|
||||
class PageInstance : public Instance {
|
||||
public:
|
||||
PageInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
const std::map<int,Param::Instance*> &getChildren() const;
|
||||
protected :
|
||||
mutable std::map<int,Param::Instance*> _children; // if set in a notify hook, this need not be mutable
|
||||
};
|
||||
|
||||
class IntegerInstance : public Instance, public KeyframeParam {
|
||||
public:
|
||||
IntegerInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
|
||||
// Deriving implementatation needs to overide these
|
||||
virtual OfxStatus get(int&) = 0;
|
||||
virtual OfxStatus get(OfxTime time, int&) = 0;
|
||||
virtual OfxStatus set(int) = 0;
|
||||
virtual OfxStatus set(OfxTime time, int) = 0;
|
||||
|
||||
// probably derived class does not need to implement, default is an approximation
|
||||
virtual OfxStatus derive(OfxTime time, int&) ;
|
||||
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, int&) ;
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus deriveV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
|
||||
};
|
||||
|
||||
class ChoiceInstance : public Instance, public KeyframeParam {
|
||||
public:
|
||||
ChoiceInstance(Descriptor& descriptor, Param::SetInstance* instance = 0);
|
||||
|
||||
// callback which should set option as appropriate
|
||||
virtual void setOption(int num);
|
||||
|
||||
// Deriving implementatation needs to overide these
|
||||
virtual OfxStatus get(int&) = 0;
|
||||
virtual OfxStatus get(OfxTime time, int&) = 0;
|
||||
virtual OfxStatus set(int) = 0;
|
||||
virtual OfxStatus set(OfxTime time, int) = 0;
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(OfxTime time, va_list arg);
|
||||
|
||||
/// overridden from Instance
|
||||
virtual void notify(const std::string &name, bool single, int num);
|
||||
};
|
||||
|
||||
class DoubleInstance : public Instance, public KeyframeParam {
|
||||
public:
|
||||
DoubleInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
|
||||
// Deriving implementatation needs to overide these
|
||||
virtual OfxStatus get(double&) = 0;
|
||||
virtual OfxStatus get(OfxTime time, double&) = 0;
|
||||
virtual OfxStatus set(double) = 0;
|
||||
virtual OfxStatus set(OfxTime time, double) = 0;
|
||||
virtual OfxStatus derive(OfxTime time, double&) = 0;
|
||||
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, double&) = 0;
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus deriveV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
|
||||
};
|
||||
|
||||
class BooleanInstance : public Instance, public KeyframeParam {
|
||||
public:
|
||||
BooleanInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
|
||||
// Deriving implementatation needs to overide these
|
||||
virtual OfxStatus get(bool&) = 0;
|
||||
virtual OfxStatus get(OfxTime time, bool&) = 0;
|
||||
virtual OfxStatus set(bool) = 0;
|
||||
virtual OfxStatus set(OfxTime time, bool) = 0;
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(OfxTime time, va_list arg);
|
||||
};
|
||||
|
||||
class RGBAInstance : public Instance, public KeyframeParam {
|
||||
public:
|
||||
RGBAInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
|
||||
// Deriving implementatation needs to overide these
|
||||
virtual OfxStatus get(double&,double&,double&,double&) = 0;
|
||||
virtual OfxStatus get(OfxTime time, double&,double&,double&,double&) = 0;
|
||||
virtual OfxStatus set(double,double,double,double) = 0;
|
||||
virtual OfxStatus set(OfxTime time, double,double,double,double) = 0;
|
||||
|
||||
// derived class does not need to implement, default is an approximation
|
||||
virtual OfxStatus derive(OfxTime time, double&,double&,double&,double&) ;
|
||||
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, double&,double&,double&,double&) ;
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus deriveV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
|
||||
};
|
||||
|
||||
class RGBInstance : public Instance, public KeyframeParam {
|
||||
public:
|
||||
RGBInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
|
||||
// Deriving implementatation needs to overide these
|
||||
virtual OfxStatus get(double&,double&,double&) = 0;
|
||||
virtual OfxStatus get(OfxTime time, double&,double&,double&) = 0;
|
||||
virtual OfxStatus set(double,double,double) = 0;
|
||||
virtual OfxStatus set(OfxTime time, double,double,double) = 0;
|
||||
|
||||
// derived class does not need to implement, default is an approximation
|
||||
virtual OfxStatus derive(OfxTime time, double&,double&,double&) ;
|
||||
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, double&,double&,double&) ;
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus deriveV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
|
||||
};
|
||||
|
||||
class Double2DInstance : public Instance, public KeyframeParam {
|
||||
public:
|
||||
Double2DInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
|
||||
// Deriving implementatation needs to overide these
|
||||
virtual OfxStatus get(double&,double&) = 0;
|
||||
virtual OfxStatus get(OfxTime time, double&,double&) = 0;
|
||||
virtual OfxStatus set(double,double) = 0;
|
||||
virtual OfxStatus set(OfxTime time, double,double) = 0;
|
||||
|
||||
// derived class does not need to implement, default is an approximation
|
||||
virtual OfxStatus derive(OfxTime time, double&,double&) ;
|
||||
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, double&,double&) ;
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus deriveV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
|
||||
};
|
||||
|
||||
class Integer2DInstance : public Instance, public KeyframeParam {
|
||||
public:
|
||||
Integer2DInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
|
||||
// Deriving implementatation needs to overide these
|
||||
virtual OfxStatus get(int&,int&) = 0;
|
||||
virtual OfxStatus get(OfxTime time, int&,int&) = 0;
|
||||
virtual OfxStatus set(int,int) = 0;
|
||||
virtual OfxStatus set(OfxTime time, int,int) = 0;
|
||||
|
||||
// derived class does not need to implement, default is an approximation
|
||||
virtual OfxStatus derive(OfxTime time, int&,int&) ;
|
||||
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, int&,int&) ;
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus deriveV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
|
||||
};
|
||||
|
||||
class Double3DInstance : public Instance , public KeyframeParam{
|
||||
public:
|
||||
Double3DInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
|
||||
// Deriving implementatation needs to overide these
|
||||
virtual OfxStatus get(double&,double&,double&) = 0;
|
||||
virtual OfxStatus get(OfxTime time, double&,double&,double&) = 0;
|
||||
virtual OfxStatus set(double,double,double) = 0;
|
||||
virtual OfxStatus set(OfxTime time, double,double,double) = 0;
|
||||
|
||||
// derived class does not need to implement, default is an approximation
|
||||
virtual OfxStatus derive(OfxTime time, double&,double&,double&) ;
|
||||
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, double&,double&,double&) ;
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus deriveV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
|
||||
};
|
||||
|
||||
class Integer3DInstance : public Instance, public KeyframeParam {
|
||||
public:
|
||||
Integer3DInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
|
||||
virtual OfxStatus get(int&,int&,int&) = 0;
|
||||
virtual OfxStatus get(OfxTime time, int&,int&,int&) = 0;
|
||||
virtual OfxStatus set(int,int,int) = 0;
|
||||
virtual OfxStatus set(OfxTime time, int,int,int) = 0;
|
||||
|
||||
// derived class does not need to implement, default is an approximation
|
||||
virtual OfxStatus derive(OfxTime time, int&,int&,int&) ;
|
||||
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, int&,int&,int&) ;
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus getV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus deriveV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
|
||||
};
|
||||
|
||||
class StringInstance : public Instance, public KeyframeParam {
|
||||
std::string _returnValue; ///< location to hold temporary return value. Should delegate this to implementation!!!
|
||||
public:
|
||||
StringInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
|
||||
virtual OfxStatus get(std::string &) = 0;
|
||||
virtual OfxStatus get(OfxTime time, std::string &) = 0;
|
||||
virtual OfxStatus set(const char*) = 0;
|
||||
virtual OfxStatus set(OfxTime time, const char*) = 0;
|
||||
|
||||
/// implementation of var args function
|
||||
/// Be careful: the char* is only valid until next API call
|
||||
/// see http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#ArchitectureStrings
|
||||
virtual OfxStatus getV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
/// Be careful: the char* is only valid until next API call
|
||||
/// see http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#ArchitectureStrings
|
||||
virtual OfxStatus getV(OfxTime time, va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(va_list arg);
|
||||
|
||||
/// implementation of var args function
|
||||
virtual OfxStatus setV(OfxTime time, va_list arg);
|
||||
};
|
||||
|
||||
class CustomInstance : public StringInstance {
|
||||
public:
|
||||
CustomInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : StringInstance(descriptor,instance) {}
|
||||
};
|
||||
|
||||
class PushbuttonInstance : public Instance, public KeyframeParam {
|
||||
public:
|
||||
PushbuttonInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
|
||||
};
|
||||
|
||||
/// A set of parameters
|
||||
///
|
||||
/// As we are the owning object we delete the params inside ourselves. It was tempting
|
||||
/// to make params autoref objects and have shared ownership with the client code
|
||||
/// but that adds complexity for no strong gain.
|
||||
class SetInstance : public BaseSet {
|
||||
protected:
|
||||
std::map<std::string, Instance*> _params; ///< params by name
|
||||
std::list<Instance *> _paramList; ///< params list
|
||||
|
||||
public :
|
||||
/// ctor
|
||||
///
|
||||
/// The propery set being passed in belongs to the owning
|
||||
/// plugin instance.
|
||||
explicit SetInstance();
|
||||
|
||||
/// dtor.
|
||||
virtual ~SetInstance();
|
||||
|
||||
/// get the params
|
||||
const std::map<std::string, Instance*> &getParams() const;
|
||||
|
||||
/// get the params
|
||||
const std::list<Instance*> &getParamList() const;
|
||||
|
||||
// get the param
|
||||
Instance* getParam(const std::string &name) const {
|
||||
std::map<std::string,Instance*>::const_iterator it = _params.find(name);
|
||||
if(it!=_params.end())
|
||||
return it->second;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// The inheriting plugin instance needs to set this up to deal with
|
||||
/// plug-ins changing their own values.
|
||||
virtual void paramChangedByPlugin(Param::Instance *param) = 0;
|
||||
|
||||
/// add a param
|
||||
virtual OfxStatus addParam(const std::string& name, Instance* instance);
|
||||
|
||||
/// make a parameter instance
|
||||
///
|
||||
/// Client host code needs to implement this
|
||||
virtual Instance* newParam(const std::string& name, Descriptor& Descriptor) = 0;
|
||||
|
||||
/// Triggered when the plug-in calls OfxParameterSuiteV1::paramEditBegin
|
||||
///
|
||||
/// Client host code needs to implement this
|
||||
virtual OfxStatus editBegin(const std::string& name) = 0;
|
||||
|
||||
/// Triggered when the plug-in calls OfxParameterSuiteV1::paramEditEnd
|
||||
///
|
||||
/// Client host code needs to implement this
|
||||
virtual OfxStatus editEnd() = 0;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OFXH_PARAM_H
|
||||
@@ -0,0 +1,87 @@
|
||||
|
||||
|
||||
#ifndef OFX_PLUGIN_API_CACHE
|
||||
#define OFX_PLUGIN_API_CACHE
|
||||
|
||||
// Copyright OpenFX and contributors to the OpenFX project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <map>
|
||||
|
||||
#include "ofxhPropertySuite.h"
|
||||
|
||||
namespace OFX
|
||||
{
|
||||
namespace Host {
|
||||
class Plugin;
|
||||
class PluginBinary;
|
||||
class PluginCache;
|
||||
|
||||
namespace ImageEffect {
|
||||
class ImageEffectDescriptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace OFX
|
||||
{
|
||||
namespace Host
|
||||
{
|
||||
namespace APICache {
|
||||
|
||||
/// this acts as an interface for the Plugin Cache, handling api-specific cacheing
|
||||
class PluginAPICacheI
|
||||
{
|
||||
protected:
|
||||
std::string _apiName;
|
||||
int _apiVersionMin, _apiVersionMax;
|
||||
public:
|
||||
PluginAPICacheI(const std::string &apiName, int verMin, int verMax)
|
||||
: _apiName(apiName)
|
||||
, _apiVersionMin(verMin)
|
||||
, _apiVersionMax(verMax)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~PluginAPICacheI() {}
|
||||
|
||||
virtual void loadFromPlugin(Plugin *) const = 0;
|
||||
|
||||
/// factory method, to create a new plugin (from binary)
|
||||
virtual Plugin *newPlugin(PluginBinary *, int pi, OfxPlugin *plug) = 0;
|
||||
|
||||
/// factory method, to create a new plugin (from the
|
||||
virtual Plugin *newPlugin(PluginBinary *pb, int pi, const std::string &api, int apiVersion, const std::string &pluginId,
|
||||
const std::string &rawId, int pluginMajorVersion, int pluginMinorVersion) = 0;
|
||||
|
||||
virtual void beginXmlParsing(Plugin *) = 0;
|
||||
virtual void xmlElementBegin(const std::string &, std::map<std::string, std::string>) = 0;
|
||||
virtual void xmlCharacterHandler(const std::string &) = 0;
|
||||
virtual void xmlElementEnd(const std::string &) = 0;
|
||||
virtual void endXmlParsing() = 0;
|
||||
|
||||
virtual void saveXML(Plugin *, std::ostream &) const = 0;
|
||||
|
||||
virtual void confirmPlugin(Plugin *) = 0;
|
||||
|
||||
virtual bool pluginSupported(Plugin *, std::string &reason) const = 0;
|
||||
|
||||
void registerInCache(OFX::Host::PluginCache &pluginCache);
|
||||
};
|
||||
|
||||
/// helper function to build a property set from XML. Really should be a member of the property set!!!
|
||||
void propertySetXMLRead(const std::string &el, std::map<std::string, std::string> map, Property::Set &set, Property::Property*&);
|
||||
|
||||
/// helper function to write a property set to XML. Really should be a member of the property set!!!
|
||||
void propertySetXMLWrite(std::ostream &o, const Property::Set &set, int indent=0);
|
||||
|
||||
/// helper function to write a single property from a set to XML. Really should be a member of the property set!!!
|
||||
void propertyXMLWrite(std::ostream &o, const Property::Set &set, const std::string &name, int indent=0);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,432 @@
|
||||
|
||||
|
||||
#ifndef OFX_PLUGIN_CACHE_H
|
||||
#define OFX_PLUGIN_CACHE_H
|
||||
|
||||
// Copyright OpenFX and contributors to the OpenFX project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "expat.h"
|
||||
|
||||
#include "ofxCore.h"
|
||||
#include "ofxhPropertySuite.h"
|
||||
#include "ofxhPluginAPICache.h"
|
||||
#include "ofxhBinary.h"
|
||||
|
||||
namespace OFX {
|
||||
|
||||
namespace Host {
|
||||
|
||||
class Host;
|
||||
|
||||
// forward delcarations
|
||||
class PluginDesc;
|
||||
class Plugin;
|
||||
class PluginBinary;
|
||||
class PluginCache;
|
||||
|
||||
/// C++ version of the information kept inside an OfxPlugin struct
|
||||
class PluginDesc {
|
||||
protected :
|
||||
std::string _pluginApi; ///< the API I implement
|
||||
int _apiVersion; ///< the version of the API
|
||||
|
||||
std::string _identifier; ///< the identifier of the plugin
|
||||
std::string _rawIdentifier; ///< the original identifier of the plugin
|
||||
int _versionMajor; ///< the plugin major version
|
||||
int _versionMinor; ///< the plugin minor version
|
||||
|
||||
public:
|
||||
|
||||
const std::string &getPluginApi() const {
|
||||
return _pluginApi;
|
||||
}
|
||||
|
||||
int getApiVersion() const {
|
||||
return _apiVersion;
|
||||
}
|
||||
|
||||
const std::string &getIdentifier() const {
|
||||
return _identifier;
|
||||
}
|
||||
|
||||
const std::string &getRawIdentifier() const {
|
||||
return _rawIdentifier;
|
||||
}
|
||||
|
||||
int getVersionMajor() const {
|
||||
return _versionMajor;
|
||||
}
|
||||
|
||||
int getVersionMinor() const {
|
||||
return _versionMinor;
|
||||
}
|
||||
|
||||
PluginDesc() : _apiVersion(-1) {
|
||||
}
|
||||
|
||||
virtual ~PluginDesc() {}
|
||||
|
||||
PluginDesc(const std::string &api,
|
||||
int apiVersion,
|
||||
const std::string &identifier,
|
||||
const std::string &rawIdentifier,
|
||||
int versionMajor,
|
||||
int versionMinor)
|
||||
: _pluginApi(api)
|
||||
, _apiVersion(apiVersion)
|
||||
, _identifier(identifier)
|
||||
, _rawIdentifier(rawIdentifier)
|
||||
, _versionMajor(versionMajor)
|
||||
, _versionMinor(versionMinor)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// constructor for the case where we have already loaded the plugin binary and
|
||||
/// are populating this object from it
|
||||
PluginDesc(OfxPlugin *ofxPlugin) {
|
||||
_pluginApi = ofxPlugin->pluginApi;
|
||||
_apiVersion = ofxPlugin->apiVersion;
|
||||
_rawIdentifier = ofxPlugin->pluginIdentifier;
|
||||
_identifier = ofxPlugin->pluginIdentifier;
|
||||
|
||||
// Who says the pluginIdentifier is case-insensitive? OFX 1.3 spec doesn't mention this.
|
||||
// http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#id472588
|
||||
//for (size_t i=0;i<_identifier.size();i++) {
|
||||
// _identifier[i] = tolower(_identifier[i]);
|
||||
//}
|
||||
_versionMajor = ofxPlugin->pluginVersionMajor;
|
||||
_versionMinor = ofxPlugin->pluginVersionMinor;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// class that we use to manipulate a plugin
|
||||
class Plugin : public PluginDesc {
|
||||
/// owned by the PluginBinary it lives inside
|
||||
/// Plugins can only be pass about either by pointer or reference
|
||||
private :
|
||||
Plugin(const Plugin&) : PluginDesc() {} ///< hidden
|
||||
Plugin &operator= (const Plugin&) {return *this;} ///< hidden
|
||||
|
||||
protected :
|
||||
PluginBinary *_binary; ///< the file I live inside
|
||||
int _index; ///< where I live inside that file
|
||||
public :
|
||||
Plugin();
|
||||
|
||||
PluginBinary *getBinary()
|
||||
{
|
||||
return _binary;
|
||||
}
|
||||
|
||||
const PluginBinary *getBinary() const
|
||||
{
|
||||
return _binary;
|
||||
}
|
||||
|
||||
int getIndex() const
|
||||
{
|
||||
return _index;
|
||||
}
|
||||
|
||||
/// construct this based on the struct returned by the getNthPlugin() in the binary
|
||||
Plugin(PluginBinary *bin, int idx, OfxPlugin *o) : PluginDesc(o), _binary(bin), _index(idx)
|
||||
{
|
||||
}
|
||||
|
||||
/// construct me from the cache
|
||||
Plugin(PluginBinary *bin, int idx, const std::string &api,
|
||||
int apiVersion, const std::string &identifier,
|
||||
const std::string &rawIdentifier,
|
||||
int majorVersion, int minorVersion)
|
||||
: PluginDesc(api, apiVersion, identifier, rawIdentifier, majorVersion, minorVersion)
|
||||
, _binary(bin)
|
||||
, _index(idx)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Plugin() {
|
||||
}
|
||||
|
||||
virtual APICache::PluginAPICacheI &getApiHandler() = 0;
|
||||
|
||||
bool trumps(Plugin *other) {
|
||||
int myMajor = getVersionMajor();
|
||||
int theirMajor = other->getVersionMajor();
|
||||
|
||||
int myMinor = getVersionMinor();
|
||||
int theirMinor = other->getVersionMinor();
|
||||
|
||||
if (myMajor > theirMajor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (myMajor == theirMajor && myMinor > theirMinor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class PluginHandle;
|
||||
|
||||
/// class that represents a binary file which holds plugins
|
||||
class PluginBinary {
|
||||
/// has a set of plugins inside it and which it owns
|
||||
/// These are owned by a PluginCache
|
||||
friend class PluginHandle;
|
||||
|
||||
protected :
|
||||
Binary _binary; ///< our binary object, abstracted layer ontop of OS calls, defined in ofxhBinary.h
|
||||
std::string _filePath; ///< full path to the file
|
||||
std::string _bundlePath; ///< path to the .bundle directory
|
||||
std::vector<Plugin *> _plugins; ///< my plugins
|
||||
time_t _fileModificationTime; ///< used as a time stamp to check modification times, used for caching
|
||||
off_t _fileSize; ///< file size last time we check, used for caching
|
||||
bool _binaryChanged; ///< whether the timestamp/filesize in this cache is different from that in the actual binary
|
||||
|
||||
public :
|
||||
|
||||
/// create one from the cache. this will invoke the Binary() constructor which
|
||||
/// will stat() the file.
|
||||
explicit PluginBinary(const std::string &file, const std::string &bundlePath, time_t mtime, off_t size)
|
||||
: _binary(file)
|
||||
, _filePath(file)
|
||||
, _bundlePath(bundlePath)
|
||||
, _fileModificationTime(mtime)
|
||||
, _fileSize(size)
|
||||
, _binaryChanged(false)
|
||||
{
|
||||
if (isInvalid()) {
|
||||
return;
|
||||
}
|
||||
if (_fileModificationTime != _binary.getTime() || _fileSize != _binary.getSize()) {
|
||||
_binaryChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// constructor which will open a library file, call things inside it, and then
|
||||
/// create Plugin objects as appropriate for the plugins exported therefrom
|
||||
explicit PluginBinary(const std::string &file, const std::string &bundlePath, PluginCache *cache)
|
||||
: _binary(file)
|
||||
, _filePath(file)
|
||||
, _bundlePath(bundlePath)
|
||||
, _binaryChanged(false)
|
||||
{
|
||||
loadPluginInfo(cache);
|
||||
}
|
||||
|
||||
/// dtor
|
||||
virtual ~PluginBinary();
|
||||
|
||||
|
||||
time_t getFileModificationTime() const {
|
||||
return _fileModificationTime;
|
||||
}
|
||||
|
||||
off_t getFileSize() {
|
||||
return _fileSize;
|
||||
}
|
||||
|
||||
const std::string &getFilePath() const {
|
||||
return _filePath;
|
||||
}
|
||||
|
||||
const std::string &getBundlePath() const {
|
||||
return _bundlePath;
|
||||
}
|
||||
|
||||
bool hasBinaryChanged() const {
|
||||
return _binaryChanged;
|
||||
}
|
||||
|
||||
bool isLoaded() const {
|
||||
return _binary.isLoaded();
|
||||
}
|
||||
|
||||
bool isInvalid() const {
|
||||
return _binary.isInvalid();
|
||||
}
|
||||
|
||||
void addPlugin(Plugin *pe) {
|
||||
_plugins.push_back(pe);
|
||||
}
|
||||
|
||||
void loadPluginInfo(PluginCache *);
|
||||
|
||||
/// how many plugins?
|
||||
int getNPlugins() const {return (int)_plugins.size(); }
|
||||
|
||||
/// get a plugin
|
||||
Plugin &getPlugin(int idx) {return *_plugins[idx];}
|
||||
|
||||
/// get a plugin
|
||||
const Plugin &getPlugin(int idx) const {return *_plugins[idx];}
|
||||
};
|
||||
|
||||
/// wrapper class for Plugin/PluginBinary. use in a RAIA fashion to make sure the binary gets unloaded when needed and not before.
|
||||
class PluginHandle {
|
||||
PluginBinary *_b;
|
||||
OfxPlugin *_op;
|
||||
|
||||
public:
|
||||
PluginHandle(Plugin *p, OFX::Host::Host *_host);
|
||||
virtual ~PluginHandle();
|
||||
|
||||
OfxPlugin *getOfxPlugin() {
|
||||
return _op;
|
||||
}
|
||||
|
||||
OfxPlugin *operator->() {
|
||||
return _op;
|
||||
}
|
||||
};
|
||||
|
||||
/// for later
|
||||
struct PluginCacheSupportedApi {
|
||||
std::string api;
|
||||
int minVersion;
|
||||
int maxVersion;
|
||||
APICache::PluginAPICacheI *handler;
|
||||
|
||||
PluginCacheSupportedApi(const std::string &_api, int _minVersion, int _maxVersion, APICache::PluginAPICacheI *_handler) :
|
||||
api(_api), minVersion(_minVersion), maxVersion(_maxVersion), handler(_handler)
|
||||
{
|
||||
}
|
||||
|
||||
bool matches(const std::string &_api, int _version) const
|
||||
{
|
||||
if (_api == api && _version >= minVersion && _version <= maxVersion) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/// Where we keep our plugins.
|
||||
class PluginCache {
|
||||
protected :
|
||||
OFX::Host::Property::PropSpec* _hostSpec;
|
||||
|
||||
std::list<std::string> _pluginPath; ///< list of directories to look in
|
||||
std::set<std::string> _nonrecursePath; ///< list of directories to look in (non-recursively)
|
||||
std::list<std::string> _pluginDirs; ///< list of directories we found
|
||||
std::list<PluginBinary *> _binaries; ///< all the binaries we know about, we own these
|
||||
std::list<Plugin *> _plugins; ///< all the plugins inside the binaries, we don't own these, populated from _binaries
|
||||
std::set<std::string> _knownBinFiles;
|
||||
|
||||
PluginBinary *_xmlCurrentBinary;
|
||||
Plugin *_xmlCurrentPlugin;
|
||||
|
||||
std::list<PluginCacheSupportedApi> _apiHandlers;
|
||||
|
||||
void scanDirectory(std::set<std::string> &foundBinFiles, const std::string &dir, bool recurse);
|
||||
|
||||
bool _ignoreCache;
|
||||
std::string _cacheVersion;
|
||||
|
||||
bool _dirty;
|
||||
bool _enablePluginSeek; ///< Turn off to make all seekPluginFile() calls return an empty string
|
||||
|
||||
static PluginCache* gPluginCachePtr; ///< singleton plugin cache
|
||||
|
||||
public:
|
||||
/// ctor, which inits _pluginPath to default locations and not much else
|
||||
PluginCache();
|
||||
|
||||
/// dtor
|
||||
~PluginCache();
|
||||
|
||||
/// get our plugin cache
|
||||
static PluginCache* getPluginCache();
|
||||
|
||||
/// clear our plugin cache
|
||||
static void clearPluginCache();
|
||||
|
||||
/// get the list in which plugins are sought
|
||||
const std::list<std::string> &getPluginPath() {
|
||||
return _pluginPath;
|
||||
}
|
||||
|
||||
/// was the cache outdated?
|
||||
bool dirty() const {
|
||||
return _dirty;
|
||||
}
|
||||
|
||||
/// add a file to the plugin path
|
||||
void addFileToPath(const std::string &f, bool recurse=true) {
|
||||
_pluginPath.push_back(f);
|
||||
if (!recurse) {
|
||||
_nonrecursePath.insert(f);
|
||||
}
|
||||
}
|
||||
|
||||
/// prepend a file to the plugin path
|
||||
void prependFileToPath(const std::string &f, bool recurse=true) {
|
||||
_pluginPath.push_front(f);
|
||||
if (!recurse) {
|
||||
_nonrecursePath.insert(f);
|
||||
}
|
||||
}
|
||||
|
||||
/// specify which subdirectory of /usr/OFX or equivilant
|
||||
/// (as well as 'Plugins') to look in for plugins.
|
||||
void setPluginHostPath(const std::string &hostId);
|
||||
|
||||
/// set the version string to write to the cache,
|
||||
/// and also that we expect on cachess read in
|
||||
void setCacheVersion(const std::string &cacheVersion) {
|
||||
_cacheVersion = cacheVersion;
|
||||
}
|
||||
|
||||
// populate the cache. must call scanPluginFiles() after to check for changes.
|
||||
void readCache(std::istream &is);
|
||||
|
||||
// seek a particular file on the OFX plugin path
|
||||
std::string seekPluginFile(const std::string &baseName) const;
|
||||
|
||||
/// Sets behaviour of seekPluginFile().
|
||||
/// Enable (the default): normal operation; disable: returns an empty string instead
|
||||
void setPluginSeekEnabled(bool enabled) { _enablePluginSeek = enabled; }
|
||||
|
||||
/// scan for plugins
|
||||
void scanPluginFiles();
|
||||
|
||||
// write the plugin cache output file to the given stream
|
||||
void writePluginCache(std::ostream &os) const;
|
||||
|
||||
// callback function for the XML
|
||||
void elementBeginCallback(void *userData, const XML_Char *name, const XML_Char **attrs);
|
||||
void elementCharCallback(void *userData, const XML_Char *data, int len);
|
||||
void elementEndCallback(void *userData, const XML_Char *name);
|
||||
|
||||
/// register an API cache handler
|
||||
void registerAPICache(const std::string &api, int min, int max, APICache::PluginAPICacheI *apiCache) {
|
||||
_apiHandlers.push_back(PluginCacheSupportedApi(api, min, max, apiCache));
|
||||
}
|
||||
|
||||
/// find the API cache handler for the given api/apiverson
|
||||
APICache::PluginAPICacheI* findApiHandler(const std::string &api, int apiver);
|
||||
|
||||
/// obtain a list of plugins to walk through
|
||||
const std::list<Plugin *> &getPlugins() const {
|
||||
return _plugins;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
|
||||
|
||||
#ifndef _ofxhProgress_h_
|
||||
#define _ofxhProgress_h_
|
||||
|
||||
#include "ofxProgress.h"
|
||||
|
||||
namespace OFX {
|
||||
namespace Host {
|
||||
namespace Progress {
|
||||
|
||||
/// Things that display progress derive from this ABC and implement the following
|
||||
/// functions.
|
||||
class ProgressI {
|
||||
public :
|
||||
virtual ~ProgressI() {}
|
||||
|
||||
/// Start doing progress.
|
||||
virtual void progressStart(const std::string &message, const std::string &messageid) = 0;
|
||||
|
||||
/// finish yer progress
|
||||
virtual void progressEnd() = 0;
|
||||
|
||||
/// set the progress to some level of completion, returns
|
||||
/// false if you should abandon processing, true to continue
|
||||
virtual bool progressUpdate(double t) = 0;
|
||||
};
|
||||
|
||||
} // namespace progress
|
||||
} // namespace Host
|
||||
} // namespace OFX
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,545 @@
|
||||
|
||||
|
||||
#ifndef OFX_PROPERTY_SUITE_H
|
||||
#define OFX_PROPERTY_SUITE_H
|
||||
#include "ofxCore.h"
|
||||
// Copyright OpenFX and contributors to the OpenFX project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
namespace OFX {
|
||||
namespace Host {
|
||||
namespace Property {
|
||||
/// simple function to turn a thing into a std string
|
||||
template<class T> inline std::string castToString(T i) {
|
||||
std::ostringstream o;
|
||||
o << i;
|
||||
return o.str();
|
||||
}
|
||||
|
||||
/// simple function to turn a string into an int
|
||||
inline int stringToInt(const std::string &s) {
|
||||
std::istringstream is(s);
|
||||
int number;
|
||||
is >> number;
|
||||
return number;
|
||||
}
|
||||
|
||||
/// simple function to turn a string into a double
|
||||
inline double stringToDouble(const std::string &s) {
|
||||
std::istringstream is(s);
|
||||
double number;
|
||||
is >> number;
|
||||
return number;
|
||||
}
|
||||
|
||||
// forward declarations
|
||||
class Property;
|
||||
class Set;
|
||||
|
||||
/// exception, representing an OfxStatus
|
||||
class Exception {
|
||||
OfxStatus _stat;
|
||||
|
||||
public:
|
||||
/// ctor
|
||||
Exception(OfxStatus stat) : _stat(stat)
|
||||
{
|
||||
}
|
||||
|
||||
/// get the status
|
||||
OfxStatus getStatus() const
|
||||
{
|
||||
return _stat;
|
||||
}
|
||||
};
|
||||
|
||||
/// type of a property
|
||||
enum TypeEnum {
|
||||
eNone = -1,
|
||||
eInt = 0,
|
||||
eDouble = 1,
|
||||
eString = 2,
|
||||
ePointer = 3
|
||||
};
|
||||
|
||||
/// type holder, for integers, used to template up int properties
|
||||
struct IntValue {
|
||||
typedef int APIType; ///< C type of the property that is passed across the raw API
|
||||
typedef int APITypeConstless; ///< C type of the property that is passed across the raw API, without any const it
|
||||
typedef int Type; ///< Type we actually hold and deal with the propery in everything by the raw API
|
||||
typedef int ReturnType; ///< type to return from a function call
|
||||
static const TypeEnum typeCode = eInt;
|
||||
static int kEmpty;
|
||||
};
|
||||
|
||||
/// type holder, for doubles, used to template up double properties
|
||||
struct DoubleValue {
|
||||
typedef double APIType;
|
||||
typedef double APITypeConstless;
|
||||
typedef double Type;
|
||||
typedef double ReturnType; ///< type to return from a function call
|
||||
static const TypeEnum typeCode = eDouble;
|
||||
static double kEmpty;
|
||||
};
|
||||
|
||||
/// type holder, for pointers, used to template up pointer properties
|
||||
struct PointerValue {
|
||||
typedef void *APIType;
|
||||
typedef void *APITypeConstless;
|
||||
typedef void *Type;
|
||||
typedef void *ReturnType; ///< type to return from a function call
|
||||
static const TypeEnum typeCode = ePointer;
|
||||
static void *kEmpty;
|
||||
};
|
||||
|
||||
/// type holder, for strings, used to template up string properties
|
||||
struct StringValue {
|
||||
typedef const char *APIType;
|
||||
typedef char *APITypeConstless;
|
||||
typedef std::string Type;
|
||||
typedef const std::string &ReturnType; ///< type to return from a function call
|
||||
static const TypeEnum typeCode = eString;
|
||||
static std::string kEmpty;
|
||||
};
|
||||
|
||||
/// array representing the names of the various types, in order of TypeEnum
|
||||
extern const char *gTypeNames[];
|
||||
|
||||
/// Sits on a property and can override the local property value when a value is being fetched
|
||||
/// only one of these can be in any property (as the thing has only a single value).
|
||||
class GetHook {
|
||||
public :
|
||||
/// dtor
|
||||
virtual ~GetHook()
|
||||
{
|
||||
}
|
||||
|
||||
/// We specialise this to do some magic so that it calls get string/int/double/pointer appropriately
|
||||
/// this is what is called by the propertytemplate code to fetch values out of a hook.
|
||||
template<class T> typename T::ReturnType getProperty(const std::string &name, int index=0) const;
|
||||
|
||||
/// We specialise this to do some magic so that it calls get int/double/pointer appropriately
|
||||
/// this is what is called by the propertytemplate code to fetch values out of a hook.
|
||||
template<class T> void getPropertyN(const std::string &name, typename T::APIType *values, int count) const;
|
||||
|
||||
/// override this to fetch a single value at the given index.
|
||||
virtual const std::string& getStringProperty(const std::string &name, int index = 0) const;
|
||||
|
||||
/// override this to fetch a multiple values in a multi-dimension property
|
||||
virtual void getStringPropertyN(const std::string &name, const char** values, int count) const;
|
||||
|
||||
/// override this to fetch a single value at the given index.
|
||||
virtual int getIntProperty(const std::string &name, int index = 0) const;
|
||||
|
||||
/// override this to fetch a multiple values in a multi-dimension property
|
||||
virtual void getIntPropertyN(const std::string &name, int *values, int count) const;
|
||||
|
||||
/// override this to fetch a single value at the given index.
|
||||
virtual double getDoubleProperty(const std::string &name, int index = 0) const;
|
||||
|
||||
/// override this to fetch a multiple values in a multi-dimension property
|
||||
virtual void getDoublePropertyN(const std::string &name, double *values, int count) const;
|
||||
|
||||
/// override this to fetch a single value at the given index.
|
||||
virtual void *getPointerProperty(const std::string &name, int index = 0) const;
|
||||
|
||||
/// override this to fetch a multiple values in a multi-dimension property
|
||||
virtual void getPointerPropertyN(const std::string &name, void **values, int count) const;
|
||||
|
||||
/// override this to fetch the dimension size.
|
||||
virtual int getDimension(const std::string &name) const;
|
||||
|
||||
/// override this to handle a reset().
|
||||
virtual void reset(const std::string &name);
|
||||
};
|
||||
|
||||
/// Sits on a property and is called when the local property is being set.
|
||||
/// It notify or notifyN is called whenever the plugin sets a property
|
||||
/// Many of these can sit on a property, as various objects will need to know when a property
|
||||
/// has been changed. On notification you should fetch properties with a 'raw' call, rather
|
||||
/// than the standard calls, as you may be fetching through a getHook and you won't see
|
||||
/// the local value that has been shoved into the property.
|
||||
class NotifyHook {
|
||||
public :
|
||||
/// dtor
|
||||
virtual ~NotifyHook() {}
|
||||
|
||||
/// override this to be notified when a property changes
|
||||
/// \arg name is the name of the property just set
|
||||
/// \arg singleValue is whether setProperty on a single index was call, otherwise N properties were set
|
||||
/// \arg indexOrN is the index if single value is true, or the count if singleValue is false
|
||||
virtual void notify(const std::string &name, bool singleValue, int indexOrN) = 0;
|
||||
};
|
||||
|
||||
/// base class for all properties
|
||||
class Property {
|
||||
protected :
|
||||
std::string _name; ///< name of this property
|
||||
TypeEnum _type; ///< type of this property
|
||||
int _dimension; ///< the fixed dimension of this property
|
||||
bool _pluginReadOnly; ///< set is forbidden through suite: value may still change between get() calls
|
||||
std::vector<NotifyHook *> _notifyHooks; ///< hooks to call whenever the property is set
|
||||
GetHook *_getHook; ///< if we are not storing props locally, they are stored via fetching from here
|
||||
|
||||
friend class Set;
|
||||
public :
|
||||
/// ctor
|
||||
Property(const std::string &name,
|
||||
TypeEnum type,
|
||||
int dimension = 1,
|
||||
bool pluginReadOnly=false);
|
||||
|
||||
/// copy ctor
|
||||
Property(const Property &other);
|
||||
|
||||
/// dtor
|
||||
virtual ~Property()
|
||||
{
|
||||
}
|
||||
|
||||
/// is it read only?
|
||||
bool getPluginReadOnly() const {return _pluginReadOnly; }
|
||||
|
||||
/// change the state of readonlyness
|
||||
void setPluginReadOnly(bool v) {_pluginReadOnly = v;}
|
||||
|
||||
/// override this to return a clone of the property
|
||||
virtual Property *deepCopy() = 0;
|
||||
|
||||
/// get the name of this property
|
||||
const std::string &getName()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
/// get the type of this property
|
||||
TypeEnum getType()
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
/// add a notify hook
|
||||
void addNotifyHook(NotifyHook *hook)
|
||||
{
|
||||
_notifyHooks.push_back(hook);
|
||||
}
|
||||
|
||||
/// set the get hook
|
||||
void setGetHook(GetHook *hook)
|
||||
{
|
||||
_getHook = hook;
|
||||
}
|
||||
|
||||
/// call notify on the contained notify hooks
|
||||
void notify(bool single, int indexOrN);
|
||||
|
||||
// get the current dimension of this property
|
||||
virtual int getDimension() const = 0;
|
||||
|
||||
/// get the fixed dimension of this property
|
||||
int getFixedDimension() const {
|
||||
return _dimension;
|
||||
}
|
||||
|
||||
/// are we a fixed dim property
|
||||
bool isFixedSize() const
|
||||
{
|
||||
return _dimension != 0;
|
||||
}
|
||||
|
||||
/// reset this property to the default
|
||||
virtual void reset() = 0;
|
||||
|
||||
// get a string representing the value of this property at element nth
|
||||
virtual std::string getStringValue(int nth) = 0;
|
||||
};
|
||||
|
||||
/// this represents a generic property.
|
||||
/// template parameter T is the type descriptor of the
|
||||
/// type of property to model. the class holds an internal _value vector which can be used
|
||||
/// to store the values. if set and get hooks are installed, these will be called instead
|
||||
/// of using this variable.
|
||||
/// Make sure that T::ReturnType is const if appropriate, as no extra qualifiers are applied here.
|
||||
template<class T>
|
||||
class PropertyTemplate : public Property
|
||||
{
|
||||
public :
|
||||
typedef typename T::Type Type;
|
||||
typedef typename T::ReturnType ReturnType;
|
||||
typedef typename T::APIType APIType;
|
||||
|
||||
protected :
|
||||
/// this is the present value of the property
|
||||
std::vector<Type> _value;
|
||||
|
||||
/// this is the default value of the property
|
||||
std::vector<Type> _defaultValue;
|
||||
|
||||
public :
|
||||
/// constructor
|
||||
PropertyTemplate(const std::string &name,
|
||||
int dimension,
|
||||
bool pluginReadOnly,
|
||||
APIType defaultValue);
|
||||
|
||||
PropertyTemplate(const PropertyTemplate<T> &pt);
|
||||
|
||||
PropertyTemplate<T> *deepCopy() {
|
||||
return new PropertyTemplate(*this);
|
||||
}
|
||||
|
||||
virtual ~PropertyTemplate()
|
||||
{
|
||||
}
|
||||
|
||||
/// get the vector
|
||||
const std::vector<Type> &getValues()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
// get multiple values
|
||||
void getValueN(APIType *value, int count) const;
|
||||
|
||||
#ifdef WINDOWS
|
||||
#pragma warning( disable : 4181 )
|
||||
#endif
|
||||
/// get one value
|
||||
const ReturnType getValue(int index=0) const;
|
||||
|
||||
/// get one value, without going through the getHook
|
||||
const ReturnType getValueRaw(int index=0) const;
|
||||
|
||||
#ifdef WINDOWS
|
||||
#pragma warning( default : 4181 )
|
||||
#endif
|
||||
// get multiple values, without going through the getHook
|
||||
void getValueNRaw(APIType *value, int count) const;
|
||||
|
||||
/// set one value
|
||||
void setValue(const Type &value, int index=0);
|
||||
|
||||
/// set multiple values
|
||||
void setValueN(const APIType *value, int count);
|
||||
|
||||
/// reset
|
||||
void reset();
|
||||
|
||||
/// get the size of the vector
|
||||
int getDimension() const;
|
||||
|
||||
/// return the value as a string
|
||||
inline std::string getStringValue(int idx) {
|
||||
return castToString(_value[idx]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef PropertyTemplate<IntValue> Int; /// Our int property
|
||||
typedef PropertyTemplate<DoubleValue> Double; /// Our double property
|
||||
typedef PropertyTemplate<StringValue> String; /// Our string property
|
||||
typedef PropertyTemplate<PointerValue> Pointer; /// Our pointer property
|
||||
|
||||
/// A class that is used to initialise a property set. Feed in an array of these to
|
||||
/// a property and it will construct a bunch of properties. Terminate such an array
|
||||
/// with an empty (all zero) set.
|
||||
struct PropSpec {
|
||||
const char *name; ///< name of the property
|
||||
TypeEnum type; ///< type
|
||||
int dimension; ///< fixed dimension of the property, set to zero if variable dimension
|
||||
bool readonly; ///< is the property plug-in read only
|
||||
const char *defaultValue; ///< Default value as a string. Pointers are ignored and always null.
|
||||
};
|
||||
static const PropSpec propSpecEnd = {0, eNone, 0, false, 0};
|
||||
|
||||
/// A std::map of properties by name
|
||||
typedef std::map<std::string, Property *> PropertyMap;
|
||||
|
||||
|
||||
//................................................................................
|
||||
/// Class that holds a set of properties and manipulates them
|
||||
/// The 'fetch' methods return a property object.
|
||||
/// The 'get' methods return a property value
|
||||
class Set {
|
||||
private :
|
||||
static const int kMagic = 0x12082007; ///< magic number for property sets, and Connie's birthday :-)
|
||||
const int _magic; ///< to check for handles being nice
|
||||
|
||||
protected :
|
||||
PropertyMap _props; ///< Our properties.
|
||||
|
||||
/// chained property set, which is read only
|
||||
/// these are searched on a get if not found
|
||||
/// on a local search
|
||||
Set *_chainedSet;
|
||||
|
||||
/// hide assignment
|
||||
void operator=(const Set &);
|
||||
|
||||
/// set a particular property
|
||||
template<class T> void setProperty(const std::string &property, int index, const typename T::Type &value);
|
||||
|
||||
/// set the first N of a particular property
|
||||
template<class T> void setPropertyN(const std::string &property, int count, const typename T::APIType *value);
|
||||
|
||||
/// get a particular property
|
||||
template<class T> typename T::ReturnType getProperty(const std::string &property, int index) const;
|
||||
|
||||
/// get the first N of a particular property
|
||||
template<class T> void getPropertyN(const std::string &property, int index, typename T::APIType *v) const;
|
||||
|
||||
/// get a particular property without going through any getHook
|
||||
template<class T> typename T::ReturnType getPropertyRaw(const std::string &property, int index) const;
|
||||
|
||||
/// get a particular property without going through any getHook
|
||||
template<class T> void getPropertyRawN(const std::string &property, int count, typename T::APIType *v) const;
|
||||
|
||||
public :
|
||||
/// take an array of of PropSpecs (which must be terminated with an entry in which
|
||||
/// ->name is null), and turn these into a Set
|
||||
explicit Set(const PropSpec *);
|
||||
|
||||
/// deep copies the property set
|
||||
explicit Set(const Set &);
|
||||
|
||||
/// empty ctor
|
||||
explicit Set();
|
||||
|
||||
/// destructor
|
||||
virtual ~Set();
|
||||
|
||||
/// adds a bunch of properties from PropSpec
|
||||
void addProperties(const PropSpec *);
|
||||
|
||||
/// add one new property
|
||||
void createProperty(const PropSpec &s);
|
||||
|
||||
/// add one new property
|
||||
void addProperty(Property *prop);
|
||||
|
||||
/// set the chained property set
|
||||
void setChainedSet(Set *s) {_chainedSet = s;}
|
||||
|
||||
/// grab the internal properties map
|
||||
const PropertyMap &getProperties() const
|
||||
{
|
||||
return _props;
|
||||
}
|
||||
|
||||
/// set the get hook for a particular property. users may need to call particular
|
||||
/// specialised versions of this.
|
||||
void setGetHook(const std::string &s, GetHook *ghook) const;
|
||||
|
||||
/// add a set hook for a particular property. users may need to call particular
|
||||
/// specialised versions of this.
|
||||
void addNotifyHook(const std::string &name, NotifyHook *hook) const;
|
||||
|
||||
/// Fetchs a pointer to a property of the given name, following the property chain if the
|
||||
/// 'followChain' arg is not false.
|
||||
Property *fetchProperty(const std::string &name, bool followChain = false) const;
|
||||
|
||||
/// get property with the particular name and type. if the property is
|
||||
/// missing or is of the wrong type, return an error status. if this is a sloppy
|
||||
/// property set and the property is missing, a new one will be created of the right
|
||||
/// type
|
||||
template<class T> bool fetchTypedProperty(const std::string &name, T *&prop, bool followChain = false) const;
|
||||
|
||||
/// retrieve the nameed string property
|
||||
String *fetchStringProperty(const std::string &name, bool followChain = false) const;
|
||||
|
||||
/// retrieve the named double property
|
||||
Double *fetchDoubleProperty(const std::string &name, bool followChain = false) const;
|
||||
|
||||
/// retrieve the named double property
|
||||
Pointer *fetchPointerProperty(const std::string &name, bool followChain = false) const;
|
||||
|
||||
/// retrieve the named double property
|
||||
Int *fetchIntProperty(const std::string &name, bool followChain = false) const;
|
||||
|
||||
|
||||
|
||||
/// get a particular int property without fetching via a get hook, useful for notifies
|
||||
int getIntPropertyRaw(const std::string &property, int index = 0) const;
|
||||
|
||||
/// get a particular double property without fetching via a get hook, useful for notifies
|
||||
double getDoublePropertyRaw(const std::string &property, int index = 0) const;
|
||||
|
||||
/// get a particular pointer property without fetching via a get hook, useful for notifies
|
||||
void *getPointerPropertyRaw(const std::string &property, int index = 0) const;
|
||||
|
||||
/// get a particular string property
|
||||
const std::string &getStringPropertyRaw(const std::string &property, int index = 0) const;
|
||||
|
||||
/// get the value of a particular string property
|
||||
const std::string &getStringProperty(const std::string &property, int index = 0) const;
|
||||
|
||||
/// get the value of a particular int property
|
||||
int getIntProperty(const std::string &property, int index = 0) const;
|
||||
|
||||
/// get the value of a particular double property
|
||||
void getIntPropertyN(const std::string &property, int *v, int N) const;
|
||||
|
||||
/// get the value of a particular double property
|
||||
double getDoubleProperty(const std::string &property, int index = 0) const;
|
||||
|
||||
/// get the value of a particular double property
|
||||
void getDoublePropertyN(const std::string &property, double *v, int N) const;
|
||||
|
||||
/// get the value of a particular pointer property
|
||||
void *getPointerProperty(const std::string &property, int index = 0) const;
|
||||
|
||||
|
||||
|
||||
/// set a particular string property without fetching via a get hook, useful for notifies
|
||||
void setStringProperty(const std::string &property, const std::string &value, int index = 0);
|
||||
|
||||
/// get a particular int property
|
||||
void setIntProperty(const std::string &property, int v, int index = 0);
|
||||
|
||||
/// get a particular double property
|
||||
void setIntPropertyN(const std::string &property, const int *v, int N);
|
||||
|
||||
/// get a particular double property
|
||||
void setDoubleProperty(const std::string &property, double v, int index = 0);
|
||||
|
||||
/// get a particular double property
|
||||
void setDoublePropertyN(const std::string &property, const double *v, int N);
|
||||
|
||||
/// get a particular double property
|
||||
void setPointerProperty(const std::string &property, void *v, int index = 0);
|
||||
|
||||
|
||||
|
||||
/// get the dimension of a particular property
|
||||
int getDimension(const std::string &property) const;
|
||||
|
||||
/// is the given string one of the values of a multi-dimensional string prop
|
||||
/// this returns a non negative index if it is found, otherwise, -1
|
||||
int findStringPropValueIndex(const std::string &propName,
|
||||
const std::string &propValue) const;
|
||||
|
||||
|
||||
/// get a handle on this object for passing to the C API
|
||||
OfxPropertySetHandle getHandle() const
|
||||
{
|
||||
return (OfxPropertySetHandle)this;
|
||||
}
|
||||
|
||||
/// is this a nice property set, or a dodgy pointer passed back to us
|
||||
bool verifyMagic() { return _magic == kMagic; }
|
||||
};
|
||||
|
||||
|
||||
/// return the OFX function suite that manages properties
|
||||
const void *GetSuite(int version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
|
||||
|
||||
#ifndef _ofxhTimeLine_h_
|
||||
#define _ofxhTimeLine_h_
|
||||
|
||||
#include "ofxTimeLine.h"
|
||||
|
||||
|
||||
|
||||
namespace OFX::Host::TimeLine {
|
||||
|
||||
/// Things that implement timeline controls derive from this ABC and implement the following
|
||||
/// functions.
|
||||
class TimeLineI {
|
||||
public :
|
||||
virtual ~TimeLineI() = default;
|
||||
|
||||
/// get the current time on the timeline. This is not necessarily the same
|
||||
/// time as being passed to an action (eg render)
|
||||
virtual double timeLineGetTime() = 0;
|
||||
|
||||
/// set the timeline to a specific time
|
||||
virtual void timeLineGotoTime(double t) = 0;
|
||||
|
||||
/// get the first and last times available on the effect's timeline
|
||||
virtual void timeLineGetBounds(double &t1, double &t2) = 0;
|
||||
};
|
||||
|
||||
} // namespace progress
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,154 @@
|
||||
|
||||
|
||||
#ifndef _ofxhUtilities_h_
|
||||
#define _ofxhUtilities_h_
|
||||
|
||||
// Copyright OpenFX and contributors to the OpenFX project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include "ofxCore.h"
|
||||
|
||||
// macro that intercepts any exception that passes through a plugin's entry point, and transforms it into a message on the host using Host::vmessage()
|
||||
#define CatchAllSetStatus(stat,host,plugin,msg) \
|
||||
catch ( const std::bad_alloc& ba ) { \
|
||||
(stat) = kOfxStatErrMemory; \
|
||||
if (host) { \
|
||||
try { \
|
||||
(host)->message(kOfxMessageError, "", \
|
||||
"%s: Memory allocation error occured in plugin %s (%s)", \
|
||||
(msg), (plugin)->pluginIdentifier, ba.what()); \
|
||||
} catch (...) { \
|
||||
} \
|
||||
} \
|
||||
} catch ( const std::exception &e ) { \
|
||||
(stat) = kOfxStatFailed; \
|
||||
if (host) { \
|
||||
try { \
|
||||
(host)->message(kOfxMessageError, "", \
|
||||
"%s: Exception occured in plugin %s (%s)", \
|
||||
(msg), (plugin)->pluginIdentifier, e.what()); \
|
||||
} catch (...) { \
|
||||
} \
|
||||
} \
|
||||
} catch ( ... ) { \
|
||||
(stat) = kOfxStatFailed; \
|
||||
if (host) { \
|
||||
try { \
|
||||
(host)->message(kOfxMessageError, "", \
|
||||
"%s:Exception occured in plugin %s", \
|
||||
(msg), (plugin)->pluginIdentifier); \
|
||||
} catch (...) { \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
namespace OFX {
|
||||
|
||||
/// class that is a std::vector of std::strings
|
||||
typedef std::vector<std::string> StringVec;
|
||||
|
||||
/// class that is a std::vector of std::strings
|
||||
inline void SetStringVecValue(StringVec &sv, const std::string &value, size_t index = 0)
|
||||
{
|
||||
size_t size = sv.size();
|
||||
if(size <= index) {
|
||||
while(size < index) {
|
||||
sv.push_back("");
|
||||
++size;
|
||||
}
|
||||
sv.push_back(value);
|
||||
}
|
||||
else
|
||||
sv[index] = value;
|
||||
}
|
||||
|
||||
/// get me deepest bit depth
|
||||
std::string FindDeepestBitDepth(const std::string &s1, const std::string &s2);
|
||||
|
||||
/// get the min value
|
||||
template<class T> inline T Minimum(const T &a, const T &b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
/// get the min value
|
||||
template<class T> inline T Maximum(const T &a, const T &b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
/// clamp the value
|
||||
template<class T> inline T Clamp(const T &v, const T &mn, const T &mx)
|
||||
{
|
||||
if(v < mn) return mn;
|
||||
if(v > mx) return mx;
|
||||
return v;
|
||||
}
|
||||
|
||||
/// clamp the rect in v to the given bounds
|
||||
inline OfxRectD Clamp(const OfxRectD &v,
|
||||
const OfxRectD &bounds)
|
||||
{
|
||||
OfxRectD r;
|
||||
r.x1 = Clamp(v.x1, bounds.x1, bounds.x2);
|
||||
r.x2 = Clamp(v.x2, bounds.x1, bounds.x2);
|
||||
r.y1 = Clamp(v.y1, bounds.y1, bounds.y2);
|
||||
r.y2 = Clamp(v.y2, bounds.y1, bounds.y2);
|
||||
return r;
|
||||
}
|
||||
|
||||
/// get the union of the two rects
|
||||
inline OfxRectD Union(const OfxRectD &a,
|
||||
const OfxRectD &b)
|
||||
{
|
||||
OfxRectD r;
|
||||
r.x1 = Minimum(a.x1, b.x1);
|
||||
r.x2 = Maximum(a.x2, b.x2);
|
||||
r.y1 = Minimum(a.y1, b.y1);
|
||||
r.y2 = Maximum(a.y2, b.y2);
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const char* StatStr(OfxStatus stat) {
|
||||
switch(stat) {
|
||||
case kOfxStatOK:
|
||||
return "kOfxStatOK";
|
||||
case kOfxStatFailed:
|
||||
return "kOfxStatFailed";
|
||||
case kOfxStatErrFatal:
|
||||
return "kOfxStatErrFatal";
|
||||
case kOfxStatErrUnknown:
|
||||
return "kOfxStatErrUnknown";
|
||||
case kOfxStatErrMissingHostFeature:
|
||||
return "kOfxStatErrMissingHostFeature";
|
||||
case kOfxStatErrUnsupported:
|
||||
return "kOfxStatErrUnsupported";
|
||||
case kOfxStatErrExists:
|
||||
return "kOfxStatErrExists";
|
||||
case kOfxStatErrFormat:
|
||||
return "kOfxStatErrFormat";
|
||||
case kOfxStatErrMemory:
|
||||
return "kOfxStatErrMemory";
|
||||
case kOfxStatErrBadHandle:
|
||||
return "kOfxStatErrBadHandle";
|
||||
case kOfxStatErrBadIndex:
|
||||
return "kOfxStatErrBadIndex";
|
||||
case kOfxStatErrValue:
|
||||
return "kOfxStatErrValue";
|
||||
case kOfxStatReplyYes:
|
||||
return "kOfxStatReplyYes";
|
||||
case kOfxStatReplyNo:
|
||||
return "kOfxStatReplyNo";
|
||||
case kOfxStatReplyDefault:
|
||||
return "kOfxStatReplyDefault";
|
||||
default:
|
||||
return "(unknown error code)";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
|
||||
|
||||
#ifndef OFX_XML_H
|
||||
#define OFX_XML_H
|
||||
|
||||
// Copyright OpenFX and contributors to the OpenFX project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
namespace OFX {
|
||||
|
||||
namespace XML {
|
||||
|
||||
inline std::string escape(const std::string &s) {
|
||||
std::string ns;
|
||||
for (size_t i=0;i<s.size();i++) {
|
||||
// The are exactly five characters which must be escaped
|
||||
// http://www.w3.org/TR/xml/#syntax
|
||||
switch (s[i]) {
|
||||
case '<':
|
||||
ns += "<";
|
||||
break;
|
||||
case '>':
|
||||
ns += ">";
|
||||
break;
|
||||
case '&':
|
||||
ns += "&";
|
||||
break;
|
||||
case '"':
|
||||
ns += """;
|
||||
break;
|
||||
case '\'':
|
||||
ns += "'";
|
||||
break;
|
||||
default: {
|
||||
unsigned char c = (unsigned char)(s[i]);
|
||||
// Escape even the whitespace characters '\n' '\r' '\t', although they are valid
|
||||
// XML, because they would be converted to space when re-read.
|
||||
// See http://www.w3.org/TR/xml/#AVNormalize
|
||||
if ((0x01 <= c && c <= 0x1f) || (0x7F <= c && c <= 0x9F)) {
|
||||
// these characters must be escaped in XML 1.1
|
||||
// http://www.w3.org/TR/xml/#sec-references
|
||||
ns += "&#x";
|
||||
if (c > 0xf) {
|
||||
int d = c / 0x10;
|
||||
ns += d < 10 ? ('0' + d) : ('A' + d - 10);
|
||||
}
|
||||
int d = c & 0xf;
|
||||
ns += d < 10 ? ('0' + d) : ('A' + d - 10);
|
||||
ns += ';';
|
||||
} else {
|
||||
ns += s[i];
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
return ns;
|
||||
}
|
||||
|
||||
inline std::string attribute(const std::string &at, const std::string &val)
|
||||
{
|
||||
return at + "=" + "\"" + escape(val) + "\" ";
|
||||
}
|
||||
|
||||
inline std::string attribute(const std::string &st, int val)
|
||||
{
|
||||
std::ostringstream o;
|
||||
o << val;
|
||||
return attribute(st, o.str());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
|
||||
|
||||
#include "ofxhBinary.h"
|
||||
|
||||
using namespace OFX;
|
||||
|
||||
Binary::Binary(const std::string &binaryPath): _binaryPath(binaryPath), _invalid(false), _dlHandle(0), _users(0)
|
||||
{
|
||||
struct stat sb;
|
||||
if (stat(binaryPath.c_str(), &sb) != 0) {
|
||||
_invalid = true;
|
||||
_time = 0;
|
||||
_size = 0;
|
||||
}
|
||||
else {
|
||||
_time = sb.st_mtime;
|
||||
_size = sb.st_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// actually open the binary.
|
||||
void Binary::load()
|
||||
{
|
||||
if(_invalid)
|
||||
return;
|
||||
|
||||
#if defined (UNIX)
|
||||
_dlHandle = dlopen(_binaryPath.c_str(), RTLD_LAZY|RTLD_LOCAL);
|
||||
#else
|
||||
_dlHandle = LoadLibrary(_binaryPath.c_str());
|
||||
#endif
|
||||
if (_dlHandle == 0) {
|
||||
#if defined (UNIX)
|
||||
std::cerr << "couldn't open library " << _binaryPath << " because " << dlerror() << std::endl;
|
||||
#else
|
||||
LPVOID lpMsgBuf = NULL;
|
||||
DWORD err = GetLastError();
|
||||
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0, NULL);
|
||||
|
||||
std::cerr << "couldn't open library " << _binaryPath << " because " << (char*)lpMsgBuf << " was returned" << std::endl;
|
||||
if (lpMsgBuf != NULL) {
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
#endif
|
||||
_invalid = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// close the binary
|
||||
void Binary::unload() {
|
||||
if (_dlHandle != 0) {
|
||||
#if defined (UNIX)
|
||||
dlclose(_dlHandle);
|
||||
#elif defined (WINDOWS)
|
||||
FreeLibrary(_dlHandle);
|
||||
#endif
|
||||
_dlHandle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// look up a symbol in the binary file and return it as a pointer.
|
||||
/// returns null pointer if not found, or if the library is not loaded.
|
||||
void *Binary::findSymbol(const std::string &symbol) {
|
||||
if (_dlHandle != 0) {
|
||||
#if defined(UNIX)
|
||||
return dlsym(_dlHandle, symbol.c_str());
|
||||
#elif defined (WINDOWS)
|
||||
return (void*)GetProcAddress(_dlHandle, symbol.c_str());
|
||||
#endif
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Binary::ref()
|
||||
{
|
||||
if (_users == 0) {
|
||||
load();
|
||||
}
|
||||
_users++;
|
||||
}
|
||||
|
||||
void Binary::unref()
|
||||
{
|
||||
_users--;
|
||||
if (_users == 0) {
|
||||
unload();
|
||||
}
|
||||
if (_users < 0) {
|
||||
_users = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+654
@@ -0,0 +1,654 @@
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
// ofx
|
||||
#include "ofxCore.h"
|
||||
|
||||
// ofx host
|
||||
#include "ofxhBinary.h"
|
||||
#include "ofxhPropertySuite.h"
|
||||
#include "ofxhClip.h"
|
||||
#include "ofxhImageEffect.h"
|
||||
#ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
#include "ofxGPURender.h"
|
||||
#endif
|
||||
|
||||
namespace OFX {
|
||||
|
||||
namespace Host {
|
||||
|
||||
namespace ImageEffect {
|
||||
|
||||
/// properties common to the desciptor and instance
|
||||
/// the desc and set them, the instance cannot
|
||||
static const Property::PropSpec clipDescriptorStuffs[] = {
|
||||
{ kOfxPropType, Property::eString, 1, true, kOfxTypeClip },
|
||||
{ kOfxPropName, Property::eString, 1, true, "SET ME ON CONSTRUCTION" },
|
||||
{ kOfxPropLabel, Property::eString, 1, false, "" } ,
|
||||
{ kOfxPropShortLabel, Property::eString, 1, false, "" },
|
||||
{ kOfxPropLongLabel, Property::eString, 1, false, "" },
|
||||
{ kOfxImageEffectPropSupportedComponents, Property::eString, 0, false, "" },
|
||||
{ kOfxImageEffectPropTemporalClipAccess, Property::eInt, 1, false, "0" },
|
||||
{ kOfxImageClipPropOptional, Property::eInt, 1, false, "0" },
|
||||
{ kOfxImageClipPropIsMask, Property::eInt, 1, false, "0" },
|
||||
{ kOfxImageClipPropFieldExtraction, Property::eString, 1, false, kOfxImageFieldDoubled },
|
||||
{ kOfxImageEffectPropSupportsTiles, Property::eInt, 1, false, "1" },
|
||||
Property::propSpecEnd,
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// props to clips descriptors and instances
|
||||
|
||||
// base ctor, for a descriptor
|
||||
ClipBase::ClipBase()
|
||||
: _properties(clipDescriptorStuffs)
|
||||
{
|
||||
}
|
||||
|
||||
/// props to clips and
|
||||
ClipBase::ClipBase(const ClipBase &v)
|
||||
: _properties(v._properties)
|
||||
{
|
||||
/// we are an instance, we need to reset the props to read only
|
||||
const Property::PropertyMap &map = _properties.getProperties();
|
||||
Property::PropertyMap::const_iterator i;
|
||||
for(i = map.begin(); i != map.end(); ++i) {
|
||||
(*i).second->setPluginReadOnly(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// name of the clip
|
||||
const std::string &ClipBase::getShortLabel() const
|
||||
{
|
||||
const std::string &s = _properties.getStringProperty(kOfxPropShortLabel);
|
||||
if(s == "") {
|
||||
return getLabel();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/// name of the clip
|
||||
const std::string &ClipBase::getLabel() const
|
||||
{
|
||||
const std::string &s = _properties.getStringProperty(kOfxPropLabel);
|
||||
if(s == "") {
|
||||
return getName();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/// name of the clip
|
||||
const std::string &ClipBase::getLongLabel() const
|
||||
{
|
||||
const std::string &s = _properties.getStringProperty(kOfxPropLongLabel);
|
||||
if(s == "") {
|
||||
return getLabel();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/// return a std::vector of supported comp
|
||||
const std::vector<std::string> &ClipBase::getSupportedComponents() const
|
||||
{
|
||||
Property::String *p = _properties.fetchStringProperty(kOfxImageEffectPropSupportedComponents);
|
||||
assert(p != NULL);
|
||||
return p->getValues();
|
||||
}
|
||||
|
||||
/// is the given component supported
|
||||
bool ClipBase::isSupportedComponent(const std::string &comp) const
|
||||
{
|
||||
return _properties.findStringPropValueIndex(kOfxImageEffectPropSupportedComponents, comp) != -1;
|
||||
}
|
||||
|
||||
/// does the clip do random temporal access
|
||||
bool ClipBase::temporalAccess() const
|
||||
{
|
||||
return _properties.getIntProperty(kOfxImageEffectPropTemporalClipAccess) != 0;
|
||||
}
|
||||
|
||||
/// is the clip optional
|
||||
bool ClipBase::isOptional() const
|
||||
{
|
||||
return _properties.getIntProperty(kOfxImageClipPropOptional) != 0;
|
||||
}
|
||||
|
||||
/// is the clip a nominal 'mask' clip
|
||||
bool ClipBase::isMask() const
|
||||
{
|
||||
return _properties.getIntProperty(kOfxImageClipPropIsMask) != 0;
|
||||
}
|
||||
|
||||
/// how does this clip like fielded images to be presented to it
|
||||
const std::string &ClipBase::getFieldExtraction() const
|
||||
{
|
||||
return _properties.getStringProperty(kOfxImageClipPropFieldExtraction);
|
||||
}
|
||||
|
||||
/// is the clip a nominal 'mask' clip
|
||||
bool ClipBase::supportsTiles() const
|
||||
{
|
||||
return _properties.getIntProperty(kOfxImageEffectPropSupportsTiles) != 0;
|
||||
}
|
||||
|
||||
const Property::Set& ClipBase::getProps() const
|
||||
{
|
||||
return _properties;
|
||||
}
|
||||
|
||||
Property::Set& ClipBase::getProps()
|
||||
{
|
||||
return _properties;
|
||||
}
|
||||
|
||||
/// get a handle on the properties of the clip descriptor for the C api
|
||||
OfxPropertySetHandle ClipBase::getPropHandle() const
|
||||
{
|
||||
return _properties.getHandle();
|
||||
}
|
||||
|
||||
/// get a handle on the clip descriptor for the C api
|
||||
OfxImageClipHandle ClipBase::getHandle() const
|
||||
{
|
||||
return (OfxImageClipHandle)this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// descriptor
|
||||
ClipDescriptor::ClipDescriptor(const std::string &name)
|
||||
: ClipBase()
|
||||
{
|
||||
_properties.setStringProperty(kOfxPropName,name);
|
||||
}
|
||||
|
||||
/// extra properties for the instance, these are fetched from the host
|
||||
/// via a get hook and some virtuals
|
||||
static const Property::PropSpec clipInstanceStuffs[] = {
|
||||
{ kOfxImageEffectPropPixelDepth, Property::eString, 1, true, kOfxBitDepthNone },
|
||||
{ kOfxImageEffectPropComponents, Property::eString, 1, true, kOfxImageComponentNone },
|
||||
{ kOfxImageClipPropUnmappedPixelDepth, Property::eString, 1, true, kOfxBitDepthNone },
|
||||
{ kOfxImageClipPropUnmappedComponents, Property::eString, 1, true, kOfxImageComponentNone },
|
||||
{ kOfxImageEffectPropPreMultiplication, Property::eString, 1, true, kOfxImageOpaque },
|
||||
{ kOfxImagePropPixelAspectRatio, Property::eDouble, 1, true, "1.0" },
|
||||
{ kOfxImageEffectPropFrameRate, Property::eDouble, 1, true, "25.0" },
|
||||
{ kOfxImageEffectPropFrameRange, Property::eDouble, 2, true, "0" },
|
||||
{ kOfxImageClipPropFieldOrder, Property::eString, 1, true, kOfxImageFieldNone },
|
||||
{ kOfxImageClipPropConnected, Property::eInt, 1, true, "0" },
|
||||
{ kOfxImageEffectPropUnmappedFrameRange, Property::eDouble, 2, true, "0" },
|
||||
{ kOfxImageEffectPropUnmappedFrameRate, Property::eDouble, 1, true, "25.0" },
|
||||
{ kOfxImageClipPropContinuousSamples, Property::eInt, 1, true, "0" },
|
||||
Property::propSpecEnd,
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// instance
|
||||
ClipInstance::ClipInstance(ImageEffect::Instance* effectInstance, ClipDescriptor& desc)
|
||||
: ClipBase(desc)
|
||||
, _effectInstance(effectInstance)
|
||||
, _isOutput(desc.isOutput())
|
||||
, _pixelDepth(kOfxBitDepthNone)
|
||||
, _components(kOfxImageComponentNone)
|
||||
{
|
||||
// this will a parameters that are needed in an instance but not a
|
||||
// Descriptor
|
||||
_properties.addProperties(clipInstanceStuffs);
|
||||
int i = 0;
|
||||
while(clipInstanceStuffs[i].name) {
|
||||
const Property::PropSpec& spec = clipInstanceStuffs[i];
|
||||
|
||||
switch (spec.type) {
|
||||
case Property::eDouble:
|
||||
case Property::eString:
|
||||
case Property::eInt:
|
||||
_properties.setGetHook(spec.name, this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// do nothing
|
||||
int ClipInstance::getDimension(const std::string &name) const
|
||||
{
|
||||
if(name == kOfxImageEffectPropUnmappedFrameRange || name == kOfxImageEffectPropFrameRange)
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// don't know what to do
|
||||
void ClipInstance::reset(const std::string &/*name*/) {
|
||||
//printf("failing in %s\n", __PRETTY_FUNCTION__);
|
||||
throw Property::Exception(kOfxStatErrMissingHostFeature);
|
||||
}
|
||||
|
||||
const std::string &ClipInstance::getComponents() const
|
||||
{
|
||||
return _components;
|
||||
}
|
||||
|
||||
/// set the current set of components
|
||||
/// called by clip preferences action
|
||||
void ClipInstance::setComponents(const std::string &s)
|
||||
{
|
||||
_components = s;
|
||||
}
|
||||
|
||||
// get the virutals for viewport size, pixel scale, background colour
|
||||
void ClipInstance::getDoublePropertyN(const std::string &name, double *values, int n) const
|
||||
{
|
||||
if(name==kOfxImagePropPixelAspectRatio){
|
||||
if(n>1) throw Property::Exception(kOfxStatErrValue);
|
||||
*values = getAspectRatio();
|
||||
}
|
||||
else if(name==kOfxImageEffectPropFrameRate){
|
||||
if(n>1) throw Property::Exception(kOfxStatErrValue);
|
||||
*values = getFrameRate();
|
||||
}
|
||||
else if(name==kOfxImageEffectPropFrameRange){
|
||||
if(n>2) throw Property::Exception(kOfxStatErrValue);
|
||||
getFrameRange(values[0], values[1]);
|
||||
}
|
||||
else if(name==kOfxImageEffectPropUnmappedFrameRate){
|
||||
if(n>1) throw Property::Exception(kOfxStatErrValue);
|
||||
*values = getUnmappedFrameRate();
|
||||
}
|
||||
else if(name==kOfxImageEffectPropUnmappedFrameRange){
|
||||
if(n>2) throw Property::Exception(kOfxStatErrValue);
|
||||
getUnmappedFrameRange(values[0], values[1]);
|
||||
}
|
||||
else
|
||||
throw Property::Exception(kOfxStatErrValue);
|
||||
}
|
||||
|
||||
// get the virutals for viewport size, pixel scale, background colour
|
||||
double ClipInstance::getDoubleProperty(const std::string &name, int n) const
|
||||
{
|
||||
if(name==kOfxImagePropPixelAspectRatio){
|
||||
if(n!=0) throw Property::Exception(kOfxStatErrValue);
|
||||
return getAspectRatio();
|
||||
}
|
||||
else if(name==kOfxImageEffectPropFrameRate){
|
||||
if(n!=0) throw Property::Exception(kOfxStatErrValue);
|
||||
return getFrameRate();
|
||||
}
|
||||
else if(name==kOfxImageEffectPropFrameRange){
|
||||
if(n>1) throw Property::Exception(kOfxStatErrValue);
|
||||
double range[2];
|
||||
getFrameRange(range[0], range[1]);
|
||||
return range[n];
|
||||
}
|
||||
else if(name==kOfxImageEffectPropUnmappedFrameRate){
|
||||
if(n>0) throw Property::Exception(kOfxStatErrValue);
|
||||
return getUnmappedFrameRate();
|
||||
}
|
||||
else if(name==kOfxImageEffectPropUnmappedFrameRange){
|
||||
if(n>1) throw Property::Exception(kOfxStatErrValue);
|
||||
double range[2];
|
||||
getUnmappedFrameRange(range[0], range[1]);
|
||||
return range[n];
|
||||
}
|
||||
else
|
||||
throw Property::Exception(kOfxStatErrValue);
|
||||
}
|
||||
|
||||
// get the virutals for viewport size, pixel scale, background colour
|
||||
int ClipInstance::getIntProperty(const std::string &name, int n) const
|
||||
{
|
||||
if(n!=0) throw Property::Exception(kOfxStatErrValue);
|
||||
if(name==kOfxImageClipPropConnected){
|
||||
return getConnected();
|
||||
}
|
||||
else if(name==kOfxImageClipPropContinuousSamples){
|
||||
return getContinuousSamples();
|
||||
}
|
||||
else
|
||||
throw Property::Exception(kOfxStatErrValue);
|
||||
}
|
||||
|
||||
// get the virutals for viewport size, pixel scale, background colour
|
||||
void ClipInstance::getIntPropertyN(const std::string &name, int *values, int n) const
|
||||
{
|
||||
if(n!=0) throw Property::Exception(kOfxStatErrValue);
|
||||
*values = getIntProperty(name, 0);
|
||||
}
|
||||
|
||||
// get the virutals for viewport size, pixel scale, background colour
|
||||
const std::string &ClipInstance::getStringProperty(const std::string &name, int n) const
|
||||
{
|
||||
if(n!=0) throw Property::Exception(kOfxStatErrValue);
|
||||
if(name==kOfxImageEffectPropPixelDepth){
|
||||
return getPixelDepth();
|
||||
}
|
||||
else if(name==kOfxImageEffectPropComponents){
|
||||
return getComponents();
|
||||
}
|
||||
else if(name==kOfxImageClipPropUnmappedComponents){
|
||||
return getUnmappedComponents();
|
||||
}
|
||||
else if(name==kOfxImageClipPropUnmappedPixelDepth){
|
||||
return getUnmappedBitDepth();
|
||||
}
|
||||
else if(name==kOfxImageEffectPropPreMultiplication){
|
||||
return getPremult();
|
||||
}
|
||||
else if(name==kOfxImageClipPropFieldOrder){
|
||||
return getFieldOrder();
|
||||
}
|
||||
else
|
||||
throw Property::Exception(kOfxStatErrValue);
|
||||
}
|
||||
|
||||
// fetch multiple values in a multi-dimension property
|
||||
void ClipInstance::getStringPropertyN(const std::string &name, const char** values, int count) const
|
||||
{
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
if(count!=1) throw Property::Exception(kOfxStatErrValue);
|
||||
if(name==kOfxImageEffectPropPixelDepth){
|
||||
values[0] = getPixelDepth().c_str();
|
||||
}
|
||||
else if(name==kOfxImageEffectPropComponents){
|
||||
values[0] = getComponents().c_str();
|
||||
}
|
||||
else if(name==kOfxImageClipPropUnmappedComponents){
|
||||
values[0] = getUnmappedComponents().c_str();
|
||||
}
|
||||
else if(name==kOfxImageClipPropUnmappedPixelDepth){
|
||||
values[0] = getUnmappedBitDepth().c_str();
|
||||
}
|
||||
else if(name==kOfxImageEffectPropPreMultiplication){
|
||||
values[0] = getPremult().c_str();
|
||||
}
|
||||
else if(name==kOfxImageClipPropFieldOrder){
|
||||
values[0] = getFieldOrder().c_str();
|
||||
}
|
||||
else
|
||||
throw Property::Exception(kOfxStatErrValue);
|
||||
}
|
||||
|
||||
// notify override properties
|
||||
void ClipInstance::notify(const std::string &/*name*/, bool /*isSingle*/, int /*indexOrN*/)
|
||||
{
|
||||
}
|
||||
|
||||
OfxStatus ClipInstance::instanceChangedAction(const std::string &why,
|
||||
OfxTime time,
|
||||
OfxPointD renderScale)
|
||||
{
|
||||
Property::PropSpec stuff[] = {
|
||||
{ kOfxPropType, Property::eString, 1, true, kOfxTypeClip },
|
||||
{ kOfxPropName, Property::eString, 1, true, getName().c_str() },
|
||||
{ kOfxPropChangeReason, Property::eString, 1, true, why.c_str() },
|
||||
{ kOfxPropTime, Property::eDouble, 1, true, "0" },
|
||||
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" },
|
||||
Property::propSpecEnd
|
||||
};
|
||||
|
||||
Property::Set inArgs(stuff);
|
||||
|
||||
// add the second dimension of the render scale
|
||||
inArgs.setDoubleProperty(kOfxPropTime,time);
|
||||
inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2);
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)_effectInstance<<"->"<<kOfxActionInstanceChanged<<"("<<kOfxTypeClip<<","<<getName()<<","<<why<<","<<time<<",("<<renderScale.x<<","<<renderScale.y<<"))"<<std::endl;
|
||||
# endif
|
||||
|
||||
OfxStatus st;
|
||||
if(_effectInstance){
|
||||
st = _effectInstance->mainEntry(kOfxActionInstanceChanged, _effectInstance->getHandle(), &inArgs, 0);
|
||||
} else {
|
||||
st = kOfxStatFailed;
|
||||
}
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)_effectInstance<<"->"<<kOfxActionInstanceChanged<<"("<<kOfxTypeClip<<","<<getName()<<","<<why<<","<<time<<",("<<renderScale.x<<","<<renderScale.y<<"))->"<<StatStr(st)<<std::endl;
|
||||
# endif
|
||||
return st;
|
||||
}
|
||||
|
||||
/// given the colour component, find the nearest set of supported colour components
|
||||
const std::string &ClipInstance::findSupportedComp(const std::string &s) const
|
||||
{
|
||||
static const std::string none(kOfxImageComponentNone);
|
||||
static const std::string rgba(kOfxImageComponentRGBA);
|
||||
static const std::string rgb(kOfxImageComponentRGB);
|
||||
static const std::string alpha(kOfxImageComponentAlpha);
|
||||
/// is it there
|
||||
if(isSupportedComponent(s))
|
||||
return s;
|
||||
|
||||
/// were we fed some custom non chromatic component by getUnmappedComponents? Return it.
|
||||
/// we should never be here mind, so a bit weird
|
||||
if(!_effectInstance->isChromaticComponent(s))
|
||||
return s;
|
||||
|
||||
/// Means we have RGBA or Alpha being passed in and the clip
|
||||
/// only supports the other one, so return that
|
||||
if(s == rgba) {
|
||||
if(isSupportedComponent(rgb))
|
||||
return rgb;
|
||||
if(isSupportedComponent(alpha))
|
||||
return alpha;
|
||||
} else if(s == alpha) {
|
||||
if(isSupportedComponent(rgba))
|
||||
return rgba;
|
||||
if(isSupportedComponent(rgb))
|
||||
return rgb;
|
||||
}
|
||||
|
||||
/// wierd, must be some custom bit , if only one, choose that, otherwise no idea
|
||||
/// how to map, you need to derive to do so.
|
||||
const std::vector<std::string> &supportedComps = getSupportedComponents();
|
||||
if(supportedComps.size() == 1)
|
||||
return supportedComps[0];
|
||||
|
||||
return none;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Image
|
||||
//
|
||||
|
||||
static const Property::PropSpec imageBaseStuffs[] = {
|
||||
{ kOfxPropType, Property::eString, 1, false, kOfxTypeImage },
|
||||
{ kOfxImageEffectPropPixelDepth, Property::eString, 1, true, kOfxBitDepthNone },
|
||||
{ kOfxImageEffectPropComponents, Property::eString, 1, true, kOfxImageComponentNone },
|
||||
{ kOfxImageEffectPropPreMultiplication, Property::eString, 1, true, kOfxImageOpaque },
|
||||
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "1.0" },
|
||||
{ kOfxImagePropPixelAspectRatio, Property::eDouble, 1, true, "1.0" },
|
||||
{ kOfxImagePropBounds, Property::eInt, 4, true, "0" },
|
||||
{ kOfxImagePropRegionOfDefinition, Property::eInt, 4, true, "0", },
|
||||
{ kOfxImagePropRowBytes, Property::eInt, 1, true, "0", },
|
||||
{ kOfxImagePropField, Property::eString, 1, true, "", },
|
||||
{ kOfxImagePropUniqueIdentifier, Property::eString, 1, true, "" },
|
||||
Property::propSpecEnd
|
||||
};
|
||||
|
||||
ImageBase::ImageBase()
|
||||
: Property::Set(imageBaseStuffs)
|
||||
, _referenceCount(1)
|
||||
{
|
||||
}
|
||||
|
||||
/// called during ctor to get bits from the clip props into ours
|
||||
void ImageBase::getClipBits(ClipInstance& instance)
|
||||
{
|
||||
Property::Set& clipProperties = instance.getProps();
|
||||
|
||||
// get and set the clip instance pixel depth
|
||||
const std::string &depth = clipProperties.getStringProperty(kOfxImageEffectPropPixelDepth);
|
||||
setStringProperty(kOfxImageEffectPropPixelDepth, depth);
|
||||
|
||||
// get and set the clip instance components
|
||||
const std::string &comps = clipProperties.getStringProperty(kOfxImageEffectPropComponents);
|
||||
setStringProperty(kOfxImageEffectPropComponents, comps);
|
||||
|
||||
// get and set the clip instance premultiplication
|
||||
setStringProperty(kOfxImageEffectPropPreMultiplication, clipProperties.getStringProperty(kOfxImageEffectPropPreMultiplication));
|
||||
|
||||
// get and set the clip instance pixel aspect ratio
|
||||
setDoubleProperty(kOfxImagePropPixelAspectRatio, clipProperties.getDoubleProperty(kOfxImagePropPixelAspectRatio));
|
||||
}
|
||||
|
||||
/// make an image from a clip instance
|
||||
ImageBase::ImageBase(ClipInstance& instance)
|
||||
: Property::Set(imageBaseStuffs)
|
||||
, _referenceCount(1)
|
||||
{
|
||||
getClipBits(instance);
|
||||
}
|
||||
|
||||
// construction based on clip instance
|
||||
ImageBase::ImageBase(ClipInstance& instance,
|
||||
double renderScaleX,
|
||||
double renderScaleY,
|
||||
const OfxRectI &bounds,
|
||||
const OfxRectI &rod,
|
||||
int rowBytes,
|
||||
std::string field,
|
||||
std::string uniqueIdentifier)
|
||||
: Property::Set(imageBaseStuffs)
|
||||
, _referenceCount(1)
|
||||
{
|
||||
getClipBits(instance);
|
||||
|
||||
// set other data
|
||||
setDoubleProperty(kOfxImageEffectPropRenderScale,renderScaleX, 0);
|
||||
setDoubleProperty(kOfxImageEffectPropRenderScale,renderScaleY, 1);
|
||||
setIntProperty(kOfxImagePropBounds,bounds.x1, 0);
|
||||
setIntProperty(kOfxImagePropBounds,bounds.y1, 1);
|
||||
setIntProperty(kOfxImagePropBounds,bounds.x2, 2);
|
||||
setIntProperty(kOfxImagePropBounds,bounds.y2, 3);
|
||||
setIntProperty(kOfxImagePropRegionOfDefinition,rod.x1, 0);
|
||||
setIntProperty(kOfxImagePropRegionOfDefinition,rod.y1, 1);
|
||||
setIntProperty(kOfxImagePropRegionOfDefinition,rod.x2, 2);
|
||||
setIntProperty(kOfxImagePropRegionOfDefinition,rod.y2, 3);
|
||||
setIntProperty(kOfxImagePropRowBytes,rowBytes);
|
||||
|
||||
setStringProperty(kOfxImagePropField,field);
|
||||
setStringProperty(kOfxImageClipPropFieldOrder,field);
|
||||
setStringProperty(kOfxImagePropUniqueIdentifier,uniqueIdentifier);
|
||||
}
|
||||
|
||||
OfxRectI ImageBase::getBounds() const
|
||||
{
|
||||
OfxRectI bounds = {0, 0, 0, 0};
|
||||
getIntPropertyN(kOfxImagePropBounds, &bounds.x1, 4);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
OfxRectI ImageBase::getROD() const
|
||||
{
|
||||
OfxRectI rod = {0, 0, 0, 0};
|
||||
getIntPropertyN(kOfxImagePropRegionOfDefinition, &rod.x1, 4);
|
||||
return rod;
|
||||
}
|
||||
|
||||
ImageBase::~ImageBase() {
|
||||
//assert(_referenceCount <= 0);
|
||||
}
|
||||
|
||||
// release the reference
|
||||
void ImageBase::releaseReference()
|
||||
{
|
||||
_referenceCount -= 1;
|
||||
if(_referenceCount <= 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
static const Property::PropSpec imageStuffs[] = {
|
||||
{ kOfxImagePropData, Property::ePointer, 1, true, NULL },
|
||||
Property::propSpecEnd
|
||||
};
|
||||
|
||||
Image::Image()
|
||||
: ImageBase()
|
||||
{
|
||||
addProperties(imageStuffs);
|
||||
}
|
||||
|
||||
/// make an image from a clip instance
|
||||
Image::Image(ClipInstance& instance)
|
||||
: ImageBase(instance)
|
||||
{
|
||||
addProperties(imageStuffs);
|
||||
}
|
||||
|
||||
// construction based on clip instance
|
||||
Image::Image(ClipInstance& instance,
|
||||
double renderScaleX,
|
||||
double renderScaleY,
|
||||
void* data,
|
||||
const OfxRectI &bounds,
|
||||
const OfxRectI &rod,
|
||||
int rowBytes,
|
||||
std::string field,
|
||||
std::string uniqueIdentifier)
|
||||
: ImageBase(instance, renderScaleX, renderScaleY, bounds, rod, rowBytes, field, uniqueIdentifier)
|
||||
{
|
||||
addProperties(imageStuffs);
|
||||
|
||||
// set other data
|
||||
setPointerProperty(kOfxImagePropData,data);
|
||||
}
|
||||
|
||||
Image::~Image() {
|
||||
//assert(_referenceCount <= 0);
|
||||
}
|
||||
# ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
static const Property::PropSpec textureStuffs[] = {
|
||||
{ kOfxImageEffectPropOpenGLTextureIndex, Property::eInt, 1, true, "-1" },
|
||||
{ kOfxImageEffectPropOpenGLTextureTarget, Property::eInt, 1, true, "-1" },
|
||||
Property::propSpecEnd
|
||||
};
|
||||
|
||||
Texture::Texture()
|
||||
: ImageBase()
|
||||
{
|
||||
addProperties(textureStuffs);
|
||||
}
|
||||
|
||||
/// make an image from a clip instance
|
||||
Texture::Texture(ClipInstance& instance)
|
||||
: ImageBase(instance)
|
||||
{
|
||||
addProperties(textureStuffs);
|
||||
}
|
||||
|
||||
// construction based on clip instance
|
||||
Texture::Texture(ClipInstance& instance,
|
||||
double renderScaleX,
|
||||
double renderScaleY,
|
||||
int index,
|
||||
int target,
|
||||
const OfxRectI &bounds,
|
||||
const OfxRectI &rod,
|
||||
int rowBytes,
|
||||
std::string field,
|
||||
std::string uniqueIdentifier)
|
||||
: ImageBase(instance, renderScaleX, renderScaleY, bounds, rod, rowBytes, field, uniqueIdentifier)
|
||||
{
|
||||
addProperties(textureStuffs);
|
||||
|
||||
// set other data
|
||||
setIntProperty(kOfxImageEffectPropOpenGLTextureIndex, index);
|
||||
setIntProperty(kOfxImageEffectPropOpenGLTextureTarget, target);
|
||||
}
|
||||
|
||||
|
||||
Texture::~Texture() {
|
||||
//assert(_referenceCount <= 0);
|
||||
}
|
||||
# endif
|
||||
} // Clip
|
||||
|
||||
} // Host
|
||||
|
||||
} // OFX
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <string.h>
|
||||
|
||||
// ofx
|
||||
#include "ofxCore.h"
|
||||
#include "ofxProperty.h"
|
||||
#include "ofxMultiThread.h"
|
||||
#include "ofxMemory.h"
|
||||
|
||||
#include "ofxhHost.h"
|
||||
|
||||
typedef OfxPlugin* (*OfxGetPluginType)(int);
|
||||
|
||||
namespace OFX {
|
||||
|
||||
namespace Host {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// simple memory suite
|
||||
namespace Memory {
|
||||
static OfxStatus memoryAlloc(void */*handle*/, size_t bytes, void **data)
|
||||
{
|
||||
*data = malloc(bytes);
|
||||
if (*data) {
|
||||
return kOfxStatOK;
|
||||
} else {
|
||||
return kOfxStatErrMemory;
|
||||
}
|
||||
}
|
||||
|
||||
static OfxStatus memoryFree(void *data)
|
||||
{
|
||||
free(data);
|
||||
return kOfxStatOK;
|
||||
}
|
||||
|
||||
static const struct OfxMemorySuiteV1 gMallocSuite = {
|
||||
memoryAlloc,
|
||||
memoryFree
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace OFX {
|
||||
namespace Host {
|
||||
/// our own internal property for storing away our private pointer to our host descriptor
|
||||
#define kOfxHostSupportHostPointer "sf.openfx.net.OfxHostSupportHostPointer"
|
||||
|
||||
static const Property::PropSpec hostStuffs[] = {
|
||||
{ kOfxPropAPIVersion, Property::eInt, 0, false, "" },
|
||||
{ kOfxPropType, Property::eString, 1, false, "Host" },
|
||||
{ kOfxPropName, Property::eString, 1, false, "UNKNOWN" },
|
||||
{ kOfxPropLabel, Property::eString, 1, false, "UNKNOWN" },
|
||||
{ kOfxPropVersion, Property::eInt, 0, false, "0" },
|
||||
{ kOfxPropVersionLabel, Property::eString, 1, false, "" },
|
||||
{ kOfxHostSupportHostPointer, Property::ePointer, 0, false, NULL },
|
||||
Property::propSpecEnd
|
||||
};
|
||||
|
||||
static const void *fetchSuite(OfxPropertySetHandle hostProps, const char *suiteName, int suiteVersion)
|
||||
{
|
||||
Property::Set* properties = reinterpret_cast<Property::Set*>(hostProps);
|
||||
|
||||
Host* host = (Host*)properties->getPointerProperty(kOfxHostSupportHostPointer);
|
||||
|
||||
if(host)
|
||||
return host->fetchSuite(suiteName,suiteVersion);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Base Host
|
||||
Host::Host() : _properties(hostStuffs)
|
||||
{
|
||||
_host.host = _properties.getHandle();
|
||||
_host.fetchSuite = OFX::Host::fetchSuite;
|
||||
|
||||
// record the host descriptor in the propert set
|
||||
_properties.setPointerProperty(kOfxHostSupportHostPointer,this);
|
||||
}
|
||||
|
||||
OfxHost *Host::getHandle() {
|
||||
return &_host;
|
||||
}
|
||||
|
||||
OfxStatus Host::message(const char* type,
|
||||
const char* id,
|
||||
const char* format,
|
||||
...) {
|
||||
try {
|
||||
OfxStatus stat;
|
||||
va_list args;
|
||||
va_start(args,format);
|
||||
stat = vmessage(type,id,format,args);
|
||||
va_end(args);
|
||||
return stat;
|
||||
} catch (...) {
|
||||
return kOfxStatFailed;
|
||||
}
|
||||
}
|
||||
|
||||
const void *Host::fetchSuite(const char *suiteName, int suiteVersion)
|
||||
{
|
||||
if (strcmp(suiteName, kOfxPropertySuite)==0 && suiteVersion == 1) {
|
||||
return Property::GetSuite(suiteVersion);
|
||||
}
|
||||
else if (strcmp(suiteName, kOfxMemorySuite)==0 && suiteVersion == 1) {
|
||||
return (void*)&Memory::gMallocSuite;
|
||||
}
|
||||
|
||||
///printf("fetchSuite failed with host = %p, name = %s, version = %i\n", this, suiteName, suiteVersion);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // Host
|
||||
|
||||
} // OFX
|
||||
+2809
File diff suppressed because it is too large
Load Diff
+592
@@ -0,0 +1,592 @@
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <ctype.h>
|
||||
|
||||
// ofx
|
||||
#include "ofxImageEffect.h"
|
||||
|
||||
// ofx host
|
||||
#include "ofxhBinary.h"
|
||||
#include "ofxhPropertySuite.h"
|
||||
#include "ofxhClip.h"
|
||||
#include "ofxhParam.h"
|
||||
#include "ofxhMemory.h"
|
||||
#include "ofxhImageEffect.h"
|
||||
#include "ofxhPluginAPICache.h"
|
||||
#include "ofxhPluginCache.h"
|
||||
#include "ofxhHost.h"
|
||||
#include "ofxhImageEffectAPI.h"
|
||||
#include "ofxhXml.h"
|
||||
|
||||
// Disable the "this pointer used in base member initialiser list" warning in Windows
|
||||
namespace OFX {
|
||||
|
||||
namespace Host {
|
||||
|
||||
namespace ImageEffect {
|
||||
|
||||
/// our global host bobject, set when the cache is created
|
||||
OFX::Host::ImageEffect::Host *gImageEffectHost;
|
||||
|
||||
/// ctor
|
||||
#ifdef WINDOWS
|
||||
#pragma warning( disable : 4355 )
|
||||
#endif
|
||||
ImageEffectPlugin::ImageEffectPlugin(PluginCache &pc, PluginBinary *pb, int pi, OfxPlugin *pl)
|
||||
: Plugin(pb, pi, pl)
|
||||
, _pc(pc)
|
||||
, _baseDescriptor(NULL)
|
||||
, _madeKnownContexts(false)
|
||||
{
|
||||
_baseDescriptor = gImageEffectHost->makeDescriptor(this);
|
||||
}
|
||||
|
||||
ImageEffectPlugin::ImageEffectPlugin(PluginCache &pc,
|
||||
PluginBinary *pb,
|
||||
int pi,
|
||||
const std::string &api,
|
||||
int apiVersion,
|
||||
const std::string &pluginId,
|
||||
const std::string &rawId,
|
||||
int pluginMajorVersion,
|
||||
int pluginMinorVersion)
|
||||
: Plugin(pb, pi, api, apiVersion, pluginId, rawId, pluginMajorVersion, pluginMinorVersion)
|
||||
, _pc(pc)
|
||||
, _baseDescriptor(NULL)
|
||||
, _madeKnownContexts(false)
|
||||
{
|
||||
_baseDescriptor = gImageEffectHost->makeDescriptor(this);
|
||||
}
|
||||
|
||||
#ifdef WINDOWS
|
||||
#pragma warning( default : 4355 )
|
||||
#endif
|
||||
|
||||
ImageEffectPlugin::~ImageEffectPlugin()
|
||||
{
|
||||
_contexts.clear();
|
||||
if(_pluginHandle) {
|
||||
OfxPlugin *op = _pluginHandle->getOfxPlugin();
|
||||
OfxStatus stat;
|
||||
try {
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)op<<"->"<<kOfxActionUnload<<"()"<<std::endl;
|
||||
# endif
|
||||
stat = op->mainEntry(kOfxActionUnload, 0, 0, 0);
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)op<<"->"<<kOfxActionUnload<<"()->"<<StatStr(stat)<<std::endl;
|
||||
# endif
|
||||
} CatchAllSetStatus(stat, gImageEffectHost, op, kOfxActionUnload);
|
||||
(void)stat;
|
||||
}
|
||||
delete _baseDescriptor;
|
||||
}
|
||||
|
||||
APICache::PluginAPICacheI &ImageEffectPlugin::getApiHandler()
|
||||
{
|
||||
return _pc;
|
||||
}
|
||||
|
||||
|
||||
/// get the image effect descriptor
|
||||
Descriptor &ImageEffectPlugin::getDescriptor() {
|
||||
return *_baseDescriptor;
|
||||
}
|
||||
|
||||
/// get the image effect descriptor const version
|
||||
const Descriptor &ImageEffectPlugin::getDescriptor() const {
|
||||
return *_baseDescriptor;
|
||||
}
|
||||
|
||||
void ImageEffectPlugin::addContext(const std::string &context, std::unique_ptr<Descriptor> ied)
|
||||
{
|
||||
_contexts[context] = std::move(ied);
|
||||
_knownContexts.insert(context);
|
||||
_madeKnownContexts = true;
|
||||
}
|
||||
|
||||
void ImageEffectPlugin::addContext(const std::string &context)
|
||||
{
|
||||
_knownContexts.insert(context);
|
||||
_madeKnownContexts = true;
|
||||
}
|
||||
|
||||
void ImageEffectPlugin::addContextInternal(const std::string &context) const
|
||||
{
|
||||
_knownContexts.insert(context);
|
||||
_madeKnownContexts = true;
|
||||
}
|
||||
|
||||
void ImageEffectPlugin::saveXML(std::ostream &os)
|
||||
{
|
||||
APICache::propertySetXMLWrite(os, getDescriptor().getProps(), 6);
|
||||
}
|
||||
|
||||
const std::set<std::string> &ImageEffectPlugin::getContexts() const {
|
||||
if (_madeKnownContexts) {
|
||||
return _knownContexts;
|
||||
}
|
||||
else {
|
||||
const OFX::Host::Property::Set &eProps = getDescriptor().getProps();
|
||||
int size = eProps.getDimension(kOfxImageEffectPropSupportedContexts);
|
||||
for (int j=0;j<size;j++) {
|
||||
std::string context = eProps.getStringProperty(kOfxImageEffectPropSupportedContexts, j);
|
||||
addContextInternal(context);
|
||||
}
|
||||
return _knownContexts;
|
||||
}
|
||||
}
|
||||
|
||||
PluginHandle *ImageEffectPlugin::getPluginHandle()
|
||||
{
|
||||
if(!_pluginHandle) {
|
||||
_pluginHandle.reset(new OFX::Host::PluginHandle(this, _pc.getHost()));
|
||||
|
||||
OfxPlugin *op = _pluginHandle->getOfxPlugin();
|
||||
|
||||
if (!op) {
|
||||
_pluginHandle.reset();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OfxStatus stat;
|
||||
try {
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)op<<"->"<<kOfxActionLoad<<"()"<<std::endl;
|
||||
# endif
|
||||
stat = op->mainEntry(kOfxActionLoad, 0, 0, 0);
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)op<<"->"<<kOfxActionLoad<<"()->"<<StatStr(stat)<<std::endl;
|
||||
# endif
|
||||
} CatchAllSetStatus(stat, gImageEffectHost, op, kOfxActionLoad);
|
||||
|
||||
if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
|
||||
_pluginHandle.reset();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
try {
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)op<<"->"<<kOfxActionDescribe<<"()"<<std::endl;
|
||||
# endif
|
||||
stat = op->mainEntry(kOfxActionDescribe, getDescriptor().getHandle(), 0, 0);
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)op<<"->"<<kOfxActionDescribe<<"()->"<<StatStr(stat)<<std::endl;
|
||||
# endif
|
||||
} CatchAllSetStatus(stat, gImageEffectHost, op, kOfxActionDescribe);
|
||||
|
||||
if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
|
||||
_pluginHandle.reset();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return _pluginHandle.get();
|
||||
}
|
||||
|
||||
Descriptor *ImageEffectPlugin::getContext(const std::string &context)
|
||||
{
|
||||
std::map<std::string, std::unique_ptr<Descriptor>>::iterator it = _contexts.find(context);
|
||||
|
||||
if (it != _contexts.end()) {
|
||||
//printf("found context description.\n");
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
if (_knownContexts.find(context) == _knownContexts.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// printf("doing context description.\n");
|
||||
|
||||
OFX::Host::Property::PropSpec inargspec[] = {
|
||||
{ kOfxImageEffectPropContext, OFX::Host::Property::eString, 1, true, context.c_str() },
|
||||
Property::propSpecEnd
|
||||
};
|
||||
|
||||
OFX::Host::Property::Set inarg(inargspec);
|
||||
|
||||
PluginHandle *ph = getPluginHandle();
|
||||
std::unique_ptr<ImageEffect::Descriptor> newContext( gImageEffectHost->makeDescriptor(getDescriptor(), this));
|
||||
|
||||
OfxStatus stat;
|
||||
try {
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)ph->getOfxPlugin()<<"->"<<kOfxImageEffectActionDescribeInContext<<"("<<context<<")"<<std::endl;
|
||||
# endif
|
||||
stat = ph->getOfxPlugin()->mainEntry(kOfxImageEffectActionDescribeInContext, newContext->getHandle(), inarg.getHandle(), 0);
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)ph->getOfxPlugin()<<"->"<<kOfxImageEffectActionDescribeInContext<<"("<<context<<")->"<<StatStr(stat)<<std::endl;
|
||||
# endif
|
||||
} CatchAllSetStatus(stat, gImageEffectHost, ph->getOfxPlugin(), kOfxImageEffectActionDescribeInContext);
|
||||
|
||||
if (stat == kOfxStatOK || stat == kOfxStatReplyDefault) {
|
||||
_contexts[context] = std::move(newContext);
|
||||
return _contexts[context].get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ImageEffect::Instance* ImageEffectPlugin::createInstance(const std::string &context, void *clientData)
|
||||
{
|
||||
|
||||
/// todo - we need to make sure action:load is called, then action:describe again
|
||||
/// (not because we are expecting the results to change, but because plugin
|
||||
/// might get confused otherwise), then a describe_in_context
|
||||
|
||||
getPluginHandle();
|
||||
|
||||
Descriptor *desc = getContext(context);
|
||||
|
||||
if (desc) {
|
||||
ImageEffect::Instance *instance = gImageEffectHost->newInstance(clientData,
|
||||
this,
|
||||
*desc,
|
||||
context);
|
||||
instance->populate();
|
||||
return instance;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ImageEffectPlugin::unload() {
|
||||
if (_pluginHandle) {
|
||||
OfxStatus stat;
|
||||
try {
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)_pluginHandle->getOfxPlugin()<<"->"<<kOfxActionUnload<<"()"<<std::endl;
|
||||
# endif
|
||||
stat = (*_pluginHandle)->mainEntry(kOfxActionUnload, 0, 0, 0);
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)_pluginHandle->getOfxPlugin()<<"->"<<kOfxActionUnload<<"()->"<<StatStr(stat)<<std::endl;
|
||||
# endif
|
||||
} CatchAllSetStatus(stat, gImageEffectHost, (*_pluginHandle), kOfxActionUnload);
|
||||
(void)stat;
|
||||
}
|
||||
}
|
||||
|
||||
PluginCache::PluginCache(OFX::Host::ImageEffect::Host &host)
|
||||
: PluginAPICacheI(kOfxImageEffectPluginApi, 1, 1)
|
||||
, _currentPlugin(0)
|
||||
, _currentProp(0)
|
||||
, _currentContext(0)
|
||||
, _currentParam(0)
|
||||
, _currentClip(0)
|
||||
, _host(&host)
|
||||
{
|
||||
gImageEffectHost = &host;
|
||||
}
|
||||
|
||||
PluginCache::~PluginCache() {}
|
||||
|
||||
/// get the plugin by id. vermaj and vermin can be specified. if they are not it will
|
||||
/// pick the highest found version.
|
||||
ImageEffectPlugin *PluginCache::getPluginById(const std::string &id, int vermaj, int vermin)
|
||||
{
|
||||
// return the highest version one, which fits the pattern provided
|
||||
ImageEffectPlugin *sofar = 0;
|
||||
std::string identifier = id;
|
||||
|
||||
// Who says the pluginIdentifier is case-insensitive? OFX 1.3 spec doesn't mention this.
|
||||
// http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#id472588
|
||||
//for (size_t i=0;i<identifier.size();i++) {
|
||||
// identifier[i] = tolower(identifier[i]);
|
||||
//}
|
||||
|
||||
for (std::vector<ImageEffectPlugin *>::iterator i=_plugins.begin();i!=_plugins.end();i++) {
|
||||
ImageEffectPlugin *p = *i;
|
||||
|
||||
if (p->getIdentifier() != identifier) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vermaj != -1 && p->getVersionMajor() != vermaj) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vermin != -1 && p->getVersionMinor() != vermin) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!sofar || p->trumps(sofar)) {
|
||||
sofar = p;
|
||||
}
|
||||
}
|
||||
|
||||
return sofar;
|
||||
}
|
||||
|
||||
/// whether we support this plugin.
|
||||
bool PluginCache::pluginSupported(OFX::Host::Plugin *p, std::string &reason) const {
|
||||
return gImageEffectHost->pluginSupported(dynamic_cast<OFX::Host::ImageEffect::ImageEffectPlugin *>(p), reason);
|
||||
}
|
||||
|
||||
/// get the plugin by label. vermaj and vermin can be specified. if they are not it will
|
||||
/// pick the highest found version.
|
||||
ImageEffectPlugin *PluginCache::getPluginByLabel(const std::string &label, int vermaj, int vermin)
|
||||
{
|
||||
// return the highest version one, which fits the pattern provided
|
||||
ImageEffectPlugin *sofar = 0;
|
||||
|
||||
for (std::vector<ImageEffectPlugin *>::iterator i=_plugins.begin();i!=_plugins.end();i++) {
|
||||
ImageEffectPlugin *p = *i;
|
||||
|
||||
if (p->getDescriptor().getProps().getStringProperty(kOfxPropLabel) != label) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vermaj != -1 && p->getVersionMajor() != vermaj) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vermin != -1 && p->getVersionMinor() != vermin) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!sofar || p->trumps(sofar)) {
|
||||
sofar = p;
|
||||
}
|
||||
}
|
||||
|
||||
return sofar;
|
||||
}
|
||||
|
||||
const std::vector<ImageEffectPlugin *>& PluginCache::getPlugins() const
|
||||
{
|
||||
return _plugins;
|
||||
}
|
||||
|
||||
const std::map<std::string, ImageEffectPlugin *>& PluginCache::getPluginsByID() const
|
||||
{
|
||||
return _pluginsByID;
|
||||
}
|
||||
|
||||
/// handle the case where the info needs filling in from the file. runs the "describe" action on the plugin.
|
||||
void PluginCache::loadFromPlugin(Plugin *op) const {
|
||||
std::string msg = "loading ";
|
||||
msg += op->getRawIdentifier();
|
||||
|
||||
_host->loadingStatus(msg);
|
||||
|
||||
ImageEffectPlugin *p = dynamic_cast<ImageEffectPlugin*>(op);
|
||||
assert(p);
|
||||
|
||||
PluginHandle plug(p, _host);
|
||||
|
||||
OfxStatus stat;
|
||||
try {
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)plug.getOfxPlugin()<<"->"<<kOfxActionLoad<<"()"<<std::endl;
|
||||
# endif
|
||||
stat = plug->mainEntry(kOfxActionLoad, 0, 0, 0);
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)plug.getOfxPlugin()<<"->"<<kOfxActionLoad<<"()->"<<StatStr(stat)<<std::endl;
|
||||
# endif
|
||||
} CatchAllSetStatus(stat, gImageEffectHost, plug, kOfxActionLoad);
|
||||
|
||||
if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
|
||||
std::cerr << "load failed on plugin " << op->getIdentifier() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)plug.getOfxPlugin()<<"->"<<kOfxActionDescribe<<"()"<<std::endl;
|
||||
# endif
|
||||
stat = plug->mainEntry(kOfxActionDescribe, p->getDescriptor().getHandle(), 0, 0);
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)plug.getOfxPlugin()<<"->"<<kOfxActionDescribe<<"()->"<<StatStr(stat)<<std::endl;
|
||||
# endif
|
||||
} CatchAllSetStatus(stat, gImageEffectHost, plug, kOfxActionDescribe);
|
||||
|
||||
if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
|
||||
std::cerr << "describe failed on plugin " << op->getIdentifier() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
ImageEffect::Descriptor &e = p->getDescriptor();
|
||||
Property::Set &eProps = e.getProps();
|
||||
|
||||
int size = eProps.getDimension(kOfxImageEffectPropSupportedContexts);
|
||||
|
||||
for (int j=0;j<size;j++) {
|
||||
std::string context = eProps.getStringProperty(kOfxImageEffectPropSupportedContexts, j);
|
||||
p->addContext(context);
|
||||
}
|
||||
|
||||
try {
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)plug.getOfxPlugin()<<"->"<<kOfxActionUnload<<"()"<<std::endl;
|
||||
# endif
|
||||
stat = plug->mainEntry(kOfxActionUnload, 0, 0, 0);
|
||||
# ifdef OFX_DEBUG_ACTIONS
|
||||
std::cout << "OFX: "<<(void*)plug.getOfxPlugin()<<"->"<<kOfxActionUnload<<"()->"<<StatStr(stat)<<std::endl;
|
||||
# endif
|
||||
} CatchAllSetStatus(stat, gImageEffectHost, plug, kOfxActionUnload);
|
||||
|
||||
if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
|
||||
std::cerr << "unload failed on plugin " << op->getIdentifier() << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// handler for preparing to read in a chunk of XML from the cache, set up context to do this
|
||||
void PluginCache::beginXmlParsing(Plugin *p) {
|
||||
_currentPlugin = dynamic_cast<ImageEffectPlugin*>(p);
|
||||
}
|
||||
|
||||
/// XML handler : element begins (everything is stored in elements and attributes)
|
||||
void PluginCache::xmlElementBegin(const std::string &el, std::map<std::string, std::string> map)
|
||||
{
|
||||
if (el == "apiproperties") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (el == "context") {
|
||||
std::unique_ptr<Descriptor> newContext(gImageEffectHost->makeDescriptor(_currentPlugin->getBinary()->getBundlePath(), _currentPlugin));
|
||||
_currentContext = newContext.get();
|
||||
_currentPlugin->addContext(map["name"], std::move(newContext));
|
||||
return;
|
||||
}
|
||||
|
||||
if (el == "param" && _currentContext) {
|
||||
std::string pname = map["name"];
|
||||
std::string ptype = map["type"];
|
||||
|
||||
_currentParam = _currentContext->paramDefine(ptype.c_str(), pname.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (el == "clip" && _currentContext) {
|
||||
std::string cname = map["name"];
|
||||
|
||||
_currentClip = new ClipDescriptor(cname);
|
||||
_currentContext->addClip(cname, _currentClip);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentContext && _currentParam) {
|
||||
APICache::propertySetXMLRead(el, map, _currentParam->getProperties(), _currentProp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentContext && _currentClip) {
|
||||
APICache::propertySetXMLRead(el, map, _currentClip->getProps(), _currentProp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_currentContext && !_currentParam) {
|
||||
APICache::propertySetXMLRead(el, map, _currentPlugin->getDescriptor().getProps(), _currentProp);
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "element " << el << "\n";
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void PluginCache::xmlCharacterHandler(const std::string &) {
|
||||
}
|
||||
|
||||
void PluginCache::xmlElementEnd(const std::string &el) {
|
||||
if (el == "param") {
|
||||
_currentParam = 0;
|
||||
}
|
||||
|
||||
if (el == "context") {
|
||||
_currentContext = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PluginCache::endXmlParsing() {
|
||||
_currentPlugin = 0;
|
||||
}
|
||||
|
||||
void PluginCache::saveXML(Plugin *ip, std::ostream &os) const {
|
||||
ImageEffectPlugin *p = dynamic_cast<ImageEffectPlugin*>(ip);
|
||||
if (p) {
|
||||
p->saveXML(os);
|
||||
}
|
||||
}
|
||||
|
||||
void PluginCache::confirmPlugin(Plugin *p) {
|
||||
ImageEffectPlugin *plugin = dynamic_cast<ImageEffectPlugin*>(p);
|
||||
if (!plugin) {
|
||||
return;
|
||||
}
|
||||
_plugins.push_back(plugin);
|
||||
|
||||
if (_pluginsByID.find(plugin->getIdentifier()) != _pluginsByID.end()) {
|
||||
ImageEffectPlugin *otherPlugin = _pluginsByID[plugin->getIdentifier()];
|
||||
if (plugin->trumps(otherPlugin)) {
|
||||
_pluginsByID[plugin->getIdentifier()] = plugin;
|
||||
}
|
||||
} else {
|
||||
_pluginsByID[plugin->getIdentifier()] = plugin;
|
||||
}
|
||||
|
||||
MajorPlugin maj(plugin);
|
||||
|
||||
if (_pluginsByIDMajor.find(maj) != _pluginsByIDMajor.end()) {
|
||||
ImageEffectPlugin *otherPlugin = _pluginsByIDMajor[maj];
|
||||
if (plugin->trumps(otherPlugin)) {
|
||||
_pluginsByIDMajor[maj] = plugin;
|
||||
}
|
||||
} else {
|
||||
_pluginsByIDMajor[maj] = plugin;
|
||||
}
|
||||
}
|
||||
|
||||
Plugin *PluginCache::newPlugin(PluginBinary *pb,
|
||||
int pi,
|
||||
OfxPlugin *pl) {
|
||||
ImageEffectPlugin *plugin = new ImageEffectPlugin(*this, pb, pi, pl);
|
||||
return plugin;
|
||||
}
|
||||
|
||||
Plugin *PluginCache::newPlugin(PluginBinary *pb,
|
||||
int pi,
|
||||
const std::string &api,
|
||||
int apiVersion,
|
||||
const std::string &pluginId,
|
||||
const std::string &rawId,
|
||||
int pluginMajorVersion,
|
||||
int pluginMinorVersion)
|
||||
{
|
||||
ImageEffectPlugin *plugin = new ImageEffectPlugin(*this, pb, pi, api, apiVersion, pluginId, rawId, pluginMajorVersion, pluginMinorVersion);
|
||||
return plugin;
|
||||
}
|
||||
|
||||
void PluginCache::dumpToStdOut()
|
||||
{
|
||||
if (_pluginsByID.empty())
|
||||
std::cout << "No Plug-ins Found." << std::endl;
|
||||
|
||||
for(std::map<std::string, ImageEffectPlugin *>::const_iterator it = _pluginsByID.begin(); it != _pluginsByID.end(); ++it)
|
||||
{
|
||||
std::cout << "Plug-in:" << it->first << std::endl;
|
||||
std::cout << "\t" << "Filepath: " << it->second->getBinary()->getFilePath();
|
||||
std::cout<< "(" << it->second->getIndex() << ")" << std::endl;
|
||||
|
||||
std::cout << "Contexts:" << std::endl;
|
||||
const std::set<std::string>& contexts = it->second->getContexts();
|
||||
for (std::set<std::string>::const_iterator it2 = contexts.begin(); it2 != contexts.end(); ++it2)
|
||||
std::cout << "\t* " << *it2 << std::endl;
|
||||
const Descriptor& d = it->second->getDescriptor();
|
||||
std::cout << "Inputs:" << std::endl;
|
||||
const std::map<std::string, ClipDescriptor*>& inputs = d.getClips();
|
||||
for (std::map<std::string, ClipDescriptor*>::const_iterator it2 = inputs.begin(); it2 != inputs.end(); ++it2)
|
||||
std::cout << "\t\t* " << it2->first << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} // ImageEffect
|
||||
|
||||
} // Host
|
||||
|
||||
} // OFX
|
||||
|
||||
+444
@@ -0,0 +1,444 @@
|
||||
|
||||
|
||||
// ofx
|
||||
#include "ofxKeySyms.h"
|
||||
#include "ofxCore.h"
|
||||
#include "ofxImageEffect.h"
|
||||
|
||||
// ofx host
|
||||
#include "ofxhBinary.h"
|
||||
#include "ofxhPropertySuite.h"
|
||||
#include "ofxhClip.h"
|
||||
#include "ofxhParam.h"
|
||||
#include "ofxhMemory.h"
|
||||
#include "ofxhImageEffect.h"
|
||||
#include "ofxhInteract.h"
|
||||
#include "ofxOld.h" // old plugins may rely on deprecated properties being present
|
||||
|
||||
namespace OFX {
|
||||
|
||||
namespace Host {
|
||||
|
||||
namespace Interact {
|
||||
|
||||
//
|
||||
// descriptor
|
||||
//
|
||||
static const Property::PropSpec interactDescriptorStuffs[] = {
|
||||
{ kOfxInteractPropHasAlpha , Property::eInt, 1, true, "0" },
|
||||
{ kOfxInteractPropBitDepth , Property::eInt, 1, true, "0" },
|
||||
Property::propSpecEnd
|
||||
};
|
||||
|
||||
Descriptor::Descriptor()
|
||||
: _properties(interactDescriptorStuffs)
|
||||
, _state(eUninitialised)
|
||||
, _entryPoint(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Descriptor::~Descriptor()
|
||||
{
|
||||
}
|
||||
|
||||
/// call describe on this descriptor
|
||||
bool Descriptor::describe(int bitDepthPerComponent, bool hasAlpha)
|
||||
{
|
||||
if(_state == eUninitialised) {
|
||||
_properties.setIntProperty(kOfxInteractPropBitDepth, bitDepthPerComponent);
|
||||
_properties.setIntProperty(kOfxInteractPropHasAlpha, (int)(hasAlpha));
|
||||
|
||||
OfxStatus stat = callEntry(kOfxActionDescribe, getHandle(), NULL, NULL);
|
||||
if(stat == kOfxStatOK || stat == kOfxStatReplyDefault) {
|
||||
_state = eDescribed;
|
||||
}
|
||||
else {
|
||||
_state = eFailed;
|
||||
}
|
||||
}
|
||||
return _state == eDescribed;
|
||||
}
|
||||
|
||||
// call the interactive entry point
|
||||
OfxStatus Descriptor::callEntry(const char *action,
|
||||
void *handle,
|
||||
OfxPropertySetHandle inArgs,
|
||||
OfxPropertySetHandle outArgs)
|
||||
{
|
||||
if(_entryPoint && _state != eFailed) {
|
||||
return _entryPoint(action, handle, inArgs, outArgs);
|
||||
}
|
||||
else
|
||||
return kOfxStatFailed;
|
||||
|
||||
return kOfxStatOK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static const Property::PropSpec interactInstanceStuffs[] = {
|
||||
{ kOfxPropEffectInstance, Property::ePointer, 1, true, NULL },
|
||||
{ kOfxPropInstanceData, Property::ePointer, 1, false, NULL },
|
||||
{ kOfxInteractPropPixelScale, Property::eDouble, 2, true, "1.0f" },
|
||||
{ kOfxInteractPropBackgroundColour , Property::eDouble, 3, true, "0.0f" },
|
||||
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
|
||||
{ kOfxInteractPropViewportSize, Property::eDouble, 2, true, "100.0f" },
|
||||
#endif
|
||||
{ kOfxInteractPropSlaveToParam , Property::eString, 0, false, ""},
|
||||
{ kOfxInteractPropSuggestedColour , Property::eDouble, 3, true, "1.0f" },
|
||||
Property::propSpecEnd
|
||||
};
|
||||
|
||||
static const Property::PropSpec interactArgsStuffs[] = {
|
||||
{ kOfxPropEffectInstance, Property::ePointer, 1, false, NULL },
|
||||
{ kOfxPropTime, Property::eDouble, 1, false, "0.0" },
|
||||
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, false, "0.0" },
|
||||
{ kOfxInteractPropBackgroundColour , Property::eDouble, 3, false, "0.0f" },
|
||||
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
|
||||
{ kOfxInteractPropViewportSize, Property::eDouble, 2, false, "0.0f" },
|
||||
#endif
|
||||
{ kOfxInteractPropPixelScale, Property::eDouble, 2, false, "1.0f" },
|
||||
{ kOfxInteractPropPenPosition, Property::eDouble, 2, false, "0.0" },
|
||||
{ kOfxInteractPropPenViewportPosition, Property::eInt, 2, false, "0" }, // new in OFX 1.2
|
||||
{ kOfxInteractPropPenPressure, Property::eDouble, 1, false, "0.0" },
|
||||
{ kOfxPropKeyString, Property::eString, 1, false, "" },
|
||||
{ kOfxPropKeySym, Property::eInt, 1, false, "0" },
|
||||
Property::propSpecEnd
|
||||
};
|
||||
|
||||
// instance
|
||||
|
||||
Instance::Instance(Descriptor& desc, void *effectInstance)
|
||||
: _descriptor(desc)
|
||||
, _properties(interactInstanceStuffs)
|
||||
, _state(desc.getState())
|
||||
, _effectInstance(effectInstance)
|
||||
, _argProperties(interactArgsStuffs)
|
||||
{
|
||||
_properties.setPointerProperty(kOfxPropEffectInstance, effectInstance);
|
||||
_properties.setChainedSet(&desc.getProperties()); /// chain it into the descriptor props
|
||||
_properties.setGetHook(kOfxInteractPropPixelScale, this);
|
||||
_properties.setGetHook(kOfxInteractPropBackgroundColour,this);
|
||||
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
|
||||
_properties.setGetHook(kOfxInteractPropViewportSize,this);
|
||||
#endif
|
||||
_properties.setGetHook(kOfxInteractPropSuggestedColour,this);
|
||||
|
||||
_argProperties.setGetHook(kOfxInteractPropPixelScale, this);
|
||||
_argProperties.setGetHook(kOfxInteractPropBackgroundColour,this);
|
||||
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
|
||||
_argProperties.setGetHook(kOfxInteractPropViewportSize,this);
|
||||
#endif
|
||||
}
|
||||
|
||||
Instance::~Instance()
|
||||
{
|
||||
/// call it directly incase CI failed and we should always tidy up after create instance
|
||||
callEntry(kOfxActionDestroyInstance, NULL);
|
||||
}
|
||||
|
||||
/// call the entry point in the descriptor with action and the given args
|
||||
OfxStatus Instance::callEntry(const char *action, Property::Set *inArgs)
|
||||
{
|
||||
if(_state != eFailed) {
|
||||
OfxPropertySetHandle inHandle = inArgs ? inArgs->getHandle() : NULL ;
|
||||
return _descriptor.callEntry(action, getHandle(), inHandle, NULL);
|
||||
}
|
||||
return kOfxStatFailed;
|
||||
}
|
||||
|
||||
// do nothing
|
||||
int Instance::getDimension(const std::string &name) const
|
||||
{
|
||||
if(name == kOfxInteractPropPixelScale){
|
||||
return 2;
|
||||
}
|
||||
else if(name == kOfxInteractPropBackgroundColour){
|
||||
return 3;
|
||||
}
|
||||
else if(name == kOfxInteractPropSuggestedColour
|
||||
){
|
||||
return 3;
|
||||
}
|
||||
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
|
||||
else if(name == kOfxInteractPropViewportSize){
|
||||
return 2;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw Property::Exception(kOfxStatErrValue);
|
||||
}
|
||||
|
||||
// do nothing function
|
||||
void Instance::reset(const std::string &/*name*/)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
double Instance::getDoubleProperty(const std::string &name, int index) const
|
||||
{
|
||||
if(name == kOfxInteractPropPixelScale){
|
||||
if(index>=2) throw Property::Exception(kOfxStatErrBadIndex);
|
||||
double first[2];
|
||||
getPixelScale(first[0],first[1]);
|
||||
return first[index];
|
||||
}
|
||||
else if(name == kOfxInteractPropBackgroundColour){
|
||||
if(index>=3) throw Property::Exception(kOfxStatErrBadIndex);
|
||||
double first[3];
|
||||
getBackgroundColour(first[0],first[1],first[2]);
|
||||
return first[index];
|
||||
}
|
||||
else if(name == kOfxInteractPropSuggestedColour
|
||||
){
|
||||
if(index>=3) throw Property::Exception(kOfxStatErrBadIndex);
|
||||
double first[3];
|
||||
bool stat = getSuggestedColour(first[0],first[1],first[2]);
|
||||
if (!stat) throw Property::Exception(kOfxStatReplyDefault);
|
||||
return first[index];
|
||||
}
|
||||
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
|
||||
else if(name == kOfxInteractPropViewportSize){
|
||||
if(index>=2) throw Property::Exception(kOfxStatErrBadIndex);
|
||||
double first[2];
|
||||
getViewportSize(first[0],first[1]);
|
||||
return first[index];
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw Property::Exception(kOfxStatErrUnknown);
|
||||
}
|
||||
|
||||
void Instance::getDoublePropertyN(const std::string &name, double *first, int n) const
|
||||
{
|
||||
if(name == kOfxInteractPropPixelScale){
|
||||
if(n>2) throw Property::Exception(kOfxStatErrBadIndex);
|
||||
getPixelScale(first[0],first[1]);
|
||||
}
|
||||
else if(name == kOfxInteractPropBackgroundColour){
|
||||
if(n>3) throw Property::Exception(kOfxStatErrBadIndex);
|
||||
getBackgroundColour(first[0],first[1],first[2]);
|
||||
}
|
||||
else if(name == kOfxInteractPropSuggestedColour
|
||||
){
|
||||
if(n>3) throw Property::Exception(kOfxStatErrBadIndex);
|
||||
bool stat = getSuggestedColour(first[0],first[1],first[2]);
|
||||
if (!stat) throw Property::Exception(kOfxStatReplyDefault);
|
||||
}
|
||||
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
|
||||
else if(name == kOfxInteractPropViewportSize){
|
||||
if(n>2) throw Property::Exception(kOfxStatErrBadIndex);
|
||||
getViewportSize(first[0],first[1]);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw Property::Exception(kOfxStatErrUnknown);
|
||||
}
|
||||
|
||||
void Instance::getSlaveToParam(std::vector<std::string>& params) const
|
||||
{
|
||||
int nSlaveParams = _properties.getDimension(kOfxInteractPropSlaveToParam);
|
||||
|
||||
for (int i=0; i<nSlaveParams; i++) {
|
||||
std::string param = _properties.getStringProperty(kOfxInteractPropSlaveToParam, i);
|
||||
params.push_back(param);
|
||||
}
|
||||
}
|
||||
|
||||
/// initialise the argument properties
|
||||
void Instance::initArgProp(OfxTime time,
|
||||
const OfxPointD &renderScale)
|
||||
{
|
||||
double pixelScale[2];
|
||||
getPixelScale(pixelScale[0], pixelScale[1]);
|
||||
_argProperties.setDoublePropertyN(kOfxInteractPropPixelScale, pixelScale, 2);
|
||||
_argProperties.setPointerProperty(kOfxPropEffectInstance, _effectInstance);
|
||||
_argProperties.setPointerProperty(kOfxPropInstanceData, _properties.getPointerProperty(kOfxPropInstanceData));
|
||||
_argProperties.setDoubleProperty(kOfxPropTime,time);
|
||||
_argProperties.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2);
|
||||
}
|
||||
|
||||
void Instance::setPenArgProps(const OfxPointD &penPos,
|
||||
const OfxPointI &penPosViewport,
|
||||
double pressure)
|
||||
{
|
||||
_argProperties.setDoublePropertyN(kOfxInteractPropPenPosition, &penPos.x, 2);
|
||||
_argProperties.setIntPropertyN(kOfxInteractPropPenViewportPosition, &penPosViewport.x, 2); // new in OFX 1.2
|
||||
_argProperties.setDoubleProperty(kOfxInteractPropPenPressure, pressure);
|
||||
}
|
||||
|
||||
void Instance::setKeyArgProps(int key,
|
||||
char* keyString)
|
||||
{
|
||||
_argProperties.setIntProperty(kOfxPropKeySym,key);
|
||||
_argProperties.setStringProperty(kOfxPropKeyString,keyString);
|
||||
}
|
||||
|
||||
OfxStatus Instance::createInstanceAction()
|
||||
{
|
||||
OfxStatus stat = callEntry(kOfxActionCreateInstance, NULL);
|
||||
if(stat == kOfxStatOK || stat == kOfxStatReplyDefault) {
|
||||
_state = eCreated;
|
||||
}
|
||||
else {
|
||||
_state = eFailed;
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
OfxStatus Instance::drawAction(OfxTime time,
|
||||
const OfxPointD &renderScale)
|
||||
{
|
||||
initArgProp(time, renderScale);
|
||||
return callEntry(kOfxInteractActionDraw, &_argProperties);
|
||||
}
|
||||
|
||||
OfxStatus Instance::penMotionAction(OfxTime time,
|
||||
const OfxPointD &renderScale,
|
||||
const OfxPointD &penPos,
|
||||
const OfxPointI &penPosViewport,
|
||||
double pressure)
|
||||
{
|
||||
initArgProp(time, renderScale);
|
||||
setPenArgProps(penPos, penPosViewport, pressure);
|
||||
return callEntry(kOfxInteractActionPenMotion,&_argProperties);
|
||||
}
|
||||
|
||||
OfxStatus Instance::penUpAction(OfxTime time,
|
||||
const OfxPointD &renderScale,
|
||||
const OfxPointD &penPos,
|
||||
const OfxPointI &penPosViewport,
|
||||
double pressure)
|
||||
{
|
||||
initArgProp(time, renderScale);
|
||||
setPenArgProps(penPos, penPosViewport, pressure);
|
||||
return callEntry(kOfxInteractActionPenUp,&_argProperties);
|
||||
}
|
||||
|
||||
OfxStatus Instance::penDownAction(OfxTime time,
|
||||
const OfxPointD &renderScale,
|
||||
const OfxPointD &penPos,
|
||||
const OfxPointI &penPosViewport,
|
||||
double pressure)
|
||||
{
|
||||
initArgProp(time, renderScale);
|
||||
setPenArgProps(penPos, penPosViewport, pressure);
|
||||
return callEntry(kOfxInteractActionPenDown,&_argProperties);
|
||||
}
|
||||
|
||||
OfxStatus Instance::keyDownAction(OfxTime time,
|
||||
const OfxPointD &renderScale,
|
||||
int key,
|
||||
char* keyString)
|
||||
{
|
||||
initArgProp(time, renderScale);
|
||||
setKeyArgProps(key, keyString);
|
||||
return callEntry(kOfxInteractActionKeyDown,&_argProperties);
|
||||
}
|
||||
|
||||
OfxStatus Instance::keyUpAction(OfxTime time,
|
||||
const OfxPointD &renderScale,
|
||||
int key,
|
||||
char* keyString)
|
||||
{
|
||||
initArgProp(time, renderScale);
|
||||
setKeyArgProps(key, keyString);
|
||||
return callEntry(kOfxInteractActionKeyUp,&_argProperties);
|
||||
}
|
||||
|
||||
OfxStatus Instance::keyRepeatAction(OfxTime time,
|
||||
const OfxPointD &renderScale,
|
||||
int key,
|
||||
char* keyString)
|
||||
{
|
||||
initArgProp(time, renderScale);
|
||||
setKeyArgProps(key, keyString);
|
||||
return callEntry(kOfxInteractActionKeyRepeat,&_argProperties);
|
||||
}
|
||||
|
||||
OfxStatus Instance::gainFocusAction(OfxTime time,
|
||||
const OfxPointD &renderScale)
|
||||
{
|
||||
initArgProp(time, renderScale);
|
||||
return callEntry(kOfxInteractActionGainFocus,&_argProperties);
|
||||
}
|
||||
|
||||
OfxStatus Instance::loseFocusAction(OfxTime time,
|
||||
const OfxPointD &renderScale)
|
||||
{
|
||||
initArgProp(time, renderScale);
|
||||
return callEntry(kOfxInteractActionLoseFocus,&_argProperties);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Interact suite functions
|
||||
|
||||
static OfxStatus interactSwapBuffers(OfxInteractHandle handle)
|
||||
{
|
||||
try {
|
||||
Interact::Instance *interactInstance = reinterpret_cast<Interact::Instance*>(handle);
|
||||
if(interactInstance)
|
||||
return interactInstance->swapBuffers();
|
||||
else
|
||||
return kOfxStatErrBadHandle;
|
||||
} catch (...) {
|
||||
return kOfxStatFailed;
|
||||
}
|
||||
}
|
||||
|
||||
static OfxStatus interactRedraw(OfxInteractHandle handle)
|
||||
{
|
||||
try {
|
||||
Interact::Instance *interactInstance = reinterpret_cast<Interact::Instance*>(handle);
|
||||
if(interactInstance)
|
||||
return interactInstance->redraw();
|
||||
else
|
||||
return kOfxStatErrBadHandle;
|
||||
} catch (...) {
|
||||
return kOfxStatFailed;
|
||||
}
|
||||
}
|
||||
|
||||
static OfxStatus interactGetPropertySet(OfxInteractHandle handle, OfxPropertySetHandle *property)
|
||||
{
|
||||
try {
|
||||
Interact::Base *interact = reinterpret_cast<Interact::Base*>(handle);
|
||||
if (!property) {
|
||||
return kOfxStatErrBadHandle;
|
||||
}
|
||||
|
||||
if (interact) {
|
||||
*property = interact->getPropHandle();
|
||||
|
||||
return kOfxStatOK;
|
||||
}
|
||||
*property = NULL;
|
||||
|
||||
return kOfxStatErrBadHandle;
|
||||
} catch (...) {
|
||||
return kOfxStatFailed;
|
||||
}
|
||||
}
|
||||
|
||||
/// the interact suite
|
||||
static const OfxInteractSuiteV1 gSuite = {
|
||||
interactSwapBuffers,
|
||||
interactRedraw,
|
||||
interactGetPropertySet
|
||||
};
|
||||
|
||||
/// function to get the sutie
|
||||
const void *GetSuite(int version) {
|
||||
if(version == 1)
|
||||
return (void *) &gSuite;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
} // Interact
|
||||
|
||||
} // Host
|
||||
|
||||
} // OFX
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
|
||||
|
||||
// ofx host
|
||||
|
||||
// ofx
|
||||
#include "ofxCore.h"
|
||||
#include "ofxImageEffect.h"
|
||||
|
||||
// ofx host
|
||||
#include "ofxhMemory.h"
|
||||
|
||||
namespace OFX {
|
||||
|
||||
namespace Host {
|
||||
|
||||
namespace Memory {
|
||||
|
||||
Instance::Instance() : _ptr(0), _locked(0) {}
|
||||
|
||||
Instance::~Instance() {
|
||||
delete [] _ptr;
|
||||
}
|
||||
|
||||
bool Instance::alloc(size_t nBytes) {
|
||||
if(!_locked){
|
||||
if(_ptr)
|
||||
freeMem();
|
||||
_ptr = new char[nBytes];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
OfxImageMemoryHandle Instance::getHandle(){
|
||||
return (OfxImageMemoryHandle)this;
|
||||
}
|
||||
|
||||
void Instance::freeMem(){
|
||||
delete [] _ptr;
|
||||
_ptr = 0;
|
||||
_locked = 0;
|
||||
}
|
||||
|
||||
void* Instance::getPtr() {
|
||||
return _ptr;
|
||||
}
|
||||
|
||||
void Instance::lock() {
|
||||
++_locked;
|
||||
}
|
||||
|
||||
void Instance::unlock() {
|
||||
if (_locked > 0) {
|
||||
--_locked;
|
||||
}
|
||||
}
|
||||
|
||||
} // Memory
|
||||
|
||||
} // Host
|
||||
|
||||
} // OFX
|
||||
|
||||
+2300
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,135 @@
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
// ofx
|
||||
#include "ofxCore.h"
|
||||
#include "ofxImageEffect.h"
|
||||
|
||||
// ofx host
|
||||
#include "ofxhBinary.h"
|
||||
#include "ofxhPropertySuite.h"
|
||||
#include "ofxhClip.h"
|
||||
#include "ofxhParam.h"
|
||||
#include "ofxhMemory.h"
|
||||
#include "ofxhImageEffect.h"
|
||||
#include "ofxhPluginAPICache.h"
|
||||
#include "ofxhPluginCache.h"
|
||||
#include "ofxhHost.h"
|
||||
#include "ofxhImageEffectAPI.h"
|
||||
#include "ofxhXml.h"
|
||||
|
||||
namespace OFX
|
||||
{
|
||||
namespace Host
|
||||
{
|
||||
namespace APICache
|
||||
{
|
||||
void PluginAPICacheI::registerInCache(OFX::Host::PluginCache &pluginCache) {
|
||||
pluginCache.registerAPICache(_apiName, _apiVersionMin, _apiVersionMax, this);
|
||||
}
|
||||
|
||||
void propertySetXMLRead(const std::string &el,
|
||||
std::map<std::string, std::string> map,
|
||||
Property::Set &set,
|
||||
Property::Property *¤tProp) {
|
||||
if (el == "property") {
|
||||
std::string propName = map["name"];
|
||||
std::string propType = map["type"];
|
||||
int dimension = atoi(map["dimension"].c_str());
|
||||
|
||||
currentProp = set.fetchProperty(propName, false);
|
||||
|
||||
if(!currentProp) {
|
||||
if (propType == "int") {
|
||||
currentProp = new Property::Int(propName, dimension, false, 0);
|
||||
} else if (propType == "string") {
|
||||
currentProp = new Property::String(propName, dimension, false, "");
|
||||
} else if (propType == "double") {
|
||||
currentProp = new Property::Double(propName, dimension, false, 0);
|
||||
} else if (propType == "pointer") {
|
||||
currentProp = new Property::Pointer(propName, dimension, false, 0);
|
||||
}
|
||||
set.addProperty(currentProp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (el == "value" && currentProp) {
|
||||
int index = atoi(map["index"].c_str());
|
||||
std::string value = map["value"];
|
||||
|
||||
switch (currentProp->getType()) {
|
||||
case Property::eInt:
|
||||
set.setIntProperty(currentProp->getName(), atoi(value.c_str()), index);
|
||||
break;
|
||||
case Property::eString:
|
||||
set.setStringProperty(currentProp->getName(), value, index);
|
||||
break;
|
||||
case Property::eDouble:
|
||||
set.setDoubleProperty(currentProp->getName(), atof(value.c_str()), index);
|
||||
break;
|
||||
case Property::ePointer:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "got unrecognised key " << el << "\n";
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
static void propertyXMLWrite(std::ostream &o, Property::Property *prop, const std::string &indent="")
|
||||
{
|
||||
if (prop->getType() != Property::ePointer) {
|
||||
|
||||
o << indent << "<property "
|
||||
<< XML::attribute("name", prop->getName())
|
||||
<< XML::attribute("type", Property::gTypeNames[prop->getType()])
|
||||
<< XML::attribute("dimension", prop->getFixedDimension())
|
||||
<< ">\n";
|
||||
|
||||
for (int i=0;i<prop->getDimension();i++) {
|
||||
o << indent << " <value "
|
||||
<< XML::attribute("index", i)
|
||||
<< XML::attribute("value", prop->getStringValue(i))
|
||||
<< "/>\n";
|
||||
}
|
||||
|
||||
o << indent << "</property>\n";
|
||||
}
|
||||
}
|
||||
|
||||
void propertyXMLWrite(std::ostream &o, const Property::Set &set, const std::string &name, int indent)
|
||||
{
|
||||
Property::Property *prop = set.fetchProperty(name);
|
||||
|
||||
if(prop) {
|
||||
std::string indent_prefix(indent, ' ');
|
||||
propertyXMLWrite(o, prop, indent_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
void propertySetXMLWrite(std::ostream &o, const Property::Set &set, int indent)
|
||||
{
|
||||
std::string indent_prefix(indent, ' ');
|
||||
|
||||
for (Property::PropertyMap::const_iterator i = set.getProperties().begin();
|
||||
i != set.getProperties().end();
|
||||
i++)
|
||||
{
|
||||
Property::Property *prop = i->second;
|
||||
propertyXMLWrite(o, prop, indent_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,694 @@
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "expat.h"
|
||||
|
||||
// ofx
|
||||
#include "ofxCore.h"
|
||||
#include "ofxImageEffect.h"
|
||||
|
||||
// ofx host
|
||||
#include "ofxhBinary.h"
|
||||
#include "ofxhPropertySuite.h"
|
||||
#include "ofxhMemory.h"
|
||||
#include "ofxhPluginAPICache.h"
|
||||
#include "ofxhPluginCache.h"
|
||||
#include "ofxhHost.h"
|
||||
#include "ofxhXml.h"
|
||||
|
||||
#if defined (__linux__) || defined (__FreeBSD__)
|
||||
|
||||
#define DIRLIST_SEP_CHARS ":;"
|
||||
#define DIRSEP "/"
|
||||
#include <dirent.h>
|
||||
|
||||
static const char *getArchStr()
|
||||
{
|
||||
if(sizeof(void *) == 4) {
|
||||
#if defined(__linux__)
|
||||
return "Linux-x86";
|
||||
#else
|
||||
return "FreeBSD-x86";
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#if defined(__linux__)
|
||||
return "Linux-x86-64";
|
||||
#else
|
||||
return "FreeBSD-x86-64";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#define ARCHSTR getArchStr()
|
||||
|
||||
#elif defined (__APPLE__)
|
||||
|
||||
#define DIRLIST_SEP_CHARS ";:"
|
||||
#if defined(__x86_64) || defined(__x86_64__)
|
||||
#define ARCHSTR "MacOS-x86-64"
|
||||
#else
|
||||
#define ARCHSTR "MacOS"
|
||||
#endif
|
||||
#define DIRSEP "/"
|
||||
#include <dirent.h>
|
||||
|
||||
#elif defined (WINDOWS)
|
||||
#define DIRLIST_SEP_CHARS ";"
|
||||
#ifdef _WIN64
|
||||
#define ARCHSTR "win64"
|
||||
#else
|
||||
#define ARCHSTR "win32"
|
||||
#endif
|
||||
#define DIRSEP "\\"
|
||||
|
||||
#include "shlobj.h"
|
||||
#include "tchar.h"
|
||||
#endif
|
||||
|
||||
OFX::Host::PluginCache* OFX::Host::PluginCache::gPluginCachePtr = 0;
|
||||
|
||||
// Define this to enable ofx plugin cache debug messages.
|
||||
//#define CACHE_DEBUG
|
||||
|
||||
using namespace OFX::Host;
|
||||
|
||||
|
||||
/// try to open the plugin bundle object and query it for plugins
|
||||
void PluginBinary::loadPluginInfo(PluginCache *cache) {
|
||||
if (isInvalid()) {
|
||||
return;
|
||||
}
|
||||
_fileModificationTime = _binary.getTime();
|
||||
_fileSize = _binary.getSize();
|
||||
_binaryChanged = false;
|
||||
|
||||
// Take a reference to load the binary only once per session. It will
|
||||
// eventually be unloaded in the destructor (see below).
|
||||
// This avoid lots of useless calls to dlopen()/dlclose().
|
||||
if (!_binary.isLoaded()) {
|
||||
_binary.ref();
|
||||
}
|
||||
|
||||
int (*getNo)(void) = (int(*)()) _binary.findSymbol("OfxGetNumberOfPlugins");
|
||||
OfxPlugin* (*getPlug)(int) = (OfxPlugin*(*)(int)) _binary.findSymbol("OfxGetPlugin");
|
||||
|
||||
if (getNo == 0 || getPlug == 0) {
|
||||
|
||||
_binary.setInvalid(true);
|
||||
|
||||
} else {
|
||||
int pluginCount = (*getNo)();
|
||||
|
||||
_plugins.reserve(pluginCount);
|
||||
|
||||
for (int i=0;i<pluginCount;i++) {
|
||||
OfxPlugin *plug = (*getPlug)(i);
|
||||
|
||||
APICache::PluginAPICacheI *api = cache->findApiHandler(plug->pluginApi, plug->apiVersion);
|
||||
assert(api);
|
||||
|
||||
_plugins.push_back(api->newPlugin(this, i, plug));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PluginBinary::~PluginBinary() {
|
||||
std::vector<Plugin*>::iterator i = _plugins.begin();
|
||||
while (i != _plugins.end()) {
|
||||
delete *i;
|
||||
i++;
|
||||
}
|
||||
// release the last reference to the binary, which should unload it
|
||||
// if this reference was taken by loadPluginInfo().
|
||||
if (_binary.isLoaded()) {
|
||||
_binary.unref();
|
||||
}
|
||||
assert(!_binary.isLoaded());
|
||||
}
|
||||
|
||||
PluginHandle::PluginHandle(Plugin *p, OFX::Host::Host *host)
|
||||
{
|
||||
_b = p->getBinary();
|
||||
_b->_binary.ref();
|
||||
_op = 0;
|
||||
OfxPlugin* (*getPlug)(int) = (OfxPlugin*(*)(int)) _b->_binary.findSymbol("OfxGetPlugin");
|
||||
if (getPlug) {
|
||||
_op = getPlug(p->getIndex());
|
||||
if (_op) {
|
||||
_op->setHost(host->getHandle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PluginHandle::~PluginHandle() {
|
||||
_b->_binary.unref();
|
||||
}
|
||||
|
||||
|
||||
#if defined (WINDOWS)
|
||||
const TCHAR *getStdOFXPluginPath(const std::string &hostId = "Plugins")
|
||||
{
|
||||
static TCHAR buffer[MAX_PATH];
|
||||
static int gotIt = 0;
|
||||
if(!gotIt) {
|
||||
gotIt = 1;
|
||||
SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, SHGFP_TYPE_CURRENT, buffer);
|
||||
strcat_s(buffer, MAX_PATH, __T("\\OFX\\Plugins"));
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
std::string OFXGetEnv(const char* e)
|
||||
{
|
||||
#if defined(WINDOWS) && !defined(__MINGW32__)
|
||||
size_t requiredSize;
|
||||
getenv_s(&requiredSize, 0, 0, e);
|
||||
std::vector<char> buffer(requiredSize);
|
||||
if(requiredSize >0)
|
||||
{
|
||||
getenv_s(&requiredSize, &buffer.front(), requiredSize, e);
|
||||
return &buffer.front();
|
||||
}
|
||||
return "";
|
||||
#else
|
||||
if(getenv(e))
|
||||
return getenv(e);
|
||||
#endif
|
||||
return "";
|
||||
}
|
||||
|
||||
PluginCache* PluginCache::getPluginCache()
|
||||
{
|
||||
if(!gPluginCachePtr)
|
||||
gPluginCachePtr = new PluginCache();
|
||||
return gPluginCachePtr;
|
||||
}
|
||||
|
||||
void PluginCache::clearPluginCache()
|
||||
{
|
||||
delete gPluginCachePtr;
|
||||
gPluginCachePtr = 0;
|
||||
}
|
||||
|
||||
PluginCache::~PluginCache()
|
||||
{
|
||||
for(std::list<PluginBinary *>::iterator it=_binaries.begin(); it != _binaries.end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
_binaries.clear();
|
||||
}
|
||||
|
||||
PluginCache::PluginCache() : _hostSpec(0), _xmlCurrentBinary(0), _xmlCurrentPlugin(0) {
|
||||
|
||||
_cacheVersion = "";
|
||||
_ignoreCache = false;
|
||||
_dirty = false;
|
||||
_enablePluginSeek = true;
|
||||
|
||||
std::string s = OFXGetEnv("OFX_PLUGIN_PATH");
|
||||
|
||||
|
||||
while (s.length()) {
|
||||
|
||||
int spos = int(s.find_first_of(DIRLIST_SEP_CHARS));
|
||||
|
||||
std::string path;
|
||||
|
||||
if (spos != -1) {
|
||||
path = s.substr(0, spos);
|
||||
s = s.substr(spos+1);
|
||||
}
|
||||
else {
|
||||
path = s;
|
||||
s = "";
|
||||
}
|
||||
|
||||
_pluginPath.push_back(path);
|
||||
}
|
||||
|
||||
#if defined(WINDOWS)
|
||||
_pluginPath.push_back(getStdOFXPluginPath());
|
||||
_pluginPath.push_back("C:\\Program Files\\Common Files\\OFX\\Plugins");
|
||||
#endif
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
_pluginPath.push_back("/usr/OFX/Plugins");
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
_pluginPath.push_back("/Library/OFX/Plugins");
|
||||
#endif
|
||||
}
|
||||
|
||||
void PluginCache::setPluginHostPath(const std::string &hostId) {
|
||||
#if defined(WINDOWS)
|
||||
_pluginPath.push_back(getStdOFXPluginPath(hostId));
|
||||
_pluginPath.push_back("C:\\Program Files\\Common Files\\OFX\\" + hostId);
|
||||
#endif
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
_pluginPath.push_back("/usr/OFX/" + hostId);
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
_pluginPath.push_back("/Library/OFX/" + hostId);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PluginCache::scanDirectory(std::set<std::string> &foundBinFiles, const std::string &dir, bool recurse)
|
||||
{
|
||||
#ifdef CACHE_DEBUG
|
||||
printf("looking in %s for plugins\n", dir.c_str());
|
||||
#endif
|
||||
|
||||
#if defined (WINDOWS)
|
||||
WIN32_FIND_DATA findData;
|
||||
HANDLE findHandle;
|
||||
#else
|
||||
DIR *d = opendir(dir.c_str());
|
||||
if (!d) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
_pluginDirs.push_back(dir.c_str());
|
||||
|
||||
#if defined (UNIX)
|
||||
while (dirent *de = readdir(d))
|
||||
#elif defined (WINDOWS)
|
||||
findHandle = FindFirstFile((dir + "\\*").c_str(), &findData);
|
||||
|
||||
if (findHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (1)
|
||||
#endif
|
||||
{
|
||||
#if defined (UNIX)
|
||||
std::string name = de->d_name;
|
||||
bool isdir = true;
|
||||
#else
|
||||
std::string name = findData.cFileName;
|
||||
bool isdir = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
#endif
|
||||
if (name.find(".ofx.bundle") != std::string::npos) {
|
||||
std::string barename = name.substr(0, name.length() - strlen(".bundle"));
|
||||
std::string bundlename = dir + DIRSEP + name;
|
||||
std::string binpath = dir + DIRSEP + name + DIRSEP "Contents" DIRSEP + ARCHSTR + DIRSEP + barename;
|
||||
|
||||
// don't insert binpath yet, do it later because of Mac OS X Universal stuff
|
||||
//foundBinFiles.insert(binpath);
|
||||
|
||||
#if defined(__APPLE__) && (defined(__x86_64) || defined(__x86_64__))
|
||||
/* From the OpenFX specification:
|
||||
|
||||
MacOS-x86-64 - for Apple Macintosh OS X, specifically on
|
||||
intel x86 CPUs running AMD's 64 bit extensions. 64 bit host
|
||||
applications should check this first, and if it doesn't
|
||||
exist or is empty, fall back to "MacOS" looking for a
|
||||
universal binary.
|
||||
*/
|
||||
|
||||
std::string binpath_universal = dir + DIRSEP + name + DIRSEP "Contents" DIRSEP + "MacOS" + DIRSEP + barename;
|
||||
if (_knownBinFiles.find(binpath_universal) != _knownBinFiles.end()) {
|
||||
binpath = binpath_universal;
|
||||
}
|
||||
#endif
|
||||
if (_knownBinFiles.find(binpath) == _knownBinFiles.end()) {
|
||||
#ifdef CACHE_DEBUG
|
||||
printf("found non-cached binary %s\n", binpath.c_str());
|
||||
#endif
|
||||
_dirty = true;
|
||||
|
||||
// the binary was not in the cache
|
||||
|
||||
PluginBinary *pb = 0;
|
||||
#if defined(__x86_64) || defined(__x86_64__)
|
||||
pb = new PluginBinary(binpath, bundlename, this);
|
||||
# if defined(__APPLE__)
|
||||
if (pb->isInvalid()) {
|
||||
// fallback to "MacOS"
|
||||
delete pb;
|
||||
binpath = binpath_universal;
|
||||
pb = new PluginBinary(binpath, bundlename, this);
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
pb = new PluginBinary(binpath, bundlename, this);
|
||||
#endif
|
||||
_binaries.push_back(pb);
|
||||
_knownBinFiles.insert(binpath);
|
||||
foundBinFiles.insert(binpath);
|
||||
|
||||
for (int j=0;j<pb->getNPlugins();j++) {
|
||||
Plugin *plug = &pb->getPlugin(j);
|
||||
const APICache::PluginAPICacheI &api = plug->getApiHandler();
|
||||
api.loadFromPlugin(plug);
|
||||
}
|
||||
} else {
|
||||
#ifdef CACHE_DEBUG
|
||||
printf("found cached binary %s\n", binpath.c_str());
|
||||
#endif
|
||||
}
|
||||
// insert final path (universal or not) in the list of found files
|
||||
foundBinFiles.insert(binpath);
|
||||
} else {
|
||||
if (isdir && (recurse && name[0] != '@' && name != "." && name != "..")) {
|
||||
scanDirectory(foundBinFiles, dir + DIRSEP + name, recurse);
|
||||
}
|
||||
}
|
||||
#if defined(WINDOWS)
|
||||
int rval = FindNextFile(findHandle, &findData);
|
||||
|
||||
if (rval == 0) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(UNIX)
|
||||
closedir(d);
|
||||
#else
|
||||
FindClose(findHandle);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string PluginCache::seekPluginFile(const std::string &baseName) const {
|
||||
// Exit early if disabled
|
||||
if (!_enablePluginSeek)
|
||||
return "";
|
||||
|
||||
for (std::list<std::string>::const_iterator paths= _pluginDirs.begin();
|
||||
paths != _pluginDirs.end();
|
||||
paths++) {
|
||||
std::string candidate = *paths + DIRSEP + baseName;
|
||||
FILE *f = fopen(candidate.c_str(), "r");
|
||||
if (f) {
|
||||
fclose(f);
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void PluginCache::scanPluginFiles()
|
||||
{
|
||||
std::set<std::string> foundBinFiles;
|
||||
|
||||
for (std::list<std::string>::iterator paths= _pluginPath.begin();
|
||||
paths != _pluginPath.end();
|
||||
paths++) {
|
||||
scanDirectory(foundBinFiles, *paths, _nonrecursePath.find(*paths) == _nonrecursePath.end());
|
||||
}
|
||||
|
||||
std::list<PluginBinary *>::iterator i=_binaries.begin();
|
||||
while (i!=_binaries.end()) {
|
||||
PluginBinary *pb = *i;
|
||||
|
||||
if (foundBinFiles.find(pb->getFilePath()) == foundBinFiles.end()) {
|
||||
|
||||
// the binary was in the cache, but was not on the path
|
||||
|
||||
_dirty = true;
|
||||
i = _binaries.erase(i);
|
||||
delete pb;
|
||||
|
||||
} else {
|
||||
|
||||
bool binChanged = pb->hasBinaryChanged();
|
||||
|
||||
// the binary was in the cache, but the binary has changed and thus we need to reload
|
||||
if (binChanged) {
|
||||
pb->loadPluginInfo(this);
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
for (int j=0;j<pb->getNPlugins();j++) {
|
||||
Plugin *plug = &pb->getPlugin(j);
|
||||
APICache::PluginAPICacheI &api = plug->getApiHandler();
|
||||
|
||||
if (binChanged) {
|
||||
api.loadFromPlugin(plug);
|
||||
}
|
||||
|
||||
std::string reason;
|
||||
|
||||
if (api.pluginSupported(plug, reason)) {
|
||||
_plugins.push_back(plug);
|
||||
api.confirmPlugin(plug);
|
||||
} else {
|
||||
std::cerr << "ignoring plugin " << plug->getIdentifier() <<
|
||||
" as unsupported (" << reason << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// callback for XML parser
|
||||
static void elementBeginHandler(void *userData, const XML_Char *name, const XML_Char **atts) {
|
||||
PluginCache::getPluginCache()->elementBeginCallback(userData, name, atts);
|
||||
}
|
||||
|
||||
/// callback for XML parser
|
||||
static void elementCharHandler(void *userData, const XML_Char *data, int len) {
|
||||
PluginCache::getPluginCache()->elementCharCallback(userData, data, len);
|
||||
}
|
||||
|
||||
/// callback for XML parser
|
||||
static void elementEndHandler(void *userData, const XML_Char *name) {
|
||||
PluginCache::getPluginCache()->elementEndCallback(userData, name);
|
||||
}
|
||||
|
||||
static bool mapHasAll(const std::map<std::string, std::string> &attmap, const char **atts) {
|
||||
while (*atts) {
|
||||
if (attmap.find(*atts) == attmap.end()) {
|
||||
return false;
|
||||
}
|
||||
atts++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PluginCache::elementBeginCallback(void */*userData*/, const XML_Char *name, const XML_Char **atts) {
|
||||
if (_ignoreCache) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string ename = name;
|
||||
std::map<std::string, std::string> attmap;
|
||||
|
||||
while (*atts) {
|
||||
attmap[atts[0]] = atts[1];
|
||||
atts += 2;
|
||||
}
|
||||
|
||||
/// XXX: validate in general
|
||||
|
||||
if (ename == "cache") {
|
||||
std::string cacheversion = attmap["version"];
|
||||
if (cacheversion != _cacheVersion) {
|
||||
#ifdef CACHE_DEBUG
|
||||
printf("mismatched version, ignoring cache (got '%s', wanted '%s')\n",
|
||||
cacheversion.c_str(),
|
||||
_cacheVersion.c_str());
|
||||
#endif
|
||||
_ignoreCache = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ename == "binary") {
|
||||
const char *binAtts[] = {"path", "bundle_path", "mtime", "size", NULL};
|
||||
|
||||
if (!mapHasAll(attmap, binAtts)) {
|
||||
// no path: bad XML
|
||||
}
|
||||
|
||||
std::string fname = attmap["path"];
|
||||
std::string bname = attmap["bundle_path"];
|
||||
time_t mtime = OFX::Host::Property::stringToInt(attmap["mtime"]);
|
||||
size_t size = OFX::Host::Property::stringToInt(attmap["size"]);
|
||||
|
||||
_xmlCurrentBinary = new PluginBinary(fname, bname, mtime, size);
|
||||
_binaries.push_back(_xmlCurrentBinary);
|
||||
_knownBinFiles.insert(fname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ename == "plugin" && _xmlCurrentBinary && !_xmlCurrentBinary->hasBinaryChanged()) {
|
||||
const char *plugAtts[] = {"api", "name", "index", "api_version", "major_version", "minor_version", NULL};
|
||||
|
||||
if (!mapHasAll(attmap, plugAtts)) {
|
||||
// no path: bad XML
|
||||
}
|
||||
|
||||
std::string api = attmap["api"];
|
||||
std::string rawIdentifier = attmap["name"];
|
||||
|
||||
std::string identifier = rawIdentifier;
|
||||
|
||||
// Who says the pluginIdentifier is case-insensitive? OFX 1.3 spec doesn't mention this.
|
||||
// http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#id472588
|
||||
//for (size_t i=0;i<identifier.size();i++) {
|
||||
// identifier[i] = tolower(identifier[i]);
|
||||
//}
|
||||
|
||||
int idx = OFX::Host::Property::stringToInt(attmap["index"]);
|
||||
int api_version = OFX::Host::Property::stringToInt(attmap["api_version"]);
|
||||
int major_version = OFX::Host::Property::stringToInt(attmap["major_version"]);
|
||||
int minor_version = OFX::Host::Property::stringToInt(attmap["minor_version"]);
|
||||
|
||||
APICache::PluginAPICacheI *apiCache = findApiHandler(api, api_version);
|
||||
if (apiCache) {
|
||||
|
||||
Plugin *pe = apiCache->newPlugin(_xmlCurrentBinary, idx, api, api_version, identifier, rawIdentifier, major_version, minor_version);
|
||||
_xmlCurrentBinary->addPlugin(pe);
|
||||
_xmlCurrentPlugin = pe;
|
||||
apiCache->beginXmlParsing(pe);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (_xmlCurrentPlugin) {
|
||||
APICache::PluginAPICacheI &api = _xmlCurrentPlugin->getApiHandler();
|
||||
api.xmlElementBegin(name, attmap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PluginCache::elementCharCallback(void */*userData*/, const XML_Char *data, int size)
|
||||
{
|
||||
if (_ignoreCache) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string s(data, size);
|
||||
if (_xmlCurrentPlugin) {
|
||||
APICache::PluginAPICacheI &api = _xmlCurrentPlugin->getApiHandler();
|
||||
api.xmlCharacterHandler(s);
|
||||
} else {
|
||||
/// XXX: we only want whitespace
|
||||
}
|
||||
}
|
||||
|
||||
void PluginCache::elementEndCallback(void */*userData*/, const XML_Char *name) {
|
||||
if (_ignoreCache) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string ename = name;
|
||||
|
||||
/// XXX: validation?
|
||||
|
||||
if (ename == "plugin") {
|
||||
if (_xmlCurrentPlugin) {
|
||||
APICache::PluginAPICacheI &api = _xmlCurrentPlugin->getApiHandler();
|
||||
api.endXmlParsing();
|
||||
}
|
||||
_xmlCurrentPlugin = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ename == "bundle") {
|
||||
_xmlCurrentBinary = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_xmlCurrentPlugin) {
|
||||
APICache::PluginAPICacheI &api = _xmlCurrentPlugin->getApiHandler();
|
||||
api.xmlElementEnd(name);
|
||||
}
|
||||
}
|
||||
|
||||
void PluginCache::readCache(std::istream &ifs) {
|
||||
XML_Parser xP = XML_ParserCreate(NULL);
|
||||
XML_SetElementHandler(xP, elementBeginHandler, elementEndHandler);
|
||||
XML_SetCharacterDataHandler(xP, elementCharHandler);
|
||||
|
||||
while (ifs.good()) {
|
||||
char buf[1001] = {0};
|
||||
ifs.read(buf, 1000);
|
||||
|
||||
if (buf[0] == 0) {
|
||||
XML_Parse(xP, "", 0, XML_TRUE);
|
||||
break;
|
||||
}
|
||||
|
||||
int p = XML_Parse(xP, buf, int(strlen(buf)), XML_FALSE);
|
||||
|
||||
if (p == XML_STATUS_ERROR) {
|
||||
std::cout << "xml error : " << XML_GetErrorCode(xP) << std::endl;
|
||||
/// XXX: do something here
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XML_ParserFree(xP);
|
||||
}
|
||||
|
||||
void PluginCache::writePluginCache(std::ostream &os) const {
|
||||
#ifdef CACHE_DEBUG
|
||||
printf("writing pluginCache with version = %s\n", _cacheVersion.c_str());
|
||||
#endif
|
||||
|
||||
os << "<cache version=\"" << _cacheVersion << "\">\n";
|
||||
for (std::list<PluginBinary *>::const_iterator i=_binaries.begin();i!=_binaries.end();i++) {
|
||||
PluginBinary *b = *i;
|
||||
os << "<bundle>\n";
|
||||
os << " <binary "
|
||||
<< XML::attribute("bundle_path", b->getBundlePath())
|
||||
<< XML::attribute("path", b->getFilePath())
|
||||
<< XML::attribute("mtime", int(b->getFileModificationTime()))
|
||||
<< XML::attribute("size", int(b->getFileSize())) << "/>\n";
|
||||
|
||||
for (int j=0;j<b->getNPlugins();j++) {
|
||||
Plugin *p = &b->getPlugin(j);
|
||||
|
||||
|
||||
os << " <plugin "
|
||||
<< XML::attribute("name", p->getRawIdentifier())
|
||||
<< XML::attribute("index", p->getIndex())
|
||||
<< XML::attribute("api", p->getPluginApi())
|
||||
<< XML::attribute("api_version", p->getApiVersion())
|
||||
<< XML::attribute("major_version", p->getVersionMajor())
|
||||
<< XML::attribute("minor_version", p->getVersionMinor())
|
||||
<< ">\n";
|
||||
|
||||
const APICache::PluginAPICacheI &api = p->getApiHandler();
|
||||
os << " <apiproperties>\n";
|
||||
api.saveXML(p, os);
|
||||
os << " </apiproperties>\n";
|
||||
|
||||
os << " </plugin>\n";
|
||||
}
|
||||
os << "</bundle>\n";
|
||||
}
|
||||
os << "</cache>\n";
|
||||
}
|
||||
|
||||
|
||||
APICache::PluginAPICacheI *PluginCache::findApiHandler(const std::string &api, int version) {
|
||||
std::list<PluginCacheSupportedApi>::iterator i = _apiHandlers.begin();
|
||||
while (i != _apiHandlers.end()) {
|
||||
if (i->matches(api, version)) {
|
||||
return i->handler;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
|
||||
|
||||
#include "ofxCore.h"
|
||||
#include "ofxhUtilities.h"
|
||||
|
||||
namespace OFX {
|
||||
|
||||
/// get me deepest bit depth
|
||||
std::string FindDeepestBitDepth(const std::string &s1, const std::string &s2)
|
||||
{
|
||||
if(s1 == kOfxBitDepthNone) {
|
||||
return s2;
|
||||
}
|
||||
else if(s1 == kOfxBitDepthByte) {
|
||||
if(s2 == kOfxBitDepthShort || s2 == kOfxBitDepthFloat)
|
||||
return s2;
|
||||
return s1;
|
||||
}
|
||||
else if(s1 == kOfxBitDepthShort) {
|
||||
if(s2 == kOfxBitDepthFloat)
|
||||
return s2;
|
||||
return s1;
|
||||
}
|
||||
else if(s1 == kOfxBitDepthHalf) {
|
||||
if(s2 == kOfxBitDepthFloat)
|
||||
return s2;
|
||||
return s1;
|
||||
}
|
||||
else if(s1 == kOfxBitDepthFloat) {
|
||||
return s1;
|
||||
}
|
||||
else {
|
||||
return s2; // oooh this might be bad dad.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user