change: Switch to offical OpenFX Support. Still can't compile.
This commit is contained in:
+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