Skip to content

Commit

Permalink
WIP OpenFX
Browse files Browse the repository at this point in the history
  • Loading branch information
darbyjohnston committed Aug 16, 2024
1 parent 88f8412 commit e188f05
Show file tree
Hide file tree
Showing 14 changed files with 716 additions and 72 deletions.
1 change: 1 addition & 0 deletions bin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_executable(toucan-render main.cpp)
target_link_libraries(toucan-render toucan)
set_target_properties(toucan-render PROPERTIES FOLDER bin)
add_dependencies(toucan-render toucan-invert)

install(
TARGETS toucan-render
Expand Down
23 changes: 5 additions & 18 deletions bin/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,21 @@
// Copyright (c) 2024 Darby Johnston
// All rights reserved.

#include <toucan/Host.h>
#include <toucan/Init.h>
#include <toucan/Plugin.h>
#include <toucan/TimelineTraverse.h>
#include <toucan/Util.h>

#include <OpenImageIO/imagebufalgo.h>

#include <iostream>

using namespace toucan;

int main(int argc, char** argv)
{
std::filesystem::path searchPath = std::filesystem::path(argv[0]).parent_path() / ".." / "..";
std::vector<std::filesystem::path> pluginPaths;
findPlugins(searchPath, pluginPaths);
for (auto const& path : pluginPaths)
{
std::cout << path.string() << std::endl;
try
{
auto plugin = std::make_shared<Plugin>(path);
}
catch (const std::exception& e)
{
std::cout << "ERROR: " << e.what() << std::endl;
}
}
std::filesystem::path parentPath = std::filesystem::path(argv[0]).parent_path();
auto host = std::make_shared<Host>(std::vector<std::filesystem::path>{
parentPath,
parentPath / ".." / ".."});
return 0;

// Command line arguments.
Expand Down
10 changes: 9 additions & 1 deletion lib/toucan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set(HEADERS
FillOp.h
FlipOp.h
FlopOp.h
Host.h
ImageOp.h
Init.h
InvertOp.h
Expand All @@ -14,6 +15,7 @@ set(HEADERS
NoiseOp.h
Plugin.h
PowOp.h
PropertySet.h
ReadOp.h
ResizeOp.h
RotateOp.h
Expand All @@ -23,6 +25,7 @@ set(HEADERS
TimelineTraverse.h
TransitionOp.h
Util.h)
set(HEADERS_PRIVATE)
set(SOURCE
BoxOp.cpp
CheckersOp.cpp
Expand All @@ -31,6 +34,7 @@ set(SOURCE
FillOp.cpp
FlipOp.cpp
FlopOp.cpp
Host.cpp
ImageOp.cpp
Init.cpp
InvertOp.cpp
Expand All @@ -39,6 +43,7 @@ set(SOURCE
NoiseOp.cpp
Plugin.cpp
PowOp.cpp
PropertySet.cpp
ReadOp.cpp
ResizeOp.cpp
RotateOp.cpp
Expand All @@ -48,8 +53,11 @@ set(SOURCE
TimelineTraverse.cpp
TransitionOp.cpp
Util.cpp)
if(WIN32)
list(APPEND SOURCE UtilWin32.cpp)
endif()

add_library(toucan ${HEADERS} ${SOURCE})
add_library(toucan ${HEADERS} ${HEADERS_PRIVATE} ${SOURCE})
target_link_libraries(toucan PUBLIC OTIO OpenImageIO::OpenImageIO)
set_target_properties(toucan PROPERTIES FOLDER lib)
set_target_properties(toucan PROPERTIES PUBLIC_HEADER "${HEADERS}")
Expand Down
145 changes: 145 additions & 0 deletions lib/toucan/Host.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2024 Darby Johnston
// All rights reserved.

#include "Host.h"

#include "Util.h"

#include <iostream>
#include <sstream>

namespace toucan
{
Host::Host(const std::vector<std::filesystem::path>& searchPath)
{
_propertySet.setPointer("host", 0, this);

_propertySuite.propSetPointer = &PropertySet::setPointer;
_propertySuite.propSetString = &PropertySet::setString;
_propertySuite.propSetDouble = &PropertySet::setDouble;
_propertySuite.propSetInt = &PropertySet::setInt;
_propertySuite.propSetPointerN = &PropertySet::setPointerN;
_propertySuite.propSetStringN = &PropertySet::setStringN;
_propertySuite.propSetDoubleN = &PropertySet::setDoubleN;
_propertySuite.propSetIntN = &PropertySet::setIntN;
_propertySuite.propGetPointer = &PropertySet::getPointer;
_propertySuite.propGetString = &PropertySet::getString;
_propertySuite.propGetDouble = &PropertySet::getDouble;
_propertySuite.propGetInt = &PropertySet::getInt;
_propertySuite.propGetPointerN = &PropertySet::getPointerN;
_propertySuite.propGetStringN = &PropertySet::getStringN;
_propertySuite.propGetDoubleN = &PropertySet::getDoubleN;
_propertySuite.propGetIntN = &PropertySet::getIntN;
_propertySuite.propReset = &PropertySet::reset;
_propertySuite.propGetDimension = &PropertySet::getDimension;

_effectSuite.getPropertySet = &_getPropertySet;

_host.host = reinterpret_cast<OfxPropertySetHandle>(&_propertySet);
_host.fetchSuite = &_fetchSuite;

std::vector<std::filesystem::path> pluginPaths;
for (const auto& path : searchPath)
{
findPlugins(path, pluginPaths);
}
for (auto const& path : pluginPaths)
{
//std::cout << path.string() << std::endl;
try
{
auto plugin = std::make_shared<Plugin>(path);
const int pluginCount = plugin->getCount();
//std::cout << "plugin count: " << pluginCount << std::endl;
if (pluginCount > 0)
{
OfxPlugin* ofxPlugin = plugin->getPlugin(0);
//std::cout << " plugin: " << ofxPlugin->pluginIdentifier << std::endl;
ofxPlugin->setHost(&_host);
OfxStatus ofxStatus = ofxPlugin->mainEntry(
kOfxActionLoad,
nullptr,
nullptr,
nullptr);
switch (ofxStatus)
{
case kOfxStatOK:
case kOfxStatReplyDefault:
_plugins.push_back(plugin);
break;
case kOfxStatErrFatal:
{
std::stringstream ss;
ss << "Fatal error in plugin: " << path.string();
throw std::runtime_error(ss.str());
break;
}
case kOfxStatFailed:
default:
break;
}
}
}
catch (const std::exception& e)
{
std::cout << "ERROR: " << e.what() << std::endl;
}
}

for (const auto& plugin : _plugins)
{
OfxStatus ofxStatus = plugin->getPlugin(0)->mainEntry(
kOfxActionDescribe,
plugin.get(),
nullptr,
nullptr);
char* s = nullptr;
plugin->getPropertySet(0)->getString(kOfxPropLabel, 0, &s);
std::cout << "plugin: " << s << std::endl;
plugin->getPropertySet(0)->getString(kOfxImageEffectPluginPropGrouping, 0, &s);
std::cout << " group: " << s << std::endl;
plugin->getPropertySet(0)->getString(kOfxImageEffectPropSupportedContexts, 0, &s);
std::cout << " context: " << s << std::endl;
}
}

Host::~Host()
{
for (const auto& plugin : _plugins)
{
OfxStatus ofxStatus = plugin->getPlugin(0)->mainEntry(
kOfxActionUnload,
nullptr,
nullptr,
nullptr);
}
}

const void* Host::_fetchSuite(OfxPropertySetHandle handle, const char* suiteName, int suiteVersion)
{
const void* out = nullptr;

PropertySet* hostPropertySet = reinterpret_cast<PropertySet*>(handle);
void* hostP = nullptr;
hostPropertySet->getPointer("host", 0, &hostP);
Host* host = reinterpret_cast<Host*>(hostP);

if (strcmp(suiteName, kOfxPropertySuite) == 0)
{
out = &host->_propertySuite;
}
else if (strcmp(suiteName, kOfxImageEffectSuite) == 0)
{
out = &host->_effectSuite;
}
return out;
}

OfxStatus Host::_getPropertySet(OfxImageEffectHandle handle, OfxPropertySetHandle* propHandle)
{
Plugin* plugin = reinterpret_cast<Plugin*>(handle);
*propHandle = reinterpret_cast<OfxPropertySetHandle>(plugin->getPropertySet(0));
return kOfxStatOK;
}
}
35 changes: 35 additions & 0 deletions lib/toucan/Host.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2024 Darby Johnston
// All rights reserved.

#pragma once

#include <toucan/Plugin.h>
#include <toucan/PropertySet.h>

#include <OpenFX/ofxImageEffect.h>

#include <filesystem>
#include <memory>

namespace toucan
{
class Host : public std::enable_shared_from_this<Host>
{
public:
Host(const std::vector<std::filesystem::path>& searchPath);

~Host();

private:
static const void* _fetchSuite(OfxPropertySetHandle host, const char* suiteName, int suiteVersion);

static OfxStatus _getPropertySet(OfxImageEffectHandle, OfxPropertySetHandle* propHandle);

PropertySet _propertySet;
OfxPropertySuiteV1 _propertySuite;
OfxImageEffectSuiteV1 _effectSuite;
OfxHost _host;
std::vector<std::shared_ptr<Plugin> > _plugins;
};
}
46 changes: 37 additions & 9 deletions lib/toucan/Plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include "Plugin.h"

#include "Util.h"

#include <OpenFX/ofxCore.h>

#include <iostream>
Expand All @@ -21,13 +23,21 @@ namespace toucan
{
namespace
{
typedef int(__cdecl* GetNumberOfPluginsFnc)(void);
typedef OfxPlugin* (__cdecl* OfxGetPluginFnc)(int);
typedef int(__cdecl* GetNumberOfPluginsFunc)(void);
typedef OfxPlugin* (__cdecl* GetPluginFunc)(int);
typedef void(__cdecl* SetHostFunc)(OfxHost*);
typedef OfxStatus (__cdecl* MainEntryPointFunc)(
const char*,
const void*,
OfxPropertySetHandle,
OfxPropertySetHandle);
}

struct Plugin::Private
{
HINSTANCE pluginInstance = NULL;
HINSTANCE pluginInstance = nullptr;
GetNumberOfPluginsFunc getNumberOfPlugins = nullptr;
GetPluginFunc getPlugin = nullptr;
};

Plugin::Plugin(const std::filesystem::path& path) :
Expand All @@ -41,20 +51,38 @@ namespace toucan
throw std::runtime_error(ss.str());
}

GetNumberOfPluginsFnc getNumberOfPluginsFunc = (GetNumberOfPluginsFnc)GetProcAddress(
_p->getNumberOfPlugins = (GetNumberOfPluginsFunc)GetProcAddress(
_p->pluginInstance,
"OfxGetNumberOfPlugins");
if (!getNumberOfPluginsFunc)
_p->getPlugin = (GetPluginFunc)GetProcAddress(
_p->pluginInstance,
"OfxGetPlugin");

if (_p->getNumberOfPlugins)
{
std::stringstream ss;
ss << "Cannot get number of plugins";
throw std::runtime_error(ss.str());
_effectPropertySets.resize(_p->getNumberOfPlugins());
}
std::cout << "Number of plugins: " << getNumberOfPluginsFunc() << std::endl;
}

Plugin::~Plugin()
{
FreeLibrary(_p->pluginInstance);
}

int Plugin::getCount()
{
return _p->getNumberOfPlugins ? _p->getNumberOfPlugins() : 0;
}

OfxPlugin* Plugin::getPlugin(int index)
{
return _p->getPlugin ? _p->getPlugin(index) : nullptr;
}

PropertySet* Plugin::getPropertySet(int index)
{
return index >= 0 && index < _effectPropertySets.size() ?
&_effectPropertySets[index] :
nullptr;
}
}
11 changes: 11 additions & 0 deletions lib/toucan/Plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

#pragma once

#include <toucan/PropertySet.h>

#include <OpenFX/ofxCore.h>

#include <filesystem>
#include <memory>

Expand All @@ -16,7 +20,14 @@ namespace toucan

~Plugin();

int getCount();

OfxPlugin* getPlugin(int);

PropertySet* getPropertySet(int);

private:
std::vector<PropertySet> _effectPropertySets;
struct Private;
std::unique_ptr<Private> _p;
};
Expand Down
Loading

0 comments on commit e188f05

Please sign in to comment.