change: Switch to offical OpenFX Support. Still can't compile.

This commit is contained in:
Mike Solar
2025-09-03 21:14:56 +08:00
parent 7ff76427f9
commit b649b5e1bd
198 changed files with 57444 additions and 980 deletions
+104
View File
@@ -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
View File
@@ -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
View File
@@ -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
File diff suppressed because it is too large Load Diff
+592
View File
@@ -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
View File
@@ -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
View File
@@ -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
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 *&currentProp) {
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);
}
}
}
}
}
+694
View File
@@ -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
+37
View File
@@ -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.
}
}
}