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

This commit is contained in:
Mike Solar
2025-09-03 21:14:56 +08:00
parent 7ff76427f9
commit b649b5e1bd
198 changed files with 57444 additions and 980 deletions
-147
View File
@@ -1,147 +0,0 @@
# Generated from CLion Inspection settings
---
Checks: '-*,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-bad-signal-to-kill-thread,
bugprone-branch-clone,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-fold-init-type,
bugprone-forward-declaration-namespace,
bugprone-forwarding-reference-overload,
bugprone-inaccurate-erase,
bugprone-incorrect-roundings,
bugprone-integer-division,
bugprone-lambda-function-name,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-pointer-arithmetic-in-alloc,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-no-escape,
bugprone-parent-virtual-call,
bugprone-posix-return,
bugprone-reserved-identifier,
bugprone-sizeof-container,
bugprone-sizeof-expression,
bugprone-spuriously-wake-up-functions,
bugprone-string-constructor,
bugprone-string-integer-assignment,
bugprone-string-literal-with-embedded-nul,
bugprone-suspicious-enum-usage,
bugprone-suspicious-include,
bugprone-suspicious-memset-usage,
bugprone-suspicious-missing-comma,
bugprone-suspicious-semicolon,
bugprone-suspicious-string-compare,
bugprone-suspicious-memory-comparison,
bugprone-suspicious-realloc-usage,
bugprone-swapped-arguments,
bugprone-terminating-continue,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-self-assignment,
bugprone-unused-raii,
bugprone-unused-return-value,
bugprone-use-after-move,
bugprone-virtual-near-miss,
cert-dcl21-cpp,
cert-dcl58-cpp,
cert-err34-c,
cert-err52-cpp,
cert-err60-cpp,
cert-flp30-c,
cert-msc50-cpp,
cert-msc51-cpp,
cert-str34-c,
cppcoreguidelines-interfaces-global-init,
cppcoreguidelines-narrowing-conversions,
cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-slicing,
google-default-arguments,
google-explicit-constructor,
google-runtime-operator,
hicpp-exception-baseclass,
hicpp-multiway-paths-covered,
misc-misplaced-const,
misc-new-delete-overloads,
misc-no-recursion,
misc-non-copyable-objects,
misc-throw-by-value-catch-by-reference,
misc-unconventional-assign-operator,
misc-uniqueptr-reset-release,
modernize-avoid-bind,
modernize-concat-nested-namespaces,
modernize-deprecated-headers,
modernize-deprecated-ios-base-aliases,
modernize-loop-convert,
modernize-make-shared,
modernize-make-unique,
modernize-pass-by-value,
modernize-raw-string-literal,
modernize-redundant-void-arg,
modernize-replace-auto-ptr,
modernize-replace-disallow-copy-and-assign-macro,
modernize-replace-random-shuffle,
modernize-return-braced-init-list,
modernize-shrink-to-fit,
modernize-unary-static-assert,
modernize-use-auto,
modernize-use-bool-literals,
modernize-use-emplace,
modernize-use-equals-default,
modernize-use-equals-delete,
modernize-use-nodiscard,
modernize-use-noexcept,
modernize-use-nullptr,
modernize-use-override,
modernize-use-transparent-functors,
modernize-use-uncaught-exceptions,
mpi-buffer-deref,
mpi-type-mismatch,
openmp-use-default-none,
performance-faster-string-find,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-algorithm,
performance-inefficient-string-concatenation,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-move-constructor-init,
performance-no-automatic-move,
performance-noexcept-move-constructor,
performance-trivially-destructible,
performance-type-promotion-in-math-fn,
performance-unnecessary-copy-initialization,
performance-unnecessary-value-param,
portability-simd-intrinsics,
readability-avoid-const-params-in-decls,
readability-const-return-type,
readability-container-size-empty,
readability-convert-member-functions-to-static,
readability-delete-null-pointer,
readability-deleted-default,
readability-inconsistent-declaration-parameter-name,
readability-make-member-function-const,
readability-misleading-indentation,
readability-misplaced-array-index,
readability-non-const-parameter,
readability-redundant-control-flow,
readability-redundant-declaration,
readability-redundant-function-ptr-dereference,
readability-redundant-smartptr-get,
readability-redundant-string-cstr,
readability-redundant-string-init,
readability-simplify-subscript-expr,
readability-static-accessed-through-instance,
readability-static-definition-in-anonymous-namespace,
readability-string-compare,
readability-uniqueptr-delete-release,
readability-use-anyofallof'
+1 -1
View File
@@ -1,6 +1,6 @@
# CMake artifacts
/build*/
build
# Doxygen
/docs/
+1 -5
View File
@@ -1,10 +1,6 @@
[submodule "ext/core"]
[submodule "ext/core"]README
path = ext/core
url = https://github.com/olive-editor/core
[submodule "ext/KDDockWidgets"]
path = ext/KDDockWidgets
url = https://github.com/olive-editor/KDDockWidgets.git
[submodule "third_party/openfx"]
path = third_party/openfx
url = https://github.com/AcademySoftwareFoundation/openfx.git
branch = main
+10 -3
View File
@@ -14,10 +14,16 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
cmake_minimum_required(VERSION 3.30 FATAL_ERROR)
project(olive-editor VERSION 0.2.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_SCAN_FOR_MODULES ON)
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD ON)
find_package(expat REQUIRED)
option(BUILD_QT6 "Build with Qt 6 over 5 (experimental)" ON)
option(BUILD_DOXYGEN "Build Doxygen documentation" OFF)
option(BUILD_TESTS "Build unit tests" OFF)
@@ -31,10 +37,11 @@ set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
# Generates a compile_commands.json in the build dir, link that to the repo
# root to enrich your IDE with clangd language server protocol functionalities
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_subdirectory(third_party/openfx/HostSupport)
# Sanitizers
add_library(olive-sanitizers INTERFACE)
include(cmake/Sanitizers.cmake)
@@ -168,7 +175,7 @@ list(APPEND OLIVE_LIBRARIES
)
# Link FFmpeg
find_package(FFMPEG 3.0 REQUIRED
find_package(FFMPEG 7.0 REQUIRED
COMPONENTS
avutil
avcodec
+6 -5
View File
@@ -18,7 +18,6 @@
set(OLIVE_SOURCES
core.h
core.cpp
pluginSupport/DrawSuite.cpp
)
#set(OLIVE_RESOURCES)
@@ -33,7 +32,6 @@ add_subdirectory(dialog)
add_subdirectory(node)
add_subdirectory(packaging)
add_subdirectory(panel)
add_subdirectory(pluginSupport)
add_subdirectory(render)
add_subdirectory(shaders)
add_subdirectory(task)
@@ -75,8 +73,10 @@ add_library(libolive-editor
${OLIVE_SOURCES}
${OLIVE_RESOURCES}
)
target_include_directories(libolive-editor PUBLIC ../third_party/openfx/include)
add_subdirectory(pluginSupport)
target_compile_features(libolive-editor PUBLIC cxx_std_23)
include_directories(../third_party/openfx/include
../third_party/openfx/HostSupport/include)
# Remove prefix - prevents CMake calling it "liblibolive-editor"
set_target_properties(libolive-editor PROPERTIES PREFIX "")
@@ -86,7 +86,8 @@ add_executable(olive-editor
$<TARGET_OBJECTS:libolive-editor>
$<TARGET_OBJECTS:olive-version-obj>
)
target_include_directories(olive-editor PUBLIC pluginSupport)
target_link_libraries(olive-editor PUBLIC OfxHost)
# Create docs if doxygen was found
if(DOXYGEN_FOUND)
set(DOXYGEN_PROJECT_NAME "Olive")
+10 -1
View File
@@ -52,7 +52,7 @@ extern "C" {
#ifdef USE_CRASHPAD
#include "common/crashpadinterface.h"
#endif // USE_CRASHPAD
#include "OlivePlugin.cpp"
int decompress_project(const QString &project)
{
if (project.isEmpty()) {
@@ -214,6 +214,11 @@ int main(int argc, char *argv[])
QStringLiteral("project"),
QCoreApplication::translate("main", "Project to open on startup"));
auto no_plugin = parser.AddOption(
{ QStringLiteral("-no-plugin") },
QCoreApplication::translate("main", "Don't load plugins")
);
// Qt options re-implemented (add to this as necessary)
//
// Because we don't use QCommandLineParser, we must filter out Qt's arguments ourselves. Here,
@@ -280,6 +285,10 @@ int main(int argc, char *argv[])
}
}
if (!no_plugin->IsSet()) {
olive::plugin::loadPlugins("plugins");
}
if (crash_option->IsSet()) {
startup_params.set_crash_on_startup(true);
}
+1 -1
View File
@@ -20,7 +20,7 @@
#define PLUGIN_NODES_H
#include "node/node.h"
#include "pluginSupport/Plugin.h"
#include "pluginSupport/OlivePlugin.h"
#include "pluginSupport/OlivePlugin.cpp"
namespace olive
{
namespace plugin
+5 -21
View File
@@ -1,22 +1,6 @@
set(OLIVE_SOURCES
${OLIVE_SOURCES}
pluginSupport/OlivePlugin.h
pluginSupport/OlivePlugin.cpp
pluginSupport/Dialog.cpp
pluginSupport/Core.cpp
pluginSupport/DrawSuite.cpp
pluginSupport/GpuRender.cpp
pluginSupport/ImageEffect.cpp
pluginSupport/Interact.cpp
pluginSupport/KeySyms.cpp
pluginSupport/Memory.cpp
pluginSupport/MultiThread.cpp
pluginSupport/OpenGLRender.cpp
pluginSupport/Param.cpp
pluginSupport/ParametricParam.cpp
pluginSupport/Pixels.cpp
pluginSupport/Progress.cpp
pluginSupport/Property.cpp
pluginSupport/TimeLine.cpp
PARENT_SCOPE
target_sources(libolive-editor PRIVATE
OliveHost.h
OliveHost.cpp
OliveInstance.h
OliveInstance.cpp
)
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-25
View File
@@ -1,25 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QMessageBox>
#include <ofxDialog.h>
OfxStatus NotifyRedrawPending()
{
return kOfxStatReplyDefault;
}
-19
View File
@@ -1,19 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "DrawSuite.h"
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+85
View File
@@ -0,0 +1,85 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "node/project.h"
#include "ofxhImageEffect.h"
#include <cstddef>
#include <ofxhPluginCache.h>
#include <ofxhBinary.h>
#include <QApplication>
#include <QDir>
#include "OliveHost.h"
using namespace OFX::Host;
using namespace olive::plugin;
void loadPlugins(QString path)
{
QDir dir=(QCoreApplication::applicationDirPath()+path);
QFileInfoList files=dir.entryInfoList();
for (auto& file:files) {
if (file.isDir()) {
OFX::Binary binary(file.absoluteFilePath().toStdString());
}
}
}
OliveHost::~OliveHost()
{
for(auto& descriptor:descriptors_){
delete descriptor;
descriptor=nullptr;
}
for(auto& instance:instances_){
delete instance;
instance=nullptr;
}
}
ImageEffect::Descriptor *
OliveHost::makeDescriptor(ImageEffect::ImageEffectPlugin* plugin)
{
ImageEffect::Descriptor* desc = new ImageEffect::Descriptor(plugin);
descriptors_.append(desc);
return desc;
}
ImageEffect::Descriptor *
OliveHost::makeDescriptor(const ImageEffect::Descriptor &rootContext,
ImageEffect::ImageEffectPlugin *plugin)
{
ImageEffect::Descriptor* desc = new ImageEffect::Descriptor(rootContext,plugin);
descriptors_.append(desc);
return desc;
}
ImageEffect::Descriptor *
OliveHost::makeDescriptor(const std::string &bundlePath,
ImageEffect::ImageEffectPlugin *plugin)
{
ImageEffect::Descriptor* desc = new ImageEffect::Descriptor(bundlePath, plugin);
descriptors_.append(desc);
return desc;
}
OFX::Host::ImageEffect::Instance* OliveHost::newInstance(void* clientData,
OFX::Host::ImageEffect::ImageEffectPlugin* plugin,
OFX::Host::ImageEffect::Descriptor& desc,
const std::string& context){
//ImageEffect::Instance* instance=new ImageEffect::Instance(clientData,plugin,desc,context);
instances_.append(instance);
return instance;
};
+69
View File
@@ -0,0 +1,69 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ofxhHost.h"
#include "ofxhImageEffectAPI.h"
#include "ofxCore.h"
#include "ofxhImageEffect.h"
#include <QVariant>
#include <cstdint>
#include <QString>
#include <QMap>
#include <any>
#include <list>
#include <OpenImageIO/detail/fmt/chrono.h>
#include <qlist.h>
namespace olive {
namespace plugin {
void loadPlugins(QString path);
class OliveHost: public OFX::Host::ImageEffect::Host{
public:
OliveHost()=default;
~OliveHost() override;
bool pluginSupported(OFX::Host::ImageEffect::ImageEffectPlugin *plugin,
std::string &reason) const override
{
return true;
};
OFX::Host::ImageEffect::Instance* newInstance(void* clientData,
OFX::Host::ImageEffect::ImageEffectPlugin* plugin,
OFX::Host::ImageEffect::Descriptor& desc,
const std::string& context) override;
OFX::Host::ImageEffect::Descriptor *makeDescriptor(
OFX::Host::ImageEffect::ImageEffectPlugin* plugin) override;
OFX::Host::ImageEffect::Descriptor *makeDescriptor(
const OFX::Host::ImageEffect::Descriptor &rootContext,
OFX::Host::ImageEffect::ImageEffectPlugin *plugin) override;
OFX::Host::ImageEffect::Descriptor *makeDescriptor(
const std::string &bundlePath,
OFX::Host::ImageEffect::ImageEffectPlugin *plugin) override;
private:
QList<OFX::Host::ImageEffect::Descriptor*> descriptors_;
QList<OFX::Host::ImageEffect::Instance*> instances_;
};
}
}
+64
View File
@@ -0,0 +1,64 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "OliveInstance.h"
#include "ofxCore.h"
#include "ofxMessage.h"
#include <cstdio>
#include <QMessageBox>
#include <qmessagebox.h>
#include <string.h>
#include <QString>
namespace olive{
namespace plugin {
OfxStatus OliveInstance::vmessage(const char* type,
const char* id,
const char* format,
va_list args){
char *buffer=new char[1024];
memset(buffer, 0, 1024*sizeof(char));
vsprintf(buffer, format, args);
QString message(buffer);
delete [] buffer;
if(strncmp(type, kOfxMessageQuestion, strlen(kOfxMessageQuestion))){
auto ret= QMessageBox::information(nullptr,
"", message,
QMessageBox::Ok, QMessageBox::Cancel);
if(ret==QMessageBox::Ok){
return kOfxStatReplyYes;
}
else {
return kOfxStatReplyNo;
}
}
else{
QMessageBox::information(nullptr,
"", message);
return kOfxStatOK;
}
}
}
}
+58
View File
@@ -0,0 +1,58 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ofxImageEffect.h"
#include "ofxhImageEffect.h"
namespace olive {
namespace plugin{
class OliveInstance : public OFX::Host::ImageEffect::Instance {
public:
OliveInstance(
OFX::Host::ImageEffect::ImageEffectPlugin* plugin,
OFX::Host::ImageEffect::Descriptor& desc,
const std::string& context,
bool interactive)
: OFX::Host::ImageEffect::Instance(plugin, desc, context, interactive)
{
}
~OliveInstance() override = default;
virtual const std::string &getDefaultOutputFielding() const{
return kOfxImageFieldNone;
};
OFX::Host::ImageEffect::ClipInstance *newClipInstance(
OFX::Host::ImageEffect::Instance *plugin,
OFX::Host::ImageEffect::ClipDescriptor *descriptor,
int index) override;
OfxStatus vmessage(const char* type,
const char* id,
const char* format,
va_list args) override;
OfxStatus setPersistentMessage(const char* type,
const char* id,
const char* format,
va_list args) override;
OfxStatus clearPersistentMessage() override;
};
}
}
-215
View File
@@ -1,215 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "OlivePlugin.h"
#include <utility>
olive::plugin::OlivePlugin::~OlivePlugin()
{
for (void *p:mems) {
free(p);
}
}
OfxStatus olive::plugin::OlivePlugin::getProp(QString key, int index,
char **str)
{
*str=nullptr;
if (stringProps.contains(key)) {
if (stringProps[key].count()>index) {
*str=stringProps[key][index];
return kOfxStatOK;
}
return kOfxStatErrBadIndex;
}
return kOfxStatErrUnknown;
}
OfxStatus olive::plugin::OlivePlugin::getPropN(QString key,
char ***str)
{
*str=nullptr;
if (stringProps.contains(key)) {
*str=stringProps[key].data();
return kOfxStatOK;
}
return kOfxStatErrUnknown;
}
OfxStatus olive::plugin::OlivePlugin::getProp(QString key, int index,
void **str)
{
*str=nullptr;
if (pointerProps.contains(key)) {
if (pointerProps[key].count()>index) {
*str=pointerProps[key][index];
return kOfxStatOK;
}
return kOfxStatErrBadIndex;
}
return kOfxStatErrUnknown;
}
OfxStatus olive::plugin::OlivePlugin::getPropN(QString key,
void ***p)
{
*p=nullptr;
if (pointerProps.contains(key)) {
*p=pointerProps[key].data();
return kOfxStatOK;
}
return kOfxStatErrUnknown;
}
OfxStatus olive::plugin::OlivePlugin::getProp(QString key, int index,
int* p)
{
*p=0;
if (intProps.contains(key)) {
if (intProps[key].count()>index) {
*p=intProps[key][index];
return kOfxStatOK;
}
return kOfxStatErrBadIndex;
}
return kOfxStatErrUnknown;
}
OfxStatus olive::plugin::OlivePlugin::getPropN(QString key,
int **p)
{
*p=nullptr;
if (intProps.contains(key)) {
*p=intProps[key].data();
return kOfxStatOK;
}
return kOfxStatErrUnknown;
}
OfxStatus olive::plugin::OlivePlugin::getProp(QString key, int index,
double* p)
{
*p=0;
if (doubleProps.contains(key)) {
if (doubleProps[key].count()>index) {
*p=doubleProps[key][index];
return kOfxStatOK;
}
return kOfxStatErrBadIndex;
}
return kOfxStatErrUnknown;
}
OfxStatus olive::plugin::OlivePlugin::getPropN(QString key,
double **p)
{
*p=nullptr;
if (doubleProps.contains(key)) {
*p=doubleProps[key].data();
return kOfxStatOK;
}
return kOfxStatErrUnknown;
}
OfxStatus olive::plugin::OlivePlugin::setProp(QString key, int index, char *str)
{
char *p=(char*)calloc(strlen(str)+1,sizeof(char));
strcpy(p,str);
if (stringProps.contains(key)) {
if (stringProps[key].count()>index) {
stringProps[key].insert(index, p);
return kOfxStatOK;
}
stringProps[key].emplace_back(p);
return kOfxStatOK;
}
QVector<char *> vec;
vec.emplace_back(str);
stringProps[key]=vec;
return kOfxStatOK;
}
OfxStatus olive::plugin::OlivePlugin::setPropN(QString key, int count, char **strs)
{
QVector<char *> vector;
for (int i=0;i<count;i++) {
char *p=(char*)calloc(strlen(strs[i])+1,sizeof(char));
strcpy(p,strs[i]);
vector.emplace_back(p);
}
stringProps[key]=vector;
}
OfxStatus olive::plugin::OlivePlugin::setProp(QString key, int index, void *p)
{
if (pointerProps.contains(key)) {
if (pointerProps[key].count()>index) {
pointerProps[key].insert(index, p);
return kOfxStatOK;
}
pointerProps[key].emplace_back(p);
return kOfxStatOK;
}
QVector<void *> vec;
vec.emplace_back(p);
pointerProps[key]=vec;
return kOfxStatOK;
}
OfxStatus olive::plugin::OlivePlugin::setPropN(QString key,int count, void **ps)
{
QVector<void *> vector;
vector.reserve(count);
memcpy(vector.data(), ps, sizeof(void *)*count);
pointerProps[key]=vector;
return kOfxStatOK;
}
OfxStatus olive::plugin::OlivePlugin::setProp(QString key, int index, int p)
{
if (intProps.contains(key)) {
if (intProps[key].count()>index) {
intProps[key].insert(index, p);
return kOfxStatOK;
}
intProps[key].emplace_back(p);
return kOfxStatOK;
}
QVector<int> vec;
vec.emplace_back(p);
intProps[key]=vec;
return kOfxStatOK;
}
OfxStatus olive::plugin::OlivePlugin::setPropN(QString key,int count, int *ps)
{
QVector<int> vector;
vector.reserve(count);
memcpy(vector.data(), ps, sizeof(int)*count);
intProps[key]=vector;
return kOfxStatOK;
}
OfxStatus olive::plugin::OlivePlugin::setProp(QString key, int index, double p)
{
if (doubleProps.contains(key)) {
if (doubleProps[key].count()>index) {
doubleProps[key].insert(index, p);
return kOfxStatOK;
}
doubleProps[key].emplace_back(p);
return kOfxStatOK;
}
QVector<double> vec;
vec.emplace_back(p);
doubleProps[key]=vec;
return kOfxStatOK;
}
OfxStatus olive::plugin::OlivePlugin::setPropN(QString key,int count, double *ps)
{
QVector<double> vector;
vector.reserve(count);
memcpy(vector.data(), ps, sizeof(doubleProps)*count);
doubleProps[key]=vector;
return kOfxStatOK;
}
-81
View File
@@ -1,81 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OLIVE_PLUGIN_H
#define OLIVE_PLUGIN_H
#include "OlivePlugin.h"
#include "ofxCore.h"
#include <QVariant>
#include <cstdint>
#include <QString>
#include <QMap>
#include <any>
#include <list>
#include <OpenImageIO/detail/fmt/chrono.h>
namespace olive
{
namespace plugin
{
class Value;
enum class Type {
FLOAT, STRING, INT, POINTER, ARRAY, NONE
};
struct plugin_mem_ptr {
void *mem;
int32_t count=0;
};
class OlivePlugin {
public:
OlivePlugin()=default;
~OlivePlugin();
OfxStatus getProp(QString key, int index, char **str);
OfxStatus getPropN(QString key, char *** strs);
OfxStatus getProp(QString key, int index, void **p);
OfxStatus getPropN(QString key, void ***ps);
OfxStatus getProp(QString key, int index, int *p);
OfxStatus getPropN(QString key, int **ps);
OfxStatus getProp(QString key, int index, double *p);
OfxStatus getPropN(QString key, double **ps);
OfxStatus setProp(QString key, int index, char *str);
OfxStatus setPropN(QString key,int count, char ** strs);
OfxStatus setProp(QString key, int index, void *p);
OfxStatus setPropN(QString key,int count, void **ps);
OfxStatus setProp(QString key, int index, int p);
OfxStatus setPropN(QString key,int count, int *ps);
OfxStatus setProp(QString key, int index, double p);
OfxStatus setPropN(QString key, int count, double *ps);
void addMem(void *mem)
{
mems.emplace_back(mem);
}
private:
uint64_t id;
QString name;
QString version;
QMap<QString, QVector<char *>> stringProps;
QMap<QString, QVector<int>> intProps;
QMap<QString, QVector<double>> doubleProps;
QMap<QString, QVector<void *>> pointerProps;
std::list<void *> mems;
};
}
}
struct OfxPropertySetStruct {
olive::plugin::OlivePlugin* plugin;
};
#endif //OLIVE_PLUGIN_H
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-217
View File
@@ -1,217 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "node/plugins/Plugin.h"
#include <ofxProperty.h>
#include <OpenImageIO/simd.h>
#include <oneapi/tbb/detail/_template_helpers.h>
OfxStatus propSetPointer(OfxPropertySetHandle properties,
const char *property, int index, void *value)
{
if (properties->plugin) {
if (index<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->setProp(property, index, value);
}
return kOfxStatErrBadHandle;
}
OfxStatus propSetString(OfxPropertySetHandle properties,
const char *property, int index, const char *value)
{
if (properties->plugin) {
if (index<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->setProp(property, index, const_cast<char *>(value));
}
return kOfxStatErrBadHandle;
}
OfxStatus propSetDouble(OfxPropertySetHandle properties,
const char *property, int index, double value)
{
if (properties->plugin) {
if (index<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->setProp(property, index, value);
}
return kOfxStatErrBadHandle;
}
OfxStatus propSetInt(OfxPropertySetHandle properties, const char *property,
int index, int value)
{
if (properties->plugin) {
if (index<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->setProp(property, index, value);
}
return kOfxStatErrBadHandle;
}
OfxStatus propSetPointerN(OfxPropertySetHandle properties,
const char *property, int count, void * const*value)
{
if (properties->plugin) {
if (count<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->setPropN(property, count, const_cast<void**>(value));
}
return kOfxStatErrBadHandle;
}
OfxStatus propSetStringN(OfxPropertySetHandle properties,
const char *property, int index, int count,const char *const *value)
{
if (properties->plugin) {
if (count<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->setPropN(property, count, const_cast<char**>(value));
}
return kOfxStatErrBadHandle;
}
OfxStatus propSetDoubleN(OfxPropertySetHandle properties,
const char *property,int count, const double* value)
{
if (properties->plugin) {
if (count<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->setPropN(property, count, const_cast<double *>(value));
}
return kOfxStatErrBadHandle;
}
OfxStatus propSetIntN(OfxPropertySetHandle properties, const char *property,
int count, const int *value)
{
if (properties->plugin) {
if (count<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->setPropN(property, count, const_cast<int *>(value));
}
return kOfxStatErrBadHandle;
}
OfxStatus propGetPointer(OfxPropertySetHandle properties,
const char *property, int index, void **value)
{
if (properties->plugin) {
if (index<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->getProp(property, index, value);
}
return kOfxStatErrBadHandle;
}
OfxStatus propGetString(OfxPropertySetHandle properties,
const char *property, int index, char **value)
{
std::any val;
if (properties->plugin) {
if (index<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->getProp(property, index, value);
}
return kOfxStatErrBadHandle;
}
OfxStatus propGetDouble(OfxPropertySetHandle properties,
const char *property, int index, double *value)
{
if (properties->plugin) {
if (index<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->getProp(property, index, value);
}
return kOfxStatErrBadHandle;
}
OfxStatus propGetInt(OfxPropertySetHandle properties, const char *property,
int index, int *value)
{
if (properties->plugin) {
if (index<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->getProp(property, index, value);
}
return kOfxStatErrBadHandle;
}
OfxStatus propGetPointerN(OfxPropertySetHandle properties,
const char *property, int count, void ***value)
{
if (properties->plugin) {
if (count<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->getPropN(property, value);
}
return kOfxStatErrBadHandle;
}
OfxStatus propGetStringN(OfxPropertySetHandle properties,
const char *property, int count, char ***value)
{
if (properties->plugin) {
if (count<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->getPropN(property, value);
}
return kOfxStatErrBadHandle;
}
OfxStatus propSetDoubleN(OfxPropertySetHandle properties,
const char *property, int index, int count, double** value)
{
if (properties->plugin) {
if (count<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->getPropN(property, value);
}
return kOfxStatErrBadHandle;
}
OfxStatus propSetIntN(OfxPropertySetHandle properties, const char *property,
int index, int count, int **value)
{
if (properties->plugin) {
if (count<0) {
return kOfxStatErrBadIndex;
}
return properties->plugin->getPropN(property, value);
}
return kOfxStatErrBadHandle;
}
-17
View File
@@ -1,17 +0,0 @@
/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
Submodule third_party/openfx deleted from 6aa45d8179
+37
View File
@@ -0,0 +1,37 @@
Dependencies
------------
Dependent upon the following
*the expat library (expat.h) - to parse XML
*ofx header files
How to build the library
------------------------
UNIX
- simply type 'make' in this directory, it will create 'libofxHost.a' in directory ./lib
- the Makefile assumes expat is installed in a standard system location, if it is not,
you need to do the following
make EXPAT_INCLUDE=-IDIRECTORY_WITH_EXPAT
WINDOWS
- use the vc8 projects
How to build the examples
------------------------
UNIX
- make the ofxHostLib.a library
- in the examples directory type 'make',
- the Makefile assumes expat is installed in a standard system location, if it is not,
you need to do the following
make EXPAT_INCLUDE=-IDIRECTORY_WITH_EXPAT EXPAT_LIB=SOMEWHERE/libexpat.a
WINDOWS
- use the vc8 projects
+22
View File
@@ -0,0 +1,22 @@
set(OFX_HOSTSUPPORT_HEADER_DIR "include")
set(OFX_HOSTSUPPORT_LIBRARY_DIR "src")
set(OFX_HEADER_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../include")
aux_source_directory(OFX_HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/../include")
file(GLOB_RECURSE OFX_HOSTSUPPORT_HEADER_FILES "${OFX_HOSTSUPPORT_HEADER_DIR}/*.h")
file(GLOB_RECURSE OFX_HOSTSUPPORT_LIBRARY_FILES "${OFX_HOSTSUPPORT_LIBRARY_DIR}/*.cpp")
add_library(OfxHost STATIC
${OFX_HEADER_FILES}
${OFX_HOSTSUPPORT_HEADER_FILES}
${OFX_HOSTSUPPORT_LIBRARY_FILES})
set_target_properties(OfxHost PROPERTIES LINKER_LANGUAGE CXX)
if(NOT MSVC)
set_target_properties(OfxHost PROPERTIES COMPILE_FLAGS "-fPIC")
endif()
target_link_libraries(OfxHost PUBLIC expat::expat)
target_include_directories(OfxHost PUBLIC
${OFX_HEADER_DIR}
${OFX_HOSTSUPPORT_HEADER_DIR}
${expat_INCLUDE_DIR})
+69
View File
@@ -0,0 +1,69 @@
This directory contains source to an implementation of an OFX host C++ support library.
This library skins the raw C API with a C++ layer, which is easy to program and abstracts
the base API.
It does several things,
- skins the C API with C++ classes, the host application 'only' needs to
- derive several classes
- implement a bunch of virtual methods
- set some OFX properties
- does most of the complicated logic in OFX,
- regions of interest calls
- clip preferences calls
- provides a persistent plug-in caching mechanism so that
- newly installed plug-ins are described into a cache file,
- the cache persists as an XML file with enough information
to construct simple menus etc..
- once cached, plug-ins need only be loaded on demand.
- is extensible beyond the base API,
- allows hosts to provide extra suites and properties fairly easily.
- it is generic beyond ImageEffects APIs, so other APIs can be implemented
on the core sections of it.
Apart from standard C and C++ libraries it is dependent on the expat XML library.
You'll still need to understand what the API actually does, its just that the implementation details that become easier.
The layer could do with some improvement, specifically,
- support for the external XML resource file,
- a degree more tidying up,
- parameter interacts
- more documentation.
Released under a BSD-style licence: see source.
Authors:
Abigail Brady <abigail@thefoundry.co.uk>
Andrew Whitmore <andy@thefoundry.co.uk>
Bruno Nicoletti <bruno@thefoundry.co.uk>
Release Notes
-------------
26/03/2007
Minimum implementation, which allows plugin descriptions to be cached. Includes property sets and
property suite and implementation of plugin description. Support for describing in context and
parameters not fully enabled.
29/03/2007
Support for describing in contexts and parameters. These are cached as well.
25/06/2007
Major overhaul of the thing,
- propertys made simpler to use
- re-namespaced several classes so that anything to do with image effects are
in the ImageEffect namespace
- made the host layer do the logic for several Image Effect actions
- clip preferences
- regions of interest
- simplified the function signatures of the actions
- the 'Host' class now acts as,
- a factory,
- a filter for constructed objects,
- a description of the host application to the plugin.
# SPDX-License-Identifier: BSD-3-Clause
+17
View File
@@ -0,0 +1,17 @@
Things to do. This is a wish list of features to add to the host layer...
Common Base Class for All Plugin Instances
- currently using a void * to pass instance pointers to components that do not
need to know about image effects (eg: interact base classes).
- Should have a base 'Plugin::Instance' class that ImageEffect::Instance and any
other kind of plugin instance should derive from.
XML Resource Support
- have the host layer manage the external XML resource file and relabel things appropriately.
Support for Custom Params
- not there yet
- should have the host layer manage most of the custom param animation stuff as well.
+96
View File
@@ -0,0 +1,96 @@
#ifndef OFX_BINARY_H
#define OFX_BINARY_H
// Copyright OpenFX and contributors to the OpenFX project.
// SPDX-License-Identifier: BSD-3-Clause
#include <string>
#include <iostream>
#if defined(WIN32) || defined(WIN64)
#define I386
#elif defined(__linux__) || defined(__FreeBSD__)
#define UNIX
#ifdef __i386__
#define I386
#elif defined(__amd64__)
#define AMD64
#else
#error cannot detect architecture
#endif
#elif defined( __APPLE__)
#define UNIX
#else
#error cannot detect operating system
#endif
#if defined(UNIX)
#include <dlfcn.h>
#elif defined (WINDOWS)
#include "windows.h"
#include <assert.h>
#endif
#include <sys/stat.h>
namespace OFX
{
/// class representing a DLL/Shared Object/etc
class Binary {
/// destruction will close the library and invalidate
/// any function pointers returned by lookupSymbol()
protected :
std::string _binaryPath;
bool _invalid;
#if defined(UNIX)
void *_dlHandle;
#elif defined (WINDOWS)
HINSTANCE _dlHandle;
#endif
time_t _time;
off_t _size;
int _users;
public :
/// create object representing the binary. will stat() it,
/// and this fails, will set binary to be invalid.
Binary(const std::string &binaryPath);
~Binary() { unload(); }
bool isLoaded() const { return _dlHandle != 0; }
/// is this binary invalid? (did the a stat() or load() on the file fail,
/// or are we missing a some of the symbols?
bool isInvalid() const { return _invalid; }
/// set invalid status (e.g. called by user if a mandatory symbol was missing)
void setInvalid(bool invalid) { _invalid = invalid; }
/// Last modification time of the file.
time_t getTime() const { return _time; }
/// Current size of the file.
off_t getSize() const { return _size; }
/// Path to the file.
const std::string &getBinaryPath() const { return _binaryPath; }
void ref();
void unref();
/// open the binary.
void load();
/// close the binary
void unload();
/// look up a symbol in the binary file and return it as a pointer.
/// returns null pointer if not found, or if the library is not loaded.
void *findSymbol(const std::string &symbol);
};
}
#endif
+499
View File
@@ -0,0 +1,499 @@
// Copyright OpenFX and contributors to the OpenFX project.
// SPDX-License-Identifier: BSD-3-Clause
#ifndef OFX_CLIP_H
#define OFX_CLIP_H
#include "ofxImageEffect.h"
#include "ofxhPropertySuite.h"
#include "ofxhUtilities.h"
namespace OFX {
namespace Host {
namespace ImageEffect {
// forward declarations
class Image;
class Instance;
# ifdef OFX_SUPPORTS_OPENGLRENDER
class Texture;
# endif
/// Base to both descriptor and instance it
/// is used to basically fetch common properties
/// by function name
class ClipBase {
protected :
Property::Set _properties;
public :
/// base ctor, for a descriptor
ClipBase();
virtual ~ClipBase() { }
/// ctor, when copy constructing an instance from a descripto
explicit ClipBase(const ClipBase &other);
/// name of the clip
const std::string &getName() const
{
return _properties.getStringProperty(kOfxPropName);
}
/// name of the clip
const std::string &getShortLabel() const;
/// name of the clip
const std::string &getLabel() const;
/// name of the clip
const std::string &getLongLabel() const;
/// return a std::vector of supported comp
const std::vector<std::string> &getSupportedComponents() const;
/// is the given component supported
bool isSupportedComponent(const std::string &comp) const;
/// does the clip do random temporal access
bool temporalAccess() const;
/// is the clip optional
bool isOptional() const;
/// is the clip a nominal 'mask' clip
bool isMask() const;
/// how does this clip like fielded images to be presented to it
const std::string &getFieldExtraction() const;
/// is the clip a nominal 'mask' clip
bool supportsTiles() const;
/// get property set, const version
const Property::Set &getProps() const;
/// get property set , non const version
Property::Set &getProps();
/// get a handle on the properties of the clip descriptor for the C api
OfxPropertySetHandle getPropHandle() const;
/// get a handle on the clip descriptor/instance for the C api
OfxImageClipHandle getHandle() const;
virtual bool verifyMagic() {
return true;
}
};
/// a clip descriptor
class ClipDescriptor : public ClipBase {
public:
/// constructor
ClipDescriptor(const std::string &name);
/// is the clip an output clip
bool isOutput() const {return getName() == kOfxImageEffectOutputClipName; }
};
/// a clip instance
class ClipInstance : public ClipBase
, protected Property::GetHook
, protected Property::NotifyHook {
protected:
ImageEffect::Instance* _effectInstance; ///< image effect instance
bool _isOutput; ///< are we the output clip
std::string _pixelDepth; ///< what is the bit depth we is at. Set during the clip prefernces action.
std::string _components; ///< what components do we have. Set during the clip prefernces action.
public:
ClipInstance(ImageEffect::Instance* effectInstance, ClipDescriptor& desc);
/// is the clip an output clip
bool isOutput() const {return _isOutput;}
/// notify override properties
virtual void notify(const std::string &name, bool isSingle, int indexOrN);
/// get hook override
virtual void reset(const std::string &name);
// get the virtuals for viewport size, pixel scale, background colour
virtual double getDoubleProperty(const std::string &name, int index) const;
// get the virtuals for viewport size, pixel scale, background colour
virtual void getDoublePropertyN(const std::string &name, double *values, int count) const;
// get the virtuals for viewport size, pixel scale, background colour
virtual int getIntProperty(const std::string &name, int index) const;
// get the virtuals for viewport size, pixel scale, background colour
virtual void getIntPropertyN(const std::string &name, int *values, int count) const;
// get the virtuals for viewport size, pixel scale, background colour
virtual const std::string &getStringProperty(const std::string &name, int index) const;
// fetch multiple values in a multi-dimension property
virtual void getStringPropertyN(const std::string &name, const char** values, int count) const;
// get hook virtuals
virtual int getDimension(const std::string &name) const;
// instance changed action
OfxStatus instanceChangedAction(const std::string &why,
OfxTime time,
OfxPointD renderScale);
// properties of an instance that are live
/// Pixel Depth - fetch depth of all chromatic component in this clip
///
/// kOfxBitDepthNone (implying a clip is unconnected, not valid for an image)
/// kOfxBitDepthByte
/// kOfxBitDepthShort
/// kOfxBitDepthHalf
/// kOfxBitDepthFloat
const std::string &getPixelDepth() const
{
return _pixelDepth;
}
/// set the current pixel depth
/// called by clip preferences action
void setPixelDepth(const std::string &s)
{
_pixelDepth = s;
}
/// Components that can be fetched from this clip -
///
/// kOfxImageComponentNone (implying a clip is unconnected, not valid for an image)
/// kOfxImageComponentRGBA
/// kOfxImageComponentRGB
/// kOfxImageComponentAlpha
/// and any custom ones you may think of
virtual const std::string &getComponents() const;
/// set the current set of components
/// called by clip preferences action
virtual void setComponents(const std::string &s);
/// Get the Raw Unmapped Pixel Depth from the host for chromatic planes
///
/// \returns
/// - kOfxBitDepthNone (implying a clip is unconnected image)
/// - kOfxBitDepthByte
/// - kOfxBitDepthShort
/// - kOfxBitDepthHalf
/// - kOfxBitDepthFloat
virtual const std::string &getUnmappedBitDepth() const = 0;
/// Get the Raw Unmapped Components from the host
///
/// \returns
/// - kOfxImageComponentNone (implying a clip is unconnected, not valid for an image)
/// - kOfxImageComponentRGBA
/// - kOfxImageComponentAlpha
virtual const std::string &getUnmappedComponents() const = 0;
// PreMultiplication -
//
// kOfxImageOpaque - the image is opaque and so has no premultiplication state
// kOfxImagePreMultiplied - the image is premultiplied by it's alpha
// kOfxImageUnPreMultiplied - the image is unpremultiplied
virtual const std::string &getPremult() const = 0;
// Pixel Aspect Ratio -
//
// The pixel aspect ratio of a clip or image.
virtual double getAspectRatio() const = 0;
// Frame Rate -
//
// The frame rate of a clip or instance's project.
virtual double getFrameRate() const = 0;
// Frame Range (startFrame, endFrame) -
//
// The frame range over which a clip has images.
virtual void getFrameRange(double &startFrame, double &endFrame) const = 0;
/// Field Order - Which spatial field occurs temporally first in a frame.
/// \returns
/// - kOfxImageFieldNone - the clip material is unfielded
/// - kOfxImageFieldLower - the clip material is fielded, with image rows 0,2,4.... occuring first in a frame
/// - kOfxImageFieldUpper - the clip material is fielded, with image rows line 1,3,5.... occuring first in a frame
virtual const std::string &getFieldOrder() const = 0;
// Connected -
//
// Says whether the clip is actually connected at the moment.
virtual bool getConnected() const = 0;
// Unmapped Frame Rate -
//
// The unmapped frame rate.
virtual double getUnmappedFrameRate() const = 0;
// Unmapped Frame Range -
//
// The unmapped frame range over which an output clip has images.
virtual void getUnmappedFrameRange(double &unmappedStartFrame, double &unmappedEndFrame) const = 0;
// Continuous Samples -
//
// 0 if the images can only be sampled at discreet times (eg: the clip is a sequence of frames),
// 1 if the images can only be sampled continuously (eg: the clip is infact an animating roto spline and can be rendered anywhen).
virtual bool getContinuousSamples() const = 0;
/// override this to fill in the image at the given time.
/// The bounds of the image on the image plane should be
/// 'appropriate', typically the value returned in getRegionsOfInterest
/// on the effect instance. Outside a render call, the optionalBounds should
/// be 'appropriate' for the.
/// If bounds is not null, fetch the indicated section of the canonical image plane.
virtual ImageEffect::Image* getImage(OfxTime time, const OfxRectD *optionalBounds) = 0;
# ifdef OFX_SUPPORTS_OPENGLRENDER
/// override this to fill in the OpenGL texture at the given time.
/// The bounds of the image on the image plane should be
/// 'appropriate', typically the value returned in getRegionsOfInterest
/// on the effect instance. Outside a render call, the optionalBounds should
/// be 'appropriate' for the.
/// If bounds is not null, fetch the indicated section of the canonical image plane.
virtual ImageEffect::Texture* loadTexture(OfxTime time, const char *format, const OfxRectD *optionalBounds) = 0;
# endif
/// override this to return the rod on the clip
virtual OfxRectD getRegionOfDefinition(OfxTime time) const = 0;
/// given the colour component, find the nearest set of supported colour components
/// override this for extra wierd custom component depths
virtual const std::string &findSupportedComp(const std::string &s) const;
};
/// instance of an image inside an image effect
class ImageBase : public Property::Set {
protected :
/// called during ctors to get bits from the clip props into ours
void getClipBits(ClipInstance& instance);
int _referenceCount; ///< reference count on this image
public:
// default constructor
virtual ~ImageBase();
/// basic ctor, makes empty property set but sets not value
ImageBase();
/// construct from a clip instance, but leave the
/// filling it to the calling code via the propery set
explicit ImageBase(ClipInstance& instance);
// Render Scale (renderScaleX,renderScaleY) -
//
// The proxy render scale currently being applied.
// ------
// Bounds (bx1,by1,bx2,by2) -
//
// The bounds of an image's pixels. The bounds, in PixelCoordinates, are of the
// addressable pixels in an image's data pointer. The order of the values is
// x1, y1, x2, y2. X values are x1 &lt;= X &lt; x2 Y values are y1 &lt;= Y &lt; y2
// ------
// ROD (rodx1,rody1,rodx2,rody2) -
//
// The full region of definition. The ROD, in PixelCoordinates, are of the
// addressable pixels in an image's data pointer. The order of the values is
// x1, y1, x2, y2. X values are x1 &lt;= X &lt; x2 Y values are y1 &lt;= Y &lt; y2
// ------
// Row Bytes -
//
// The number of bytes in a row of an image.
// ------
// Field -
//
// kOfxImageFieldNone - the image is an unfielded frame
// kOfxImageFieldBoth - the image is fielded and contains both interlaced fields
// kOfxImageFieldLower - the image is fielded and contains a single field, being the lower field (rows 0,2,4...)
// kOfxImageFieldUpper - the image is fielded and contains a single field, being the upper field (rows 1,3,5...)
// ------
// Unique Identifier -
//
// Uniquely labels an image. This is host set and allows a plug-in to differentiate between images. This is
// especially useful if a plugin caches analysed information about the image (for example motion vectors). The
// plugin can label the cached information with this identifier. If a user connects a different clip to the
// analysed input, or the image has changed in some way then the plugin can detect this via an identifier change
// and re-evaluate the cached information.
// construction based on clip instance
ImageBase(ClipInstance& instance, // construct from clip instance taking pixel depth, components, pre mult and aspect ratio
double renderScaleX,
double renderScaleY,
const OfxRectI &bounds,
const OfxRectI &rod,
int rowBytes,
std::string field,
std::string uniqueIdentifier);
// OfxImageClipHandle getHandle();
OfxPropertySetHandle getPropHandle() const { return Property::Set::getHandle(); }
/// get the bounds of the pixels in memory
OfxRectI getBounds() const;
/// get the full region of this image
OfxRectI getROD() const;
/// release the reference count, which, if zero, deletes this
void releaseReference();
/// add a reference to this image
void addReference() {_referenceCount++;}
};
/// instance of an image inside an image effect
class Image : public ImageBase {
public:
// default constructor
virtual ~Image();
/// basic ctor, makes empty property set but sets not value
Image();
/// construct from a clip instance, but leave the
/// filling it to the calling code via the propery set
explicit Image(ClipInstance& instance);
// Render Scale (renderScaleX,renderScaleY) -
//
// The proxy render scale currently being applied.
// ------
// Data -
//
// The pixel data pointer of an image.
// ------
// Bounds (bx1,by1,bx2,by2) -
//
// The bounds of an image's pixels. The bounds, in PixelCoordinates, are of the
// addressable pixels in an image's data pointer. The order of the values is
// x1, y1, x2, y2. X values are x1 &lt;= X &lt; x2 Y values are y1 &lt;= Y &lt; y2
// ------
// ROD (rodx1,rody1,rodx2,rody2) -
//
// The full region of definition. The ROD, in PixelCoordinates, are of the
// addressable pixels in an image's data pointer. The order of the values is
// x1, y1, x2, y2. X values are x1 &lt;= X &lt; x2 Y values are y1 &lt;= Y &lt; y2
// ------
// Row Bytes -
//
// The number of bytes in a row of an image.
// ------
// Field -
//
// kOfxImageFieldNone - the image is an unfielded frame
// kOfxImageFieldBoth - the image is fielded and contains both interlaced fields
// kOfxImageFieldLower - the image is fielded and contains a single field, being the lower field (rows 0,2,4...)
// kOfxImageFieldUpper - the image is fielded and contains a single field, being the upper field (rows 1,3,5...)
// ------
// Unique Identifier -
//
// Uniquely labels an image. This is host set and allows a plug-in to differentiate between images. This is
// especially useful if a plugin caches analysed information about the image (for example motion vectors). The
// plugin can label the cached information with this identifier. If a user connects a different clip to the
// analysed input, or the image has changed in some way then the plugin can detect this via an identifier change
// and re-evaluate the cached information.
// construction based on clip instance
Image(ClipInstance& instance, // construct from clip instance taking pixel depth, components, pre mult and aspect ratio
double renderScaleX,
double renderScaleY,
void* data,
const OfxRectI &bounds,
const OfxRectI &rod,
int rowBytes,
std::string field,
std::string uniqueIdentifier);
};
# ifdef OFX_SUPPORTS_OPENGLRENDER
/// instance of an OpenGL texture inside an image effect
class Texture : public ImageBase {
public:
// default constructor
virtual ~Texture();
/// basic ctor, makes empty property set but sets not value
Texture();
/// construct from a clip instance, but leave the
/// filling it to the calling code via the propery set
explicit Texture(ClipInstance& instance);
// Render Scale (renderScaleX,renderScaleY) -
//
// The proxy render scale currently being applied.
// ------
// Index -
//
// The texture id (cast to GLuint).
// ------
// Target -
//
// The texture target (cast to GLenum).
// ------
// Bounds (bx1,by1,bx2,by2) -
//
// The bounds of an image's pixels. The bounds, in PixelCoordinates, are of the
// addressable pixels in an image's data pointer. The order of the values is
// x1, y1, x2, y2. X values are x1 &lt;= X &lt; x2 Y values are y1 &lt;= Y &lt; y2
// ------
// ROD (rodx1,rody1,rodx2,rody2) -
//
// The full region of definition. The ROD, in PixelCoordinates, are of the
// addressable pixels in an image's data pointer. The order of the values is
// x1, y1, x2, y2. X values are x1 &lt;= X &lt; x2 Y values are y1 &lt;= Y &lt; y2
// ------
// Row Bytes -
//
// The number of bytes in a row of an image.
// ------
// Field -
//
// kOfxImageFieldNone - the image is an unfielded frame
// kOfxImageFieldBoth - the image is fielded and contains both interlaced fields
// kOfxImageFieldLower - the image is fielded and contains a single field, being the lower field (rows 0,2,4...)
// kOfxImageFieldUpper - the image is fielded and contains a single field, being the upper field (rows 1,3,5...)
// ------
// Unique Identifier -
//
// Uniquely labels an image. This is host set and allows a plug-in to differentiate between images. This is
// especially useful if a plugin caches analysed information about the image (for example motion vectors). The
// plugin can label the cached information with this identifier. If a user connects a different clip to the
// analysed input, or the image has changed in some way then the plugin can detect this via an identifier change
// and re-evaluate the cached information.
// construction based on clip instance
Texture(ClipInstance& instance, // construct from clip instance taking pixel depth, components, pre mult and aspect ratio
double renderScaleX,
double renderScaleY,
int index,
int target,
const OfxRectI &bounds,
const OfxRectI &rod,
int rowBytes,
std::string field,
std::string uniqueIdentifier);
};
# endif
} // Memory
} // Host
} // OFX
#endif // OFX_CLIP_H
+84
View File
@@ -0,0 +1,84 @@
#ifndef OFX_HOST_H
#define OFX_HOST_H
// Copyright OpenFX and contributors to the OpenFX project.
// SPDX-License-Identifier: BSD-3-Clause
#include <map>
#include <string>
#include <cstdarg>
#include "ofxCore.h"
#include "ofxImageEffect.h"
#include "ofxTimeLine.h"
#include "ofxhPropertySuite.h"
namespace OFX {
namespace Host {
/// a plugin what we use
class Plugin;
/// a param descriptor
namespace Param {
class Descriptor;
}
/// Base class for all objects passed to a plugin by the 'setHost' function
/// passed back by any plug-in.
class Host {
protected :
OfxHost _host;
Property::Set _properties;
public:
Host();
virtual ~Host() {}
/// get the props on this host
Property::Set &getProperties() {return _properties; }
/// fetch a suite
/// The base class returns the following suites
/// PropertySuite
/// MemorySuite
virtual const void *fetchSuite(const char *suiteName, int suiteVersion);
/// get the C API handle that is passed across the API to represent this host
OfxHost *getHandle();
/// override this to handle do post-construction initialisation on a Param::Descriptor
virtual void initParamDescriptor(Param::Descriptor *) { }
/// is my magic number valid?
bool verifyMagic() { return true; }
/// message (called when an exception occurs, calls vmessage)
OfxStatus message(const char* type,
const char* id,
const char* format,
...);
/// vmessage
virtual OfxStatus vmessage(const char* type,
const char* id,
const char* format,
va_list args) = 0;
/// setPersistentMessage
virtual OfxStatus setPersistentMessage(const char* type,
const char* id,
const char* format,
va_list args) = 0;
/// clearPersistentMessage
virtual OfxStatus clearPersistentMessage() = 0;
};
}
}
#endif
+679
View File
@@ -0,0 +1,679 @@
#ifndef OFX_IMAGE_EFFECT_H
#define OFX_IMAGE_EFFECT_H
#include "ofxCore.h"
#include "ofxImageEffect.h"
#include "ofxhHost.h"
#include "ofxhClip.h"
#include "ofxhProgress.h"
#include "ofxhTimeLine.h"
#include "ofxhParam.h"
#include "ofxhMemory.h"
#include "ofxhInteract.h"
#ifdef _MSC_VER
//Use visual studio extension
#define __PRETTY_FUNCTION__ __FUNCSIG__
#endif
namespace OFX {
namespace Host {
// forward declare
class Plugin;
namespace Memory {
class Instance;
}
namespace ImageEffect {
// forward declare
class ImageEffectPlugin;
class OverlayInstance;
class Instance;
class Descriptor;
/// An image effect host, passed to the setHost function of all image effect plugins
class Host : public OFX::Host::Host {
public :
Host();
/// fetch a suite
virtual const void *fetchSuite(const char *suiteName, int suiteVersion);
/// Create a new instance of an image effect plug-in.
///
/// It is called by ImageEffectPlugin::createInstance which the
/// client code calls when it wants to make a new instance.
///
/// \arg clientData - the clientData passed into the ImageEffectPlugin::createInstance
/// \arg plugin - the plugin being created
/// \arg desc - the descriptor for that plugin
/// \arg context - the context to be created in
virtual Instance* newInstance(void* clientData,
ImageEffectPlugin* plugin,
Descriptor& desc,
const std::string& context) = 0;
/// Function called as each plugin binary is found and loaded from disk
///
/// Use this in any dialogue etc... showing progress
virtual void loadingStatus(const std::string &);
/// Override this to filter out plugins which the host can't support for whatever reason
///
/// \arg plugin - the plugin to examine
/// \arg reason - set this to report the reason the plugin was not loaded
virtual bool pluginSupported(ImageEffectPlugin *plugin, std::string &reason) const;
/// Override this to create a descriptor, this makes the 'root' descriptor
virtual Descriptor *makeDescriptor(ImageEffectPlugin* plugin) = 0;
/// used to construct a context description, rootContext is the main context
virtual Descriptor *makeDescriptor(const Descriptor &rootContext, ImageEffectPlugin *plug) = 0;
/// used to construct populate the cache
virtual Descriptor *makeDescriptor(const std::string &bundlePath, ImageEffectPlugin *plug) = 0;
/// Override this to initialise an image effect descriptor after it has been
/// created.
virtual void initDescriptor(Descriptor* desc);
#ifdef OFX_SUPPORTS_MULTITHREAD
// these functions must be implemented if the host supports OfxMultiThreadSuiteV1
// all the following functions are described in ofxMultiThread.h
//
/// @see OfxMultiThreadSuiteV1.multiThread()
virtual OfxStatus multiThread(OfxThreadFunctionV1 func,unsigned int nThreads, void *customArg) = 0;
/// @see OfxMultiThreadSuiteV1.multiThreadNumCPUS()
virtual OfxStatus multiThreadNumCPUS(unsigned int *nCPUs) const = 0;
/// @see OfxMultiThreadSuiteV1.multiThreadIndex()
virtual OfxStatus multiThreadIndex(unsigned int *threadIndex) const = 0;
/// @see OfxMultiThreadSuiteV1.multiThreadIsSpawnedThread()
virtual int multiThreadIsSpawnedThread() const = 0;
/// @see OfxMultiThreadSuiteV1.mutexCreate()
virtual OfxStatus mutexCreate(OfxMutexHandle *mutex, int lockCount) = 0;
/// @see OfxMultiThreadSuiteV1.mutexDestroy()
virtual OfxStatus mutexDestroy(const OfxMutexHandle mutex) = 0;
/// @see OfxMultiThreadSuiteV1.mutexLock()
virtual OfxStatus mutexLock(const OfxMutexHandle mutex) = 0;
/// @see OfxMultiThreadSuiteV1.mutexUnLock()
virtual OfxStatus mutexUnLock(const OfxMutexHandle mutex) = 0;
/// @see OfxMultiThreadSuiteV1.mutexTryLock()
virtual OfxStatus mutexTryLock(const OfxMutexHandle mutex) = 0;
#endif // OFX_SUPPORTS_MULTITHREAD
# ifdef OFX_SUPPORTS_OPENGLRENDER
/// @see OfxImageEffectOpenGLRenderSuiteV1.flushResources()
virtual OfxStatus flushOpenGLResources() const = 0;
# endif
/// override this to use your own memory instance - must inherrit from memory::instance
virtual Memory::Instance* newMemoryInstance(size_t nBytes);
// return an memory::instance calls makeMemoryInstance that can be overriden
Memory::Instance* imageMemoryAlloc(size_t nBytes);
};
/// our global host object, set when the plugin cache is created
extern Host *gImageEffectHost;
////////////////////////////////////////////////////////////////////////////////
/// base class to both effect descriptors and instances
class Base {
protected:
Property::Set _properties;
public:
Base(const Property::Set &set);
Base(const Property::PropSpec * propSpec);
virtual ~Base();
/// is my magic number valid?
virtual bool verifyMagic() { return true; }
/// obtain a handle on this for passing to the C api
OfxImageEffectHandle getHandle() const;
/// get the properties set
Property::Set &getProps();
/// get the properties set, const version
const Property::Set &getProps() const;
/// name of the clip
const std::string &getShortLabel() const;
/// name of the clip
const std::string &getLabel() const;
/// name of the clip
const std::string &getLongLabel() const;
/// is the given context supported
bool isContextSupported(const std::string &s) const;
/// what is the name of the group the plug-in belongs to
const std::string &getPluginGrouping() const;
/// is the effect single instance
bool isSingleInstance() const;
/// what is the thread safety on this effect
const std::string &getRenderThreadSafety() const;
/// should the host attempt to managed multi-threaded rendering if it can
/// via tiling or some such
bool getHostFrameThreading() const;
/// get the overlay interact main entry if it exists
OfxPluginEntryPoint *getOverlayInteractMainEntry() const;
/// does the effect support images of differing sizes
bool supportsMultiResolution() const;
/// does the effect support tiled rendering
bool supportsTiles() const;
/// does this effect need random temporal access
bool temporalAccess() const;
/// is the given RGBA/A pixel depth supported by the effect
bool isPixelDepthSupported(const std::string &s) const;
/// when field rendering, does the effect need to be called
/// twice to render a frame in all circumstances (with different fields)
bool fieldRenderTwiceAlways() const;
/// does the effect support multiple clip depths
bool supportsMultipleClipDepths() const;
/// does the effect support multiple clip pixel aspect ratios
bool supportsMultipleClipPARs() const;
/// does changing the named param re-tigger a clip preferences action
bool isClipPreferencesSlaveParam(const std::string &s) const;
};
/// an image effect plugin descriptor
class Descriptor
: public Base
, public Param::SetDescriptor {
private :
// private CC
Descriptor(const Descriptor &other)
: Base(other._properties)
, Param::SetDescriptor()
, _plugin(other._plugin)
{}
protected:
Plugin *_plugin; ///< the plugin I belong to
std::map<std::string, ClipDescriptor*> _clips; ///< clips descriptors by name
std::vector<ClipDescriptor*> _clipsByOrder; ///< clip descriptors in order of declaration
mutable Interact::Descriptor _overlayDescriptor; ///< descriptor to use for overlays, it has delayed description
public:
/// used to construct the global description
Descriptor(Plugin *plug);
/// used to construct a context description, 'other' is the main context
Descriptor(const Descriptor &rootContext, Plugin *plug);
/// used to construct populate the cache
Descriptor(const std::string &bundlePath, Plugin *plug);
/// dtor
virtual ~Descriptor();
/// implemented for Param::SetDescriptor
virtual Property::Set &getParamSetProps();
/// get the plugin I belong to
Plugin *getPlugin() const {return _plugin;}
/// create a new clip and add this to the clip map
virtual ClipDescriptor *defineClip(const std::string &name);
/// get the clips
const std::map<std::string, ClipDescriptor*> &getClips() const;
/// add a new clip
void addClip(const std::string &name, ClipDescriptor *clip);
/// get the clips in order of construction
const std::vector<ClipDescriptor*> &getClipsByOrder() const
{
return _clipsByOrder;
}
/// Get the interact description, this will also call describe on the interact
/// This will return NULL if there is not main entry point or if the description failed
/// otherwise it will return the described overlay
Interact::Descriptor &getOverlayDescriptor(int bitDepthPerComponent = 8, bool hasAlpha = false);
};
/// a map used to specify needed frame ranges on set of clips
typedef std::map<ClipInstance *, std::vector<OfxRangeD> > RangeMap;
/// an image effect plugin instance.
///
/// Client code needs to filling the pure virtuals in this.
class Instance : public Base,
public Param::SetInstance,
public Progress::ProgressI,
public TimeLine::TimeLineI,
private Property::NotifyHook,
private Property::GetHook
{
protected:
OFX::Host::ImageEffect::ImageEffectPlugin *_plugin;
std::string _context;
Descriptor *_descriptor;
std::map<std::string, ClipInstance*> _clips;
bool _interactive;
bool _created;
bool _clipPrefsDirty; ///< do we need to re-run the clip prefs action
bool _continuousSamples; ///< set by clip prefs
bool _frameVarying; ///< set by clip prefs
std::string _outputPreMultiplication; ///< set by clip prefs
std::string _outputFielding; ///< set by clip prefs
double _outputFrameRate; ///< set by clip prefs
public:
/// constructor based on clip descriptor
Instance(ImageEffectPlugin* plugin,
Descriptor &other,
const std::string &context,
bool interactive);
virtual ~Instance();
/// implemented for Param::SetInstance
virtual Property::Set &getParamSetProps();
/// implemented for Param::SetInstance
virtual void paramChangedByPlugin(Param::Instance *param);
/// get the descriptor for this instance
const Descriptor &getDescriptor() const {return *_descriptor;}
/// return the plugin this instance was created with
OFX::Host::ImageEffect::ImageEffectPlugin*getPlugin() const { return _plugin; }
/// return the context this instance was created with
const std::string &getContext() const { return _context; }
/// get the descriptor for this instance
Descriptor &getDescriptor() {return *_descriptor;}
/// get default output fielding. This is passed into the clip prefs action
/// and might be mapped (if the host allows such a thing)
virtual const std::string &getDefaultOutputFielding() const = 0;
/// get output fielding as set in the clip preferences action.
const std::string &getOutputFielding() const {return _outputFielding; }
/// get output fielding as set in the clip preferences action.
const std::string &getOutputPreMultiplication() const {return _outputPreMultiplication; }
/// get the output frame rate, as set in the clip prefences action.
double getOutputFrameRate() const {return _outputFrameRate;}
/// called after construction to populate the various members
/// ideally should be called in the ctor, but it relies on
/// virtuals so has to be delayed until after the effect is
/// constructed
OfxStatus populate();
/// get the nth clip, in order of declaration
ClipInstance* getNthClip(int index);
/// get the nth clip, in order of declaration
int getNClips() const
{
return int(_clips.size());
}
/// are the clip preferences currently dirty
bool areClipPrefsDirty() const {return _clipPrefsDirty;}
/// are all the non optional clips connected
bool checkClipConnectionStatus() const;
/// can this this instance render images at arbitrary times, not just frame boundaries
/// set by getClipPreferenceAction()
bool continuousSamples() const {return _continuousSamples;}
/// does this instance generate a different picture on a frame change, even if the
/// params and input images are exactly the same. eg: random noise generator
bool isFrameVarying() const {return _frameVarying;}
/// pure virtuals that must be overriden
virtual ClipInstance* getClip(const std::string& name) const;
/// override this to make processing abort, return 1 to abort processing
virtual int abort();
/// override this to use your own memory instance - must inherrit from memory::instance
virtual Memory::Instance* newMemoryInstance(size_t nBytes);
// return an memory::instance calls makeMemoryInstance that can be overriden
Memory::Instance* imageMemoryAlloc(size_t nBytes);
/// make a clip
virtual ClipInstance* newClipInstance(ImageEffect::Instance* plugin,
ClipDescriptor* descriptor,
int index) = 0;
/// message suite
virtual OfxStatus vmessage(const char* type,
const char* id,
const char* format,
va_list args) = 0;
virtual OfxStatus setPersistentMessage(const char* type,
const char* id,
const char* format,
va_list args) = 0;
virtual OfxStatus clearPersistentMessage() = 0;
/// call the effect entry point
virtual OfxStatus mainEntry(const char *action,
const void *handle,
Property::Set *inArgs,
Property::Set *outArgs);
int upperGetDimension(const std::string &name);
/// overridden from Property::Notify
virtual void notify(const std::string &name, bool singleValue, int indexOrN);
/// overridden from gethook, get the virutals for viewport size, pixel scale, background colour
virtual double getDoubleProperty(const std::string &name, int index) const;
/// overridden from gethook, get the virutals for viewport size, pixel scale, background colour
virtual void getDoublePropertyN(const std::string &name, double *values, int count) const;
/// overridden from gethook, don't know what to do
virtual void reset(const std::string &name);
//// overridden from gethook
virtual int getDimension(const std::string &name) const;
//
// live parameters
//
// The size of the current project in canonical coordinates.
// The size of a project is a sub set of the kOfxImageEffectPropProjectExtent. For example a
// project may be a PAL SD project, but only be a letter-box within that. The project size is
// the size of this sub window.
virtual void getProjectSize(double& xSize, double& ySize) const = 0;
// The offset of the current project in canonical coordinates.
// The offset is related to the kOfxImageEffectPropProjectSize and is the offset from the origin
// of the project 'subwindow'. For example for a PAL SD project that is in letterbox form, the
// project offset is the offset to the bottom left hand corner of the letter box. The project
// offset is in canonical coordinates.
virtual void getProjectOffset(double& xOffset, double& yOffset) const = 0;
// The extent of the current project in canonical coordinates.
// The extent is the size of the 'output' for the current project. See ProjectCoordinateSystems
// for more infomation on the project extent. The extent is in canonical coordinates and only
// returns the top right position, as the extent is always rooted at 0,0. For example a PAL SD
// project would have an extent of 768, 576.
virtual void getProjectExtent(double& xSize, double& ySize) const = 0;
// The pixel aspect ratio of the current project
virtual double getProjectPixelAspectRatio() const = 0;
// The duration of the effect
// This contains the duration of the plug-in effect, in frames.
virtual double getEffectDuration() const = 0;
// For an instance, this is the frame rate of the project the effect is in.
virtual double getFrameRate() const = 0;
/// This is called whenever a param is changed by the plugin so that
/// the recursive instanceChangedAction will be fed the correct frame
virtual double getFrameRecursive() const = 0;
/// This is called whenever a param is changed by the plugin so that
/// the recursive instanceChangedAction will be fed the correct
/// renderScale
virtual void getRenderScaleRecursive(double &x, double &y) const = 0;
/// Get whether the component is a supported 'chromatic' component (RGBA or alpha) in
/// the base API.
/// Override this if you have extended your chromatic colour types (eg RGB) and want
/// the clip preferences logic to still work
virtual bool isChromaticComponent(const std::string &str) const;
/// function to check for multiple bit depth support
/// The answer will depend on host, plugin and context
virtual bool canCurrentlyHandleMultipleClipDepths() const;
/// calculate the default rod for this effect instance
virtual OfxRectD calcDefaultRegionOfDefinition(OfxTime time,
OfxPointD renderScale) const;
//
// actions
//
/// this is used to populate with any extra action in argumnents that may be needed
virtual void setCustomInArgs(const std::string &action, Property::Set &inArgs);
/// this is used to populate with any extra action out argumnents that may be needed
virtual void setCustomOutArgs(const std::string &action, Property::Set &outArgs);
/// this is used retrieve any out args after the action was called in mainEntry
virtual void examineOutArgs(const std::string &action, OfxStatus stat, const Property::Set &outArgs);
/// create an instance. This needs to be called _after_ construction and
/// _after_ the host populates it's params and clips with the 'correct'
/// values (either persisted ones or the defaults)
virtual OfxStatus createInstanceAction();
// begin/change/end instance changed
//
// why -
//
// kOfxChangeUserEdited - the user or host changed the instance somehow and
// caused a change to something, this includes undo/redos,
// resets and loading values from files or presets,
// kOfxChangePluginEdited - the plugin itself has changed the value of the instance
// in some action
// kOfxChangeTime - the time has changed and this has affected the value
// of the object because it varies over time
//
virtual OfxStatus beginInstanceChangedAction(const std::string &why);
virtual OfxStatus paramInstanceChangedAction(const std::string &paramName,
const std::string & why,
OfxTime time,
OfxPointD renderScale);
virtual OfxStatus clipInstanceChangedAction(const std::string &clipName,
const std::string & why,
OfxTime time,
OfxPointD renderScale);
virtual OfxStatus endInstanceChangedAction(const std::string &why);
// purge your caches
virtual OfxStatus purgeCachesAction();
// sync your private data
virtual OfxStatus syncPrivateDataAction();
// begin/end edit instance
virtual OfxStatus beginInstanceEditAction();
virtual OfxStatus endInstanceEditAction();
# ifdef OFX_SUPPORTS_OPENGLRENDER
// attach/detach OpenGL context
virtual OfxStatus contextAttachedAction();
virtual OfxStatus contextDetachedAction();
# endif
// render action
virtual OfxStatus beginRenderAction(OfxTime startFrame,
OfxTime endFrame,
OfxTime step,
bool interactive,
OfxPointD renderScale,
bool sequentialRender,
bool interactiveRender
);
virtual OfxStatus renderAction(OfxTime time,
const std::string & field,
const OfxRectI &renderRoI,
OfxPointD renderScale,
bool sequentialRender,
bool interactiveRender,
bool draftRender
);
virtual OfxStatus endRenderAction(OfxTime startFrame,
OfxTime endFrame,
OfxTime step,
bool interactive,
OfxPointD renderScale,
bool sequentialRender,
bool interactiveRender
);
/// Call the region of definition action the plugin at the given time
/// and with the given render scales. The value is returned in rod.
/// Note that if the plugin does not trap the action the default
/// RoD is calculated and returned.
virtual OfxStatus getRegionOfDefinitionAction(OfxTime time,
OfxPointD renderScale,
OfxRectD &rod);
/// call the get region of interest action on the plugin for the
/// given frame and renderscale. The render RoI is passed in in
/// roi, the std::map will contain the requested rois. Note
/// That this call will check for tiling support and for
/// default replies and set up the correct rois in these cases
/// as well
virtual OfxStatus getRegionOfInterestAction(OfxTime time,
OfxPointD renderScale,
const OfxRectD &roi,
std::map<ClipInstance *, OfxRectD> &rois);
// get frames needed to render the given frame
virtual OfxStatus getFrameNeededAction(OfxTime time,
RangeMap &rangeMap);
// is identity
virtual OfxStatus isIdentityAction(OfxTime &time,
const std::string & field,
const OfxRectI &renderRoI,
OfxPointD renderScale,
std::string &clip);
// time domain
virtual OfxStatus getTimeDomainAction(OfxRangeD& range);
/// Get the interact description, this will also call describe on the interact
/// This will return NULL if there is not main entry point or if the description failed
/// otherwise it will return the described overlay
/// This is called by the CTOR of OverlayInteract to get the descriptor to do things with
Interact::Descriptor &getOverlayDescriptor(int bitDepthPerComponent = 8, bool hasAlpha = false);
/// Setup the default clip preferences on the clips
virtual void setDefaultClipPreferences();
/// Initialise the clip preferences arguments, override this to do
/// stuff with wierd components etc... Calls setDefaultClipPreferences
virtual void setupClipPreferencesArgs(Property::Set &args);
/// Run the clip preferences action from the effect.
///
/// This will look into the input clips and output clip
/// and set the following properties that the effect should
/// fetch the image at.
/// - pixel depth
/// - components
/// - pixel aspect ratio
/// It will also set on the effect itselff
/// - whether it is continuously samplable
/// - the premult state of the output
/// - whether the effect is frame varying
/// - the fielding of the output clip
///
/// This will be run automatically by the effect in the following situations...
/// - an input clip is changed
/// - a clip preferences slave param is changed
///
/// The host still needs to call this explicitly just after the effect is wired
/// up.
virtual bool getClipPreferences();
/// calls getClipPreferences only if the prefs are dirty
///
/// returns whether the clips prefs were dirty or not
bool runGetClipPrefsConditionally()
{
if(areClipPrefsDirty()) {
getClipPreferences();
return true;
}
return false;
}
/// find the best supported bit depth for the given one. Override this if you define
/// more depths
virtual const std::string &bestSupportedDepth(const std::string &depth) const;
/// find the most chromatic components out of the two. Override this if you define
/// more chromatic components
virtual const std::string &findMostChromaticComponents(const std::string &a, const std::string &b) const;
};
////////////////////////////////////////////////////////////////////////////////
/// An overlay interact for image effects, derived from one of these to
/// be an overlay interact
class OverlayInteract : public Interact::Instance {
protected :
/// our image effect instance
ImageEffect::Instance &_instance;
public :
/// ctor this calls Instance->getOverlayDescriptor to get the descriptor
OverlayInteract(ImageEffect::Instance &v, int bitDepthPerComponent = 8, bool hasAlpha = false);
};
} // namespace ImageEffect
} // namespace Host
} // namespace OFX
#endif // OFX_IMAGE_EFFECT_H
@@ -0,0 +1,221 @@
#ifndef OFXH_IMAGE_EFFECT_API_H
#define OFXH_IMAGE_EFFECT_API_H
#include "ofxhPluginAPICache.h"
#include "ofxhPluginCache.h"
#include <string>
#include <map>
#include <set>
#include <memory>
#include <utility>
#include "ofxCore.h"
#include "ofxImageEffect.h"
#include "ofxhImageEffect.h"
#include "ofxhHost.h"
namespace OFX::Host::ImageEffect {
class PluginCache;
/// subclass of Plugin representing an ImageEffect plugin. used to store API-specific
/// data
class ImageEffectPlugin : public Plugin {
PluginCache &_pc;
// this comes off Descriptor's property set after a describe
// context independent
Descriptor *_baseDescriptor; /// NEEDS TO BE MADE WITH A FACTORY FUNCTION ON THE HOST!!!!!!
/// map to store contexts in
std::map<std::string, std::unique_ptr<Descriptor>> _contexts;
mutable std::set<std::string> _knownContexts;
mutable bool _madeKnownContexts;
std::unique_ptr<PluginHandle> _pluginHandle;
void addContextInternal(const std::string &context) const;
public:
ImageEffectPlugin(PluginCache &pc, PluginBinary *pb, int pi, OfxPlugin *pl);
ImageEffectPlugin(PluginCache &pc,
PluginBinary *pb,
int pi,
const std::string &api,
int apiVersion,
const std::string &pluginId,
const std::string &rawId,
int pluginMajorVersion,
int pluginMinorVersion);
~ImageEffectPlugin() override;
/// return the API handler this plugin was constructed by
APICache::PluginAPICacheI &getApiHandler() override;
/// get the base image effect descriptor
Descriptor &getDescriptor();
/// get the base image effect descriptor, const version
const Descriptor &getDescriptor() const;
/// get the image effect descriptor for the context
Descriptor *getContext(const std::string &context);
void addContext(const std::string &context);
void addContext(const std::string &context, std::unique_ptr<Descriptor> ied);
virtual void saveXML(std::ostream &os);
const std::set<std::string>& getContexts() const;
PluginHandle *getPluginHandle();
void unload();
/// this is called to make an instance of the effect
/// the client data ptr is what is passed back to the client creation function
ImageEffect::Instance* createInstance(const std::string &context, void *clientDataPtr);
};
class MajorPlugin {
std::string _id;
int _major;
public:
MajorPlugin(std::string id, int major) : _id(std::move(id)), _major(major) {
}
explicit MajorPlugin(ImageEffectPlugin *iep) : _id(iep->getIdentifier()), _major(iep->getVersionMajor()) {
}
[[nodiscard]] const std::string &getId() const {
return _id;
}
[[nodiscard]] int getMajor() const {
return _major;
}
bool operator<(const MajorPlugin &other) const {
if (_id < other._id)
return true;
if (_id > other._id)
return false;
if (_major < other._major)
return true;
return false;
}
};
/// implementation of the specific Image Effect handler API cache.
class PluginCache : public APICache::PluginAPICacheI {
public:
private:
/// all plugins
std::vector<ImageEffectPlugin *> _plugins;
/// latest version of each plugin by ID
std::map<std::string, ImageEffectPlugin *> _pluginsByID;
/// latest minor version of each plugin by (ID,major)
std::map<MajorPlugin, ImageEffectPlugin *> _pluginsByIDMajor;
/// xml parsing state
ImageEffectPlugin *_currentPlugin;
/// xml parsing state
Property::Property *_currentProp;
Descriptor *_currentContext;
Param::Descriptor *_currentParam;
ClipDescriptor *_currentClip;
/// pointer to our image effect host
OFX::Host::ImageEffect::Host* _host;
public:
explicit PluginCache(OFX::Host::ImageEffect::Host &host);
~PluginCache() override;
/// get the plugin by id. vermaj and vermin can be specified. if they are not it will
/// pick the highest found version.
ImageEffectPlugin *getPluginById(const std::string &id, int vermaj=-1, int vermin=-1);
/// get the plugin by label. vermaj and vermin can be specified. if they are not it will
/// pick the highest found version.
ImageEffectPlugin *getPluginByLabel(const std::string &label, int vermaj=-1, int vermin=-1);
OFX::Host::ImageEffect::Host *getHost() {
return _host;
}
[[nodiscard]] const std::vector<ImageEffectPlugin *>& getPlugins() const;
[[nodiscard]] const std::map<std::string, ImageEffectPlugin *>& getPluginsByID() const;
[[nodiscard]] const std::map<MajorPlugin, ImageEffectPlugin *>& getPluginsByIDMajor() const
{
return _pluginsByIDMajor;
}
/// handle the case where the info needs filling in from the file. runs the "describe" action on the plugin.
void loadFromPlugin(Plugin *p) const override;
/// handler for preparing to read in a chunk of XML from the cache, set up context to do this
void beginXmlParsing(Plugin *p) override;
/// XML handler : element begins (everything is stored in elements and attributes)
void xmlElementBegin(const std::string &el, std::map<std::string, std::string> map) override;
void xmlCharacterHandler(const std::string &) override;
void xmlElementEnd(const std::string &el) override;
void endXmlParsing() override;
void saveXML(Plugin *ip, std::ostream &os) const override;
void confirmPlugin(Plugin *p) override;
bool pluginSupported(Plugin *p, std::string &reason) const override;
Plugin *newPlugin(PluginBinary *pb,
int pi,
OfxPlugin *pl) override;
Plugin *newPlugin(PluginBinary *pb,
int pi,
const std::string &api,
int apiVersion,
const std::string &pluginId,
const std::string &rawId,
int pluginMajorVersion,
int pluginMinorVersion) override;
void dumpToStdOut();
};
} // ImageEffect
// Host
// OFX
#endif
+278
View File
@@ -0,0 +1,278 @@
#ifndef OFX_INTERACT_H
#define OFX_INTERACT_H
#include "ofxInteract.h"
#include "ofxOld.h" // old plugins may rely on deprecated properties being present
#include "ofxhPropertySuite.h"
namespace OFX {
namespace Host {
namespace Interact {
/// fetch a versioned suite for our interact
const void *GetSuite(int version);
class Base {
public:
virtual ~Base() {
}
/// grab a handle on the parameter for passing to the C API
OfxInteractHandle getHandle() {return (OfxInteractHandle)this;}
/// get the property handle for this instance/descriptor
virtual OfxPropertySetHandle getPropHandle() = 0;
};
/// state the interact can be in
enum State {
eUninitialised,
eDescribed,
eCreated,
eFailed
};
/// Descriptor for an interact. Interacts all share a single description
class Descriptor : public Base {
protected:
Property::Set _properties; ///< its props
State _state; ///< how is it feeling today
OfxPluginEntryPoint *_entryPoint; ///< the entry point for this overlay
public:
/// CTOR
Descriptor();
/// dtor
virtual ~Descriptor();
/// set the main entry points
void setEntryPoint(OfxPluginEntryPoint *entryPoint) {_entryPoint = entryPoint;}
/// call describe on this descriptor, returns true if all went well
bool describe(int bitDepthPerComponent, bool hasAlpha);
/// grab a handle on the properties of this parameter for the C api
OfxPropertySetHandle getPropHandle() {return _properties.getHandle();}
/// get prop set
const Property::Set &getProperties() const {return _properties;}
/// get a non const prop set
Property::Set &getProperties() {return _properties;}
/// call the entry point with action and the given args
OfxStatus callEntry(const char *action,
void *handle,
OfxPropertySetHandle inArgs,
OfxPropertySetHandle outArgs);
/// what is it's state?
State getState() const {return _state;}
};
/// a generic interact, it doesn't belong to anything in particular
/// we need to generify this slighty more and remove the renderscale args
/// into a derived class, as they only belong to image effect plugins
class Instance : public Base, protected Property::GetHook {
protected:
Descriptor &_descriptor; ///< who we are
Property::Set _properties; ///< its props
State _state; ///< how is it feeling today
void *_effectInstance; ///< this is ugly, we need a base class to all plugin instances at some point.
Property::Set _argProperties;
/// initialise the argument properties
void initArgProp(OfxTime time,
const OfxPointD &renderScale);
/// set pen props in the args
void setPenArgProps(const OfxPointD &penPos,
const OfxPointI &penPosViewport,
double pressure);
/// set key args in the props
void setKeyArgProps(int key,
char* keyString);
public:
Instance(Descriptor &desc, void *effectInstance);
virtual ~Instance();
/// what is it's state?
State getState() const {return _state;}
/// grab a handle on the properties of this parameter for the C api
OfxPropertySetHandle getPropHandle() {return _properties.getHandle();}
/// get prop set
const Property::Set &getProperties() const {return _properties;}
/// call the entry point in the descriptor with action and the given args
virtual OfxStatus callEntry(const char *action,
Property::Set *inArgs);
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
/// hooks to kOfxInteractPropViewportSize in the property set
/// this is actually redundant and is to be deprecated
virtual void getViewportSize(double &width, double &height) const = 0;
#endif
// hooks to live kOfxInteractPropPixelScale in the property set
virtual void getPixelScale(double& xScale, double& yScale) const = 0;
// hooks to kOfxInteractPropBackgroundColour in the property set
virtual void getBackgroundColour(double &r, double &g, double &b) const = 0;
// hooks to kOfxInteractPropSuggestedColour and kOfxPropOverlayColour in the property set
// return false if there is no color suggestion by the host.
virtual bool getSuggestedColour(double &r, double &g, double &b) const = 0;
/// implement
virtual OfxStatus swapBuffers() = 0;
/// implement this
virtual OfxStatus redraw() = 0;
/// returns the params the interact uses
virtual void getSlaveToParam(std::vector<std::string>& params) const;
// do nothing
virtual int getDimension(const std::string &name) const;
// don't know what to do
virtual void reset(const std::string &name);
/// the gethook virutals for pixel scale, background colour
virtual double getDoubleProperty(const std::string &name, int index) const;
/// for pixel scale and background colour
virtual void getDoublePropertyN(const std::string &name, double *first, int n) const;
/// call create instance
virtual OfxStatus createInstanceAction();
// interact action - kOfxInteractActionDraw
//
// Params -
//
// time - the effect time at which changed occured
// renderScale - the render scale
virtual OfxStatus drawAction(OfxTime time, const OfxPointD &renderScale);
// interact action - kOfxInteractActionPenMotion
//
// Params -
//
// time - the effect time at which changed occured
// renderScale - the render scale
// penX - the X position
// penY - the Y position
// pressure - the pen pressue 0 to 1
virtual OfxStatus penMotionAction(OfxTime time,
const OfxPointD &renderScale,
const OfxPointD &penPos,
const OfxPointI &penPosViewport,
double pressure);
// interact action - kOfxInteractActionPenUp
//
// Params -
//
// time - the effect time at which changed occured
// renderScale - the render scale
// penX - the X position
// penY - the Y position
// pressure - the pen pressue 0 to 1
virtual OfxStatus penUpAction(OfxTime time,
const OfxPointD &renderScale,
const OfxPointD &penPos,
const OfxPointI &penPosViewport,
double pressure);
// interact action - kOfxInteractActionPenDown
//
// Params -
//
// time - the effect time at which changed occured
// renderScale - the render scale
// penX - the X position
// penY - the Y position
// pressure - the pen pressue 0 to 1
virtual OfxStatus penDownAction(OfxTime time,
const OfxPointD &renderScale,
const OfxPointD &penPos,
const OfxPointI &penPosViewport,
double pressure);
// interact action - kOfxInteractActionkeyDown
//
// Params -
//
// time - the effect time at which changed occured
// renderScale - the render scale
// key - the pressed key
// keyString - the pressed key string
virtual OfxStatus keyDownAction(OfxTime time,
const OfxPointD &renderScale,
int key,
char* keyString);
// interact action - kOfxInteractActionkeyUp
//
// Params -
//
// time - the effect time at which changed occured
// renderScale - the render scale
// key - the pressed key
// keyString - the pressed key string
virtual OfxStatus keyUpAction(OfxTime time,
const OfxPointD &renderScale,
int key,
char* keyString);
// interact action - kOfxInteractActionkeyRepeat
//
// Params -
//
// time - the effect time at which changed occured
// renderScale - the render scale
// key - the pressed key
// keyString - the pressed key string
virtual OfxStatus keyRepeatAction(OfxTime time,
const OfxPointD &renderScale,
int key,
char* keyString);
// interact action - kOfxInteractActionLoseFocus
//
// Params -
//
// time - the effect time at which changed occured
// renderScale - the render scale
virtual OfxStatus gainFocusAction(OfxTime time,
const OfxPointD &renderScale);
// interact action - kOfxInteractActionLoseFocus
//
// Params -
//
// time - the effect time at which changed occured
// renderScale - the render scale
virtual OfxStatus loseFocusAction(OfxTime time,
const OfxPointD &renderScale);
};
} // Interact
} // Host
} // OFX
#endif // OFX_INTERACT_H
+39
View File
@@ -0,0 +1,39 @@
#ifndef OFX_MEMORY_H
#define OFX_MEMORY_H
#include "ofxImageEffect.h"
namespace OFX {
namespace Host {
namespace Memory {
class Instance {
public:
Instance();
virtual ~Instance();
virtual bool alloc(size_t nBytes);
virtual OfxImageMemoryHandle getHandle();
virtual void freeMem();
virtual void* getPtr();
virtual void lock();
virtual void unlock();
virtual bool verifyMagic() { return true; }
protected:
char* _ptr;
int _locked;
};
} // Memory
} // Host
} // OFX
#endif // OFX_MEMORY_H
+678
View File
@@ -0,0 +1,678 @@
#ifndef OFXH_PARAM_H
#define OFXH_PARAM_H
#include <string>
#include <map>
#include <list>
#include <cstdarg>
//ofx
#include "ofxParam.h"
//ofxh
#include "ofxhPropertySuite.h"
namespace OFX {
namespace Host {
namespace Param {
/// fetch the param suite
const void *GetSuite(int version);
bool isColourParam(const std::string &paramType);
bool isIntParam(const std::string &paramType);
/// is this a standard type
bool isStandardType(const std::string &type);
/// base class for all params
class Base {
private:
Base();
protected:
std::string _paramName;
std::string _paramType;
Property::Set _properties;
public:
Base(const std::string &name, const std::string &type);
Base(const std::string &name, const std::string &type, const Property::Set &properties);
virtual ~Base();
/// grab a handle on the parameter for passing to the C API
OfxParamHandle getHandle() const;
virtual bool verifyMagic() { return true; }
/// grab a handle on the properties of this parameter for the C api
OfxPropertySetHandle getPropHandle() const;
const Property::Set &getProperties() const;
Property::Set &getProperties();
const std::string &getType() const;
const std::string &getName() const;
const std::string &getParentName() const;
const std::string &getLabel() const;
const std::string &getShortLabel() const;
const std::string &getLongLabel() const;
const std::string &getScriptName() const;
const std::string &getDoubleType() const;
const std::string &getDefaultCoordinateSystem() const;
const std::string &getCacheInvalidation() const;
const std::string &getHint() const;
bool getEnabled() const;
bool getCanUndo() const;
bool getSecret() const;
bool getIsPersistant() const;
bool getEvaluateOnChange() const;
bool getCanAnimate() const;
};
/// the Descriptor of a plugin parameter
class Descriptor : public Base {
Descriptor();
public:
/// make a parameter, with the given type and name
Descriptor(const std::string &type, const std::string &name);
/// add standard param props, will call the below
void addStandardParamProps(const std::string &type);
/// add standard properties to a params that can take an interact
void addInteractParamProps(const std::string &type);
/// add standard properties to a value holding param
void addValueParamProps(const std::string &type, Property::TypeEnum valueType, int dim);
/// add standard properties to a value holding param
void addNumericParamProps(const std::string &type, Property::TypeEnum valueType, int dim);
};
/// base class to the param set instance and param set descriptor
class BaseSet {
public:
virtual ~BaseSet();
/// obtain a handle on this set for passing to the C api
OfxParamSetHandle getParamSetHandle() const;
/// get the property handle that lives with the set
/// The plugin descriptor/instance that derives from
/// this will provide this.
virtual Property::Set &getParamSetProps() = 0;
};
/// a set of parameters
class SetDescriptor : public BaseSet {
std::map<std::string, Descriptor*> _paramMap;
std::list<Descriptor *> _paramList;
/// CC doesn't exist
SetDescriptor(const SetDescriptor &);
public:
/// default ctor
SetDescriptor();
/// dtor
virtual ~SetDescriptor();
/// get the map of params
const std::map<std::string, Descriptor*> &getParams() const;
/// get the list of params
const std::list<Descriptor *> &getParamList() const;
/// define a param
virtual Descriptor *paramDefine(const char *paramType,
const char *name);
/// add a param in
virtual void addParam(const std::string &name, Descriptor *p);
};
// forward declare
class SetInstance;
/// the description of a plugin parameter
class Instance : public Base, protected Property::NotifyHook {
Instance();
protected:
SetInstance* _paramSetInstance;
Instance* _parentInstance;
public:
virtual ~Instance();
/// make a parameter, with the given type and name
explicit Instance(Descriptor& descriptor, Param::SetInstance* instance = 0);
// OfxStatus instanceChangedAction(const std::string &why,
// OfxTime time,
// double renderScaleX,
// double renderScaleY);
// get the param instance
OFX::Host::Param::SetInstance* getParamSetInstance() { return _paramSetInstance; }
// set/get parent instance
void setParentInstance(Instance* instance);
Instance* getParentInstance();
// copy one parameter to another, with a range (NULL means to copy all animation)
virtual OfxStatus copyFrom(const Instance &instance, OfxTime offset, const OfxRangeD* range);
// callback which should set enabled state as appropriate
virtual void setEnabled();
// callback which should set secret state as appropriate
virtual void setSecret();
/// callback which should update label
virtual void setLabel();
/// callback which should set range
virtual void setRange();
/// callback which should set display range
virtual void setDisplayRange();
/// callback which should set evaluate on change
virtual void setEvaluateOnChange();
// va list calls below turn the var args (oh what a mistake)
// suite functions into virtual function calls on instances
// they are not to be overridden by host implementors by
// by the various typeed param instances so that they can
// deconstruct the var args lists
/// get a value, implemented by instances to deconstruct var args
virtual OfxStatus getV(va_list arg);
/// get a value, implemented by instances to deconstruct var args
virtual OfxStatus getV(OfxTime time, va_list arg);
/// set a value, implemented by instances to deconstruct var args
virtual OfxStatus setV(va_list arg);
/// key a value, implemented by instances to deconstruct var args
virtual OfxStatus setV(OfxTime time, va_list arg);
/// derive a value, implemented by instances to deconstruct var args
virtual OfxStatus deriveV(OfxTime time, va_list arg);
/// integrate a value, implemented by instances to deconstruct var args
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
/// overridden from Property::NotifyHook
virtual void notify(const std::string &name, bool single, int num);
};
class KeyframeParam {
public:
virtual OfxStatus getNumKeys(unsigned int &nKeys) const ;
virtual OfxStatus getKeyTime(int nth, OfxTime& time) const ;
virtual OfxStatus getKeyIndex(OfxTime time, int direction, int & index) const ;
virtual OfxStatus deleteKey(OfxTime time) ;
virtual OfxStatus deleteAllKeys() ;
virtual ~KeyframeParam() {
}
};
class GroupInstance : public Instance {
protected:
std::vector<Param::Instance*> _children;
public:
GroupInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
void setChildren(std::vector<Param::Instance*> children);
const std::vector<Param::Instance*> &getChildren() const;
};
class PageInstance : public Instance {
public:
PageInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
const std::map<int,Param::Instance*> &getChildren() const;
protected :
mutable std::map<int,Param::Instance*> _children; // if set in a notify hook, this need not be mutable
};
class IntegerInstance : public Instance, public KeyframeParam {
public:
IntegerInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
// Deriving implementatation needs to overide these
virtual OfxStatus get(int&) = 0;
virtual OfxStatus get(OfxTime time, int&) = 0;
virtual OfxStatus set(int) = 0;
virtual OfxStatus set(OfxTime time, int) = 0;
// probably derived class does not need to implement, default is an approximation
virtual OfxStatus derive(OfxTime time, int&) ;
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, int&) ;
/// implementation of var args function
virtual OfxStatus getV(va_list arg);
/// implementation of var args function
virtual OfxStatus getV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus setV(va_list arg);
/// implementation of var args function
virtual OfxStatus setV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus deriveV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
};
class ChoiceInstance : public Instance, public KeyframeParam {
public:
ChoiceInstance(Descriptor& descriptor, Param::SetInstance* instance = 0);
// callback which should set option as appropriate
virtual void setOption(int num);
// Deriving implementatation needs to overide these
virtual OfxStatus get(int&) = 0;
virtual OfxStatus get(OfxTime time, int&) = 0;
virtual OfxStatus set(int) = 0;
virtual OfxStatus set(OfxTime time, int) = 0;
/// implementation of var args function
virtual OfxStatus getV(va_list arg);
/// implementation of var args function
virtual OfxStatus getV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus setV(va_list arg);
/// implementation of var args function
virtual OfxStatus setV(OfxTime time, va_list arg);
/// overridden from Instance
virtual void notify(const std::string &name, bool single, int num);
};
class DoubleInstance : public Instance, public KeyframeParam {
public:
DoubleInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
// Deriving implementatation needs to overide these
virtual OfxStatus get(double&) = 0;
virtual OfxStatus get(OfxTime time, double&) = 0;
virtual OfxStatus set(double) = 0;
virtual OfxStatus set(OfxTime time, double) = 0;
virtual OfxStatus derive(OfxTime time, double&) = 0;
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, double&) = 0;
/// implementation of var args function
virtual OfxStatus getV(va_list arg);
/// implementation of var args function
virtual OfxStatus getV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus setV(va_list arg);
/// implementation of var args function
virtual OfxStatus setV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus deriveV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
};
class BooleanInstance : public Instance, public KeyframeParam {
public:
BooleanInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
// Deriving implementatation needs to overide these
virtual OfxStatus get(bool&) = 0;
virtual OfxStatus get(OfxTime time, bool&) = 0;
virtual OfxStatus set(bool) = 0;
virtual OfxStatus set(OfxTime time, bool) = 0;
/// implementation of var args function
virtual OfxStatus getV(va_list arg);
/// implementation of var args function
virtual OfxStatus getV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus setV(va_list arg);
/// implementation of var args function
virtual OfxStatus setV(OfxTime time, va_list arg);
};
class RGBAInstance : public Instance, public KeyframeParam {
public:
RGBAInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
// Deriving implementatation needs to overide these
virtual OfxStatus get(double&,double&,double&,double&) = 0;
virtual OfxStatus get(OfxTime time, double&,double&,double&,double&) = 0;
virtual OfxStatus set(double,double,double,double) = 0;
virtual OfxStatus set(OfxTime time, double,double,double,double) = 0;
// derived class does not need to implement, default is an approximation
virtual OfxStatus derive(OfxTime time, double&,double&,double&,double&) ;
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, double&,double&,double&,double&) ;
/// implementation of var args function
virtual OfxStatus getV(va_list arg);
/// implementation of var args function
virtual OfxStatus getV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus setV(va_list arg);
/// implementation of var args function
virtual OfxStatus setV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus deriveV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
};
class RGBInstance : public Instance, public KeyframeParam {
public:
RGBInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
// Deriving implementatation needs to overide these
virtual OfxStatus get(double&,double&,double&) = 0;
virtual OfxStatus get(OfxTime time, double&,double&,double&) = 0;
virtual OfxStatus set(double,double,double) = 0;
virtual OfxStatus set(OfxTime time, double,double,double) = 0;
// derived class does not need to implement, default is an approximation
virtual OfxStatus derive(OfxTime time, double&,double&,double&) ;
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, double&,double&,double&) ;
/// implementation of var args function
virtual OfxStatus getV(va_list arg);
/// implementation of var args function
virtual OfxStatus getV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus setV(va_list arg);
/// implementation of var args function
virtual OfxStatus setV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus deriveV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
};
class Double2DInstance : public Instance, public KeyframeParam {
public:
Double2DInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
// Deriving implementatation needs to overide these
virtual OfxStatus get(double&,double&) = 0;
virtual OfxStatus get(OfxTime time, double&,double&) = 0;
virtual OfxStatus set(double,double) = 0;
virtual OfxStatus set(OfxTime time, double,double) = 0;
// derived class does not need to implement, default is an approximation
virtual OfxStatus derive(OfxTime time, double&,double&) ;
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, double&,double&) ;
/// implementation of var args function
virtual OfxStatus getV(va_list arg);
/// implementation of var args function
virtual OfxStatus getV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus setV(va_list arg);
/// implementation of var args function
virtual OfxStatus setV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus deriveV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
};
class Integer2DInstance : public Instance, public KeyframeParam {
public:
Integer2DInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
// Deriving implementatation needs to overide these
virtual OfxStatus get(int&,int&) = 0;
virtual OfxStatus get(OfxTime time, int&,int&) = 0;
virtual OfxStatus set(int,int) = 0;
virtual OfxStatus set(OfxTime time, int,int) = 0;
// derived class does not need to implement, default is an approximation
virtual OfxStatus derive(OfxTime time, int&,int&) ;
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, int&,int&) ;
/// implementation of var args function
virtual OfxStatus getV(va_list arg);
/// implementation of var args function
virtual OfxStatus getV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus setV(va_list arg);
/// implementation of var args function
virtual OfxStatus setV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus deriveV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
};
class Double3DInstance : public Instance , public KeyframeParam{
public:
Double3DInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
// Deriving implementatation needs to overide these
virtual OfxStatus get(double&,double&,double&) = 0;
virtual OfxStatus get(OfxTime time, double&,double&,double&) = 0;
virtual OfxStatus set(double,double,double) = 0;
virtual OfxStatus set(OfxTime time, double,double,double) = 0;
// derived class does not need to implement, default is an approximation
virtual OfxStatus derive(OfxTime time, double&,double&,double&) ;
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, double&,double&,double&) ;
/// implementation of var args function
virtual OfxStatus getV(va_list arg);
/// implementation of var args function
virtual OfxStatus getV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus setV(va_list arg);
/// implementation of var args function
virtual OfxStatus setV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus deriveV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
};
class Integer3DInstance : public Instance, public KeyframeParam {
public:
Integer3DInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
virtual OfxStatus get(int&,int&,int&) = 0;
virtual OfxStatus get(OfxTime time, int&,int&,int&) = 0;
virtual OfxStatus set(int,int,int) = 0;
virtual OfxStatus set(OfxTime time, int,int,int) = 0;
// derived class does not need to implement, default is an approximation
virtual OfxStatus derive(OfxTime time, int&,int&,int&) ;
virtual OfxStatus integrate(OfxTime time1, OfxTime time2, int&,int&,int&) ;
/// implementation of var args function
virtual OfxStatus getV(va_list arg);
/// implementation of var args function
virtual OfxStatus getV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus setV(va_list arg);
/// implementation of var args function
virtual OfxStatus setV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus deriveV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus integrateV(OfxTime time1, OfxTime time2, va_list arg);
};
class StringInstance : public Instance, public KeyframeParam {
std::string _returnValue; ///< location to hold temporary return value. Should delegate this to implementation!!!
public:
StringInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
virtual OfxStatus get(std::string &) = 0;
virtual OfxStatus get(OfxTime time, std::string &) = 0;
virtual OfxStatus set(const char*) = 0;
virtual OfxStatus set(OfxTime time, const char*) = 0;
/// implementation of var args function
/// Be careful: the char* is only valid until next API call
/// see http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#ArchitectureStrings
virtual OfxStatus getV(va_list arg);
/// implementation of var args function
/// Be careful: the char* is only valid until next API call
/// see http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#ArchitectureStrings
virtual OfxStatus getV(OfxTime time, va_list arg);
/// implementation of var args function
virtual OfxStatus setV(va_list arg);
/// implementation of var args function
virtual OfxStatus setV(OfxTime time, va_list arg);
};
class CustomInstance : public StringInstance {
public:
CustomInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : StringInstance(descriptor,instance) {}
};
class PushbuttonInstance : public Instance, public KeyframeParam {
public:
PushbuttonInstance(Descriptor& descriptor, Param::SetInstance* instance = 0) : Instance(descriptor,instance) {}
};
/// A set of parameters
///
/// As we are the owning object we delete the params inside ourselves. It was tempting
/// to make params autoref objects and have shared ownership with the client code
/// but that adds complexity for no strong gain.
class SetInstance : public BaseSet {
protected:
std::map<std::string, Instance*> _params; ///< params by name
std::list<Instance *> _paramList; ///< params list
public :
/// ctor
///
/// The propery set being passed in belongs to the owning
/// plugin instance.
explicit SetInstance();
/// dtor.
virtual ~SetInstance();
/// get the params
const std::map<std::string, Instance*> &getParams() const;
/// get the params
const std::list<Instance*> &getParamList() const;
// get the param
Instance* getParam(const std::string &name) const {
std::map<std::string,Instance*>::const_iterator it = _params.find(name);
if(it!=_params.end())
return it->second;
else
return 0;
}
/// The inheriting plugin instance needs to set this up to deal with
/// plug-ins changing their own values.
virtual void paramChangedByPlugin(Param::Instance *param) = 0;
/// add a param
virtual OfxStatus addParam(const std::string& name, Instance* instance);
/// make a parameter instance
///
/// Client host code needs to implement this
virtual Instance* newParam(const std::string& name, Descriptor& Descriptor) = 0;
/// Triggered when the plug-in calls OfxParameterSuiteV1::paramEditBegin
///
/// Client host code needs to implement this
virtual OfxStatus editBegin(const std::string& name) = 0;
/// Triggered when the plug-in calls OfxParameterSuiteV1::paramEditEnd
///
/// Client host code needs to implement this
virtual OfxStatus editEnd() = 0;
};
}
}
}
#endif // OFXH_PARAM_H
@@ -0,0 +1,87 @@
#ifndef OFX_PLUGIN_API_CACHE
#define OFX_PLUGIN_API_CACHE
// Copyright OpenFX and contributors to the OpenFX project.
// SPDX-License-Identifier: BSD-3-Clause
#include <string>
#include <iostream>
#include <ostream>
#include <map>
#include "ofxhPropertySuite.h"
namespace OFX
{
namespace Host {
class Plugin;
class PluginBinary;
class PluginCache;
namespace ImageEffect {
class ImageEffectDescriptor;
}
}
}
namespace OFX
{
namespace Host
{
namespace APICache {
/// this acts as an interface for the Plugin Cache, handling api-specific cacheing
class PluginAPICacheI
{
protected:
std::string _apiName;
int _apiVersionMin, _apiVersionMax;
public:
PluginAPICacheI(const std::string &apiName, int verMin, int verMax)
: _apiName(apiName)
, _apiVersionMin(verMin)
, _apiVersionMax(verMax)
{
}
virtual ~PluginAPICacheI() {}
virtual void loadFromPlugin(Plugin *) const = 0;
/// factory method, to create a new plugin (from binary)
virtual Plugin *newPlugin(PluginBinary *, int pi, OfxPlugin *plug) = 0;
/// factory method, to create a new plugin (from the
virtual Plugin *newPlugin(PluginBinary *pb, int pi, const std::string &api, int apiVersion, const std::string &pluginId,
const std::string &rawId, int pluginMajorVersion, int pluginMinorVersion) = 0;
virtual void beginXmlParsing(Plugin *) = 0;
virtual void xmlElementBegin(const std::string &, std::map<std::string, std::string>) = 0;
virtual void xmlCharacterHandler(const std::string &) = 0;
virtual void xmlElementEnd(const std::string &) = 0;
virtual void endXmlParsing() = 0;
virtual void saveXML(Plugin *, std::ostream &) const = 0;
virtual void confirmPlugin(Plugin *) = 0;
virtual bool pluginSupported(Plugin *, std::string &reason) const = 0;
void registerInCache(OFX::Host::PluginCache &pluginCache);
};
/// helper function to build a property set from XML. Really should be a member of the property set!!!
void propertySetXMLRead(const std::string &el, std::map<std::string, std::string> map, Property::Set &set, Property::Property*&);
/// helper function to write a property set to XML. Really should be a member of the property set!!!
void propertySetXMLWrite(std::ostream &o, const Property::Set &set, int indent=0);
/// helper function to write a single property from a set to XML. Really should be a member of the property set!!!
void propertyXMLWrite(std::ostream &o, const Property::Set &set, const std::string &name, int indent=0);
}
}
}
#endif
+432
View File
@@ -0,0 +1,432 @@
#ifndef OFX_PLUGIN_CACHE_H
#define OFX_PLUGIN_CACHE_H
// Copyright OpenFX and contributors to the OpenFX project.
// SPDX-License-Identifier: BSD-3-Clause
#include <string>
#include <vector>
#include <list>
#include <set>
#include <iostream>
#include <stdio.h>
#include "expat.h"
#include "ofxCore.h"
#include "ofxhPropertySuite.h"
#include "ofxhPluginAPICache.h"
#include "ofxhBinary.h"
namespace OFX {
namespace Host {
class Host;
// forward delcarations
class PluginDesc;
class Plugin;
class PluginBinary;
class PluginCache;
/// C++ version of the information kept inside an OfxPlugin struct
class PluginDesc {
protected :
std::string _pluginApi; ///< the API I implement
int _apiVersion; ///< the version of the API
std::string _identifier; ///< the identifier of the plugin
std::string _rawIdentifier; ///< the original identifier of the plugin
int _versionMajor; ///< the plugin major version
int _versionMinor; ///< the plugin minor version
public:
const std::string &getPluginApi() const {
return _pluginApi;
}
int getApiVersion() const {
return _apiVersion;
}
const std::string &getIdentifier() const {
return _identifier;
}
const std::string &getRawIdentifier() const {
return _rawIdentifier;
}
int getVersionMajor() const {
return _versionMajor;
}
int getVersionMinor() const {
return _versionMinor;
}
PluginDesc() : _apiVersion(-1) {
}
virtual ~PluginDesc() {}
PluginDesc(const std::string &api,
int apiVersion,
const std::string &identifier,
const std::string &rawIdentifier,
int versionMajor,
int versionMinor)
: _pluginApi(api)
, _apiVersion(apiVersion)
, _identifier(identifier)
, _rawIdentifier(rawIdentifier)
, _versionMajor(versionMajor)
, _versionMinor(versionMinor)
{
}
/// constructor for the case where we have already loaded the plugin binary and
/// are populating this object from it
PluginDesc(OfxPlugin *ofxPlugin) {
_pluginApi = ofxPlugin->pluginApi;
_apiVersion = ofxPlugin->apiVersion;
_rawIdentifier = ofxPlugin->pluginIdentifier;
_identifier = ofxPlugin->pluginIdentifier;
// Who says the pluginIdentifier is case-insensitive? OFX 1.3 spec doesn't mention this.
// http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#id472588
//for (size_t i=0;i<_identifier.size();i++) {
// _identifier[i] = tolower(_identifier[i]);
//}
_versionMajor = ofxPlugin->pluginVersionMajor;
_versionMinor = ofxPlugin->pluginVersionMinor;
}
};
/// class that we use to manipulate a plugin
class Plugin : public PluginDesc {
/// owned by the PluginBinary it lives inside
/// Plugins can only be pass about either by pointer or reference
private :
Plugin(const Plugin&) : PluginDesc() {} ///< hidden
Plugin &operator= (const Plugin&) {return *this;} ///< hidden
protected :
PluginBinary *_binary; ///< the file I live inside
int _index; ///< where I live inside that file
public :
Plugin();
PluginBinary *getBinary()
{
return _binary;
}
const PluginBinary *getBinary() const
{
return _binary;
}
int getIndex() const
{
return _index;
}
/// construct this based on the struct returned by the getNthPlugin() in the binary
Plugin(PluginBinary *bin, int idx, OfxPlugin *o) : PluginDesc(o), _binary(bin), _index(idx)
{
}
/// construct me from the cache
Plugin(PluginBinary *bin, int idx, const std::string &api,
int apiVersion, const std::string &identifier,
const std::string &rawIdentifier,
int majorVersion, int minorVersion)
: PluginDesc(api, apiVersion, identifier, rawIdentifier, majorVersion, minorVersion)
, _binary(bin)
, _index(idx)
{
}
virtual ~Plugin() {
}
virtual APICache::PluginAPICacheI &getApiHandler() = 0;
bool trumps(Plugin *other) {
int myMajor = getVersionMajor();
int theirMajor = other->getVersionMajor();
int myMinor = getVersionMinor();
int theirMinor = other->getVersionMinor();
if (myMajor > theirMajor) {
return true;
}
if (myMajor == theirMajor && myMinor > theirMinor) {
return true;
}
return false;
}
};
class PluginHandle;
/// class that represents a binary file which holds plugins
class PluginBinary {
/// has a set of plugins inside it and which it owns
/// These are owned by a PluginCache
friend class PluginHandle;
protected :
Binary _binary; ///< our binary object, abstracted layer ontop of OS calls, defined in ofxhBinary.h
std::string _filePath; ///< full path to the file
std::string _bundlePath; ///< path to the .bundle directory
std::vector<Plugin *> _plugins; ///< my plugins
time_t _fileModificationTime; ///< used as a time stamp to check modification times, used for caching
off_t _fileSize; ///< file size last time we check, used for caching
bool _binaryChanged; ///< whether the timestamp/filesize in this cache is different from that in the actual binary
public :
/// create one from the cache. this will invoke the Binary() constructor which
/// will stat() the file.
explicit PluginBinary(const std::string &file, const std::string &bundlePath, time_t mtime, off_t size)
: _binary(file)
, _filePath(file)
, _bundlePath(bundlePath)
, _fileModificationTime(mtime)
, _fileSize(size)
, _binaryChanged(false)
{
if (isInvalid()) {
return;
}
if (_fileModificationTime != _binary.getTime() || _fileSize != _binary.getSize()) {
_binaryChanged = true;
}
}
/// constructor which will open a library file, call things inside it, and then
/// create Plugin objects as appropriate for the plugins exported therefrom
explicit PluginBinary(const std::string &file, const std::string &bundlePath, PluginCache *cache)
: _binary(file)
, _filePath(file)
, _bundlePath(bundlePath)
, _binaryChanged(false)
{
loadPluginInfo(cache);
}
/// dtor
virtual ~PluginBinary();
time_t getFileModificationTime() const {
return _fileModificationTime;
}
off_t getFileSize() {
return _fileSize;
}
const std::string &getFilePath() const {
return _filePath;
}
const std::string &getBundlePath() const {
return _bundlePath;
}
bool hasBinaryChanged() const {
return _binaryChanged;
}
bool isLoaded() const {
return _binary.isLoaded();
}
bool isInvalid() const {
return _binary.isInvalid();
}
void addPlugin(Plugin *pe) {
_plugins.push_back(pe);
}
void loadPluginInfo(PluginCache *);
/// how many plugins?
int getNPlugins() const {return (int)_plugins.size(); }
/// get a plugin
Plugin &getPlugin(int idx) {return *_plugins[idx];}
/// get a plugin
const Plugin &getPlugin(int idx) const {return *_plugins[idx];}
};
/// wrapper class for Plugin/PluginBinary. use in a RAIA fashion to make sure the binary gets unloaded when needed and not before.
class PluginHandle {
PluginBinary *_b;
OfxPlugin *_op;
public:
PluginHandle(Plugin *p, OFX::Host::Host *_host);
virtual ~PluginHandle();
OfxPlugin *getOfxPlugin() {
return _op;
}
OfxPlugin *operator->() {
return _op;
}
};
/// for later
struct PluginCacheSupportedApi {
std::string api;
int minVersion;
int maxVersion;
APICache::PluginAPICacheI *handler;
PluginCacheSupportedApi(const std::string &_api, int _minVersion, int _maxVersion, APICache::PluginAPICacheI *_handler) :
api(_api), minVersion(_minVersion), maxVersion(_maxVersion), handler(_handler)
{
}
bool matches(const std::string &_api, int _version) const
{
if (_api == api && _version >= minVersion && _version <= maxVersion) {
return true;
}
return false;
}
};
/// Where we keep our plugins.
class PluginCache {
protected :
OFX::Host::Property::PropSpec* _hostSpec;
std::list<std::string> _pluginPath; ///< list of directories to look in
std::set<std::string> _nonrecursePath; ///< list of directories to look in (non-recursively)
std::list<std::string> _pluginDirs; ///< list of directories we found
std::list<PluginBinary *> _binaries; ///< all the binaries we know about, we own these
std::list<Plugin *> _plugins; ///< all the plugins inside the binaries, we don't own these, populated from _binaries
std::set<std::string> _knownBinFiles;
PluginBinary *_xmlCurrentBinary;
Plugin *_xmlCurrentPlugin;
std::list<PluginCacheSupportedApi> _apiHandlers;
void scanDirectory(std::set<std::string> &foundBinFiles, const std::string &dir, bool recurse);
bool _ignoreCache;
std::string _cacheVersion;
bool _dirty;
bool _enablePluginSeek; ///< Turn off to make all seekPluginFile() calls return an empty string
static PluginCache* gPluginCachePtr; ///< singleton plugin cache
public:
/// ctor, which inits _pluginPath to default locations and not much else
PluginCache();
/// dtor
~PluginCache();
/// get our plugin cache
static PluginCache* getPluginCache();
/// clear our plugin cache
static void clearPluginCache();
/// get the list in which plugins are sought
const std::list<std::string> &getPluginPath() {
return _pluginPath;
}
/// was the cache outdated?
bool dirty() const {
return _dirty;
}
/// add a file to the plugin path
void addFileToPath(const std::string &f, bool recurse=true) {
_pluginPath.push_back(f);
if (!recurse) {
_nonrecursePath.insert(f);
}
}
/// prepend a file to the plugin path
void prependFileToPath(const std::string &f, bool recurse=true) {
_pluginPath.push_front(f);
if (!recurse) {
_nonrecursePath.insert(f);
}
}
/// specify which subdirectory of /usr/OFX or equivilant
/// (as well as 'Plugins') to look in for plugins.
void setPluginHostPath(const std::string &hostId);
/// set the version string to write to the cache,
/// and also that we expect on cachess read in
void setCacheVersion(const std::string &cacheVersion) {
_cacheVersion = cacheVersion;
}
// populate the cache. must call scanPluginFiles() after to check for changes.
void readCache(std::istream &is);
// seek a particular file on the OFX plugin path
std::string seekPluginFile(const std::string &baseName) const;
/// Sets behaviour of seekPluginFile().
/// Enable (the default): normal operation; disable: returns an empty string instead
void setPluginSeekEnabled(bool enabled) { _enablePluginSeek = enabled; }
/// scan for plugins
void scanPluginFiles();
// write the plugin cache output file to the given stream
void writePluginCache(std::ostream &os) const;
// callback function for the XML
void elementBeginCallback(void *userData, const XML_Char *name, const XML_Char **attrs);
void elementCharCallback(void *userData, const XML_Char *data, int len);
void elementEndCallback(void *userData, const XML_Char *name);
/// register an API cache handler
void registerAPICache(const std::string &api, int min, int max, APICache::PluginAPICacheI *apiCache) {
_apiHandlers.push_back(PluginCacheSupportedApi(api, min, max, apiCache));
}
/// find the API cache handler for the given api/apiverson
APICache::PluginAPICacheI* findApiHandler(const std::string &api, int apiver);
/// obtain a list of plugins to walk through
const std::list<Plugin *> &getPlugins() const {
return _plugins;
}
};
}
}
#endif
+34
View File
@@ -0,0 +1,34 @@
#ifndef _ofxhProgress_h_
#define _ofxhProgress_h_
#include "ofxProgress.h"
namespace OFX {
namespace Host {
namespace Progress {
/// Things that display progress derive from this ABC and implement the following
/// functions.
class ProgressI {
public :
virtual ~ProgressI() {}
/// Start doing progress.
virtual void progressStart(const std::string &message, const std::string &messageid) = 0;
/// finish yer progress
virtual void progressEnd() = 0;
/// set the progress to some level of completion, returns
/// false if you should abandon processing, true to continue
virtual bool progressUpdate(double t) = 0;
};
} // namespace progress
} // namespace Host
} // namespace OFX
#endif
@@ -0,0 +1,545 @@
#ifndef OFX_PROPERTY_SUITE_H
#define OFX_PROPERTY_SUITE_H
#include "ofxCore.h"
// Copyright OpenFX and contributors to the OpenFX project.
// SPDX-License-Identifier: BSD-3-Clause
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <sstream>
namespace OFX {
namespace Host {
namespace Property {
/// simple function to turn a thing into a std string
template<class T> inline std::string castToString(T i) {
std::ostringstream o;
o << i;
return o.str();
}
/// simple function to turn a string into an int
inline int stringToInt(const std::string &s) {
std::istringstream is(s);
int number;
is >> number;
return number;
}
/// simple function to turn a string into a double
inline double stringToDouble(const std::string &s) {
std::istringstream is(s);
double number;
is >> number;
return number;
}
// forward declarations
class Property;
class Set;
/// exception, representing an OfxStatus
class Exception {
OfxStatus _stat;
public:
/// ctor
Exception(OfxStatus stat) : _stat(stat)
{
}
/// get the status
OfxStatus getStatus() const
{
return _stat;
}
};
/// type of a property
enum TypeEnum {
eNone = -1,
eInt = 0,
eDouble = 1,
eString = 2,
ePointer = 3
};
/// type holder, for integers, used to template up int properties
struct IntValue {
typedef int APIType; ///< C type of the property that is passed across the raw API
typedef int APITypeConstless; ///< C type of the property that is passed across the raw API, without any const it
typedef int Type; ///< Type we actually hold and deal with the propery in everything by the raw API
typedef int ReturnType; ///< type to return from a function call
static const TypeEnum typeCode = eInt;
static int kEmpty;
};
/// type holder, for doubles, used to template up double properties
struct DoubleValue {
typedef double APIType;
typedef double APITypeConstless;
typedef double Type;
typedef double ReturnType; ///< type to return from a function call
static const TypeEnum typeCode = eDouble;
static double kEmpty;
};
/// type holder, for pointers, used to template up pointer properties
struct PointerValue {
typedef void *APIType;
typedef void *APITypeConstless;
typedef void *Type;
typedef void *ReturnType; ///< type to return from a function call
static const TypeEnum typeCode = ePointer;
static void *kEmpty;
};
/// type holder, for strings, used to template up string properties
struct StringValue {
typedef const char *APIType;
typedef char *APITypeConstless;
typedef std::string Type;
typedef const std::string &ReturnType; ///< type to return from a function call
static const TypeEnum typeCode = eString;
static std::string kEmpty;
};
/// array representing the names of the various types, in order of TypeEnum
extern const char *gTypeNames[];
/// Sits on a property and can override the local property value when a value is being fetched
/// only one of these can be in any property (as the thing has only a single value).
class GetHook {
public :
/// dtor
virtual ~GetHook()
{
}
/// We specialise this to do some magic so that it calls get string/int/double/pointer appropriately
/// this is what is called by the propertytemplate code to fetch values out of a hook.
template<class T> typename T::ReturnType getProperty(const std::string &name, int index=0) const;
/// We specialise this to do some magic so that it calls get int/double/pointer appropriately
/// this is what is called by the propertytemplate code to fetch values out of a hook.
template<class T> void getPropertyN(const std::string &name, typename T::APIType *values, int count) const;
/// override this to fetch a single value at the given index.
virtual const std::string& getStringProperty(const std::string &name, int index = 0) const;
/// override this to fetch a multiple values in a multi-dimension property
virtual void getStringPropertyN(const std::string &name, const char** values, int count) const;
/// override this to fetch a single value at the given index.
virtual int getIntProperty(const std::string &name, int index = 0) const;
/// override this to fetch a multiple values in a multi-dimension property
virtual void getIntPropertyN(const std::string &name, int *values, int count) const;
/// override this to fetch a single value at the given index.
virtual double getDoubleProperty(const std::string &name, int index = 0) const;
/// override this to fetch a multiple values in a multi-dimension property
virtual void getDoublePropertyN(const std::string &name, double *values, int count) const;
/// override this to fetch a single value at the given index.
virtual void *getPointerProperty(const std::string &name, int index = 0) const;
/// override this to fetch a multiple values in a multi-dimension property
virtual void getPointerPropertyN(const std::string &name, void **values, int count) const;
/// override this to fetch the dimension size.
virtual int getDimension(const std::string &name) const;
/// override this to handle a reset().
virtual void reset(const std::string &name);
};
/// Sits on a property and is called when the local property is being set.
/// It notify or notifyN is called whenever the plugin sets a property
/// Many of these can sit on a property, as various objects will need to know when a property
/// has been changed. On notification you should fetch properties with a 'raw' call, rather
/// than the standard calls, as you may be fetching through a getHook and you won't see
/// the local value that has been shoved into the property.
class NotifyHook {
public :
/// dtor
virtual ~NotifyHook() {}
/// override this to be notified when a property changes
/// \arg name is the name of the property just set
/// \arg singleValue is whether setProperty on a single index was call, otherwise N properties were set
/// \arg indexOrN is the index if single value is true, or the count if singleValue is false
virtual void notify(const std::string &name, bool singleValue, int indexOrN) = 0;
};
/// base class for all properties
class Property {
protected :
std::string _name; ///< name of this property
TypeEnum _type; ///< type of this property
int _dimension; ///< the fixed dimension of this property
bool _pluginReadOnly; ///< set is forbidden through suite: value may still change between get() calls
std::vector<NotifyHook *> _notifyHooks; ///< hooks to call whenever the property is set
GetHook *_getHook; ///< if we are not storing props locally, they are stored via fetching from here
friend class Set;
public :
/// ctor
Property(const std::string &name,
TypeEnum type,
int dimension = 1,
bool pluginReadOnly=false);
/// copy ctor
Property(const Property &other);
/// dtor
virtual ~Property()
{
}
/// is it read only?
bool getPluginReadOnly() const {return _pluginReadOnly; }
/// change the state of readonlyness
void setPluginReadOnly(bool v) {_pluginReadOnly = v;}
/// override this to return a clone of the property
virtual Property *deepCopy() = 0;
/// get the name of this property
const std::string &getName()
{
return _name;
}
/// get the type of this property
TypeEnum getType()
{
return _type;
}
/// add a notify hook
void addNotifyHook(NotifyHook *hook)
{
_notifyHooks.push_back(hook);
}
/// set the get hook
void setGetHook(GetHook *hook)
{
_getHook = hook;
}
/// call notify on the contained notify hooks
void notify(bool single, int indexOrN);
// get the current dimension of this property
virtual int getDimension() const = 0;
/// get the fixed dimension of this property
int getFixedDimension() const {
return _dimension;
}
/// are we a fixed dim property
bool isFixedSize() const
{
return _dimension != 0;
}
/// reset this property to the default
virtual void reset() = 0;
// get a string representing the value of this property at element nth
virtual std::string getStringValue(int nth) = 0;
};
/// this represents a generic property.
/// template parameter T is the type descriptor of the
/// type of property to model. the class holds an internal _value vector which can be used
/// to store the values. if set and get hooks are installed, these will be called instead
/// of using this variable.
/// Make sure that T::ReturnType is const if appropriate, as no extra qualifiers are applied here.
template<class T>
class PropertyTemplate : public Property
{
public :
typedef typename T::Type Type;
typedef typename T::ReturnType ReturnType;
typedef typename T::APIType APIType;
protected :
/// this is the present value of the property
std::vector<Type> _value;
/// this is the default value of the property
std::vector<Type> _defaultValue;
public :
/// constructor
PropertyTemplate(const std::string &name,
int dimension,
bool pluginReadOnly,
APIType defaultValue);
PropertyTemplate(const PropertyTemplate<T> &pt);
PropertyTemplate<T> *deepCopy() {
return new PropertyTemplate(*this);
}
virtual ~PropertyTemplate()
{
}
/// get the vector
const std::vector<Type> &getValues()
{
return _value;
}
// get multiple values
void getValueN(APIType *value, int count) const;
#ifdef WINDOWS
#pragma warning( disable : 4181 )
#endif
/// get one value
const ReturnType getValue(int index=0) const;
/// get one value, without going through the getHook
const ReturnType getValueRaw(int index=0) const;
#ifdef WINDOWS
#pragma warning( default : 4181 )
#endif
// get multiple values, without going through the getHook
void getValueNRaw(APIType *value, int count) const;
/// set one value
void setValue(const Type &value, int index=0);
/// set multiple values
void setValueN(const APIType *value, int count);
/// reset
void reset();
/// get the size of the vector
int getDimension() const;
/// return the value as a string
inline std::string getStringValue(int idx) {
return castToString(_value[idx]);
}
};
typedef PropertyTemplate<IntValue> Int; /// Our int property
typedef PropertyTemplate<DoubleValue> Double; /// Our double property
typedef PropertyTemplate<StringValue> String; /// Our string property
typedef PropertyTemplate<PointerValue> Pointer; /// Our pointer property
/// A class that is used to initialise a property set. Feed in an array of these to
/// a property and it will construct a bunch of properties. Terminate such an array
/// with an empty (all zero) set.
struct PropSpec {
const char *name; ///< name of the property
TypeEnum type; ///< type
int dimension; ///< fixed dimension of the property, set to zero if variable dimension
bool readonly; ///< is the property plug-in read only
const char *defaultValue; ///< Default value as a string. Pointers are ignored and always null.
};
static const PropSpec propSpecEnd = {0, eNone, 0, false, 0};
/// A std::map of properties by name
typedef std::map<std::string, Property *> PropertyMap;
//................................................................................
/// Class that holds a set of properties and manipulates them
/// The 'fetch' methods return a property object.
/// The 'get' methods return a property value
class Set {
private :
static const int kMagic = 0x12082007; ///< magic number for property sets, and Connie's birthday :-)
const int _magic; ///< to check for handles being nice
protected :
PropertyMap _props; ///< Our properties.
/// chained property set, which is read only
/// these are searched on a get if not found
/// on a local search
Set *_chainedSet;
/// hide assignment
void operator=(const Set &);
/// set a particular property
template<class T> void setProperty(const std::string &property, int index, const typename T::Type &value);
/// set the first N of a particular property
template<class T> void setPropertyN(const std::string &property, int count, const typename T::APIType *value);
/// get a particular property
template<class T> typename T::ReturnType getProperty(const std::string &property, int index) const;
/// get the first N of a particular property
template<class T> void getPropertyN(const std::string &property, int index, typename T::APIType *v) const;
/// get a particular property without going through any getHook
template<class T> typename T::ReturnType getPropertyRaw(const std::string &property, int index) const;
/// get a particular property without going through any getHook
template<class T> void getPropertyRawN(const std::string &property, int count, typename T::APIType *v) const;
public :
/// take an array of of PropSpecs (which must be terminated with an entry in which
/// ->name is null), and turn these into a Set
explicit Set(const PropSpec *);
/// deep copies the property set
explicit Set(const Set &);
/// empty ctor
explicit Set();
/// destructor
virtual ~Set();
/// adds a bunch of properties from PropSpec
void addProperties(const PropSpec *);
/// add one new property
void createProperty(const PropSpec &s);
/// add one new property
void addProperty(Property *prop);
/// set the chained property set
void setChainedSet(Set *s) {_chainedSet = s;}
/// grab the internal properties map
const PropertyMap &getProperties() const
{
return _props;
}
/// set the get hook for a particular property. users may need to call particular
/// specialised versions of this.
void setGetHook(const std::string &s, GetHook *ghook) const;
/// add a set hook for a particular property. users may need to call particular
/// specialised versions of this.
void addNotifyHook(const std::string &name, NotifyHook *hook) const;
/// Fetchs a pointer to a property of the given name, following the property chain if the
/// 'followChain' arg is not false.
Property *fetchProperty(const std::string &name, bool followChain = false) const;
/// get property with the particular name and type. if the property is
/// missing or is of the wrong type, return an error status. if this is a sloppy
/// property set and the property is missing, a new one will be created of the right
/// type
template<class T> bool fetchTypedProperty(const std::string &name, T *&prop, bool followChain = false) const;
/// retrieve the nameed string property
String *fetchStringProperty(const std::string &name, bool followChain = false) const;
/// retrieve the named double property
Double *fetchDoubleProperty(const std::string &name, bool followChain = false) const;
/// retrieve the named double property
Pointer *fetchPointerProperty(const std::string &name, bool followChain = false) const;
/// retrieve the named double property
Int *fetchIntProperty(const std::string &name, bool followChain = false) const;
/// get a particular int property without fetching via a get hook, useful for notifies
int getIntPropertyRaw(const std::string &property, int index = 0) const;
/// get a particular double property without fetching via a get hook, useful for notifies
double getDoublePropertyRaw(const std::string &property, int index = 0) const;
/// get a particular pointer property without fetching via a get hook, useful for notifies
void *getPointerPropertyRaw(const std::string &property, int index = 0) const;
/// get a particular string property
const std::string &getStringPropertyRaw(const std::string &property, int index = 0) const;
/// get the value of a particular string property
const std::string &getStringProperty(const std::string &property, int index = 0) const;
/// get the value of a particular int property
int getIntProperty(const std::string &property, int index = 0) const;
/// get the value of a particular double property
void getIntPropertyN(const std::string &property, int *v, int N) const;
/// get the value of a particular double property
double getDoubleProperty(const std::string &property, int index = 0) const;
/// get the value of a particular double property
void getDoublePropertyN(const std::string &property, double *v, int N) const;
/// get the value of a particular pointer property
void *getPointerProperty(const std::string &property, int index = 0) const;
/// set a particular string property without fetching via a get hook, useful for notifies
void setStringProperty(const std::string &property, const std::string &value, int index = 0);
/// get a particular int property
void setIntProperty(const std::string &property, int v, int index = 0);
/// get a particular double property
void setIntPropertyN(const std::string &property, const int *v, int N);
/// get a particular double property
void setDoubleProperty(const std::string &property, double v, int index = 0);
/// get a particular double property
void setDoublePropertyN(const std::string &property, const double *v, int N);
/// get a particular double property
void setPointerProperty(const std::string &property, void *v, int index = 0);
/// get the dimension of a particular property
int getDimension(const std::string &property) const;
/// is the given string one of the values of a multi-dimensional string prop
/// this returns a non negative index if it is found, otherwise, -1
int findStringPropValueIndex(const std::string &propName,
const std::string &propValue) const;
/// get a handle on this object for passing to the C API
OfxPropertySetHandle getHandle() const
{
return (OfxPropertySetHandle)this;
}
/// is this a nice property set, or a dodgy pointer passed back to us
bool verifyMagic() { return _magic == kMagic; }
};
/// return the OFX function suite that manages properties
const void *GetSuite(int version);
}
}
}
#endif
+34
View File
@@ -0,0 +1,34 @@
#ifndef _ofxhTimeLine_h_
#define _ofxhTimeLine_h_
#include "ofxTimeLine.h"
namespace OFX::Host::TimeLine {
/// Things that implement timeline controls derive from this ABC and implement the following
/// functions.
class TimeLineI {
public :
virtual ~TimeLineI() = default;
/// get the current time on the timeline. This is not necessarily the same
/// time as being passed to an action (eg render)
virtual double timeLineGetTime() = 0;
/// set the timeline to a specific time
virtual void timeLineGotoTime(double t) = 0;
/// get the first and last times available on the effect's timeline
virtual void timeLineGetBounds(double &t1, double &t2) = 0;
};
} // namespace progress
#endif
+154
View File
@@ -0,0 +1,154 @@
#ifndef _ofxhUtilities_h_
#define _ofxhUtilities_h_
// Copyright OpenFX and contributors to the OpenFX project.
// SPDX-License-Identifier: BSD-3-Clause
#include <string>
#include <list>
#include <vector>
#include "ofxCore.h"
// macro that intercepts any exception that passes through a plugin's entry point, and transforms it into a message on the host using Host::vmessage()
#define CatchAllSetStatus(stat,host,plugin,msg) \
catch ( const std::bad_alloc& ba ) { \
(stat) = kOfxStatErrMemory; \
if (host) { \
try { \
(host)->message(kOfxMessageError, "", \
"%s: Memory allocation error occured in plugin %s (%s)", \
(msg), (plugin)->pluginIdentifier, ba.what()); \
} catch (...) { \
} \
} \
} catch ( const std::exception &e ) { \
(stat) = kOfxStatFailed; \
if (host) { \
try { \
(host)->message(kOfxMessageError, "", \
"%s: Exception occured in plugin %s (%s)", \
(msg), (plugin)->pluginIdentifier, e.what()); \
} catch (...) { \
} \
} \
} catch ( ... ) { \
(stat) = kOfxStatFailed; \
if (host) { \
try { \
(host)->message(kOfxMessageError, "", \
"%s:Exception occured in plugin %s", \
(msg), (plugin)->pluginIdentifier); \
} catch (...) { \
} \
} \
}
namespace OFX {
/// class that is a std::vector of std::strings
typedef std::vector<std::string> StringVec;
/// class that is a std::vector of std::strings
inline void SetStringVecValue(StringVec &sv, const std::string &value, size_t index = 0)
{
size_t size = sv.size();
if(size <= index) {
while(size < index) {
sv.push_back("");
++size;
}
sv.push_back(value);
}
else
sv[index] = value;
}
/// get me deepest bit depth
std::string FindDeepestBitDepth(const std::string &s1, const std::string &s2);
/// get the min value
template<class T> inline T Minimum(const T &a, const T &b)
{
return a < b ? a : b;
}
/// get the min value
template<class T> inline T Maximum(const T &a, const T &b)
{
return a > b ? a : b;
}
/// clamp the value
template<class T> inline T Clamp(const T &v, const T &mn, const T &mx)
{
if(v < mn) return mn;
if(v > mx) return mx;
return v;
}
/// clamp the rect in v to the given bounds
inline OfxRectD Clamp(const OfxRectD &v,
const OfxRectD &bounds)
{
OfxRectD r;
r.x1 = Clamp(v.x1, bounds.x1, bounds.x2);
r.x2 = Clamp(v.x2, bounds.x1, bounds.x2);
r.y1 = Clamp(v.y1, bounds.y1, bounds.y2);
r.y2 = Clamp(v.y2, bounds.y1, bounds.y2);
return r;
}
/// get the union of the two rects
inline OfxRectD Union(const OfxRectD &a,
const OfxRectD &b)
{
OfxRectD r;
r.x1 = Minimum(a.x1, b.x1);
r.x2 = Maximum(a.x2, b.x2);
r.y1 = Minimum(a.y1, b.y1);
r.y2 = Maximum(a.y2, b.y2);
return r;
}
inline const char* StatStr(OfxStatus stat) {
switch(stat) {
case kOfxStatOK:
return "kOfxStatOK";
case kOfxStatFailed:
return "kOfxStatFailed";
case kOfxStatErrFatal:
return "kOfxStatErrFatal";
case kOfxStatErrUnknown:
return "kOfxStatErrUnknown";
case kOfxStatErrMissingHostFeature:
return "kOfxStatErrMissingHostFeature";
case kOfxStatErrUnsupported:
return "kOfxStatErrUnsupported";
case kOfxStatErrExists:
return "kOfxStatErrExists";
case kOfxStatErrFormat:
return "kOfxStatErrFormat";
case kOfxStatErrMemory:
return "kOfxStatErrMemory";
case kOfxStatErrBadHandle:
return "kOfxStatErrBadHandle";
case kOfxStatErrBadIndex:
return "kOfxStatErrBadIndex";
case kOfxStatErrValue:
return "kOfxStatErrValue";
case kOfxStatReplyYes:
return "kOfxStatReplyYes";
case kOfxStatReplyNo:
return "kOfxStatReplyNo";
case kOfxStatReplyDefault:
return "kOfxStatReplyDefault";
default:
return "(unknown error code)";
}
}
}
#endif
+74
View File
@@ -0,0 +1,74 @@
#ifndef OFX_XML_H
#define OFX_XML_H
// Copyright OpenFX and contributors to the OpenFX project.
// SPDX-License-Identifier: BSD-3-Clause
namespace OFX {
namespace XML {
inline std::string escape(const std::string &s) {
std::string ns;
for (size_t i=0;i<s.size();i++) {
// The are exactly five characters which must be escaped
// http://www.w3.org/TR/xml/#syntax
switch (s[i]) {
case '<':
ns += "&lt;";
break;
case '>':
ns += "&gt;";
break;
case '&':
ns += "&amp;";
break;
case '"':
ns += "&quot;";
break;
case '\'':
ns += "&apos;";
break;
default: {
unsigned char c = (unsigned char)(s[i]);
// Escape even the whitespace characters '\n' '\r' '\t', although they are valid
// XML, because they would be converted to space when re-read.
// See http://www.w3.org/TR/xml/#AVNormalize
if ((0x01 <= c && c <= 0x1f) || (0x7F <= c && c <= 0x9F)) {
// these characters must be escaped in XML 1.1
// http://www.w3.org/TR/xml/#sec-references
ns += "&#x";
if (c > 0xf) {
int d = c / 0x10;
ns += d < 10 ? ('0' + d) : ('A' + d - 10);
}
int d = c & 0xf;
ns += d < 10 ? ('0' + d) : ('A' + d - 10);
ns += ';';
} else {
ns += s[i];
}
} break;
}
}
return ns;
}
inline std::string attribute(const std::string &at, const std::string &val)
{
return at + "=" + "\"" + escape(val) + "\" ";
}
inline std::string attribute(const std::string &st, int val)
{
std::ostringstream o;
o << val;
return attribute(st, o.str());
}
}
}
#endif
+104
View File
@@ -0,0 +1,104 @@
#include "ofxhBinary.h"
using namespace OFX;
Binary::Binary(const std::string &binaryPath): _binaryPath(binaryPath), _invalid(false), _dlHandle(0), _users(0)
{
struct stat sb;
if (stat(binaryPath.c_str(), &sb) != 0) {
_invalid = true;
_time = 0;
_size = 0;
}
else {
_time = sb.st_mtime;
_size = sb.st_size;
}
}
// actually open the binary.
void Binary::load()
{
if(_invalid)
return;
#if defined (UNIX)
_dlHandle = dlopen(_binaryPath.c_str(), RTLD_LAZY|RTLD_LOCAL);
#else
_dlHandle = LoadLibrary(_binaryPath.c_str());
#endif
if (_dlHandle == 0) {
#if defined (UNIX)
std::cerr << "couldn't open library " << _binaryPath << " because " << dlerror() << std::endl;
#else
LPVOID lpMsgBuf = NULL;
DWORD err = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL);
std::cerr << "couldn't open library " << _binaryPath << " because " << (char*)lpMsgBuf << " was returned" << std::endl;
if (lpMsgBuf != NULL) {
LocalFree(lpMsgBuf);
}
#endif
_invalid = true;
}
}
/// close the binary
void Binary::unload() {
if (_dlHandle != 0) {
#if defined (UNIX)
dlclose(_dlHandle);
#elif defined (WINDOWS)
FreeLibrary(_dlHandle);
#endif
_dlHandle = 0;
}
}
/// look up a symbol in the binary file and return it as a pointer.
/// returns null pointer if not found, or if the library is not loaded.
void *Binary::findSymbol(const std::string &symbol) {
if (_dlHandle != 0) {
#if defined(UNIX)
return dlsym(_dlHandle, symbol.c_str());
#elif defined (WINDOWS)
return (void*)GetProcAddress(_dlHandle, symbol.c_str());
#endif
} else {
return 0;
}
}
void Binary::ref()
{
if (_users == 0) {
load();
}
_users++;
}
void Binary::unref()
{
_users--;
if (_users == 0) {
unload();
}
if (_users < 0) {
_users = 0;
}
}
+654
View File
@@ -0,0 +1,654 @@
#include <assert.h>
// ofx
#include "ofxCore.h"
// ofx host
#include "ofxhBinary.h"
#include "ofxhPropertySuite.h"
#include "ofxhClip.h"
#include "ofxhImageEffect.h"
#ifdef OFX_SUPPORTS_OPENGLRENDER
#include "ofxGPURender.h"
#endif
namespace OFX {
namespace Host {
namespace ImageEffect {
/// properties common to the desciptor and instance
/// the desc and set them, the instance cannot
static const Property::PropSpec clipDescriptorStuffs[] = {
{ kOfxPropType, Property::eString, 1, true, kOfxTypeClip },
{ kOfxPropName, Property::eString, 1, true, "SET ME ON CONSTRUCTION" },
{ kOfxPropLabel, Property::eString, 1, false, "" } ,
{ kOfxPropShortLabel, Property::eString, 1, false, "" },
{ kOfxPropLongLabel, Property::eString, 1, false, "" },
{ kOfxImageEffectPropSupportedComponents, Property::eString, 0, false, "" },
{ kOfxImageEffectPropTemporalClipAccess, Property::eInt, 1, false, "0" },
{ kOfxImageClipPropOptional, Property::eInt, 1, false, "0" },
{ kOfxImageClipPropIsMask, Property::eInt, 1, false, "0" },
{ kOfxImageClipPropFieldExtraction, Property::eString, 1, false, kOfxImageFieldDoubled },
{ kOfxImageEffectPropSupportsTiles, Property::eInt, 1, false, "1" },
Property::propSpecEnd,
};
////////////////////////////////////////////////////////////////////////////////
// props to clips descriptors and instances
// base ctor, for a descriptor
ClipBase::ClipBase()
: _properties(clipDescriptorStuffs)
{
}
/// props to clips and
ClipBase::ClipBase(const ClipBase &v)
: _properties(v._properties)
{
/// we are an instance, we need to reset the props to read only
const Property::PropertyMap &map = _properties.getProperties();
Property::PropertyMap::const_iterator i;
for(i = map.begin(); i != map.end(); ++i) {
(*i).second->setPluginReadOnly(false);
}
}
/// name of the clip
const std::string &ClipBase::getShortLabel() const
{
const std::string &s = _properties.getStringProperty(kOfxPropShortLabel);
if(s == "") {
return getLabel();
}
return s;
}
/// name of the clip
const std::string &ClipBase::getLabel() const
{
const std::string &s = _properties.getStringProperty(kOfxPropLabel);
if(s == "") {
return getName();
}
return s;
}
/// name of the clip
const std::string &ClipBase::getLongLabel() const
{
const std::string &s = _properties.getStringProperty(kOfxPropLongLabel);
if(s == "") {
return getLabel();
}
return s;
}
/// return a std::vector of supported comp
const std::vector<std::string> &ClipBase::getSupportedComponents() const
{
Property::String *p = _properties.fetchStringProperty(kOfxImageEffectPropSupportedComponents);
assert(p != NULL);
return p->getValues();
}
/// is the given component supported
bool ClipBase::isSupportedComponent(const std::string &comp) const
{
return _properties.findStringPropValueIndex(kOfxImageEffectPropSupportedComponents, comp) != -1;
}
/// does the clip do random temporal access
bool ClipBase::temporalAccess() const
{
return _properties.getIntProperty(kOfxImageEffectPropTemporalClipAccess) != 0;
}
/// is the clip optional
bool ClipBase::isOptional() const
{
return _properties.getIntProperty(kOfxImageClipPropOptional) != 0;
}
/// is the clip a nominal 'mask' clip
bool ClipBase::isMask() const
{
return _properties.getIntProperty(kOfxImageClipPropIsMask) != 0;
}
/// how does this clip like fielded images to be presented to it
const std::string &ClipBase::getFieldExtraction() const
{
return _properties.getStringProperty(kOfxImageClipPropFieldExtraction);
}
/// is the clip a nominal 'mask' clip
bool ClipBase::supportsTiles() const
{
return _properties.getIntProperty(kOfxImageEffectPropSupportsTiles) != 0;
}
const Property::Set& ClipBase::getProps() const
{
return _properties;
}
Property::Set& ClipBase::getProps()
{
return _properties;
}
/// get a handle on the properties of the clip descriptor for the C api
OfxPropertySetHandle ClipBase::getPropHandle() const
{
return _properties.getHandle();
}
/// get a handle on the clip descriptor for the C api
OfxImageClipHandle ClipBase::getHandle() const
{
return (OfxImageClipHandle)this;
}
////////////////////////////////////////////////////////////////////////////////
/// descriptor
ClipDescriptor::ClipDescriptor(const std::string &name)
: ClipBase()
{
_properties.setStringProperty(kOfxPropName,name);
}
/// extra properties for the instance, these are fetched from the host
/// via a get hook and some virtuals
static const Property::PropSpec clipInstanceStuffs[] = {
{ kOfxImageEffectPropPixelDepth, Property::eString, 1, true, kOfxBitDepthNone },
{ kOfxImageEffectPropComponents, Property::eString, 1, true, kOfxImageComponentNone },
{ kOfxImageClipPropUnmappedPixelDepth, Property::eString, 1, true, kOfxBitDepthNone },
{ kOfxImageClipPropUnmappedComponents, Property::eString, 1, true, kOfxImageComponentNone },
{ kOfxImageEffectPropPreMultiplication, Property::eString, 1, true, kOfxImageOpaque },
{ kOfxImagePropPixelAspectRatio, Property::eDouble, 1, true, "1.0" },
{ kOfxImageEffectPropFrameRate, Property::eDouble, 1, true, "25.0" },
{ kOfxImageEffectPropFrameRange, Property::eDouble, 2, true, "0" },
{ kOfxImageClipPropFieldOrder, Property::eString, 1, true, kOfxImageFieldNone },
{ kOfxImageClipPropConnected, Property::eInt, 1, true, "0" },
{ kOfxImageEffectPropUnmappedFrameRange, Property::eDouble, 2, true, "0" },
{ kOfxImageEffectPropUnmappedFrameRate, Property::eDouble, 1, true, "25.0" },
{ kOfxImageClipPropContinuousSamples, Property::eInt, 1, true, "0" },
Property::propSpecEnd,
};
////////////////////////////////////////////////////////////////////////////////
// instance
ClipInstance::ClipInstance(ImageEffect::Instance* effectInstance, ClipDescriptor& desc)
: ClipBase(desc)
, _effectInstance(effectInstance)
, _isOutput(desc.isOutput())
, _pixelDepth(kOfxBitDepthNone)
, _components(kOfxImageComponentNone)
{
// this will a parameters that are needed in an instance but not a
// Descriptor
_properties.addProperties(clipInstanceStuffs);
int i = 0;
while(clipInstanceStuffs[i].name) {
const Property::PropSpec& spec = clipInstanceStuffs[i];
switch (spec.type) {
case Property::eDouble:
case Property::eString:
case Property::eInt:
_properties.setGetHook(spec.name, this);
break;
default:
break;
}
i++;
}
}
// do nothing
int ClipInstance::getDimension(const std::string &name) const
{
if(name == kOfxImageEffectPropUnmappedFrameRange || name == kOfxImageEffectPropFrameRange)
return 2;
return 1;
}
// don't know what to do
void ClipInstance::reset(const std::string &/*name*/) {
//printf("failing in %s\n", __PRETTY_FUNCTION__);
throw Property::Exception(kOfxStatErrMissingHostFeature);
}
const std::string &ClipInstance::getComponents() const
{
return _components;
}
/// set the current set of components
/// called by clip preferences action
void ClipInstance::setComponents(const std::string &s)
{
_components = s;
}
// get the virutals for viewport size, pixel scale, background colour
void ClipInstance::getDoublePropertyN(const std::string &name, double *values, int n) const
{
if(name==kOfxImagePropPixelAspectRatio){
if(n>1) throw Property::Exception(kOfxStatErrValue);
*values = getAspectRatio();
}
else if(name==kOfxImageEffectPropFrameRate){
if(n>1) throw Property::Exception(kOfxStatErrValue);
*values = getFrameRate();
}
else if(name==kOfxImageEffectPropFrameRange){
if(n>2) throw Property::Exception(kOfxStatErrValue);
getFrameRange(values[0], values[1]);
}
else if(name==kOfxImageEffectPropUnmappedFrameRate){
if(n>1) throw Property::Exception(kOfxStatErrValue);
*values = getUnmappedFrameRate();
}
else if(name==kOfxImageEffectPropUnmappedFrameRange){
if(n>2) throw Property::Exception(kOfxStatErrValue);
getUnmappedFrameRange(values[0], values[1]);
}
else
throw Property::Exception(kOfxStatErrValue);
}
// get the virutals for viewport size, pixel scale, background colour
double ClipInstance::getDoubleProperty(const std::string &name, int n) const
{
if(name==kOfxImagePropPixelAspectRatio){
if(n!=0) throw Property::Exception(kOfxStatErrValue);
return getAspectRatio();
}
else if(name==kOfxImageEffectPropFrameRate){
if(n!=0) throw Property::Exception(kOfxStatErrValue);
return getFrameRate();
}
else if(name==kOfxImageEffectPropFrameRange){
if(n>1) throw Property::Exception(kOfxStatErrValue);
double range[2];
getFrameRange(range[0], range[1]);
return range[n];
}
else if(name==kOfxImageEffectPropUnmappedFrameRate){
if(n>0) throw Property::Exception(kOfxStatErrValue);
return getUnmappedFrameRate();
}
else if(name==kOfxImageEffectPropUnmappedFrameRange){
if(n>1) throw Property::Exception(kOfxStatErrValue);
double range[2];
getUnmappedFrameRange(range[0], range[1]);
return range[n];
}
else
throw Property::Exception(kOfxStatErrValue);
}
// get the virutals for viewport size, pixel scale, background colour
int ClipInstance::getIntProperty(const std::string &name, int n) const
{
if(n!=0) throw Property::Exception(kOfxStatErrValue);
if(name==kOfxImageClipPropConnected){
return getConnected();
}
else if(name==kOfxImageClipPropContinuousSamples){
return getContinuousSamples();
}
else
throw Property::Exception(kOfxStatErrValue);
}
// get the virutals for viewport size, pixel scale, background colour
void ClipInstance::getIntPropertyN(const std::string &name, int *values, int n) const
{
if(n!=0) throw Property::Exception(kOfxStatErrValue);
*values = getIntProperty(name, 0);
}
// get the virutals for viewport size, pixel scale, background colour
const std::string &ClipInstance::getStringProperty(const std::string &name, int n) const
{
if(n!=0) throw Property::Exception(kOfxStatErrValue);
if(name==kOfxImageEffectPropPixelDepth){
return getPixelDepth();
}
else if(name==kOfxImageEffectPropComponents){
return getComponents();
}
else if(name==kOfxImageClipPropUnmappedComponents){
return getUnmappedComponents();
}
else if(name==kOfxImageClipPropUnmappedPixelDepth){
return getUnmappedBitDepth();
}
else if(name==kOfxImageEffectPropPreMultiplication){
return getPremult();
}
else if(name==kOfxImageClipPropFieldOrder){
return getFieldOrder();
}
else
throw Property::Exception(kOfxStatErrValue);
}
// fetch multiple values in a multi-dimension property
void ClipInstance::getStringPropertyN(const std::string &name, const char** values, int count) const
{
if (count == 0) {
return;
}
if(count!=1) throw Property::Exception(kOfxStatErrValue);
if(name==kOfxImageEffectPropPixelDepth){
values[0] = getPixelDepth().c_str();
}
else if(name==kOfxImageEffectPropComponents){
values[0] = getComponents().c_str();
}
else if(name==kOfxImageClipPropUnmappedComponents){
values[0] = getUnmappedComponents().c_str();
}
else if(name==kOfxImageClipPropUnmappedPixelDepth){
values[0] = getUnmappedBitDepth().c_str();
}
else if(name==kOfxImageEffectPropPreMultiplication){
values[0] = getPremult().c_str();
}
else if(name==kOfxImageClipPropFieldOrder){
values[0] = getFieldOrder().c_str();
}
else
throw Property::Exception(kOfxStatErrValue);
}
// notify override properties
void ClipInstance::notify(const std::string &/*name*/, bool /*isSingle*/, int /*indexOrN*/)
{
}
OfxStatus ClipInstance::instanceChangedAction(const std::string &why,
OfxTime time,
OfxPointD renderScale)
{
Property::PropSpec stuff[] = {
{ kOfxPropType, Property::eString, 1, true, kOfxTypeClip },
{ kOfxPropName, Property::eString, 1, true, getName().c_str() },
{ kOfxPropChangeReason, Property::eString, 1, true, why.c_str() },
{ kOfxPropTime, Property::eDouble, 1, true, "0" },
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" },
Property::propSpecEnd
};
Property::Set inArgs(stuff);
// add the second dimension of the render scale
inArgs.setDoubleProperty(kOfxPropTime,time);
inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)_effectInstance<<"->"<<kOfxActionInstanceChanged<<"("<<kOfxTypeClip<<","<<getName()<<","<<why<<","<<time<<",("<<renderScale.x<<","<<renderScale.y<<"))"<<std::endl;
# endif
OfxStatus st;
if(_effectInstance){
st = _effectInstance->mainEntry(kOfxActionInstanceChanged, _effectInstance->getHandle(), &inArgs, 0);
} else {
st = kOfxStatFailed;
}
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)_effectInstance<<"->"<<kOfxActionInstanceChanged<<"("<<kOfxTypeClip<<","<<getName()<<","<<why<<","<<time<<",("<<renderScale.x<<","<<renderScale.y<<"))->"<<StatStr(st)<<std::endl;
# endif
return st;
}
/// given the colour component, find the nearest set of supported colour components
const std::string &ClipInstance::findSupportedComp(const std::string &s) const
{
static const std::string none(kOfxImageComponentNone);
static const std::string rgba(kOfxImageComponentRGBA);
static const std::string rgb(kOfxImageComponentRGB);
static const std::string alpha(kOfxImageComponentAlpha);
/// is it there
if(isSupportedComponent(s))
return s;
/// were we fed some custom non chromatic component by getUnmappedComponents? Return it.
/// we should never be here mind, so a bit weird
if(!_effectInstance->isChromaticComponent(s))
return s;
/// Means we have RGBA or Alpha being passed in and the clip
/// only supports the other one, so return that
if(s == rgba) {
if(isSupportedComponent(rgb))
return rgb;
if(isSupportedComponent(alpha))
return alpha;
} else if(s == alpha) {
if(isSupportedComponent(rgba))
return rgba;
if(isSupportedComponent(rgb))
return rgb;
}
/// wierd, must be some custom bit , if only one, choose that, otherwise no idea
/// how to map, you need to derive to do so.
const std::vector<std::string> &supportedComps = getSupportedComponents();
if(supportedComps.size() == 1)
return supportedComps[0];
return none;
}
////////////////////////////////////////////////////////////////////////////////
// Image
//
static const Property::PropSpec imageBaseStuffs[] = {
{ kOfxPropType, Property::eString, 1, false, kOfxTypeImage },
{ kOfxImageEffectPropPixelDepth, Property::eString, 1, true, kOfxBitDepthNone },
{ kOfxImageEffectPropComponents, Property::eString, 1, true, kOfxImageComponentNone },
{ kOfxImageEffectPropPreMultiplication, Property::eString, 1, true, kOfxImageOpaque },
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "1.0" },
{ kOfxImagePropPixelAspectRatio, Property::eDouble, 1, true, "1.0" },
{ kOfxImagePropBounds, Property::eInt, 4, true, "0" },
{ kOfxImagePropRegionOfDefinition, Property::eInt, 4, true, "0", },
{ kOfxImagePropRowBytes, Property::eInt, 1, true, "0", },
{ kOfxImagePropField, Property::eString, 1, true, "", },
{ kOfxImagePropUniqueIdentifier, Property::eString, 1, true, "" },
Property::propSpecEnd
};
ImageBase::ImageBase()
: Property::Set(imageBaseStuffs)
, _referenceCount(1)
{
}
/// called during ctor to get bits from the clip props into ours
void ImageBase::getClipBits(ClipInstance& instance)
{
Property::Set& clipProperties = instance.getProps();
// get and set the clip instance pixel depth
const std::string &depth = clipProperties.getStringProperty(kOfxImageEffectPropPixelDepth);
setStringProperty(kOfxImageEffectPropPixelDepth, depth);
// get and set the clip instance components
const std::string &comps = clipProperties.getStringProperty(kOfxImageEffectPropComponents);
setStringProperty(kOfxImageEffectPropComponents, comps);
// get and set the clip instance premultiplication
setStringProperty(kOfxImageEffectPropPreMultiplication, clipProperties.getStringProperty(kOfxImageEffectPropPreMultiplication));
// get and set the clip instance pixel aspect ratio
setDoubleProperty(kOfxImagePropPixelAspectRatio, clipProperties.getDoubleProperty(kOfxImagePropPixelAspectRatio));
}
/// make an image from a clip instance
ImageBase::ImageBase(ClipInstance& instance)
: Property::Set(imageBaseStuffs)
, _referenceCount(1)
{
getClipBits(instance);
}
// construction based on clip instance
ImageBase::ImageBase(ClipInstance& instance,
double renderScaleX,
double renderScaleY,
const OfxRectI &bounds,
const OfxRectI &rod,
int rowBytes,
std::string field,
std::string uniqueIdentifier)
: Property::Set(imageBaseStuffs)
, _referenceCount(1)
{
getClipBits(instance);
// set other data
setDoubleProperty(kOfxImageEffectPropRenderScale,renderScaleX, 0);
setDoubleProperty(kOfxImageEffectPropRenderScale,renderScaleY, 1);
setIntProperty(kOfxImagePropBounds,bounds.x1, 0);
setIntProperty(kOfxImagePropBounds,bounds.y1, 1);
setIntProperty(kOfxImagePropBounds,bounds.x2, 2);
setIntProperty(kOfxImagePropBounds,bounds.y2, 3);
setIntProperty(kOfxImagePropRegionOfDefinition,rod.x1, 0);
setIntProperty(kOfxImagePropRegionOfDefinition,rod.y1, 1);
setIntProperty(kOfxImagePropRegionOfDefinition,rod.x2, 2);
setIntProperty(kOfxImagePropRegionOfDefinition,rod.y2, 3);
setIntProperty(kOfxImagePropRowBytes,rowBytes);
setStringProperty(kOfxImagePropField,field);
setStringProperty(kOfxImageClipPropFieldOrder,field);
setStringProperty(kOfxImagePropUniqueIdentifier,uniqueIdentifier);
}
OfxRectI ImageBase::getBounds() const
{
OfxRectI bounds = {0, 0, 0, 0};
getIntPropertyN(kOfxImagePropBounds, &bounds.x1, 4);
return bounds;
}
OfxRectI ImageBase::getROD() const
{
OfxRectI rod = {0, 0, 0, 0};
getIntPropertyN(kOfxImagePropRegionOfDefinition, &rod.x1, 4);
return rod;
}
ImageBase::~ImageBase() {
//assert(_referenceCount <= 0);
}
// release the reference
void ImageBase::releaseReference()
{
_referenceCount -= 1;
if(_referenceCount <= 0)
delete this;
}
static const Property::PropSpec imageStuffs[] = {
{ kOfxImagePropData, Property::ePointer, 1, true, NULL },
Property::propSpecEnd
};
Image::Image()
: ImageBase()
{
addProperties(imageStuffs);
}
/// make an image from a clip instance
Image::Image(ClipInstance& instance)
: ImageBase(instance)
{
addProperties(imageStuffs);
}
// construction based on clip instance
Image::Image(ClipInstance& instance,
double renderScaleX,
double renderScaleY,
void* data,
const OfxRectI &bounds,
const OfxRectI &rod,
int rowBytes,
std::string field,
std::string uniqueIdentifier)
: ImageBase(instance, renderScaleX, renderScaleY, bounds, rod, rowBytes, field, uniqueIdentifier)
{
addProperties(imageStuffs);
// set other data
setPointerProperty(kOfxImagePropData,data);
}
Image::~Image() {
//assert(_referenceCount <= 0);
}
# ifdef OFX_SUPPORTS_OPENGLRENDER
static const Property::PropSpec textureStuffs[] = {
{ kOfxImageEffectPropOpenGLTextureIndex, Property::eInt, 1, true, "-1" },
{ kOfxImageEffectPropOpenGLTextureTarget, Property::eInt, 1, true, "-1" },
Property::propSpecEnd
};
Texture::Texture()
: ImageBase()
{
addProperties(textureStuffs);
}
/// make an image from a clip instance
Texture::Texture(ClipInstance& instance)
: ImageBase(instance)
{
addProperties(textureStuffs);
}
// construction based on clip instance
Texture::Texture(ClipInstance& instance,
double renderScaleX,
double renderScaleY,
int index,
int target,
const OfxRectI &bounds,
const OfxRectI &rod,
int rowBytes,
std::string field,
std::string uniqueIdentifier)
: ImageBase(instance, renderScaleX, renderScaleY, bounds, rod, rowBytes, field, uniqueIdentifier)
{
addProperties(textureStuffs);
// set other data
setIntProperty(kOfxImageEffectPropOpenGLTextureIndex, index);
setIntProperty(kOfxImageEffectPropOpenGLTextureTarget, target);
}
Texture::~Texture() {
//assert(_referenceCount <= 0);
}
# endif
} // Clip
} // Host
} // OFX
+124
View File
@@ -0,0 +1,124 @@
#include <limits.h>
#include <math.h>
#include <float.h>
#include <string.h>
// ofx
#include "ofxCore.h"
#include "ofxProperty.h"
#include "ofxMultiThread.h"
#include "ofxMemory.h"
#include "ofxhHost.h"
typedef OfxPlugin* (*OfxGetPluginType)(int);
namespace OFX {
namespace Host {
////////////////////////////////////////////////////////////////////////////////
/// simple memory suite
namespace Memory {
static OfxStatus memoryAlloc(void */*handle*/, size_t bytes, void **data)
{
*data = malloc(bytes);
if (*data) {
return kOfxStatOK;
} else {
return kOfxStatErrMemory;
}
}
static OfxStatus memoryFree(void *data)
{
free(data);
return kOfxStatOK;
}
static const struct OfxMemorySuiteV1 gMallocSuite = {
memoryAlloc,
memoryFree
};
}
}
}
namespace OFX {
namespace Host {
/// our own internal property for storing away our private pointer to our host descriptor
#define kOfxHostSupportHostPointer "sf.openfx.net.OfxHostSupportHostPointer"
static const Property::PropSpec hostStuffs[] = {
{ kOfxPropAPIVersion, Property::eInt, 0, false, "" },
{ kOfxPropType, Property::eString, 1, false, "Host" },
{ kOfxPropName, Property::eString, 1, false, "UNKNOWN" },
{ kOfxPropLabel, Property::eString, 1, false, "UNKNOWN" },
{ kOfxPropVersion, Property::eInt, 0, false, "0" },
{ kOfxPropVersionLabel, Property::eString, 1, false, "" },
{ kOfxHostSupportHostPointer, Property::ePointer, 0, false, NULL },
Property::propSpecEnd
};
static const void *fetchSuite(OfxPropertySetHandle hostProps, const char *suiteName, int suiteVersion)
{
Property::Set* properties = reinterpret_cast<Property::Set*>(hostProps);
Host* host = (Host*)properties->getPointerProperty(kOfxHostSupportHostPointer);
if(host)
return host->fetchSuite(suiteName,suiteVersion);
else
return 0;
}
// Base Host
Host::Host() : _properties(hostStuffs)
{
_host.host = _properties.getHandle();
_host.fetchSuite = OFX::Host::fetchSuite;
// record the host descriptor in the propert set
_properties.setPointerProperty(kOfxHostSupportHostPointer,this);
}
OfxHost *Host::getHandle() {
return &_host;
}
OfxStatus Host::message(const char* type,
const char* id,
const char* format,
...) {
try {
OfxStatus stat;
va_list args;
va_start(args,format);
stat = vmessage(type,id,format,args);
va_end(args);
return stat;
} catch (...) {
return kOfxStatFailed;
}
}
const void *Host::fetchSuite(const char *suiteName, int suiteVersion)
{
if (strcmp(suiteName, kOfxPropertySuite)==0 && suiteVersion == 1) {
return Property::GetSuite(suiteVersion);
}
else if (strcmp(suiteName, kOfxMemorySuite)==0 && suiteVersion == 1) {
return (void*)&Memory::gMallocSuite;
}
///printf("fetchSuite failed with host = %p, name = %s, version = %i\n", this, suiteName, suiteVersion);
return NULL;
}
} // Host
} // OFX
File diff suppressed because it is too large Load Diff
+592
View File
@@ -0,0 +1,592 @@
#include <assert.h>
#include <string>
#include <map>
#include <ctype.h>
// ofx
#include "ofxImageEffect.h"
// ofx host
#include "ofxhBinary.h"
#include "ofxhPropertySuite.h"
#include "ofxhClip.h"
#include "ofxhParam.h"
#include "ofxhMemory.h"
#include "ofxhImageEffect.h"
#include "ofxhPluginAPICache.h"
#include "ofxhPluginCache.h"
#include "ofxhHost.h"
#include "ofxhImageEffectAPI.h"
#include "ofxhXml.h"
// Disable the "this pointer used in base member initialiser list" warning in Windows
namespace OFX {
namespace Host {
namespace ImageEffect {
/// our global host bobject, set when the cache is created
OFX::Host::ImageEffect::Host *gImageEffectHost;
/// ctor
#ifdef WINDOWS
#pragma warning( disable : 4355 )
#endif
ImageEffectPlugin::ImageEffectPlugin(PluginCache &pc, PluginBinary *pb, int pi, OfxPlugin *pl)
: Plugin(pb, pi, pl)
, _pc(pc)
, _baseDescriptor(NULL)
, _madeKnownContexts(false)
{
_baseDescriptor = gImageEffectHost->makeDescriptor(this);
}
ImageEffectPlugin::ImageEffectPlugin(PluginCache &pc,
PluginBinary *pb,
int pi,
const std::string &api,
int apiVersion,
const std::string &pluginId,
const std::string &rawId,
int pluginMajorVersion,
int pluginMinorVersion)
: Plugin(pb, pi, api, apiVersion, pluginId, rawId, pluginMajorVersion, pluginMinorVersion)
, _pc(pc)
, _baseDescriptor(NULL)
, _madeKnownContexts(false)
{
_baseDescriptor = gImageEffectHost->makeDescriptor(this);
}
#ifdef WINDOWS
#pragma warning( default : 4355 )
#endif
ImageEffectPlugin::~ImageEffectPlugin()
{
_contexts.clear();
if(_pluginHandle) {
OfxPlugin *op = _pluginHandle->getOfxPlugin();
OfxStatus stat;
try {
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)op<<"->"<<kOfxActionUnload<<"()"<<std::endl;
# endif
stat = op->mainEntry(kOfxActionUnload, 0, 0, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)op<<"->"<<kOfxActionUnload<<"()->"<<StatStr(stat)<<std::endl;
# endif
} CatchAllSetStatus(stat, gImageEffectHost, op, kOfxActionUnload);
(void)stat;
}
delete _baseDescriptor;
}
APICache::PluginAPICacheI &ImageEffectPlugin::getApiHandler()
{
return _pc;
}
/// get the image effect descriptor
Descriptor &ImageEffectPlugin::getDescriptor() {
return *_baseDescriptor;
}
/// get the image effect descriptor const version
const Descriptor &ImageEffectPlugin::getDescriptor() const {
return *_baseDescriptor;
}
void ImageEffectPlugin::addContext(const std::string &context, std::unique_ptr<Descriptor> ied)
{
_contexts[context] = std::move(ied);
_knownContexts.insert(context);
_madeKnownContexts = true;
}
void ImageEffectPlugin::addContext(const std::string &context)
{
_knownContexts.insert(context);
_madeKnownContexts = true;
}
void ImageEffectPlugin::addContextInternal(const std::string &context) const
{
_knownContexts.insert(context);
_madeKnownContexts = true;
}
void ImageEffectPlugin::saveXML(std::ostream &os)
{
APICache::propertySetXMLWrite(os, getDescriptor().getProps(), 6);
}
const std::set<std::string> &ImageEffectPlugin::getContexts() const {
if (_madeKnownContexts) {
return _knownContexts;
}
else {
const OFX::Host::Property::Set &eProps = getDescriptor().getProps();
int size = eProps.getDimension(kOfxImageEffectPropSupportedContexts);
for (int j=0;j<size;j++) {
std::string context = eProps.getStringProperty(kOfxImageEffectPropSupportedContexts, j);
addContextInternal(context);
}
return _knownContexts;
}
}
PluginHandle *ImageEffectPlugin::getPluginHandle()
{
if(!_pluginHandle) {
_pluginHandle.reset(new OFX::Host::PluginHandle(this, _pc.getHost()));
OfxPlugin *op = _pluginHandle->getOfxPlugin();
if (!op) {
_pluginHandle.reset();
return nullptr;
}
OfxStatus stat;
try {
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)op<<"->"<<kOfxActionLoad<<"()"<<std::endl;
# endif
stat = op->mainEntry(kOfxActionLoad, 0, 0, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)op<<"->"<<kOfxActionLoad<<"()->"<<StatStr(stat)<<std::endl;
# endif
} CatchAllSetStatus(stat, gImageEffectHost, op, kOfxActionLoad);
if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
_pluginHandle.reset();
return nullptr;
}
try {
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)op<<"->"<<kOfxActionDescribe<<"()"<<std::endl;
# endif
stat = op->mainEntry(kOfxActionDescribe, getDescriptor().getHandle(), 0, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)op<<"->"<<kOfxActionDescribe<<"()->"<<StatStr(stat)<<std::endl;
# endif
} CatchAllSetStatus(stat, gImageEffectHost, op, kOfxActionDescribe);
if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
_pluginHandle.reset();
return nullptr;
}
}
return _pluginHandle.get();
}
Descriptor *ImageEffectPlugin::getContext(const std::string &context)
{
std::map<std::string, std::unique_ptr<Descriptor>>::iterator it = _contexts.find(context);
if (it != _contexts.end()) {
//printf("found context description.\n");
return it->second.get();
}
if (_knownContexts.find(context) == _knownContexts.end()) {
return nullptr;
}
// printf("doing context description.\n");
OFX::Host::Property::PropSpec inargspec[] = {
{ kOfxImageEffectPropContext, OFX::Host::Property::eString, 1, true, context.c_str() },
Property::propSpecEnd
};
OFX::Host::Property::Set inarg(inargspec);
PluginHandle *ph = getPluginHandle();
std::unique_ptr<ImageEffect::Descriptor> newContext( gImageEffectHost->makeDescriptor(getDescriptor(), this));
OfxStatus stat;
try {
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)ph->getOfxPlugin()<<"->"<<kOfxImageEffectActionDescribeInContext<<"("<<context<<")"<<std::endl;
# endif
stat = ph->getOfxPlugin()->mainEntry(kOfxImageEffectActionDescribeInContext, newContext->getHandle(), inarg.getHandle(), 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)ph->getOfxPlugin()<<"->"<<kOfxImageEffectActionDescribeInContext<<"("<<context<<")->"<<StatStr(stat)<<std::endl;
# endif
} CatchAllSetStatus(stat, gImageEffectHost, ph->getOfxPlugin(), kOfxImageEffectActionDescribeInContext);
if (stat == kOfxStatOK || stat == kOfxStatReplyDefault) {
_contexts[context] = std::move(newContext);
return _contexts[context].get();
}
return nullptr;
}
ImageEffect::Instance* ImageEffectPlugin::createInstance(const std::string &context, void *clientData)
{
/// todo - we need to make sure action:load is called, then action:describe again
/// (not because we are expecting the results to change, but because plugin
/// might get confused otherwise), then a describe_in_context
getPluginHandle();
Descriptor *desc = getContext(context);
if (desc) {
ImageEffect::Instance *instance = gImageEffectHost->newInstance(clientData,
this,
*desc,
context);
instance->populate();
return instance;
}
return 0;
}
void ImageEffectPlugin::unload() {
if (_pluginHandle) {
OfxStatus stat;
try {
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)_pluginHandle->getOfxPlugin()<<"->"<<kOfxActionUnload<<"()"<<std::endl;
# endif
stat = (*_pluginHandle)->mainEntry(kOfxActionUnload, 0, 0, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)_pluginHandle->getOfxPlugin()<<"->"<<kOfxActionUnload<<"()->"<<StatStr(stat)<<std::endl;
# endif
} CatchAllSetStatus(stat, gImageEffectHost, (*_pluginHandle), kOfxActionUnload);
(void)stat;
}
}
PluginCache::PluginCache(OFX::Host::ImageEffect::Host &host)
: PluginAPICacheI(kOfxImageEffectPluginApi, 1, 1)
, _currentPlugin(0)
, _currentProp(0)
, _currentContext(0)
, _currentParam(0)
, _currentClip(0)
, _host(&host)
{
gImageEffectHost = &host;
}
PluginCache::~PluginCache() {}
/// get the plugin by id. vermaj and vermin can be specified. if they are not it will
/// pick the highest found version.
ImageEffectPlugin *PluginCache::getPluginById(const std::string &id, int vermaj, int vermin)
{
// return the highest version one, which fits the pattern provided
ImageEffectPlugin *sofar = 0;
std::string identifier = id;
// Who says the pluginIdentifier is case-insensitive? OFX 1.3 spec doesn't mention this.
// http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#id472588
//for (size_t i=0;i<identifier.size();i++) {
// identifier[i] = tolower(identifier[i]);
//}
for (std::vector<ImageEffectPlugin *>::iterator i=_plugins.begin();i!=_plugins.end();i++) {
ImageEffectPlugin *p = *i;
if (p->getIdentifier() != identifier) {
continue;
}
if (vermaj != -1 && p->getVersionMajor() != vermaj) {
continue;
}
if (vermin != -1 && p->getVersionMinor() != vermin) {
continue;
}
if (!sofar || p->trumps(sofar)) {
sofar = p;
}
}
return sofar;
}
/// whether we support this plugin.
bool PluginCache::pluginSupported(OFX::Host::Plugin *p, std::string &reason) const {
return gImageEffectHost->pluginSupported(dynamic_cast<OFX::Host::ImageEffect::ImageEffectPlugin *>(p), reason);
}
/// get the plugin by label. vermaj and vermin can be specified. if they are not it will
/// pick the highest found version.
ImageEffectPlugin *PluginCache::getPluginByLabel(const std::string &label, int vermaj, int vermin)
{
// return the highest version one, which fits the pattern provided
ImageEffectPlugin *sofar = 0;
for (std::vector<ImageEffectPlugin *>::iterator i=_plugins.begin();i!=_plugins.end();i++) {
ImageEffectPlugin *p = *i;
if (p->getDescriptor().getProps().getStringProperty(kOfxPropLabel) != label) {
continue;
}
if (vermaj != -1 && p->getVersionMajor() != vermaj) {
continue;
}
if (vermin != -1 && p->getVersionMinor() != vermin) {
continue;
}
if (!sofar || p->trumps(sofar)) {
sofar = p;
}
}
return sofar;
}
const std::vector<ImageEffectPlugin *>& PluginCache::getPlugins() const
{
return _plugins;
}
const std::map<std::string, ImageEffectPlugin *>& PluginCache::getPluginsByID() const
{
return _pluginsByID;
}
/// handle the case where the info needs filling in from the file. runs the "describe" action on the plugin.
void PluginCache::loadFromPlugin(Plugin *op) const {
std::string msg = "loading ";
msg += op->getRawIdentifier();
_host->loadingStatus(msg);
ImageEffectPlugin *p = dynamic_cast<ImageEffectPlugin*>(op);
assert(p);
PluginHandle plug(p, _host);
OfxStatus stat;
try {
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)plug.getOfxPlugin()<<"->"<<kOfxActionLoad<<"()"<<std::endl;
# endif
stat = plug->mainEntry(kOfxActionLoad, 0, 0, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)plug.getOfxPlugin()<<"->"<<kOfxActionLoad<<"()->"<<StatStr(stat)<<std::endl;
# endif
} CatchAllSetStatus(stat, gImageEffectHost, plug, kOfxActionLoad);
if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
std::cerr << "load failed on plugin " << op->getIdentifier() << std::endl;
return;
}
try {
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)plug.getOfxPlugin()<<"->"<<kOfxActionDescribe<<"()"<<std::endl;
# endif
stat = plug->mainEntry(kOfxActionDescribe, p->getDescriptor().getHandle(), 0, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)plug.getOfxPlugin()<<"->"<<kOfxActionDescribe<<"()->"<<StatStr(stat)<<std::endl;
# endif
} CatchAllSetStatus(stat, gImageEffectHost, plug, kOfxActionDescribe);
if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
std::cerr << "describe failed on plugin " << op->getIdentifier() << std::endl;
return;
}
ImageEffect::Descriptor &e = p->getDescriptor();
Property::Set &eProps = e.getProps();
int size = eProps.getDimension(kOfxImageEffectPropSupportedContexts);
for (int j=0;j<size;j++) {
std::string context = eProps.getStringProperty(kOfxImageEffectPropSupportedContexts, j);
p->addContext(context);
}
try {
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)plug.getOfxPlugin()<<"->"<<kOfxActionUnload<<"()"<<std::endl;
# endif
stat = plug->mainEntry(kOfxActionUnload, 0, 0, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)plug.getOfxPlugin()<<"->"<<kOfxActionUnload<<"()->"<<StatStr(stat)<<std::endl;
# endif
} CatchAllSetStatus(stat, gImageEffectHost, plug, kOfxActionUnload);
if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
std::cerr << "unload failed on plugin " << op->getIdentifier() << std::endl;
return;
}
}
/// handler for preparing to read in a chunk of XML from the cache, set up context to do this
void PluginCache::beginXmlParsing(Plugin *p) {
_currentPlugin = dynamic_cast<ImageEffectPlugin*>(p);
}
/// XML handler : element begins (everything is stored in elements and attributes)
void PluginCache::xmlElementBegin(const std::string &el, std::map<std::string, std::string> map)
{
if (el == "apiproperties") {
return;
}
if (el == "context") {
std::unique_ptr<Descriptor> newContext(gImageEffectHost->makeDescriptor(_currentPlugin->getBinary()->getBundlePath(), _currentPlugin));
_currentContext = newContext.get();
_currentPlugin->addContext(map["name"], std::move(newContext));
return;
}
if (el == "param" && _currentContext) {
std::string pname = map["name"];
std::string ptype = map["type"];
_currentParam = _currentContext->paramDefine(ptype.c_str(), pname.c_str());
return;
}
if (el == "clip" && _currentContext) {
std::string cname = map["name"];
_currentClip = new ClipDescriptor(cname);
_currentContext->addClip(cname, _currentClip);
return;
}
if (_currentContext && _currentParam) {
APICache::propertySetXMLRead(el, map, _currentParam->getProperties(), _currentProp);
return;
}
if (_currentContext && _currentClip) {
APICache::propertySetXMLRead(el, map, _currentClip->getProps(), _currentProp);
return;
}
if (!_currentContext && !_currentParam) {
APICache::propertySetXMLRead(el, map, _currentPlugin->getDescriptor().getProps(), _currentProp);
return;
}
std::cout << "element " << el << "\n";
assert(false);
}
void PluginCache::xmlCharacterHandler(const std::string &) {
}
void PluginCache::xmlElementEnd(const std::string &el) {
if (el == "param") {
_currentParam = 0;
}
if (el == "context") {
_currentContext = 0;
}
}
void PluginCache::endXmlParsing() {
_currentPlugin = 0;
}
void PluginCache::saveXML(Plugin *ip, std::ostream &os) const {
ImageEffectPlugin *p = dynamic_cast<ImageEffectPlugin*>(ip);
if (p) {
p->saveXML(os);
}
}
void PluginCache::confirmPlugin(Plugin *p) {
ImageEffectPlugin *plugin = dynamic_cast<ImageEffectPlugin*>(p);
if (!plugin) {
return;
}
_plugins.push_back(plugin);
if (_pluginsByID.find(plugin->getIdentifier()) != _pluginsByID.end()) {
ImageEffectPlugin *otherPlugin = _pluginsByID[plugin->getIdentifier()];
if (plugin->trumps(otherPlugin)) {
_pluginsByID[plugin->getIdentifier()] = plugin;
}
} else {
_pluginsByID[plugin->getIdentifier()] = plugin;
}
MajorPlugin maj(plugin);
if (_pluginsByIDMajor.find(maj) != _pluginsByIDMajor.end()) {
ImageEffectPlugin *otherPlugin = _pluginsByIDMajor[maj];
if (plugin->trumps(otherPlugin)) {
_pluginsByIDMajor[maj] = plugin;
}
} else {
_pluginsByIDMajor[maj] = plugin;
}
}
Plugin *PluginCache::newPlugin(PluginBinary *pb,
int pi,
OfxPlugin *pl) {
ImageEffectPlugin *plugin = new ImageEffectPlugin(*this, pb, pi, pl);
return plugin;
}
Plugin *PluginCache::newPlugin(PluginBinary *pb,
int pi,
const std::string &api,
int apiVersion,
const std::string &pluginId,
const std::string &rawId,
int pluginMajorVersion,
int pluginMinorVersion)
{
ImageEffectPlugin *plugin = new ImageEffectPlugin(*this, pb, pi, api, apiVersion, pluginId, rawId, pluginMajorVersion, pluginMinorVersion);
return plugin;
}
void PluginCache::dumpToStdOut()
{
if (_pluginsByID.empty())
std::cout << "No Plug-ins Found." << std::endl;
for(std::map<std::string, ImageEffectPlugin *>::const_iterator it = _pluginsByID.begin(); it != _pluginsByID.end(); ++it)
{
std::cout << "Plug-in:" << it->first << std::endl;
std::cout << "\t" << "Filepath: " << it->second->getBinary()->getFilePath();
std::cout<< "(" << it->second->getIndex() << ")" << std::endl;
std::cout << "Contexts:" << std::endl;
const std::set<std::string>& contexts = it->second->getContexts();
for (std::set<std::string>::const_iterator it2 = contexts.begin(); it2 != contexts.end(); ++it2)
std::cout << "\t* " << *it2 << std::endl;
const Descriptor& d = it->second->getDescriptor();
std::cout << "Inputs:" << std::endl;
const std::map<std::string, ClipDescriptor*>& inputs = d.getClips();
for (std::map<std::string, ClipDescriptor*>::const_iterator it2 = inputs.begin(); it2 != inputs.end(); ++it2)
std::cout << "\t\t* " << it2->first << std::endl;
}
}
} // ImageEffect
} // Host
} // OFX
+444
View File
@@ -0,0 +1,444 @@
// ofx
#include "ofxKeySyms.h"
#include "ofxCore.h"
#include "ofxImageEffect.h"
// ofx host
#include "ofxhBinary.h"
#include "ofxhPropertySuite.h"
#include "ofxhClip.h"
#include "ofxhParam.h"
#include "ofxhMemory.h"
#include "ofxhImageEffect.h"
#include "ofxhInteract.h"
#include "ofxOld.h" // old plugins may rely on deprecated properties being present
namespace OFX {
namespace Host {
namespace Interact {
//
// descriptor
//
static const Property::PropSpec interactDescriptorStuffs[] = {
{ kOfxInteractPropHasAlpha , Property::eInt, 1, true, "0" },
{ kOfxInteractPropBitDepth , Property::eInt, 1, true, "0" },
Property::propSpecEnd
};
Descriptor::Descriptor()
: _properties(interactDescriptorStuffs)
, _state(eUninitialised)
, _entryPoint(NULL)
{
}
Descriptor::~Descriptor()
{
}
/// call describe on this descriptor
bool Descriptor::describe(int bitDepthPerComponent, bool hasAlpha)
{
if(_state == eUninitialised) {
_properties.setIntProperty(kOfxInteractPropBitDepth, bitDepthPerComponent);
_properties.setIntProperty(kOfxInteractPropHasAlpha, (int)(hasAlpha));
OfxStatus stat = callEntry(kOfxActionDescribe, getHandle(), NULL, NULL);
if(stat == kOfxStatOK || stat == kOfxStatReplyDefault) {
_state = eDescribed;
}
else {
_state = eFailed;
}
}
return _state == eDescribed;
}
// call the interactive entry point
OfxStatus Descriptor::callEntry(const char *action,
void *handle,
OfxPropertySetHandle inArgs,
OfxPropertySetHandle outArgs)
{
if(_entryPoint && _state != eFailed) {
return _entryPoint(action, handle, inArgs, outArgs);
}
else
return kOfxStatFailed;
return kOfxStatOK;
}
////////////////////////////////////////////////////////////////////////////////
static const Property::PropSpec interactInstanceStuffs[] = {
{ kOfxPropEffectInstance, Property::ePointer, 1, true, NULL },
{ kOfxPropInstanceData, Property::ePointer, 1, false, NULL },
{ kOfxInteractPropPixelScale, Property::eDouble, 2, true, "1.0f" },
{ kOfxInteractPropBackgroundColour , Property::eDouble, 3, true, "0.0f" },
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
{ kOfxInteractPropViewportSize, Property::eDouble, 2, true, "100.0f" },
#endif
{ kOfxInteractPropSlaveToParam , Property::eString, 0, false, ""},
{ kOfxInteractPropSuggestedColour , Property::eDouble, 3, true, "1.0f" },
Property::propSpecEnd
};
static const Property::PropSpec interactArgsStuffs[] = {
{ kOfxPropEffectInstance, Property::ePointer, 1, false, NULL },
{ kOfxPropTime, Property::eDouble, 1, false, "0.0" },
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, false, "0.0" },
{ kOfxInteractPropBackgroundColour , Property::eDouble, 3, false, "0.0f" },
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
{ kOfxInteractPropViewportSize, Property::eDouble, 2, false, "0.0f" },
#endif
{ kOfxInteractPropPixelScale, Property::eDouble, 2, false, "1.0f" },
{ kOfxInteractPropPenPosition, Property::eDouble, 2, false, "0.0" },
{ kOfxInteractPropPenViewportPosition, Property::eInt, 2, false, "0" }, // new in OFX 1.2
{ kOfxInteractPropPenPressure, Property::eDouble, 1, false, "0.0" },
{ kOfxPropKeyString, Property::eString, 1, false, "" },
{ kOfxPropKeySym, Property::eInt, 1, false, "0" },
Property::propSpecEnd
};
// instance
Instance::Instance(Descriptor& desc, void *effectInstance)
: _descriptor(desc)
, _properties(interactInstanceStuffs)
, _state(desc.getState())
, _effectInstance(effectInstance)
, _argProperties(interactArgsStuffs)
{
_properties.setPointerProperty(kOfxPropEffectInstance, effectInstance);
_properties.setChainedSet(&desc.getProperties()); /// chain it into the descriptor props
_properties.setGetHook(kOfxInteractPropPixelScale, this);
_properties.setGetHook(kOfxInteractPropBackgroundColour,this);
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
_properties.setGetHook(kOfxInteractPropViewportSize,this);
#endif
_properties.setGetHook(kOfxInteractPropSuggestedColour,this);
_argProperties.setGetHook(kOfxInteractPropPixelScale, this);
_argProperties.setGetHook(kOfxInteractPropBackgroundColour,this);
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
_argProperties.setGetHook(kOfxInteractPropViewportSize,this);
#endif
}
Instance::~Instance()
{
/// call it directly incase CI failed and we should always tidy up after create instance
callEntry(kOfxActionDestroyInstance, NULL);
}
/// call the entry point in the descriptor with action and the given args
OfxStatus Instance::callEntry(const char *action, Property::Set *inArgs)
{
if(_state != eFailed) {
OfxPropertySetHandle inHandle = inArgs ? inArgs->getHandle() : NULL ;
return _descriptor.callEntry(action, getHandle(), inHandle, NULL);
}
return kOfxStatFailed;
}
// do nothing
int Instance::getDimension(const std::string &name) const
{
if(name == kOfxInteractPropPixelScale){
return 2;
}
else if(name == kOfxInteractPropBackgroundColour){
return 3;
}
else if(name == kOfxInteractPropSuggestedColour
){
return 3;
}
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
else if(name == kOfxInteractPropViewportSize){
return 2;
}
#endif
else
throw Property::Exception(kOfxStatErrValue);
}
// do nothing function
void Instance::reset(const std::string &/*name*/)
{
// no-op
}
double Instance::getDoubleProperty(const std::string &name, int index) const
{
if(name == kOfxInteractPropPixelScale){
if(index>=2) throw Property::Exception(kOfxStatErrBadIndex);
double first[2];
getPixelScale(first[0],first[1]);
return first[index];
}
else if(name == kOfxInteractPropBackgroundColour){
if(index>=3) throw Property::Exception(kOfxStatErrBadIndex);
double first[3];
getBackgroundColour(first[0],first[1],first[2]);
return first[index];
}
else if(name == kOfxInteractPropSuggestedColour
){
if(index>=3) throw Property::Exception(kOfxStatErrBadIndex);
double first[3];
bool stat = getSuggestedColour(first[0],first[1],first[2]);
if (!stat) throw Property::Exception(kOfxStatReplyDefault);
return first[index];
}
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
else if(name == kOfxInteractPropViewportSize){
if(index>=2) throw Property::Exception(kOfxStatErrBadIndex);
double first[2];
getViewportSize(first[0],first[1]);
return first[index];
}
#endif
else
throw Property::Exception(kOfxStatErrUnknown);
}
void Instance::getDoublePropertyN(const std::string &name, double *first, int n) const
{
if(name == kOfxInteractPropPixelScale){
if(n>2) throw Property::Exception(kOfxStatErrBadIndex);
getPixelScale(first[0],first[1]);
}
else if(name == kOfxInteractPropBackgroundColour){
if(n>3) throw Property::Exception(kOfxStatErrBadIndex);
getBackgroundColour(first[0],first[1],first[2]);
}
else if(name == kOfxInteractPropSuggestedColour
){
if(n>3) throw Property::Exception(kOfxStatErrBadIndex);
bool stat = getSuggestedColour(first[0],first[1],first[2]);
if (!stat) throw Property::Exception(kOfxStatReplyDefault);
}
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
else if(name == kOfxInteractPropViewportSize){
if(n>2) throw Property::Exception(kOfxStatErrBadIndex);
getViewportSize(first[0],first[1]);
}
#endif
else
throw Property::Exception(kOfxStatErrUnknown);
}
void Instance::getSlaveToParam(std::vector<std::string>& params) const
{
int nSlaveParams = _properties.getDimension(kOfxInteractPropSlaveToParam);
for (int i=0; i<nSlaveParams; i++) {
std::string param = _properties.getStringProperty(kOfxInteractPropSlaveToParam, i);
params.push_back(param);
}
}
/// initialise the argument properties
void Instance::initArgProp(OfxTime time,
const OfxPointD &renderScale)
{
double pixelScale[2];
getPixelScale(pixelScale[0], pixelScale[1]);
_argProperties.setDoublePropertyN(kOfxInteractPropPixelScale, pixelScale, 2);
_argProperties.setPointerProperty(kOfxPropEffectInstance, _effectInstance);
_argProperties.setPointerProperty(kOfxPropInstanceData, _properties.getPointerProperty(kOfxPropInstanceData));
_argProperties.setDoubleProperty(kOfxPropTime,time);
_argProperties.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2);
}
void Instance::setPenArgProps(const OfxPointD &penPos,
const OfxPointI &penPosViewport,
double pressure)
{
_argProperties.setDoublePropertyN(kOfxInteractPropPenPosition, &penPos.x, 2);
_argProperties.setIntPropertyN(kOfxInteractPropPenViewportPosition, &penPosViewport.x, 2); // new in OFX 1.2
_argProperties.setDoubleProperty(kOfxInteractPropPenPressure, pressure);
}
void Instance::setKeyArgProps(int key,
char* keyString)
{
_argProperties.setIntProperty(kOfxPropKeySym,key);
_argProperties.setStringProperty(kOfxPropKeyString,keyString);
}
OfxStatus Instance::createInstanceAction()
{
OfxStatus stat = callEntry(kOfxActionCreateInstance, NULL);
if(stat == kOfxStatOK || stat == kOfxStatReplyDefault) {
_state = eCreated;
}
else {
_state = eFailed;
}
return stat;
}
OfxStatus Instance::drawAction(OfxTime time,
const OfxPointD &renderScale)
{
initArgProp(time, renderScale);
return callEntry(kOfxInteractActionDraw, &_argProperties);
}
OfxStatus Instance::penMotionAction(OfxTime time,
const OfxPointD &renderScale,
const OfxPointD &penPos,
const OfxPointI &penPosViewport,
double pressure)
{
initArgProp(time, renderScale);
setPenArgProps(penPos, penPosViewport, pressure);
return callEntry(kOfxInteractActionPenMotion,&_argProperties);
}
OfxStatus Instance::penUpAction(OfxTime time,
const OfxPointD &renderScale,
const OfxPointD &penPos,
const OfxPointI &penPosViewport,
double pressure)
{
initArgProp(time, renderScale);
setPenArgProps(penPos, penPosViewport, pressure);
return callEntry(kOfxInteractActionPenUp,&_argProperties);
}
OfxStatus Instance::penDownAction(OfxTime time,
const OfxPointD &renderScale,
const OfxPointD &penPos,
const OfxPointI &penPosViewport,
double pressure)
{
initArgProp(time, renderScale);
setPenArgProps(penPos, penPosViewport, pressure);
return callEntry(kOfxInteractActionPenDown,&_argProperties);
}
OfxStatus Instance::keyDownAction(OfxTime time,
const OfxPointD &renderScale,
int key,
char* keyString)
{
initArgProp(time, renderScale);
setKeyArgProps(key, keyString);
return callEntry(kOfxInteractActionKeyDown,&_argProperties);
}
OfxStatus Instance::keyUpAction(OfxTime time,
const OfxPointD &renderScale,
int key,
char* keyString)
{
initArgProp(time, renderScale);
setKeyArgProps(key, keyString);
return callEntry(kOfxInteractActionKeyUp,&_argProperties);
}
OfxStatus Instance::keyRepeatAction(OfxTime time,
const OfxPointD &renderScale,
int key,
char* keyString)
{
initArgProp(time, renderScale);
setKeyArgProps(key, keyString);
return callEntry(kOfxInteractActionKeyRepeat,&_argProperties);
}
OfxStatus Instance::gainFocusAction(OfxTime time,
const OfxPointD &renderScale)
{
initArgProp(time, renderScale);
return callEntry(kOfxInteractActionGainFocus,&_argProperties);
}
OfxStatus Instance::loseFocusAction(OfxTime time,
const OfxPointD &renderScale)
{
initArgProp(time, renderScale);
return callEntry(kOfxInteractActionLoseFocus,&_argProperties);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Interact suite functions
static OfxStatus interactSwapBuffers(OfxInteractHandle handle)
{
try {
Interact::Instance *interactInstance = reinterpret_cast<Interact::Instance*>(handle);
if(interactInstance)
return interactInstance->swapBuffers();
else
return kOfxStatErrBadHandle;
} catch (...) {
return kOfxStatFailed;
}
}
static OfxStatus interactRedraw(OfxInteractHandle handle)
{
try {
Interact::Instance *interactInstance = reinterpret_cast<Interact::Instance*>(handle);
if(interactInstance)
return interactInstance->redraw();
else
return kOfxStatErrBadHandle;
} catch (...) {
return kOfxStatFailed;
}
}
static OfxStatus interactGetPropertySet(OfxInteractHandle handle, OfxPropertySetHandle *property)
{
try {
Interact::Base *interact = reinterpret_cast<Interact::Base*>(handle);
if (!property) {
return kOfxStatErrBadHandle;
}
if (interact) {
*property = interact->getPropHandle();
return kOfxStatOK;
}
*property = NULL;
return kOfxStatErrBadHandle;
} catch (...) {
return kOfxStatFailed;
}
}
/// the interact suite
static const OfxInteractSuiteV1 gSuite = {
interactSwapBuffers,
interactRedraw,
interactGetPropertySet
};
/// function to get the sutie
const void *GetSuite(int version) {
if(version == 1)
return (void *) &gSuite;
return NULL;
}
} // Interact
} // Host
} // OFX
+64
View File
@@ -0,0 +1,64 @@
// ofx host
// ofx
#include "ofxCore.h"
#include "ofxImageEffect.h"
// ofx host
#include "ofxhMemory.h"
namespace OFX {
namespace Host {
namespace Memory {
Instance::Instance() : _ptr(0), _locked(0) {}
Instance::~Instance() {
delete [] _ptr;
}
bool Instance::alloc(size_t nBytes) {
if(!_locked){
if(_ptr)
freeMem();
_ptr = new char[nBytes];
return true;
}
else
return false;
}
OfxImageMemoryHandle Instance::getHandle(){
return (OfxImageMemoryHandle)this;
}
void Instance::freeMem(){
delete [] _ptr;
_ptr = 0;
_locked = 0;
}
void* Instance::getPtr() {
return _ptr;
}
void Instance::lock() {
++_locked;
}
void Instance::unlock() {
if (_locked > 0) {
--_locked;
}
}
} // Memory
} // Host
} // OFX
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,135 @@
#include <assert.h>
#include <string>
#include <map>
// ofx
#include "ofxCore.h"
#include "ofxImageEffect.h"
// ofx host
#include "ofxhBinary.h"
#include "ofxhPropertySuite.h"
#include "ofxhClip.h"
#include "ofxhParam.h"
#include "ofxhMemory.h"
#include "ofxhImageEffect.h"
#include "ofxhPluginAPICache.h"
#include "ofxhPluginCache.h"
#include "ofxhHost.h"
#include "ofxhImageEffectAPI.h"
#include "ofxhXml.h"
namespace OFX
{
namespace Host
{
namespace APICache
{
void PluginAPICacheI::registerInCache(OFX::Host::PluginCache &pluginCache) {
pluginCache.registerAPICache(_apiName, _apiVersionMin, _apiVersionMax, this);
}
void propertySetXMLRead(const std::string &el,
std::map<std::string, std::string> map,
Property::Set &set,
Property::Property *&currentProp) {
if (el == "property") {
std::string propName = map["name"];
std::string propType = map["type"];
int dimension = atoi(map["dimension"].c_str());
currentProp = set.fetchProperty(propName, false);
if(!currentProp) {
if (propType == "int") {
currentProp = new Property::Int(propName, dimension, false, 0);
} else if (propType == "string") {
currentProp = new Property::String(propName, dimension, false, "");
} else if (propType == "double") {
currentProp = new Property::Double(propName, dimension, false, 0);
} else if (propType == "pointer") {
currentProp = new Property::Pointer(propName, dimension, false, 0);
}
set.addProperty(currentProp);
}
return;
}
if (el == "value" && currentProp) {
int index = atoi(map["index"].c_str());
std::string value = map["value"];
switch (currentProp->getType()) {
case Property::eInt:
set.setIntProperty(currentProp->getName(), atoi(value.c_str()), index);
break;
case Property::eString:
set.setStringProperty(currentProp->getName(), value, index);
break;
case Property::eDouble:
set.setDoubleProperty(currentProp->getName(), atof(value.c_str()), index);
break;
case Property::ePointer:
break;
default:
break;
}
return;
}
std::cout << "got unrecognised key " << el << "\n";
assert(false);
}
static void propertyXMLWrite(std::ostream &o, Property::Property *prop, const std::string &indent="")
{
if (prop->getType() != Property::ePointer) {
o << indent << "<property "
<< XML::attribute("name", prop->getName())
<< XML::attribute("type", Property::gTypeNames[prop->getType()])
<< XML::attribute("dimension", prop->getFixedDimension())
<< ">\n";
for (int i=0;i<prop->getDimension();i++) {
o << indent << " <value "
<< XML::attribute("index", i)
<< XML::attribute("value", prop->getStringValue(i))
<< "/>\n";
}
o << indent << "</property>\n";
}
}
void propertyXMLWrite(std::ostream &o, const Property::Set &set, const std::string &name, int indent)
{
Property::Property *prop = set.fetchProperty(name);
if(prop) {
std::string indent_prefix(indent, ' ');
propertyXMLWrite(o, prop, indent_prefix);
}
}
void propertySetXMLWrite(std::ostream &o, const Property::Set &set, int indent)
{
std::string indent_prefix(indent, ' ');
for (Property::PropertyMap::const_iterator i = set.getProperties().begin();
i != set.getProperties().end();
i++)
{
Property::Property *prop = i->second;
propertyXMLWrite(o, prop, indent_prefix);
}
}
}
}
}
+694
View File
@@ -0,0 +1,694 @@
#include <assert.h>
#include <map>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string.h>
#include <stdlib.h>
#include "expat.h"
// ofx
#include "ofxCore.h"
#include "ofxImageEffect.h"
// ofx host
#include "ofxhBinary.h"
#include "ofxhPropertySuite.h"
#include "ofxhMemory.h"
#include "ofxhPluginAPICache.h"
#include "ofxhPluginCache.h"
#include "ofxhHost.h"
#include "ofxhXml.h"
#if defined (__linux__) || defined (__FreeBSD__)
#define DIRLIST_SEP_CHARS ":;"
#define DIRSEP "/"
#include <dirent.h>
static const char *getArchStr()
{
if(sizeof(void *) == 4) {
#if defined(__linux__)
return "Linux-x86";
#else
return "FreeBSD-x86";
#endif
}
else {
#if defined(__linux__)
return "Linux-x86-64";
#else
return "FreeBSD-x86-64";
#endif
}
}
#define ARCHSTR getArchStr()
#elif defined (__APPLE__)
#define DIRLIST_SEP_CHARS ";:"
#if defined(__x86_64) || defined(__x86_64__)
#define ARCHSTR "MacOS-x86-64"
#else
#define ARCHSTR "MacOS"
#endif
#define DIRSEP "/"
#include <dirent.h>
#elif defined (WINDOWS)
#define DIRLIST_SEP_CHARS ";"
#ifdef _WIN64
#define ARCHSTR "win64"
#else
#define ARCHSTR "win32"
#endif
#define DIRSEP "\\"
#include "shlobj.h"
#include "tchar.h"
#endif
OFX::Host::PluginCache* OFX::Host::PluginCache::gPluginCachePtr = 0;
// Define this to enable ofx plugin cache debug messages.
//#define CACHE_DEBUG
using namespace OFX::Host;
/// try to open the plugin bundle object and query it for plugins
void PluginBinary::loadPluginInfo(PluginCache *cache) {
if (isInvalid()) {
return;
}
_fileModificationTime = _binary.getTime();
_fileSize = _binary.getSize();
_binaryChanged = false;
// Take a reference to load the binary only once per session. It will
// eventually be unloaded in the destructor (see below).
// This avoid lots of useless calls to dlopen()/dlclose().
if (!_binary.isLoaded()) {
_binary.ref();
}
int (*getNo)(void) = (int(*)()) _binary.findSymbol("OfxGetNumberOfPlugins");
OfxPlugin* (*getPlug)(int) = (OfxPlugin*(*)(int)) _binary.findSymbol("OfxGetPlugin");
if (getNo == 0 || getPlug == 0) {
_binary.setInvalid(true);
} else {
int pluginCount = (*getNo)();
_plugins.reserve(pluginCount);
for (int i=0;i<pluginCount;i++) {
OfxPlugin *plug = (*getPlug)(i);
APICache::PluginAPICacheI *api = cache->findApiHandler(plug->pluginApi, plug->apiVersion);
assert(api);
_plugins.push_back(api->newPlugin(this, i, plug));
}
}
}
PluginBinary::~PluginBinary() {
std::vector<Plugin*>::iterator i = _plugins.begin();
while (i != _plugins.end()) {
delete *i;
i++;
}
// release the last reference to the binary, which should unload it
// if this reference was taken by loadPluginInfo().
if (_binary.isLoaded()) {
_binary.unref();
}
assert(!_binary.isLoaded());
}
PluginHandle::PluginHandle(Plugin *p, OFX::Host::Host *host)
{
_b = p->getBinary();
_b->_binary.ref();
_op = 0;
OfxPlugin* (*getPlug)(int) = (OfxPlugin*(*)(int)) _b->_binary.findSymbol("OfxGetPlugin");
if (getPlug) {
_op = getPlug(p->getIndex());
if (_op) {
_op->setHost(host->getHandle());
}
}
}
PluginHandle::~PluginHandle() {
_b->_binary.unref();
}
#if defined (WINDOWS)
const TCHAR *getStdOFXPluginPath(const std::string &hostId = "Plugins")
{
static TCHAR buffer[MAX_PATH];
static int gotIt = 0;
if(!gotIt) {
gotIt = 1;
SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, SHGFP_TYPE_CURRENT, buffer);
strcat_s(buffer, MAX_PATH, __T("\\OFX\\Plugins"));
}
return buffer;
}
#endif
static
std::string OFXGetEnv(const char* e)
{
#if defined(WINDOWS) && !defined(__MINGW32__)
size_t requiredSize;
getenv_s(&requiredSize, 0, 0, e);
std::vector<char> buffer(requiredSize);
if(requiredSize >0)
{
getenv_s(&requiredSize, &buffer.front(), requiredSize, e);
return &buffer.front();
}
return "";
#else
if(getenv(e))
return getenv(e);
#endif
return "";
}
PluginCache* PluginCache::getPluginCache()
{
if(!gPluginCachePtr)
gPluginCachePtr = new PluginCache();
return gPluginCachePtr;
}
void PluginCache::clearPluginCache()
{
delete gPluginCachePtr;
gPluginCachePtr = 0;
}
PluginCache::~PluginCache()
{
for(std::list<PluginBinary *>::iterator it=_binaries.begin(); it != _binaries.end(); ++it) {
delete (*it);
}
_binaries.clear();
}
PluginCache::PluginCache() : _hostSpec(0), _xmlCurrentBinary(0), _xmlCurrentPlugin(0) {
_cacheVersion = "";
_ignoreCache = false;
_dirty = false;
_enablePluginSeek = true;
std::string s = OFXGetEnv("OFX_PLUGIN_PATH");
while (s.length()) {
int spos = int(s.find_first_of(DIRLIST_SEP_CHARS));
std::string path;
if (spos != -1) {
path = s.substr(0, spos);
s = s.substr(spos+1);
}
else {
path = s;
s = "";
}
_pluginPath.push_back(path);
}
#if defined(WINDOWS)
_pluginPath.push_back(getStdOFXPluginPath());
_pluginPath.push_back("C:\\Program Files\\Common Files\\OFX\\Plugins");
#endif
#if defined(__linux__) || defined(__FreeBSD__)
_pluginPath.push_back("/usr/OFX/Plugins");
#endif
#if defined(__APPLE__)
_pluginPath.push_back("/Library/OFX/Plugins");
#endif
}
void PluginCache::setPluginHostPath(const std::string &hostId) {
#if defined(WINDOWS)
_pluginPath.push_back(getStdOFXPluginPath(hostId));
_pluginPath.push_back("C:\\Program Files\\Common Files\\OFX\\" + hostId);
#endif
#if defined(__linux__) || defined(__FreeBSD__)
_pluginPath.push_back("/usr/OFX/" + hostId);
#endif
#if defined(__APPLE__)
_pluginPath.push_back("/Library/OFX/" + hostId);
#endif
}
void PluginCache::scanDirectory(std::set<std::string> &foundBinFiles, const std::string &dir, bool recurse)
{
#ifdef CACHE_DEBUG
printf("looking in %s for plugins\n", dir.c_str());
#endif
#if defined (WINDOWS)
WIN32_FIND_DATA findData;
HANDLE findHandle;
#else
DIR *d = opendir(dir.c_str());
if (!d) {
return;
}
#endif
_pluginDirs.push_back(dir.c_str());
#if defined (UNIX)
while (dirent *de = readdir(d))
#elif defined (WINDOWS)
findHandle = FindFirstFile((dir + "\\*").c_str(), &findData);
if (findHandle == INVALID_HANDLE_VALUE)
{
return;
}
while (1)
#endif
{
#if defined (UNIX)
std::string name = de->d_name;
bool isdir = true;
#else
std::string name = findData.cFileName;
bool isdir = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
#endif
if (name.find(".ofx.bundle") != std::string::npos) {
std::string barename = name.substr(0, name.length() - strlen(".bundle"));
std::string bundlename = dir + DIRSEP + name;
std::string binpath = dir + DIRSEP + name + DIRSEP "Contents" DIRSEP + ARCHSTR + DIRSEP + barename;
// don't insert binpath yet, do it later because of Mac OS X Universal stuff
//foundBinFiles.insert(binpath);
#if defined(__APPLE__) && (defined(__x86_64) || defined(__x86_64__))
/* From the OpenFX specification:
MacOS-x86-64 - for Apple Macintosh OS X, specifically on
intel x86 CPUs running AMD's 64 bit extensions. 64 bit host
applications should check this first, and if it doesn't
exist or is empty, fall back to "MacOS" looking for a
universal binary.
*/
std::string binpath_universal = dir + DIRSEP + name + DIRSEP "Contents" DIRSEP + "MacOS" + DIRSEP + barename;
if (_knownBinFiles.find(binpath_universal) != _knownBinFiles.end()) {
binpath = binpath_universal;
}
#endif
if (_knownBinFiles.find(binpath) == _knownBinFiles.end()) {
#ifdef CACHE_DEBUG
printf("found non-cached binary %s\n", binpath.c_str());
#endif
_dirty = true;
// the binary was not in the cache
PluginBinary *pb = 0;
#if defined(__x86_64) || defined(__x86_64__)
pb = new PluginBinary(binpath, bundlename, this);
# if defined(__APPLE__)
if (pb->isInvalid()) {
// fallback to "MacOS"
delete pb;
binpath = binpath_universal;
pb = new PluginBinary(binpath, bundlename, this);
}
# endif
#else
pb = new PluginBinary(binpath, bundlename, this);
#endif
_binaries.push_back(pb);
_knownBinFiles.insert(binpath);
foundBinFiles.insert(binpath);
for (int j=0;j<pb->getNPlugins();j++) {
Plugin *plug = &pb->getPlugin(j);
const APICache::PluginAPICacheI &api = plug->getApiHandler();
api.loadFromPlugin(plug);
}
} else {
#ifdef CACHE_DEBUG
printf("found cached binary %s\n", binpath.c_str());
#endif
}
// insert final path (universal or not) in the list of found files
foundBinFiles.insert(binpath);
} else {
if (isdir && (recurse && name[0] != '@' && name != "." && name != "..")) {
scanDirectory(foundBinFiles, dir + DIRSEP + name, recurse);
}
}
#if defined(WINDOWS)
int rval = FindNextFile(findHandle, &findData);
if (rval == 0) {
break;
}
#endif
}
#if defined(UNIX)
closedir(d);
#else
FindClose(findHandle);
#endif
}
std::string PluginCache::seekPluginFile(const std::string &baseName) const {
// Exit early if disabled
if (!_enablePluginSeek)
return "";
for (std::list<std::string>::const_iterator paths= _pluginDirs.begin();
paths != _pluginDirs.end();
paths++) {
std::string candidate = *paths + DIRSEP + baseName;
FILE *f = fopen(candidate.c_str(), "r");
if (f) {
fclose(f);
return candidate;
}
}
return "";
}
void PluginCache::scanPluginFiles()
{
std::set<std::string> foundBinFiles;
for (std::list<std::string>::iterator paths= _pluginPath.begin();
paths != _pluginPath.end();
paths++) {
scanDirectory(foundBinFiles, *paths, _nonrecursePath.find(*paths) == _nonrecursePath.end());
}
std::list<PluginBinary *>::iterator i=_binaries.begin();
while (i!=_binaries.end()) {
PluginBinary *pb = *i;
if (foundBinFiles.find(pb->getFilePath()) == foundBinFiles.end()) {
// the binary was in the cache, but was not on the path
_dirty = true;
i = _binaries.erase(i);
delete pb;
} else {
bool binChanged = pb->hasBinaryChanged();
// the binary was in the cache, but the binary has changed and thus we need to reload
if (binChanged) {
pb->loadPluginInfo(this);
_dirty = true;
}
for (int j=0;j<pb->getNPlugins();j++) {
Plugin *plug = &pb->getPlugin(j);
APICache::PluginAPICacheI &api = plug->getApiHandler();
if (binChanged) {
api.loadFromPlugin(plug);
}
std::string reason;
if (api.pluginSupported(plug, reason)) {
_plugins.push_back(plug);
api.confirmPlugin(plug);
} else {
std::cerr << "ignoring plugin " << plug->getIdentifier() <<
" as unsupported (" << reason << ")" << std::endl;
}
}
i++;
}
}
}
/// callback for XML parser
static void elementBeginHandler(void *userData, const XML_Char *name, const XML_Char **atts) {
PluginCache::getPluginCache()->elementBeginCallback(userData, name, atts);
}
/// callback for XML parser
static void elementCharHandler(void *userData, const XML_Char *data, int len) {
PluginCache::getPluginCache()->elementCharCallback(userData, data, len);
}
/// callback for XML parser
static void elementEndHandler(void *userData, const XML_Char *name) {
PluginCache::getPluginCache()->elementEndCallback(userData, name);
}
static bool mapHasAll(const std::map<std::string, std::string> &attmap, const char **atts) {
while (*atts) {
if (attmap.find(*atts) == attmap.end()) {
return false;
}
atts++;
}
return true;
}
void PluginCache::elementBeginCallback(void */*userData*/, const XML_Char *name, const XML_Char **atts) {
if (_ignoreCache) {
return;
}
std::string ename = name;
std::map<std::string, std::string> attmap;
while (*atts) {
attmap[atts[0]] = atts[1];
atts += 2;
}
/// XXX: validate in general
if (ename == "cache") {
std::string cacheversion = attmap["version"];
if (cacheversion != _cacheVersion) {
#ifdef CACHE_DEBUG
printf("mismatched version, ignoring cache (got '%s', wanted '%s')\n",
cacheversion.c_str(),
_cacheVersion.c_str());
#endif
_ignoreCache = true;
}
}
if (ename == "binary") {
const char *binAtts[] = {"path", "bundle_path", "mtime", "size", NULL};
if (!mapHasAll(attmap, binAtts)) {
// no path: bad XML
}
std::string fname = attmap["path"];
std::string bname = attmap["bundle_path"];
time_t mtime = OFX::Host::Property::stringToInt(attmap["mtime"]);
size_t size = OFX::Host::Property::stringToInt(attmap["size"]);
_xmlCurrentBinary = new PluginBinary(fname, bname, mtime, size);
_binaries.push_back(_xmlCurrentBinary);
_knownBinFiles.insert(fname);
return;
}
if (ename == "plugin" && _xmlCurrentBinary && !_xmlCurrentBinary->hasBinaryChanged()) {
const char *plugAtts[] = {"api", "name", "index", "api_version", "major_version", "minor_version", NULL};
if (!mapHasAll(attmap, plugAtts)) {
// no path: bad XML
}
std::string api = attmap["api"];
std::string rawIdentifier = attmap["name"];
std::string identifier = rawIdentifier;
// Who says the pluginIdentifier is case-insensitive? OFX 1.3 spec doesn't mention this.
// http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#id472588
//for (size_t i=0;i<identifier.size();i++) {
// identifier[i] = tolower(identifier[i]);
//}
int idx = OFX::Host::Property::stringToInt(attmap["index"]);
int api_version = OFX::Host::Property::stringToInt(attmap["api_version"]);
int major_version = OFX::Host::Property::stringToInt(attmap["major_version"]);
int minor_version = OFX::Host::Property::stringToInt(attmap["minor_version"]);
APICache::PluginAPICacheI *apiCache = findApiHandler(api, api_version);
if (apiCache) {
Plugin *pe = apiCache->newPlugin(_xmlCurrentBinary, idx, api, api_version, identifier, rawIdentifier, major_version, minor_version);
_xmlCurrentBinary->addPlugin(pe);
_xmlCurrentPlugin = pe;
apiCache->beginXmlParsing(pe);
}
return;
}
if (_xmlCurrentPlugin) {
APICache::PluginAPICacheI &api = _xmlCurrentPlugin->getApiHandler();
api.xmlElementBegin(name, attmap);
}
}
void PluginCache::elementCharCallback(void */*userData*/, const XML_Char *data, int size)
{
if (_ignoreCache) {
return;
}
std::string s(data, size);
if (_xmlCurrentPlugin) {
APICache::PluginAPICacheI &api = _xmlCurrentPlugin->getApiHandler();
api.xmlCharacterHandler(s);
} else {
/// XXX: we only want whitespace
}
}
void PluginCache::elementEndCallback(void */*userData*/, const XML_Char *name) {
if (_ignoreCache) {
return;
}
std::string ename = name;
/// XXX: validation?
if (ename == "plugin") {
if (_xmlCurrentPlugin) {
APICache::PluginAPICacheI &api = _xmlCurrentPlugin->getApiHandler();
api.endXmlParsing();
}
_xmlCurrentPlugin = 0;
return;
}
if (ename == "bundle") {
_xmlCurrentBinary = 0;
return;
}
if (_xmlCurrentPlugin) {
APICache::PluginAPICacheI &api = _xmlCurrentPlugin->getApiHandler();
api.xmlElementEnd(name);
}
}
void PluginCache::readCache(std::istream &ifs) {
XML_Parser xP = XML_ParserCreate(NULL);
XML_SetElementHandler(xP, elementBeginHandler, elementEndHandler);
XML_SetCharacterDataHandler(xP, elementCharHandler);
while (ifs.good()) {
char buf[1001] = {0};
ifs.read(buf, 1000);
if (buf[0] == 0) {
XML_Parse(xP, "", 0, XML_TRUE);
break;
}
int p = XML_Parse(xP, buf, int(strlen(buf)), XML_FALSE);
if (p == XML_STATUS_ERROR) {
std::cout << "xml error : " << XML_GetErrorCode(xP) << std::endl;
/// XXX: do something here
break;
}
}
XML_ParserFree(xP);
}
void PluginCache::writePluginCache(std::ostream &os) const {
#ifdef CACHE_DEBUG
printf("writing pluginCache with version = %s\n", _cacheVersion.c_str());
#endif
os << "<cache version=\"" << _cacheVersion << "\">\n";
for (std::list<PluginBinary *>::const_iterator i=_binaries.begin();i!=_binaries.end();i++) {
PluginBinary *b = *i;
os << "<bundle>\n";
os << " <binary "
<< XML::attribute("bundle_path", b->getBundlePath())
<< XML::attribute("path", b->getFilePath())
<< XML::attribute("mtime", int(b->getFileModificationTime()))
<< XML::attribute("size", int(b->getFileSize())) << "/>\n";
for (int j=0;j<b->getNPlugins();j++) {
Plugin *p = &b->getPlugin(j);
os << " <plugin "
<< XML::attribute("name", p->getRawIdentifier())
<< XML::attribute("index", p->getIndex())
<< XML::attribute("api", p->getPluginApi())
<< XML::attribute("api_version", p->getApiVersion())
<< XML::attribute("major_version", p->getVersionMajor())
<< XML::attribute("minor_version", p->getVersionMinor())
<< ">\n";
const APICache::PluginAPICacheI &api = p->getApiHandler();
os << " <apiproperties>\n";
api.saveXML(p, os);
os << " </apiproperties>\n";
os << " </plugin>\n";
}
os << "</bundle>\n";
}
os << "</cache>\n";
}
APICache::PluginAPICacheI *PluginCache::findApiHandler(const std::string &api, int version) {
std::list<PluginCacheSupportedApi>::iterator i = _apiHandlers.begin();
while (i != _apiHandlers.end()) {
if (i->matches(api, version)) {
return i->handler;
}
i++;
}
return 0;
}
File diff suppressed because it is too large Load Diff
+37
View File
@@ -0,0 +1,37 @@
#include "ofxCore.h"
#include "ofxhUtilities.h"
namespace OFX {
/// get me deepest bit depth
std::string FindDeepestBitDepth(const std::string &s1, const std::string &s2)
{
if(s1 == kOfxBitDepthNone) {
return s2;
}
else if(s1 == kOfxBitDepthByte) {
if(s2 == kOfxBitDepthShort || s2 == kOfxBitDepthFloat)
return s2;
return s1;
}
else if(s1 == kOfxBitDepthShort) {
if(s2 == kOfxBitDepthFloat)
return s2;
return s1;
}
else if(s1 == kOfxBitDepthHalf) {
if(s2 == kOfxBitDepthFloat)
return s2;
return s1;
}
else if(s1 == kOfxBitDepthFloat) {
return s1;
}
else {
return s2; // oooh this might be bad dad.
}
}
}
+8
View File
@@ -0,0 +1,8 @@
set(OFX_SUPPORT_HEADER_DIR "include")
file(GLOB_RECURSE OFX_SUPPORT_HEADER_FILES "${OFX_SUPPORT_HEADER_DIR}/*.h")
add_subdirectory(Library)
if(BUILD_EXAMPLE_PLUGINS)
add_subdirectory(Plugins)
add_subdirectory(PropTester)
endif()
+32
View File
@@ -0,0 +1,32 @@
Software License :
Copyright OpenFX and contributors to the OpenFX project.
SPDX-License-Identifier: BSD-3-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+57
View File
@@ -0,0 +1,57 @@
run tmpPlugin.bundle
where
l
q
run tmpPlugin.bundle
where
l
l
p myBundle
up
p myBundle
q
run blah.bundle
up
w
where
ls
w
down
down
up
l
p myBundle
q
break main
run blah
n
n
p myBundle
n
q
q
l
l
break 17
run
n
p bundleURL
n
p myBundle
n
where
p myBundle
up
w
l
p myBundle
q
break main
run
n
n
p myBundle
n
n
p nPluginsFunc
q
+16
View File
@@ -0,0 +1,16 @@
set(OFX_SUPPORT_LIBRARY_DIR ".")
file(GLOB_RECURSE OFX_SUPPORT_LIBRARY_FILES "${OFX_SUPPORT_LIBRARY_DIR}/*.cpp")
add_library(OfxSupport STATIC
${OFX_HEADER_FILES}
${OFX_SUPPORT_HEADER_FILES}
${OFX_SUPPORT_LIBRARY_FILES})
set_target_properties(OfxSupport PROPERTIES LINKER_LANGUAGE CXX)
if(NOT MSVC)
set_target_properties(OfxSupport PROPERTIES COMPILE_FLAGS "-fPIC")
endif()
target_include_directories(OfxSupport PUBLIC
${OFX_HEADER_DIR}
${OFX_SUPPORT_HEADER_DIR})
+128
View File
@@ -0,0 +1,128 @@
# Microsoft Developer Studio Project File - Name="ofxsupport" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=ofxsupport - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "ofxsupport.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ofxsupport.mak" CFG="ofxsupport - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ofxsupport - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "ofxsupport - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "ofxsupport - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "../include" /I "../../include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"ofxSupport.lib"
!ELSEIF "$(CFG)" == "ofxsupport - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../include" /I "../../include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"ofxSupport.lib"
!ENDIF
# Begin Target
# Name "ofxsupport - Win32 Release"
# Name "ofxsupport - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\ofxsCore.cpp
# End Source File
# Begin Source File
SOURCE=.\ofxsImageEffect.cpp
# End Source File
# Begin Source File
SOURCE=.\ofxsInteract.cpp
# End Source File
# Begin Source File
SOURCE=.\ofxsLog.cpp
# End Source File
# Begin Source File
SOURCE=.\ofxsMultiThread.cpp
# End Source File
# Begin Source File
SOURCE=.\ofxsParams.cpp
# End Source File
# Begin Source File
SOURCE=.\ofxsProperty.cpp
# End Source File
# Begin Source File
SOURCE=.\ofxsPropertyValidation.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\ofxsSupportPrivate.h
# End Source File
# End Group
# End Target
# End Project
+113
View File
@@ -0,0 +1,113 @@
#include "ofxsSupportPrivate.h"
#ifdef DEBUG
#include <iostream>
#if defined(__APPLE__) || defined(linux)
#include <execinfo.h>
#include <stdlib.h>
#endif
#endif
#include "ofxsMemory.h"
namespace OFX {
/** @brief Throws an @ref OFX::Exception depending on the status flag passed in */
void throwSuiteStatusException(OfxStatus stat)
{
switch (stat)
{
case kOfxStatOK :
case kOfxStatReplyYes :
case kOfxStatReplyNo :
case kOfxStatReplyDefault :
break;
case kOfxStatErrMemory :
throw std::bad_alloc();
default :
# ifdef DEBUG
std::cout << "Threw suite exception!" << std::endl;
# if defined(__APPLE__) || defined(linux)
void* callstack[128];
int i, frames = backtrace(callstack, 128);
char** strs = backtrace_symbols(callstack, frames);
for (i = 0; i < frames; ++i) {
std::cout << strs[i] << std::endl;
}
free(strs);
# endif
# endif
throw OFX::Exception::Suite(stat);
}
}
void throwHostMissingSuiteException(std::string name)
{
# ifdef DEBUG
std::cout << "Threw suite exception! Host missing '" << name << "' suite." << std::endl;
# if defined(__APPLE__) || defined(linux)
void* callstack[128];
int i, frames = backtrace(callstack, 128);
char** strs = backtrace_symbols(callstack, frames);
for (i = 0; i < frames; ++i) {
std::cout << strs[i] << std::endl;
}
free(strs);
# endif
# endif
throw OFX::Exception::Suite(kOfxStatErrUnsupported);
}
/** @brief maps status to a string */
const char* mapStatusToString(OfxStatus stat)
{
switch(stat)
{
case kOfxStatOK : return "kOfxStatOK";
case kOfxStatFailed : return "kOfxStatFailed";
case kOfxStatErrFatal : return "kOfxStatErrFatal";
case kOfxStatErrUnknown : return "kOfxStatErrUnknown";
case kOfxStatErrMissingHostFeature : return "kOfxStatErrMissingHostFeature";
case kOfxStatErrUnsupported : return "kOfxStatErrUnsupported";
case kOfxStatErrExists : return "kOfxStatErrExists";
case kOfxStatErrFormat : return "kOfxStatErrFormat";
case kOfxStatErrMemory : return "kOfxStatErrMemory";
case kOfxStatErrBadHandle : return "kOfxStatErrBadHandle";
case kOfxStatErrBadIndex : return "kOfxStatErrBadIndex";
case kOfxStatErrValue : return "kOfxStatErrValue";
case kOfxStatReplyYes : return "kOfxStatReplyYes";
case kOfxStatReplyNo : return "kOfxStatReplyNo";
case kOfxStatReplyDefault : return "kOfxStatReplyDefault";
case kOfxStatErrImageFormat : return "kOfxStatErrImageFormat";
}
return "UNKNOWN STATUS CODE";
}
/** @brief namespace for memory allocation that is done via wrapping the ofx memory suite */
namespace Memory {
/** @brief allocate n bytes, returns a pointer to it */
void *allocate(size_t nBytes, ImageEffect *effect)
{
void *data = 0;
OfxStatus stat = OFX::Private::gMemorySuite->memoryAlloc((void *)(effect ? effect->getHandle() : 0), nBytes, &data);
if(stat != kOfxStatOK)
throw std::bad_alloc();
return data;
}
/** @brief free n previously allocated memory */
void free(void *ptr) throw()
{
if(ptr)
// note we are ignore errors, this could be bad, but we don't throw on a destruction
OFX::Private::gMemorySuite->memoryFree(ptr);
}
};
}; // namespace OFX
File diff suppressed because it is too large Load Diff
+546
View File
@@ -0,0 +1,546 @@
/** @brief This file contains code that skins the ofx interact suite (for image effects) */
#include "ofxsSupportPrivate.h"
#include <algorithm> // for find
/** @brief The core 'OFX Support' namespace, used by plugin implementations. All code for these are defined in the common support libraries.
*/
namespace OFX {
/** @brief fetch a pixel scale out of the property set */
static OfxPointD getPixelScale(const PropertySet &props)
{
OfxPointD pixelScale;
pixelScale.x = props.propGetDouble(kOfxInteractPropPixelScale, 0);
pixelScale.y = props.propGetDouble(kOfxInteractPropPixelScale, 1);
return pixelScale;
}
/** @brief fetch a render scale out of the property set */
static OfxPointD getRenderScale(const PropertySet &props)
{
OfxPointD v;
v.x = props.propGetDouble(kOfxImageEffectPropRenderScale, 0);
v.y = props.propGetDouble(kOfxImageEffectPropRenderScale, 1);
return v;
}
/** @brief fetch a background colour out of the property set */
static OfxRGBColourD getBackgroundColour(const PropertySet &props)
{
OfxRGBColourD backGroundColour;
backGroundColour.r = props.propGetDouble(kOfxInteractPropBackgroundColour, 0);
backGroundColour.g = props.propGetDouble(kOfxInteractPropBackgroundColour, 1);
backGroundColour.b = props.propGetDouble(kOfxInteractPropBackgroundColour, 2);
return backGroundColour;
}
/** @brief retrieves the image effect pointer from the interact handle */
static ImageEffect *retrieveEffectFromInteractHandle(OfxInteractHandle handle)
{
// get the properties set on this handle
OfxPropertySetHandle propHandle;
OfxStatus stat = OFX::Private::gInteractSuite->interactGetPropertySet(handle, &propHandle);
throwSuiteStatusException(stat);
PropertySet interactProperties(propHandle);
// get the effect handle from this handle
OfxImageEffectHandle effectHandle = (OfxImageEffectHandle) interactProperties.propGetPointer(kOfxPropEffectInstance);
// get the effect properties
return OFX::Private::retrieveImageEffectPointer(effectHandle);
}
/** @brief ctor */
Interact::Interact(OfxInteractHandle handle)
: _interactHandle(handle)
, _effect(0)
{
// get the properties set on this handle
OfxPropertySetHandle propHandle;
OfxStatus stat = OFX::Private::gInteractSuite->interactGetPropertySet(handle, &propHandle);
throwSuiteStatusException(stat);
_interactProperties.propSetHandle(propHandle);
// set othe instance data on the property handle to point to this interact
_interactProperties.propSetPointer(kOfxPropInstanceData, (void *)this);
// get the effect handle from this handle
_effect = retrieveEffectFromInteractHandle(handle);
}
/** @brief ctor */
Interact::~Interact()
{
}
/** @brief The bitdepth of each component in the openGL frame buffer */
int
Interact::getBitDepth(void) const
{
return _interactProperties.propGetInt(kOfxInteractPropBitDepth);
}
/** @brief Does the openGL frame buffer have an alpha */
bool
Interact::hasAlpha(void) const
{
return _interactProperties.propGetInt(kOfxInteractPropHasAlpha) != 0;
}
/** @brief Returns the size of a real screen pixel under the interact's cannonical projection */
OfxPointD
Interact::getPixelScale(void) const
{
OfxPointD v;
v.x = _interactProperties.propGetDouble(kOfxInteractPropPixelScale, 0);
v.y = _interactProperties.propGetDouble(kOfxInteractPropPixelScale, 1);
return v;
}
/** @brief The suggested colour to draw a widget in an interact */
bool
Interact::getSuggestedColour(OfxRGBColourD &c) const
{
// OFX 1.2/1.3 specs say that the host should return kOfxStatReplyDefault if there is no suggested color
OfxStatus stat = OFX::Private::gPropSuite->propGetDouble(_interactProperties.propSetHandle(), kOfxInteractPropSuggestedColour, 0, &c.r);
if (stat != kOfxStatOK) {
return false; // host gave no suggestion (replied kOfxStatReplyDefault or property is unknown to host)
}
stat = OFX::Private::gPropSuite->propGetDouble(_interactProperties.propSetHandle(), kOfxInteractPropSuggestedColour, 1, &c.g);
if (stat != kOfxStatOK) {
return false; // host gave no suggestion (replied kOfxStatReplyDefault or property is unknown to host)
}
stat = OFX::Private::gPropSuite->propGetDouble(_interactProperties.propSetHandle(), kOfxInteractPropSuggestedColour, 2, &c.b);
if (stat != kOfxStatOK) {
return false; // host gave no suggestion (replied kOfxStatReplyDefault or property is unknown to host)
}
return true;
}
/** @brief Request a redraw */
void
Interact::requestRedraw(void) const
{
OfxStatus stat = OFX::Private::gInteractSuite->interactRedraw(_interactHandle);
throwSuiteStatusException(stat);
}
/** @brief Swap a buffer in the case of a double bufferred interact, this is possibly a silly one */
void
Interact::swapBuffers(void) const
{
OfxStatus stat = OFX::Private::gInteractSuite->interactSwapBuffers(_interactHandle);
throwSuiteStatusException(stat);
}
/** @brief Set a param that the interact should be redrawn on if its value changes */
void
Interact::addParamToSlaveTo(Param *p)
{
// do we have it already ?
std::list<Param *>::iterator i;
i = std::find(_slaveParams.begin(), _slaveParams.end(), p);
if(i == _slaveParams.end()) {
// we have a new one to add in here
_slaveParams.push_back(p);
// and set the property
int n = _interactProperties.propGetDimension(kOfxInteractPropSlaveToParam);
_interactProperties.propSetString(kOfxInteractPropSlaveToParam, p->getName(), n);
}
}
/** @brief Remova a param that the interact should be redrawn on if its value changes */
void
Interact::removeParamToSlaveTo(Param *p)
{
// do we have it already ?
std::list<Param *>::iterator i;
i = std::find(_slaveParams.begin(), _slaveParams.end(), p);
if(i != _slaveParams.end()) {
// clobber it from the list
_slaveParams.erase(i);
// reset the property to remove our dead one
_interactProperties.propReset(kOfxInteractPropSlaveToParam);
// and add them all in again
int n = 0;
for(i = _slaveParams.begin(); i != _slaveParams.end(); ++i, ++n) {
_interactProperties.propSetString(kOfxInteractPropSlaveToParam, (*i)->getName(), n);
}
}
}
/** @brief the background colour */
OfxRGBColourD Interact::getBackgroundColour(void) const
{
return OFX::getBackgroundColour(_interactProperties);
}
/** @brief the function called to draw in the interact */
bool
Interact::draw(const DrawArgs &/*args*/)
{
return false;
}
/** @brief the function called to handle pen motion in the interact
returns true if the interact trapped the action in some sense. This will block the action being passed to
any other interact that may share the viewer.
*/
bool
Interact::penMotion(const PenArgs &/*args*/)
{
return false;
}
/** @brief the function called to handle pen down events in the interact
returns true if the interact trapped the action in some sense. This will block the action being passed to
any other interact that may share the viewer.
*/
bool
Interact::penDown(const PenArgs &/*args*/)
{
return false;
}
/** @brief the function called to handle pen up events in the interact
returns true if the interact trapped the action in some sense. This will block the action being passed to
any other interact that may share the viewer.
*/
bool
Interact::penUp(const PenArgs &/*args*/)
{
return false;
}
/** @brief the function called to handle key down events in the interact
returns true if the interact trapped the action in some sense. This will block the action being passed to
any other interact that may share the viewer.
*/
bool
Interact::keyDown(const KeyArgs &/*args*/)
{
return false;
}
/** @brief the function called to handle key up events in the interact
returns true if the interact trapped the action in some sense. This will block the action being passed to
any other interact that may share the viewer.
*/
bool
Interact::keyUp(const KeyArgs &/*args*/)
{
return false;
}
/** @brief the function called to handle key down repeat events in the interact
returns true if the interact trapped the action in some sense. This will block the action being passed to
any other interact that may share the viewer.
*/
bool
Interact::keyRepeat(const KeyArgs &/*args*/)
{
return false;
}
/** @brief Called when the interact is given input focus */
void
Interact::gainFocus(const FocusArgs &/*args*/)
{
}
/** @brief Called when the interact is loses input focus */
void
Interact::loseFocus(const FocusArgs &/*args*/)
{
}
////////////////////////////////////////////////////////////////////////////////
// overlay interact guff
/** @brief ctor */
OverlayInteract::OverlayInteract(OfxInteractHandle handle)
: Interact(handle)
{
// add this interact into the list of overlays that the effect knows about
if(_effect)
_effect->addOverlayInteract(this);
}
/** @brief ctor */
OverlayInteract::~OverlayInteract()
{
// add this interact into the list of overlays that the effect knows about
if(_effect)
_effect->removeOverlayInteract(this);
}
////////////////////////////////////////////////////////////////////////////////
/** @brief ctor */
InteractArgs::InteractArgs(const PropertySet &props)
{
time = props.propGetDouble(kOfxPropTime);
renderScale = getRenderScale(props);
}
/** @brief ctor */
DrawArgs::DrawArgs(const PropertySet &props)
: InteractArgs(props)
{
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
viewportSize.x = props.propGetDouble(kOfxInteractPropViewportSize, 0, false);
viewportSize.y = props.propGetDouble(kOfxInteractPropViewportSize, 1, false);
#endif
backGroundColour = getBackgroundColour(props);
pixelScale = getPixelScale(props);
}
/** @brief ctor */
PenArgs::PenArgs(const PropertySet &props)
: InteractArgs(props)
{
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
viewportSize.x = props.propGetDouble(kOfxInteractPropViewportSize, 0, false);
viewportSize.y = props.propGetDouble(kOfxInteractPropViewportSize, 1, false);
#endif
pixelScale = getPixelScale(props);
backGroundColour = getBackgroundColour(props);
penPosition.x = props.propGetDouble(kOfxInteractPropPenPosition, 0);
penPosition.y = props.propGetDouble(kOfxInteractPropPenPosition, 1);
try {
penViewportPosition.x = props.propGetInt(kOfxInteractPropPenViewportPosition, 0);
penViewportPosition.y = props.propGetInt(kOfxInteractPropPenViewportPosition, 1);
} catch (OFX::Exception::PropertyUnknownToHost&) {
// Introduced in OFX 1.2. Return (-1,-1) if not available
penViewportPosition.x = penViewportPosition.y = -1.;
}
penPressure = props.propGetDouble(kOfxInteractPropPenPressure);
}
/** @brief ctor */
KeyArgs::KeyArgs(const PropertySet &props)
: InteractArgs(props)
{
time = props.propGetDouble(kOfxPropTime);
renderScale = getRenderScale(props);
keyString = props.propGetString(kOfxPropKeyString);
keySymbol = props.propGetInt(kOfxPropKeySym);
}
/** @brief ctor */
FocusArgs::FocusArgs(const PropertySet &props)
: InteractArgs(props)
{
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
viewportSize.x = props.propGetDouble(kOfxInteractPropViewportSize, 0, false);
viewportSize.y = props.propGetDouble(kOfxInteractPropViewportSize, 1, false);
#endif
pixelScale = getPixelScale(props);
backGroundColour = getBackgroundColour(props);
}
void ParamInteractDescriptor::setInteractSizeAspect(double asp)
{
_props->propSetDouble(kOfxParamPropInteractSizeAspect , asp);
}
void ParamInteractDescriptor::setInteractMinimumSize(int x, int y)
{
_props->propSetInt(kOfxParamPropInteractMinimumSize, x, 0);
_props->propSetInt(kOfxParamPropInteractMinimumSize, y, 1);
}
void ParamInteractDescriptor::setInteractPreferredSize(int x, int y)
{
_props->propSetInt(kOfxParamPropInteractPreferedSize, x, 0);
_props->propSetInt(kOfxParamPropInteractPreferedSize, y, 1);
}
ParamInteract::ParamInteract(OfxInteractHandle handle, ImageEffect* effect):Interact(handle), _effect(effect)
{}
OfxPointI ParamInteract::getInteractSize() const
{
OfxPointI ret;
ret.x = _interactProperties.propGetInt(kOfxParamPropInteractSize, 0);
ret.y = _interactProperties.propGetInt(kOfxParamPropInteractSize, 1);
return ret;
}
namespace Private {
/** @brief fetches our pointer out of the props on the handle */
static
Interact *retrieveInteractPointer(OfxInteractHandle handle)
{
Interact *instance;
// get the prop set on the handle
OfxPropertySetHandle propHandle;
OfxStatus stat = OFX::Private::gInteractSuite->interactGetPropertySet(handle, &propHandle);
throwSuiteStatusException(stat);
// make our wrapper object
PropertySet props(propHandle);
// fetch the instance data out of the properties
instance = (Interact *) props.propGetPointer(kOfxPropInstanceData);
OFX::Log::error(instance == 0, "Instance data handle in effect instance properties is NULL!");
// need to throw something here
// and dance to the music
return instance;
}
/** @brief The common entry point used by all interacts */
static
OfxStatus
interactMainEntry(const std::string &action,
OfxInteractHandle handle,
PropertySet inArgs,
PropertySet /*outArgs*/)
{
OfxStatus stat = kOfxStatReplyDefault;
// get the interact pointer
Interact *interact = retrieveInteractPointer(handle);
// if one was not made, return and do nothing
if(!interact)
return stat;
if(action == kOfxActionDestroyInstance) {
delete interact;
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionDraw) {
// make the draw args
DrawArgs drawArgs(inArgs);
if(interact->draw(drawArgs))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionPenMotion) {
// make the draw args
PenArgs args(inArgs);
if(interact->penMotion(args))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionPenDown) {
// make the draw args
PenArgs args(inArgs);
if(interact->penDown(args))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionPenUp) {
// make the draw args
PenArgs args(inArgs);
if(interact->penUp(args))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionKeyDown) {
// make the draw args
KeyArgs args(inArgs);
if(interact->keyDown(args))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionKeyUp) {
// make the draw args
KeyArgs args(inArgs);
if(interact->keyUp(args))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionKeyRepeat) {
// make the draw args
KeyArgs args(inArgs);
if(interact->keyRepeat(args))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionGainFocus) {
// make the draw args
FocusArgs args(inArgs);
interact->gainFocus(args);
}
else if(action == kOfxInteractActionLoseFocus) {
// make the draw args
FocusArgs args(inArgs);
interact->loseFocus(args);
}
return stat;
}
/** @brief The main entry for image effect overlays */
OfxStatus interactMainEntry(const char *actionRaw,
const void *handleRaw,
OfxPropertySetHandle inArgsRaw,
OfxPropertySetHandle outArgsRaw,
InteractDescriptor& desc)
{
OFX::Log::print("********************************************************************************");
OFX::Log::print("START overlayInteractMainEntry (%s)", actionRaw);
OFX::Log::indent();
OfxStatus stat = kOfxStatReplyDefault;
try {
// Cast the raw handle to be an image effect handle, because that is what it is
OfxInteractHandle handle = (OfxInteractHandle) handleRaw;
// Turn the arguments into wrapper objects to make our lives easier
OFX::PropertySet inArgs(inArgsRaw);
OFX::PropertySet outArgs(outArgsRaw);
// turn the action into a std::string
std::string action(actionRaw);
// figure the actions
if (action == kOfxActionDescribe) {
OfxPropertySetHandle propHandle;
OfxStatus stat = OFX::Private::gInteractSuite->interactGetPropertySet(handle, &propHandle);
throwSuiteStatusException(stat);
PropertySet interactProperties(propHandle);
desc.setPropertySet(&interactProperties);
desc.describe();
}
else if (action == kOfxActionCreateInstance)
{
// fetch the image effect we are being made for out of the interact's property handle
ImageEffect *effect = retrieveEffectFromInteractHandle(handle);
OFX::Interact* interact = desc.createInstance(handle, effect);
(void)interact;
// and all was well
stat = kOfxStatOK;
}
else {
stat = interactMainEntry(action, handle, inArgs, outArgs);
}
}
catch(...)
{
stat = kOfxStatFailed;
}
OFX::Log::outdent();
OFX::Log::print("STOP overlayInteractMainEntry (%s)", actionRaw);
return stat;
}
}; // end namespace private
}; // end of namespace
+129
View File
@@ -0,0 +1,129 @@
/** @file This file contains the body of functions used for logging ofx problems etc...
The log file is written to using printf style functions, rather than via c++ iostreams.
*/
#include <cassert>
#include <cstdio>
#include <cstdarg>
#include <cstdlib>
#include <string>
#include "ofxsLog.h"
namespace OFX {
namespace Log {
/** @brief log file */
static FILE *gLogFP = 0;
/// environment variable for the log file
#define kLogFileEnvVar "OFX_PLUGIN_LOGFILE"
/** @brief the global logfile name */
static std::string gLogFileName(getenv(kLogFileEnvVar) ? getenv(kLogFileEnvVar) : "ofxPluginLog.txt");
/** @brief global indent level, not MP sane */
static int gIndent = 0;
/** @brief Sets the name of the log file. */
void setFileName(const std::string &value)
{
gLogFileName = value;
}
/** @brief Opens the log file, returns whether this was sucessful or not. */
bool open(void)
{
#ifdef DEBUG
if(!gLogFP) {
gLogFP = fopen(gLogFileName.c_str(), "a");
return gLogFP != 0;
}
#endif
return gLogFP != 0;
}
/** @brief Closes the log file. */
void close(void)
{
if(gLogFP) {
fclose(gLogFP);
}
gLogFP = 0;
}
/** @brief Indent it, not MP sane at the moment */
void indent(void)
{
++gIndent;
}
/** @brief Outdent it, not MP sane at the moment */
void outdent(void)
{
--gIndent;
}
/** @brief do the indenting */
static void doIndent(void)
{
if(open()) {
for(int i = 0; i < gIndent; i++) {
fputs(" ", gLogFP);
}
}
}
/** @brief Prints to the log file. */
void print(const char *format, ...)
{
if(open()) {
doIndent();
va_list args;
va_start(args, format);
vfprintf(gLogFP, format, args);
fputc('\n', gLogFP);
fflush(gLogFP);
va_end(args);
}
}
/** @brief Prints to the log file only if the condition is true and prepends a warning notice. */
void warning(bool condition, const char *format, ...)
{
if(condition && open()) {
doIndent();
fputs("WARNING : ", gLogFP);
va_list args;
va_start(args, format);
vfprintf(gLogFP, format, args);
fputc('\n', gLogFP);
va_end(args);
fflush(gLogFP);
}
}
/** @brief Prints to the log file only if the condition is true and prepends an error notice. */
void error(bool condition, const char *format, ...)
{
if(condition && open()) {
doIndent();
fputs("ERROR : ", gLogFP);
va_list args;
va_start(args, format);
vfprintf(gLogFP, format, args);
fputc('\n', gLogFP);
va_end(args);
fflush(gLogFP);
}
}
};
};
+128
View File
@@ -0,0 +1,128 @@
#include "ofxsSupportPrivate.h"
namespace OFX {
namespace MultiThread {
////////////////////////////////////////////////////////////////////////////////
// SMP class
/** @brief ctor */
Processor::Processor(void)
{
}
/** @brief dtor */
Processor::~Processor()
{
}
/** @brief Function to pass to the multi thread suite */
void Processor::staticMultiThreadFunction(unsigned int threadIndex, unsigned int threadMax, void *customArg)
{
// cast the custom arg to one of me
Processor *me = (Processor *) customArg;
// and call my thread function
me->multiThreadFunction(threadIndex, threadMax);
}
/** @brief Function to pass to the multi thread suite */
void Processor::multiThread(unsigned int nCPUs)
{
// if 0, use all the CPUs we can
if(nCPUs == 0)
nCPUs = OFX::MultiThread::getNumCPUs();
// if 1 cpu, don't bother with the threading
if(nCPUs == 1) {
multiThreadFunction(0, 1);
}
else {
// OK do it
OfxStatus stat = kOfxStatFailed;
if(OFX::Private::gThreadSuite){
stat = OFX::Private::gThreadSuite->multiThread(staticMultiThreadFunction, nCPUs, (void *)this);
}
// did we do it?
throwSuiteStatusException(stat);
}
}
////////////////////////////////////////////////////////////////////////////////
// futility functions
/** @brief Has the current thread been spawned from an MP */
bool isSpawnedThread(void)
{
if(OFX::Private::gThreadSuite){
int v = OFX::Private::gThreadSuite->multiThreadIsSpawnedThread();
return v != 0;
}else{
return false;
}
}
/** @brief The number of CPUs that can be used for MP-ing */
unsigned int getNumCPUs(void)
{
unsigned int n = 1;
OfxStatus stat = OFX::Private::gThreadSuite ? OFX::Private::gThreadSuite->multiThreadNumCPUs(&n) : kOfxStatFailed;
if(stat != kOfxStatOK) n = 1;
return n;
}
/** @brief The index of the current thread. From 0 to numCPUs() - 1 */
unsigned int getThreadIndex(void)
{
unsigned int n = 0;
OfxStatus stat = OFX::Private::gThreadSuite ? OFX::Private::gThreadSuite->multiThreadIndex(&n) : kOfxStatFailed;
if(stat != kOfxStatOK) n = 0;
return n;
}
////////////////////////////////////////////////////////////////////////////////
// MUTEX class
/** @brief ctor */
Mutex::Mutex(int lockCount)
: _handle(0)
{
OfxStatus stat = OFX::Private::gThreadSuite ? OFX::Private::gThreadSuite->mutexCreate(&_handle, lockCount) : kOfxStatReplyDefault;
throwSuiteStatusException(stat);
}
/** @brief dtor */
Mutex::~Mutex(void)
{
OfxStatus stat = OFX::Private::gThreadSuite ? OFX::Private::gThreadSuite->mutexDestroy(_handle) : kOfxStatReplyDefault;
(void)stat;
}
/** @brief lock it, blocks until lock is gained */
void Mutex::lock()
{
OfxStatus stat = OFX::Private::gThreadSuite ? OFX::Private::gThreadSuite->mutexLock(_handle) : kOfxStatReplyDefault;
throwSuiteStatusException(stat);
}
/** @brief unlock it */
void Mutex::unlock()
{
OfxStatus stat = OFX::Private::gThreadSuite ? OFX::Private::gThreadSuite->mutexUnLock(_handle) : kOfxStatReplyDefault;
throwSuiteStatusException(stat);
}
/** @brief attempt to lock, non-blocking */
bool Mutex::tryLock()
{
OfxStatus stat = OFX::Private::gThreadSuite ? OFX::Private::gThreadSuite->mutexTryLock(_handle) : kOfxStatReplyDefault;
return stat == kOfxStatOK;
}
};
};
File diff suppressed because it is too large Load Diff
+230
View File
@@ -0,0 +1,230 @@
#include "ofxsSupportPrivate.h"
using namespace OFX::Private;
namespace OFX {
static
void throwPropertyException(OfxStatus stat,
const std::string &propName)
{
switch (stat)
{
case kOfxStatOK :
case kOfxStatReplyYes :
case kOfxStatReplyNo :
case kOfxStatReplyDefault :
// Throw nothing!
break;
case kOfxStatErrUnknown :
case kOfxStatErrUnsupported : // unsupported implies unknow here
if(OFX::PropertySet::getThrowOnUnsupportedProperties()) // are we suppressing this?
throw OFX::Exception::PropertyUnknownToHost(propName.c_str());
break;
case kOfxStatErrMemory :
throw std::bad_alloc();
break;
case kOfxStatErrValue :
throw OFX::Exception::PropertyValueIllegalToHost(propName.c_str());
break;
case kOfxStatErrBadHandle :
case kOfxStatErrBadIndex :
default :
throwSuiteStatusException(stat);
break;
}
}
/** @brief are we logging property get/set */
int PropertySet::_gPropLogging = 1;
/** @brief Do we throw an exception if a host returns 'unsupported' when setting a property */
bool PropertySet::_gThrowOnUnsupported = true;
/** @brief Virtual destructor */
PropertySet::~PropertySet() {}
/** @brief, returns the dimension of the given property from this property set */
int PropertySet::propGetDimension(const char* property, bool throwOnFailure) const
{
assert(_propHandle != 0);
int dimension = 0;
OfxStatus stat = gPropSuite->propGetDimension(_propHandle, property, &dimension);
Log::error(stat != kOfxStatOK, "Failed on fetching dimension for property %s, host returned status %s.", property, mapStatusToString(stat));
if(throwOnFailure)
throwPropertyException(stat, property);
if(_gPropLogging > 0)
Log::print("Fetched dimension of property %s, returned %d.", property, dimension);
return dimension;
}
/** @brief, resets the property to it's default value */
void PropertySet::propReset(const char* property)
{
assert(_propHandle != 0);
OfxStatus stat = gPropSuite->propReset(_propHandle, property);
Log::error(stat != kOfxStatOK, "Failed on reseting property %s to its defaults, host returned status %s.", property, mapStatusToString(stat));
throwPropertyException(stat, property);
if(_gPropLogging > 0) Log::print("Reset property %s.", property);
}
/** @brief, Set a single dimension pointer property */
void PropertySet::propSetPointer(const char* property, void *value, int idx, bool throwOnFailure)
{
assert(_propHandle != 0);
OfxStatus stat = gPropSuite->propSetPointer(_propHandle, property, idx, value);
OFX::Log::error(stat != kOfxStatOK, "Failed on setting pointer property %s[%d] to %p, host returned status %s;",
property, idx, value, mapStatusToString(stat));
if(throwOnFailure)
throwPropertyException(stat, property);
if(_gPropLogging > 0) Log::print("Set pointer property %s[%d] to be %p.", property, idx, value);
}
/** @brief, Set a single dimension string property */
void PropertySet::propSetString(const char* property, const std::string &value, int idx, bool throwOnFailure)
{
assert(_propHandle != 0);
OfxStatus stat = gPropSuite->propSetString(_propHandle, property, idx, value.c_str());
OFX::Log::error(stat != kOfxStatOK, "Failed on setting string property %s[%d] to %s, host returned status %s;",
property, idx, value.c_str(), mapStatusToString(stat));
if(throwOnFailure)
throwPropertyException(stat, property);
if(_gPropLogging > 0) Log::print("Set string property %s[%d] to be %s.", property, idx, value.c_str());
}
/** @brief, Set a single dimension double property */
void PropertySet::propSetDouble(const char* property, double value, int idx, bool throwOnFailure)
{
assert(_propHandle != 0);
OfxStatus stat = gPropSuite->propSetDouble(_propHandle, property, idx, value);
OFX::Log::error(stat != kOfxStatOK, "Failed on setting double property %s[%d] to %lf, host returned status %s;",
property, idx, value, mapStatusToString(stat));
if(throwOnFailure)
throwPropertyException(stat, property);
if(_gPropLogging > 0) Log::print("Set double property %s[%d] to be %lf.", property, idx, value);
}
/** @brief, Set a single dimension int property */
void PropertySet::propSetInt(const char* property, int value, int idx, bool throwOnFailure)
{
assert(_propHandle != 0);
OfxStatus stat = gPropSuite->propSetInt(_propHandle, property, idx, value);
OFX::Log::error(stat != kOfxStatOK, "Failed on setting int property %s[%d] to %d, host returned status %s (%d);",
property, idx, value, mapStatusToString(stat), stat);
if(throwOnFailure)
throwPropertyException(stat, property);
if(_gPropLogging > 0) Log::print("Set int property %s[%d] to be %d.", property, idx, value);
}
/** @brief, Set a multiple dimension double property */
void PropertySet::propSetDoubleN(const char* property, const double* values, int count, bool throwOnFailure)
{
assert(_propHandle != 0);
OfxStatus stat = gPropSuite->propSetDoubleN(_propHandle, property, count, values);
OFX::Log::error(stat != kOfxStatOK, "Failed on setting double property %s[0..%d], host returned status %s;",
property, count-1, mapStatusToString(stat));
if(throwOnFailure)
throwPropertyException(stat, property);
if(_gPropLogging > 0) Log::print("Set double property %s[0..%d].", property, count-1);
}
/** @brief Get single pointer property */
void* PropertySet::propGetPointer(const char* property, int idx, bool throwOnFailure) const
{
assert(_propHandle != 0);
void *value = 0;
OfxStatus stat = gPropSuite->propGetPointer(_propHandle, property, idx, &value);
OFX::Log::error(stat != kOfxStatOK, "Failed on getting pointer property %s[%d], host returned status %s;",
property, idx, mapStatusToString(stat));
if(throwOnFailure)
throwPropertyException(stat, property);
if(_gPropLogging > 0) Log::print("Retrieved pointer property %s[%d], was given %p.", property, idx, value);
return value;
}
/** @brief Get single string property */
std::string PropertySet::propGetString(const char* property, int idx, bool throwOnFailure) const
{
assert(_propHandle != 0);
char *value = NULL;
OfxStatus stat = gPropSuite->propGetString(_propHandle, property, idx, &value);
OFX::Log::error(stat != kOfxStatOK, "Failed on getting string property %s[%d], host returned status %s;",
property, idx, mapStatusToString(stat));
if(throwOnFailure)
throwPropertyException(stat, property);
if(_gPropLogging > 0) Log::print("Retrieved string property %s[%d], was given %s.", property, idx, value);
return value != NULL ? std::string(value) : std::string();
}
/** @brief Get single double property */
double PropertySet::propGetDouble(const char* property, int idx, bool throwOnFailure) const
{
assert(_propHandle != 0);
double value = 0;
OfxStatus stat = gPropSuite->propGetDouble(_propHandle, property, idx, &value);
OFX::Log::error(stat != kOfxStatOK, "Failed on getting double property %s[%d], host returned status %s;",
property, idx, mapStatusToString(stat));
if(throwOnFailure)
throwPropertyException(stat, property);
if(_gPropLogging > 0) Log::print("Retrieved double property %s[%d], was given %lf.", property, idx, value);
return value;
}
/** @brief Get single int property */
int PropertySet::propGetInt(const char* property, int idx, bool throwOnFailure) const
{
assert(_propHandle != 0);
int value = 0;
OfxStatus stat = gPropSuite->propGetInt(_propHandle, property, idx, &value);
OFX::Log::error(stat != kOfxStatOK, "Failed on getting int property %s[%d], host returned status %s;",
property, idx, mapStatusToString(stat));
if(throwOnFailure)
throwPropertyException(stat, property);
if(_gPropLogging > 0) Log::print("Retrieved int property %s[%d], was given %d.", property, idx, value);
return value;
}
std::list<std::string> PropertySet::propGetNString(const char* property, bool throwOnFailure) const
{
assert(_propHandle != 0);
std::list<std::string> ret;
int dimension = propGetDimension(property,throwOnFailure);
if (dimension <= 0) {
return ret;
}
std::vector<char*> rawValue(dimension);
OfxStatus stat = gPropSuite->propGetStringN(_propHandle, property, dimension, rawValue.data());
OFX::Log::error(stat != kOfxStatOK, "Failed on getting string property %s, host returned status %s;",
property, mapStatusToString(stat));
if(throwOnFailure)
throwPropertyException(stat, property);
if(_gPropLogging > 0) Log::print("Retrieved string property %s, was given %s.", property,rawValue.data());
for (int i = 0; i < dimension; ++i) {
ret.push_back(std::string(rawValue[i]));
}
return ret;
}
};
File diff suppressed because it is too large Load Diff
+228
View File
@@ -0,0 +1,228 @@
#ifndef _ofxsSupportPrivate_H_
#define _ofxsSupportPrivate_H_
#include "ofxsInteract.h"
#include "ofxsImageEffect.h"
#include "ofxsLog.h"
#include "ofxsMultiThread.h"
/** @brief Namespace private to the ofx support library.
*/
namespace OFX {
namespace Private {
/** @brief Pointer to the host */
extern OfxHost *gHost;
/** @brief Pointer to the effect suite */
extern OfxImageEffectSuiteV1 *gEffectSuite;
/** @brief Pointer to the property suite */
extern OfxPropertySuiteV1 *gPropSuite;
/** @brief Pointer to the interact suite */
extern OfxInteractSuiteV1 *gInteractSuite;
/** @brief Pointer to the parameter suite */
extern OfxParameterSuiteV1 *gParamSuite;
/** @brief Pointer to the general memory suite */
extern OfxMemorySuiteV1 *gMemorySuite;
/** @brief Pointer to the threading suite */
extern OfxMultiThreadSuiteV1 *gThreadSuite;
/** @brief Pointer to the message suite */
extern OfxMessageSuiteV1 *gMessageSuite;
/** @brief Pointer to the optional message suite V2 */
extern OfxMessageSuiteV2 *gMessageSuiteV2;
/** @brief Pointer to the optional progress suite */
extern OfxProgressSuiteV1 *gProgressSuiteV1;
/** @brief Pointer to the optional progress suite */
extern OfxProgressSuiteV2 *gProgressSuiteV2;
/** @brief Pointer to the optional timeline suite */
extern OfxTimeLineSuiteV1 *gTimeLineSuite;
/** @brief Pointer to the parametric parameter suite */
extern OfxParametricParameterSuiteV1* gParametricParameterSuite;
/** @brief Support lib function called on an ofx load action */
void loadAction(void);
/** @brief Support lib function called on an ofx unload action */
void unloadAction(void);
/** @brief The plugin function that gets passed the host structure.
*/
void setHost(OfxHost *host);
/** @brief fetches our pointer out of the props on the handle */
ImageEffect *retrieveImageEffectPointer(OfxImageEffectHandle handle);
/** @brief fetch the prop set from the effect handle */
OFX::PropertySet
fetchEffectProps(OfxImageEffectHandle handle);
/** @brief the set of descriptors, one per context used by kOfxActionDescribeInContext, 'eContextNone' is the one used by the kOfxActionDescribe */
typedef std::map<ContextEnum, ImageEffectDescriptor*> EffectContextMap;
typedef std::map<std::string, EffectContextMap> EffectDescriptorMap;
extern EffectDescriptorMap gEffectDescriptors;
};
/** @brief The validation code has its own namespace */
namespace Validation {
/** @brief This is uses to hold a property value, used by the property checking classes.
Could have been a union, but std::string can't be in one.
*/
struct ValueHolder {
std::string vString;
int vInt;
double vDouble;
void *vPointer;
ValueHolder(void) : vString(), vInt(0), vDouble(0.), vPointer(0) {}
ValueHolder(char *s) : vString(s), vInt(0), vDouble(0.), vPointer(0) {}
ValueHolder(const std::string &s) : vString(s), vInt(0), vDouble(0.), vPointer(0) {}
ValueHolder(int i) : vString(), vInt(i), vDouble(0.), vPointer(0) {}
ValueHolder(double d) : vString(), vInt(0), vDouble(d), vPointer(0) {}
ValueHolder(void *p) : vString(), vInt(0), vDouble(0.), vPointer(p) {}
ValueHolder &operator = (char *v) {vString = v; return *this;}
ValueHolder &operator = (std::string v) {vString = v; return *this;}
ValueHolder &operator = (void *v) {vPointer = v; return *this;}
ValueHolder &operator = (int v) {vInt = v; return *this;}
ValueHolder &operator = (double v) {vDouble = v; return *this;}
operator const char * () {return vString.c_str();}
operator std::string &() {return vString;}
operator int &() {return vInt;}
operator double &() {return vDouble;}
operator void * &() {return vPointer;}
};
/** @brief Enum used in the varargs list of the PropertyDescription constructor */
enum DescriptionTag {
eDescDefault, /** @brief following values are the default to check against */
eDescFinished /** @brief we have finished the description */
};
/** @brief class to describe properties, check their default and set their values */
class PropertyDescription
{
public :
/** @brief name of the property */
const std::string _name;
/** @brief Was it validated */
bool _exists;
/** @brief dimension of the property */
int _dimension;
/** @brief What type of property is it */
OFX::PropertyTypeEnum _ilk;
/** @brief The default value that this property should have. Empty implies no default (eg: a host name has no default). */
std::vector<ValueHolder> _defaultValue;
public :
/** @brief var args constructor that is use to describe properties */
PropertyDescription(const char *name, OFX::PropertyTypeEnum ilk, int dimension, ...);
/** @brief Die! Die! Die! */
virtual ~PropertyDescription(void) {}
/** @brief See if the property exists in the containing property set and has the correct dimension */
void validate(bool checkDefaults, PropertySet &propSet);
};
/** @brief Describes a set of properties */
class PropertySetDescription {
protected :
/** @brief name of the property set */
const std::string _setName;
/** @brief the descriptions of each property */
std::vector<PropertyDescription *> _descriptions;
/** @brief The descriptions of each property */
std::vector<PropertyDescription *> _deleteThese;
public :
/** @brief constructor.
The varargs zero terminated are made from pairs of PropertyDescription * and ints indicating the number of properties pointed to.
These are to come from static arrays and need not be deleted
*/
PropertySetDescription(const char *setName, ...);// [PropertyDescription *v, int nSetToThese]
/** @brief destructor */
virtual ~PropertySetDescription();
/** @brief add another property in */
void addProperty(PropertyDescription *desc, bool deleteOnDestruction = true);
/** @brief See if all properties exist and have the correct dimensions */
void validate(PropertySet &propSet, bool checkDefaults = true, bool logOrdinaryMessages = false);
};
/** @brief Validates the host structure and property handle */
void
validateHostProperties(OfxHost *host);
/** @brief Validates the effect descriptor properties */
void
validatePluginDescriptorProperties(PropertySet props);
/** @brief Validates the effect instance properties */
void
validatePluginInstanceProperties(PropertySet props);
/** @brief validates a clip descriptor */
void
validateClipDescriptorProperties(PropertySet props);
/** @brief validates a clip instance */
void
validateClipInstanceProperties(PropertySet props);
/** @brief validates an image or texture instance */
void
validateImageBaseProperties(PropertySet props);
/** @brief validates an image instance */
void
validateImageProperties(PropertySet props);
#ifdef OFX_SUPPORTS_OPENGLRENDER
/** @brief validates an OpenGL texture descriptor */
void
validateTextureProperties(PropertySet props);
#endif
/** @brief Validates action in/out arguments */
void
validateActionArgumentsProperties(const std::string &action, PropertySet inArgs, PropertySet outArgs);
/** @brief Validates parameter properties */
void
validateParameterProperties(ParamTypeEnum paramType,
OFX::PropertySet paramProps,
bool checkDefaults);
/** @brief initialises the validation code, call this in on load */
void initialise(void);
};
};
#endif
+29
View File
@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "ofxsupport"=.\ofxsupport.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################
+695
View File
@@ -0,0 +1,695 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="ofxsupport"
ProjectGUID="{257EC9EE-530A-4A6F-8B2E-AAB1C8458707}"
RootNamespace="ofxsupport"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\$(ConfigurationName)-$(PlatformName)"
IntermediateDirectory=".\$(ConfigurationName)-$(PlatformName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../include,../../include"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="false"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
PrecompiledHeaderFile=".\$(ConfigurationName)-$(PlatformName)/ofxsupport.pch"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="2057"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\ofxSupport.lib"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/ofxsupport.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\$(ConfigurationName)-$(PlatformName)"
IntermediateDirectory=".\$(ConfigurationName)-$(PlatformName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="../include,../../include"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\$(ConfigurationName)-$(PlatformName)/ofxsupport.pch"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="2057"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\ofxSupport.lib"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/ofxsupport.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory=".\$(ConfigurationName)-$(PlatformName)"
IntermediateDirectory=".\$(ConfigurationName)-$(PlatformName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../include,../../include"
PreprocessorDefinitions="WIN64;_DEBUG;_LIB"
MinimalRebuild="false"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
PrecompiledHeaderFile=".\$(ConfigurationName)-$(PlatformName)/ofxsupport.pch"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="2057"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\ofxSupport.lib"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/ofxsupport.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory=".\$(ConfigurationName)-$(PlatformName)"
IntermediateDirectory=".\$(ConfigurationName)-$(PlatformName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="../include,../../include"
PreprocessorDefinitions="WIN64;NDEBUG;_LIB"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\$(ConfigurationName)-$(PlatformName)/ofxsupport.pch"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="2057"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\ofxSupport.lib"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/ofxsupport.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="ofxsCore.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="ofxsImageEffect.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="ofxsInteract.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="ofxsLog.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="ofxsMultiThread.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="ofxsParams.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="ofxsProperty.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="ofxsPropertyValidation.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath="..\include\ofxscore.h"
>
</File>
<File
RelativePath="..\include\ofxsImageEffect.h"
>
</File>
<File
RelativePath="..\include\ofxsInteract.h"
>
</File>
<File
RelativePath="..\include\ofxsLog.h"
>
</File>
<File
RelativePath="..\include\ofxsMemory.h"
>
</File>
<File
RelativePath="..\include\ofxsMessage.h"
>
</File>
<File
RelativePath="..\include\ofxsMultiThread.h"
>
</File>
<File
RelativePath="..\include\ofxsParam.h"
>
</File>
<File
RelativePath="ofxsSupportPrivate.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,74 @@
#include "ofxCore.h"
#include "CoreFoundation/CoreFoundation.h"
typedef OfxPlugin *(OfxGetPluginFunc)(int nth);
typedef int (OfxGetNumberOfPluginsFunc)(void);
int
main(int argc, char *argv[])
{
CFURLRef bundleURL;
CFBundleRef myBundle;
if (argc != 2) {
fprintf(stderr, "Usage: %s <plugin>\n", argv[0]);
exit(1);
}
CFStringRef bundlePath = CFStringCreateWithCString(kCFAllocatorDefault,
argv[1],
kCFStringEncodingASCII);
// Make a CFURLRef from the CFString representation of the
// bundle's path.
bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
bundlePath,
kCFURLPOSIXPathStyle,
true );
// Make a bundle instance using the URLRef.
myBundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
if(myBundle) {
// Value returned from the loaded function.
//long result;
OfxGetNumberOfPluginsFunc *nPluginsFunc = (OfxGetNumberOfPluginsFunc *)CFBundleGetFunctionPointerForName(myBundle, CFSTR("OfxGetNumberOfPlugins") );
OfxGetPluginFunc *getPlugin = (OfxGetPluginFunc *)CFBundleGetFunctionPointerForName(myBundle, CFSTR("OfxGetPlugin") );
// If the function was found, call it with a test value.
if (nPluginsFunc && getPlugin) {
// This should add 1 to whatever was passed in
int nP = nPluginsFunc();
printf("Sucessfully loaded '%s', containing %d %s\n", argv[1], nP, (nP == 1 ? "plugin" : "plugins"));
for(int i = 0; i < nP; i++) {
// get a plugin
OfxPlugin *plugin = getPlugin(i);
if(plugin) {
printf("\tFound plugin...\n\t\tAPI = %s (%d)\n\t\tid = %s (%d.%d)\n",
plugin->pluginApi, plugin->apiVersion,
plugin->pluginIdentifier, plugin->pluginVersionMajor, plugin->pluginVersionMinor);
plugin->mainEntry(kOfxActionLoad, NULL, NULL, NULL);
plugin->mainEntry(kOfxActionUnload, NULL, NULL, NULL);
}
else
fprintf(stderr, "fetching %dth plugin returned NULL\n", i);
}
}
else
fprintf(stderr, "Failed to find symbols OfxGetPlugin or OfxGetNumberOfPlugins\n");
}
else
fprintf(stderr, "Failed to load bundle %s\n", argv[1]);
// Any CF objects returned from functions with "create" or
// "copy" in their names must be released by us!
CFRelease( bundleURL );
}
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>basic.ofx</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.0.1d1</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
</plist>
+727
View File
@@ -0,0 +1,727 @@
#ifdef _WINDOWS
#include <windows.h>
#endif
#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
#include <stdio.h>
#include "ofxsImageEffect.h"
#include "ofxsMultiThread.h"
#include "../include/ofxsProcessing.H"
////////////////////////////////////////////////////////////////////////////////
// a dumb interact that just draw's a square you can drag
static const OfxPointD kBoxSize = {20, 20};
class BasicInteract : public OFX::OverlayInteract {
protected :
enum StateEnum {
eInActive,
ePoised,
ePicked
};
OfxPointD _position;
StateEnum _state;
public :
BasicInteract(OfxInteractHandle handle, OFX::ImageEffect* /*effect*/)
: OFX::OverlayInteract(handle)
, _state(eInActive)
{
_position.x = 0;
_position.y = 0;
}
// overridden functions from OFX::Interact to do things
virtual bool draw(const OFX::DrawArgs &args);
virtual bool penMotion(const OFX::PenArgs &args);
virtual bool penDown(const OFX::PenArgs &args);
virtual bool penUp(const OFX::PenArgs &args);
};
////////////////////////////////////////////////////////////////////////////////
// rendering routines
template <class T> inline T
Minimum(T a, T b) { return (a < b) ? a : b;}
template <class T> inline T
Absolute(T a) { return (a < 0) ? -a : a;}
template <class T> inline T
Clamp(T v, int min, int max)
{
if(v < T(min)) return T(min);
if(v > T(max)) return T(max);
return v;
}
// Base class for the RGBA and the Alpha processor
class ImageScalerBase : public OFX::ImageProcessor {
protected :
OFX::Image *_srcImg;
OFX::Image *_maskImg;
double _rScale, _gScale, _bScale, _aScale;
bool _doMasking;
public :
/** @brief no arg ctor */
ImageScalerBase(OFX::ImageEffect &instance)
: OFX::ImageProcessor(instance)
, _srcImg(0)
, _maskImg(0)
, _rScale(1)
, _gScale(1)
, _bScale(1)
, _aScale(1)
, _doMasking(false)
{
}
/** @brief set the src image */
void setSrcImg(OFX::Image *v) {_srcImg = v;}
/** @brief set the optional mask image */
void setMaskImg(OFX::Image *v) {_maskImg = v;}
// Are we masking. We can't derive this from the mask image being set as NULL is a valid value for an input image
void doMasking(bool v) {_doMasking = v;}
/** @brief set the scale */
void setScales(float r, float g, float b, float a)
{
_rScale = r;
_gScale = g;
_bScale = b;
_aScale = a;
}
};
// template to do the RGBA processing
template <class PIX, int nComponents, int max>
class ImageScaler : public ImageScalerBase {
public :
// ctor
ImageScaler(OFX::ImageEffect &instance)
: ImageScalerBase(instance)
{}
// and do some processing
void multiThreadProcessImages(OfxRectI procWindow)
{
float scales[4];
scales[0] = nComponents == 1 ? (float)_aScale : (float)_rScale;
scales[1] = (float)_gScale;
scales[2] = (float)_bScale;
scales[3] = (float)_aScale;
float maskScale = 1.0f;
for(int y = procWindow.y1; y < procWindow.y2; y++) {
if(_effect.abort()) break;
PIX *dstPix = (PIX *) _dstImg->getPixelAddress(procWindow.x1, y);
for(int x = procWindow.x1; x < procWindow.x2; x++) {
PIX *srcPix = (PIX *) (_srcImg ? _srcImg->getPixelAddress(x, y) : 0);
// are we doing masking
if(_doMasking) {
// we do, get the pixel from the mask
if(!_maskImg)
maskScale = 1.0f;
else
{
PIX *maskPix = (PIX *) (_maskImg ? _maskImg->getPixelAddress(x, y) : 0);
// figure the scale factor from that pixel
maskScale = maskPix != 0 ? float(*maskPix)/float(max) : 0.0f;
}
}
// do we have a source image to scale up
if(srcPix) {
for(int c = 0; c < nComponents; c++) {
float v;
// scale the component up by the scale factor, modulated by the maskScale
if(maskScale != 1.0f)
v = srcPix[c] * (1.0f + (scales[c] - 1.0f) * maskScale);
else
v = srcPix[c] * scales[c];
if(max == 1) // implies floating point and so no clamping
dstPix[c] = PIX(v);
else // integer based and we need to clamp
dstPix[c] = PIX(Clamp(v, 0, max));
}
}
else {
// no src pixel here, be black and transparent
for(int c = 0; c < nComponents; c++) {
dstPix[c] = 0;
}
}
// increment the dst pixel
dstPix += nComponents;
}
}
}
};
////////////////////////////////////////////////////////////////////////////////
/** @brief The plugin that does our work */
class BasicPlugin : public OFX::ImageEffect {
protected :
// do not need to delete these, the ImageEffect is managing them for us
OFX::Clip *dstClip_;
OFX::Clip *srcClip_;
OFX::Clip *maskClip_;
OFX::DoubleParam *scale_;
OFX::DoubleParam *rScale_;
OFX::DoubleParam *gScale_;
OFX::DoubleParam *bScale_;
OFX::DoubleParam *aScale_;
OFX::BooleanParam *componentScalesEnabled_;
public :
/** @brief ctor */
BasicPlugin(OfxImageEffectHandle handle)
: ImageEffect(handle)
, dstClip_(0)
, srcClip_(0)
, scale_(0)
, rScale_(0)
, gScale_(0)
, bScale_(0)
, aScale_(0)
, componentScalesEnabled_(0)
{
dstClip_ = fetchClip(kOfxImageEffectOutputClipName);
srcClip_ = fetchClip(kOfxImageEffectSimpleSourceClipName);
// name of mask clip depends on the context
maskClip_ = getContext() == OFX::eContextFilter ? NULL : fetchClip(getContext() == OFX::eContextPaint ? "Brush" : "Mask");
scale_ = fetchDoubleParam("scale");
rScale_ = fetchDoubleParam("scaleR");
gScale_ = fetchDoubleParam("scaleG");
bScale_ = fetchDoubleParam("scaleB");
aScale_ = fetchDoubleParam("scaleA");
componentScalesEnabled_ = fetchBooleanParam("scaleComponents");
// set the enabledness of our RGBA sliders
setEnabledness();
}
/* sets the enabledness of the component scale params depending on the type of input image and the state of the scaleComponents param */
void setEnabledness(void);
/* Override the render */
virtual void render(const OFX::RenderArguments &args);
/* override is identity */
virtual bool isIdentity(const OFX::IsIdentityArguments &args, OFX::Clip * &identityClip, double &identityTime);
/* override changedParam */
virtual void changedParam(const OFX::InstanceChangedArgs &args, const std::string &paramName);
/* override changed clip */
virtual void changedClip(const OFX::InstanceChangedArgs &args, const std::string &clipName);
// override the rod call
virtual bool getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod);
// override the roi call
virtual void getRegionsOfInterest(const OFX::RegionsOfInterestArguments &args, OFX::RegionOfInterestSetter &rois);
/* set up and run a processor */
void
setupAndProcess(ImageScalerBase &, const OFX::RenderArguments &args);
};
////////////////////////////////////////////////////////////////////////////////
/** @brief render for the filter */
////////////////////////////////////////////////////////////////////////////////
// basic plugin render function, just a skelington to instantiate templates from
/* set up and run a processor */
void
BasicPlugin::setupAndProcess(ImageScalerBase &processor, const OFX::RenderArguments &args)
{
// get a dst image
std::unique_ptr<OFX::Image> dst(dstClip_->fetchImage(args.time));
OFX::BitDepthEnum dstBitDepth = dst->getPixelDepth();
OFX::PixelComponentEnum dstComponents = dst->getPixelComponents();
// fetch main input image
std::unique_ptr<OFX::Image> src(srcClip_->fetchImage(args.time));
// make sure bit depths are sane
if(src.get()) {
OFX::BitDepthEnum srcBitDepth = src->getPixelDepth();
OFX::PixelComponentEnum srcComponents = src->getPixelComponents();
// see if they have the same depths and bytes and all
if(srcBitDepth != dstBitDepth || srcComponents != dstComponents)
throw int(1); // HACK!! need to throw an sensible exception here!
}
std::unique_ptr<OFX::Image> mask;
// do we do masking
if(getContext() != OFX::eContextFilter) {
mask.reset(maskClip_->fetchImage(args.time));
// say we are masking
processor.doMasking(true);
// Set it in the processor
processor.setMaskImg(mask.get());
}
// get the scale parameter values...
double r, g, b, a = aScale_->getValueAtTime(args.time);
r = g = b = scale_->getValueAtTime(args.time);
// see if the individual component scales are enabled
if(componentScalesEnabled_->getValueAtTime(args.time)) {
r *= rScale_->getValueAtTime(args.time);
g *= gScale_->getValueAtTime(args.time);
b *= bScale_->getValueAtTime(args.time);
}
// set the images
processor.setDstImg(dst.get());
processor.setSrcImg(src.get());
// set the render window
processor.setRenderWindow(args.renderWindow);
// set the scales
processor.setScales((float)r, (float)g, (float)b, (float)a);
// Call the base class process member, this will call the derived templated process code
processor.process();
}
// override the rod call
bool
BasicPlugin::getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod)
{
// our RoD is the same as the 'Source' clip's, we are not interested in the mask
rod = srcClip_->getRegionOfDefinition(args.time);
// say we set it
return true;
}
// override the roi call
void
BasicPlugin::getRegionsOfInterest(const OFX::RegionsOfInterestArguments &args, OFX::RegionOfInterestSetter &rois)
{
// we don't actually need to do this as this is the default, but do it for examples sake
rois.setRegionOfInterest(*srcClip_, args.regionOfInterest);
// set it on the mask only if we are in an interesting context
if(getContext() != OFX::eContextFilter)
rois.setRegionOfInterest(*maskClip_, args.regionOfInterest);
}
// the overridden render function
void
BasicPlugin::render(const OFX::RenderArguments &args)
{
// instantiate the render code based on the pixel depth of the dst clip
OFX::BitDepthEnum dstBitDepth = dstClip_->getPixelDepth();
OFX::PixelComponentEnum dstComponents = dstClip_->getPixelComponents();
// do the rendering
if(dstComponents == OFX::ePixelComponentRGBA) {
switch(dstBitDepth) {
case OFX::eBitDepthUByte : {
ImageScaler<unsigned char, 4, 255> fred(*this);
setupAndProcess(fred, args);
}
break;
case OFX::eBitDepthUShort : {
ImageScaler<unsigned short, 4, 65535> fred(*this);
setupAndProcess(fred, args);
}
break;
case OFX::eBitDepthFloat : {
ImageScaler<float, 4, 1> fred(*this);
setupAndProcess(fred, args);
}
break;
default :
OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
}
}
else {
switch(dstBitDepth) {
case OFX::eBitDepthUByte : {
ImageScaler<unsigned char, 1, 255> fred(*this);
setupAndProcess(fred, args);
}
break;
case OFX::eBitDepthUShort : {
ImageScaler<unsigned short, 1, 65535> fred(*this);
setupAndProcess(fred, args);
}
break;
case OFX::eBitDepthFloat : {
ImageScaler<float, 1, 1> fred(*this);
setupAndProcess(fred, args);
}
break;
default :
OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
}
}
}
// overridden is identity
bool
BasicPlugin:: isIdentity(const OFX::IsIdentityArguments &args, OFX::Clip * &identityClip, double &identityTime)
{
// get the scale parameters
double scale = scale_->getValueAtTime(args.time);
double rScale = 1, gScale = 1, bScale = 1, aScale = 1;
if(componentScalesEnabled_->getValueAtTime(args.time)) {
rScale = rScale_->getValueAtTime(args.time);
gScale = gScale_->getValueAtTime(args.time);
bScale = bScale_->getValueAtTime(args.time);
aScale = aScale_->getValueAtTime(args.time);
}
rScale *= scale; gScale *= scale; bScale *= scale;
// do we do any scaling ?
if(rScale == 1 && gScale == 1 && bScale == 1 && aScale == 1) {
identityClip = srcClip_;
identityTime = args.time;
return true;
}
// nope, idenity we is
return false;
}
// set the enabledness of the individual component scales
void
BasicPlugin::setEnabledness(void)
{
// the componet enabledness depends on the clip being RGBA and the param being true
bool v = componentScalesEnabled_->getValue() && srcClip_->getPixelComponents() == OFX::ePixelComponentRGBA;
// enable them
rScale_->setEnabled(v);
gScale_->setEnabled(v);
bScale_->setEnabled(v);
aScale_->setEnabled(v);
}
// we have changed a param
void
BasicPlugin::changedParam(const OFX::InstanceChangedArgs &/*args*/, const std::string &paramName)
{
if(paramName == "scaleComponents") setEnabledness();
}
// we have changed a param
void
BasicPlugin::changedClip(const OFX::InstanceChangedArgs &/*args*/, const std::string &clipName)
{
if(clipName == kOfxImageEffectSimpleSourceClipName) setEnabledness();
}
////////////////////////////////////////////////////////////////////////////////
// stuff for the interact
// draw the interact
bool BasicInteract::draw(const OFX::DrawArgs &args)
{
OfxRGBColourF col;
switch(_state)
{
case eInActive : col.r = col.g = col.b = 0.0f; break;
case ePoised : col.r = col.g = col.b = 0.5f; break;
case ePicked : col.r = col.g = col.b = 1.0f; break;
}
// make the box a constant size on screen by scaling by the pixel scale
float dx = (float)(kBoxSize.x * args.pixelScale.x);
float dy = (float)(kBoxSize.y * args.pixelScale.y);
// Draw a cross hair, the current coordinate system aligns with the image plane.
glPushMatrix();
// draw the bo
glColor3f(col.r, col.g, col.b);
glTranslated(_position.x, _position.y, 0);
glBegin(GL_POLYGON);
glVertex2f(-dx, -dy);
glVertex2f(-dx, dy);
glVertex2f( dx, dy);
glVertex2f( dx, -dy);
glEnd();
glPopMatrix();
glPushMatrix();
// draw a complementary outline
glColor3f(1.0f - col.r, 1.0f - col.g, 1.0f - col.b);
glTranslated(_position.x, _position.y, 0);
glBegin(GL_LINE_LOOP);
glVertex2f(-dx, -dy);
glVertex2f(-dx, dy);
glVertex2f( dx, dy);
glVertex2f( dx, -dy);
glEnd();
glPopMatrix();
return true;
}
// overridden functions from OFX::Interact to do things
bool
BasicInteract::penMotion(const OFX::PenArgs &args)
{
// figure the size of the box in cannonical coords
float dx = (float)(kBoxSize.x * args.pixelScale.x);
float dy = (float)(kBoxSize.y * args.pixelScale.y);
// pen position is in cannonical coords
OfxPointD penPos = args.penPosition;
switch(_state) {
case eInActive :
case ePoised :
{
// are we in the box, become 'poised'
StateEnum newState;
penPos.x -= _position.x;
penPos.y -= _position.y;
if(Absolute(penPos.x) < dx &&
Absolute(penPos.y) < dy) {
newState = ePoised;
}
else {
newState = eInActive;
}
if(_state != newState) {
// we have a new state
_state = newState;
// and force an overlay redraw
_effect->redrawOverlays();
}
}
break;
case ePicked :
{
// move our position
_position = penPos;
// and force an overlay redraw
_effect->redrawOverlays();
}
break;
}
// we have trapped it only if the mouse ain't over it or we are actively dragging
return _state != eInActive;
}
bool
BasicInteract::penDown(const OFX::PenArgs &args)
{
// this will refigure the state
penMotion(args);
// if poised means we were over it when the pen went down, so pick it
if(_state == ePoised) {
// we are now picked
_state = ePicked;
// move our position
_position = args.penPosition;
// and request a redraw just incase
_effect->redrawOverlays();
}
return _state == ePicked;
}
bool
BasicInteract::penUp(const OFX::PenArgs &args)
{
if(_state == ePicked) {
// reset to poised for a moment
_state = ePoised;
// this will refigure the state
penMotion(args);
// and redraw for good measure
_effect->redrawOverlays();
// we did trap it
return true;
}
// we didn't trap it
return false;
}
using namespace OFX;
mDeclarePluginFactory(BasicExamplePluginFactory, {}, {});
class BasicExampleOverlayDescriptor : public DefaultEffectOverlayDescriptor<BasicExampleOverlayDescriptor, BasicInteract> {};
void BasicExamplePluginFactory::describe(OFX::ImageEffectDescriptor& desc)
{
// basic labels
desc.setLabels("Gain", "Gain", "Gain");
desc.setPluginGrouping("OFX Example (Support)");
// add the supported contexts, only filter at the moment
desc.addSupportedContext(eContextFilter);
desc.addSupportedContext(eContextGeneral);
desc.addSupportedContext(eContextPaint);
// add supported pixel depths
desc.addSupportedBitDepth(eBitDepthUByte);
desc.addSupportedBitDepth(eBitDepthUShort);
desc.addSupportedBitDepth(eBitDepthFloat);
// set a few flags
desc.setSingleInstance(false);
desc.setHostFrameThreading(false);
desc.setSupportsMultiResolution(true);
desc.setSupportsTiles(true);
desc.setTemporalClipAccess(false);
desc.setRenderTwiceAlways(false);
desc.setSupportsMultipleClipPARs(false);
desc.setOverlayInteractDescriptor( new BasicExampleOverlayDescriptor);
}
// make a double scale param
static
DoubleParamDescriptor *defineScaleParam(OFX::ImageEffectDescriptor &desc,
const std::string &name, const std::string &label, const std::string &hint,
GroupParamDescriptor *parent)
{
DoubleParamDescriptor *param = desc.defineDoubleParam(name);
param->setLabels(label, label, label);
param->setScriptName(name);
param->setHint(hint);
param->setDefault(1);
param->setRange(0, 10);
param->setIncrement(0.1);
param->setDisplayRange(0, 10);
param->setDoubleType(eDoubleTypeScale);
if(parent) param->setParent(*parent);
return param;
}
void BasicExamplePluginFactory::describeInContext(OFX::ImageEffectDescriptor& desc, OFX::ContextEnum context)
{
// Source clip only in the filter context
// create the mandated source clip
ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
srcClip->addSupportedComponent(ePixelComponentRGBA);
srcClip->addSupportedComponent(ePixelComponentAlpha);
srcClip->setTemporalClipAccess(false);
srcClip->setSupportsTiles(true);
srcClip->setIsMask(false);
// if general or paint context, define the mask clip
if(context == eContextGeneral || context == eContextPaint) {
// if paint context, it is a mandated input called 'brush'
ClipDescriptor *maskClip = context == eContextGeneral ? desc.defineClip("Mask") : desc.defineClip("Brush");
maskClip->addSupportedComponent(ePixelComponentAlpha);
maskClip->setTemporalClipAccess(false);
if(context == eContextGeneral)
maskClip->setOptional(true);
maskClip->setSupportsTiles(true);
maskClip->setIsMask(true); // we are a mask input
}
// create the mandated output clip
ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
dstClip->addSupportedComponent(ePixelComponentRGBA);
dstClip->addSupportedComponent(ePixelComponentAlpha);
dstClip->setSupportsTiles(true);
// make some pages and to things in
PageParamDescriptor *page = desc.definePageParam("Controls");
// group param to group the scales
GroupParamDescriptor *componentScalesGroup = desc.defineGroupParam("componentScales");
componentScalesGroup->setHint("Scales on the individual component");
componentScalesGroup->setLabels("Components", "Components", "Components");
// make overall scale params
DoubleParamDescriptor *param = defineScaleParam(desc, "scale", "scale", "Scales all component in the image", 0);
page->addChild(*param);
// add a boolean to enable the component scale
BooleanParamDescriptor *boolP = desc.defineBooleanParam("scaleComponents");
boolP->setDefault(true);
boolP->setHint("Enables scales on individual components");
boolP->setLabels("Scale Components", "Scale Components", "Scale Components");
boolP->setParent(*componentScalesGroup);
page->addChild(*boolP);
// make the four component scale params
param = defineScaleParam(desc, "scaleR", "red", "Scales the red component of the image", componentScalesGroup);
page->addChild(*param);
param = defineScaleParam(desc, "scaleG", "green", "Scales the green component of the image", componentScalesGroup);
page->addChild(*param);
param = defineScaleParam(desc, "scaleB", "blue", "Scales the blue component of the image", componentScalesGroup);
page->addChild(*param);
param = defineScaleParam(desc, "scaleA", "alpha", "Scales the alpha component of the image", componentScalesGroup);
page->addChild(*param);
}
ImageEffect *BasicExamplePluginFactory::createInstance(OfxImageEffectHandle handle, ContextEnum /*context*/)
{
return new BasicPlugin(handle);
}
namespace OFX
{
namespace Plugin
{
void getPluginIDs(OFX::PluginFactoryArray &ids)
{
static BasicExamplePluginFactory p("net.sf.openfx.basicPlugin", 1, 0);
ids.push_back(&p);
}
}
}
+107
View File
@@ -0,0 +1,107 @@
# Microsoft Developer Studio Project File - Name="basic" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=basic - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "basic.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "basic.mak" CFG="basic - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "basic - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "basic - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "basic - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PROPTESTER_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PROPTESTER_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib /nologo /dll /machine:I386 /out:"Release/PropTester.ofx.bundle/Contents/Win32/basic.ofx"
!ELSEIF "$(CFG)" == "basic - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PROPTESTER_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PROPTESTER_EXPORTS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\Common Files\OFX\Plugins\Basic.ofx.bundle\Contents\Win32\basic.ofx" /pdbtype:sept
!ENDIF
# Begin Target
# Name "basic - Win32 Release"
# Name "basic - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\basic.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
+44
View File
@@ -0,0 +1,44 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "basic"=.\basic.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name ofxsupport
End Project Dependency
}}}
###############################################################################
Project: "ofxsupport"=..\..\Library\ofxsupport.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################
+464
View File
@@ -0,0 +1,464 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="basic"
ProjectGUID="{F14E0B69-3767-44B1-A28C-326B09350C7E}"
RootNamespace="basic"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\$(ConfigurationName)-$(PlatformName)"
IntermediateDirectory=".\$(ConfigurationName)-$(PlatformName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Debug/$(InputName).tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../include,../../../include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PROPTESTER_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
PrecompiledHeaderFile=".\$(ConfigurationName)-$(PlatformName)/$(InputName).pch"
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="2057"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib opengl32.lib"
OutputFile="../$(OutDir)/$(InputName).ofx.bundle/Contents/Win32/$(InputName).ofx"
LinkIncremental="1"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(IntDir)/$(InputName).pdb"
ImportLibrary="$(IntDir)/$(InputName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/$(InputName).bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory=".\$(ConfigurationName)-$(PlatformName)"
IntermediateDirectory=".\$(ConfigurationName)-$(PlatformName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="3"
TypeLibraryName=".\Debug/$(InputName).tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../include,../../../include"
PreprocessorDefinitions="WIN64;_DEBUG;_WINDOWS;_USRDLL;"
MinimalRebuild="false"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
PrecompiledHeaderFile=".\$(ConfigurationName)-$(PlatformName)/$(InputName).pch"
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="2057"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib opengl32.lib"
OutputFile="../$(OutDir)/$(InputName).ofx.bundle/Contents/Win64/$(InputName).ofx"
LinkIncremental="1"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/$(InputName).pdb"
ImportLibrary="$(OutDir)/$(InputName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/$(InputName).bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\$(ConfigurationName)-$(PlatformName)"
IntermediateDirectory=".\$(ConfigurationName)-$(PlatformName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Release/$(InputName).tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="../../include,../../../include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PROPTESTER_EXPORTS"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\$(ConfigurationName)-$(PlatformName)/$(InputName).pch"
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="2057"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib opengl32.lib"
OutputFile="../$(OutDir)/$(InputName).ofx.bundle/Contents/Win32/$(InputName).ofx"
LinkIncremental="1"
SuppressStartupBanner="true"
ProgramDatabaseFile="$(IntDir)/$(InputName).pdb"
ImportLibrary="$(IntDir)/$(InputName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/$(InputName).bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory=".\$(ConfigurationName)-$(PlatformName)"
IntermediateDirectory=".\$(ConfigurationName)-$(PlatformName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="3"
TypeLibraryName=".\Release/$(InputName).tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="../../include,../../../include"
PreprocessorDefinitions="WIN64;NDEBUG;_WINDOWS;_USRDLL;"
StringPooling="false"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\$(ConfigurationName)-$(PlatformName)/$(InputName).pch"
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="2057"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib opengl32.lib"
OutputFile="../$(OutDir)/$(InputName).ofx.bundle/Contents/Win64/$(InputName).ofx"
LinkIncremental="1"
SuppressStartupBanner="true"
ProgramDatabaseFile="$(OutDir)/$(InputName).pdb"
ImportLibrary="$(OutDir)/$(InputName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/$(InputName).bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="basic.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
+48
View File
@@ -0,0 +1,48 @@
include(OpenFX)
set(PLUGINS
Basic
ChoiceParams
Field
Generator
GPUGain
Invert
MultiBundle
Retimer
Tester
Transition)
foreach(PLUGIN IN LISTS PLUGINS)
file(GLOB_RECURSE PLUGIN_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN}/*.cpp")
if (${PLUGIN} STREQUAL "GPUGain")
if(APPLE)
file(GLOB_RECURSE METAL_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN}/*.mm") # add Metal kernel
list(APPEND PLUGIN_SOURCES ${METAL_SOURCES})
endif()
if (OFX_SUPPORTS_CUDARENDER)
file(GLOB_RECURSE CUDA_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN}/*.cu")
list(APPEND PLUGIN_SOURCES ${CUDA_SOURCES})
endif()
if (NOT OFX_SUPPORTS_OPENCLRENDER)
list(FILTER PLUGIN_SOURCES EXCLUDE REGEX "OpenCLKernel")
endif()
endif()
set(TGT example-${PLUGIN}-support)
add_ofx_plugin(${TGT} ${PLUGIN})
target_sources(${TGT} PUBLIC ${PLUGIN_SOURCES})
target_link_libraries(${TGT} ${CONAN_LIBS} OfxSupport opengl::opengl)
target_include_directories(${TGT} PUBLIC ${OFX_HEADER_DIR} ${OFX_SUPPORT_HEADER_DIR})
if(APPLE)
target_link_libraries(${TGT} "-framework Metal" "-framework Foundation" "-framework QuartzCore")
if (OFX_SUPPORTS_OPENCLRENDER)
target_link_libraries(${TGT} "-framework OpenCL")
endif()
else()
if (OFX_SUPPORTS_OPENCLRENDER)
target_link_libraries(${TGT} OpenCL::Headers OpenCL::OpenCL)
endif()
endif()
endforeach()
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>choiceparams.ofx</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.0.1d1</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,681 @@
#ifdef _WINDOWS
#include <windows.h>
#endif
#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
#include <stdio.h>
#include "ofxsImageEffect.h"
#include "../include/ofxsProcessing.H"
////////////////////////////////////////////////////////////////////////////////
// a dumb interact that just draw's a square you can drag
static const OfxPointD kBoxSize = {20, 20};
class ChoiceParamsInteract : public OFX::OverlayInteract {
protected :
enum StateEnum {
eInActive,
ePoised,
ePicked
};
OfxPointD _position;
StateEnum _state;
public :
ChoiceParamsInteract(OfxInteractHandle handle, OFX::ImageEffect* /*effect*/)
: OFX::OverlayInteract(handle)
, _state(eInActive)
{
_position.x = 0;
_position.y = 0;
}
// overridden functions from OFX::Interact to do things
virtual bool draw(const OFX::DrawArgs &args);
virtual bool penMotion(const OFX::PenArgs &args);
virtual bool penDown(const OFX::PenArgs &args);
virtual bool penUp(const OFX::PenArgs &args);
};
////////////////////////////////////////////////////////////////////////////////
// rendering routines
template <class T> inline T
Minimum(T a, T b) { return (a < b) ? a : b;}
template <class T> inline T
Absolute(T a) { return (a < 0) ? -a : a;}
template <class T> inline T
Clamp(T v, int min, int max)
{
if(v < T(min)) return T(min);
if(v > T(max)) return T(max);
return v;
}
// Base class for the RGBA and the Alpha processor
class ImageScalerBase : public OFX::ImageProcessor {
protected :
OFX::Image *_srcImg;
OFX::Image *_maskImg;
double _rScale, _gScale, _bScale, _aScale;
bool _doMasking;
public :
/** @brief no arg ctor */
ImageScalerBase(OFX::ImageEffect &instance)
: OFX::ImageProcessor(instance)
, _srcImg(0)
, _maskImg(0)
, _rScale(1)
, _gScale(1)
, _bScale(1)
, _aScale(1)
, _doMasking(false)
{
}
/** @brief set the src image */
void setSrcImg(OFX::Image *v) {_srcImg = v;}
/** @brief set the optional mask image */
void setMaskImg(OFX::Image *v) {_maskImg = v;}
// Are we masking. We can't derive this from the mask image being set as NULL is a valid value for an input image
void doMasking(bool v) {_doMasking = v;}
/** @brief set the scale */
void setScales(float r, float g, float b, float a)
{
_rScale = r;
_gScale = g;
_bScale = b;
_aScale = a;
}
};
// template to do the RGBA processing
template <class PIX, int nComponents, int max>
class ImageScaler : public ImageScalerBase {
public :
// ctor
ImageScaler(OFX::ImageEffect &instance)
: ImageScalerBase(instance)
{}
// and do some processing
void multiThreadProcessImages(OfxRectI procWindow)
{
float scales[4];
scales[0] = nComponents == 1 ? (float)_aScale : (float)_rScale;
scales[1] = (float)_gScale;
scales[2] = (float)_bScale;
scales[3] = (float)_aScale;
float maskScale = 1.0f;
for(int y = procWindow.y1; y < procWindow.y2; y++) {
if(_effect.abort()) break;
PIX *dstPix = (PIX *) _dstImg->getPixelAddress(procWindow.x1, y);
for(int x = procWindow.x1; x < procWindow.x2; x++) {
PIX *srcPix = (PIX *) (_srcImg ? _srcImg->getPixelAddress(x, y) : 0);
// are we doing masking
if(_doMasking) {
// we do, get the pixel from the mask
if(!_maskImg)
maskScale = 1.0f;
else
{
PIX *maskPix = (PIX *) (_maskImg ? _maskImg->getPixelAddress(x, y) : 0);
// figure the scale factor from that pixel
maskScale = maskPix != 0 ? float(*maskPix)/float(max) : 0.0f;
}
}
// do we have a source image to scale up
if(srcPix) {
for(int c = 0; c < nComponents; c++) {
float v;
// scale the component up by the scale factor, modulated by the maskScale
if(maskScale != 1.0f)
v = srcPix[c] * (1.0f + (scales[c] - 1.0f) * maskScale);
else
v = srcPix[c] * scales[c];
if(max == 1) // implies floating point and so no clamping
dstPix[c] = PIX(v);
else // integer based and we need to clamp
dstPix[c] = PIX(Clamp(v, 0, max));
}
}
else {
// no src pixel here, be black and transparent
for(int c = 0; c < nComponents; c++) {
dstPix[c] = 0;
}
}
// increment the dst pixel
dstPix += nComponents;
}
}
}
};
////////////////////////////////////////////////////////////////////////////////
/** @brief The plugin that does our work */
class ChoiceParamsPlugin : public OFX::ImageEffect {
protected :
// do not need to delete these, the ImageEffect is managing them for us
OFX::Clip *dstClip_;
OFX::Clip *srcClip_;
OFX::Clip *maskClip_;
OFX::ChoiceParam *red_choice_;
OFX::ChoiceParam *green_choice_;
OFX::StrChoiceParam *blue_choice_;
public :
/** @brief ctor */
ChoiceParamsPlugin(OfxImageEffectHandle handle)
: ImageEffect(handle)
, dstClip_(0)
, srcClip_(0)
, red_choice_(0)
, green_choice_(0)
, blue_choice_()
{
dstClip_ = fetchClip(kOfxImageEffectOutputClipName);
srcClip_ = fetchClip(kOfxImageEffectSimpleSourceClipName);
// name of mask clip depends on the context
maskClip_ = getContext() == OFX::eContextFilter ? NULL : fetchClip(getContext() == OFX::eContextPaint ? "Brush" : "Mask");
red_choice_ = fetchChoiceParam("red_choice");
green_choice_ = fetchChoiceParam("green_choice");
if (OFX::getImageEffectHostDescription()->supportsStrChoice) {
blue_choice_ = fetchStrChoiceParam("blue_choice");
}
}
/* Override the render */
virtual void render(const OFX::RenderArguments &args);
/* override is identity */
virtual bool isIdentity(const OFX::IsIdentityArguments &args, OFX::Clip * &identityClip, double &identityTime);
/* override changedParam */
virtual void changedParam(const OFX::InstanceChangedArgs &args, const std::string &paramName);
/* override changed clip */
virtual void changedClip(const OFX::InstanceChangedArgs &args, const std::string &clipName);
// override the rod call
virtual bool getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod);
// override the roi call
virtual void getRegionsOfInterest(const OFX::RegionsOfInterestArguments &args, OFX::RegionOfInterestSetter &rois);
/* set up and run a processor */
void
setupAndProcess(ImageScalerBase &, const OFX::RenderArguments &args);
};
////////////////////////////////////////////////////////////////////////////////
/** @brief render for the filter */
////////////////////////////////////////////////////////////////////////////////
// basic plugin render function, just a skelington to instantiate templates from
/* set up and run a processor */
void
ChoiceParamsPlugin::setupAndProcess(ImageScalerBase &processor, const OFX::RenderArguments &args)
{
// get a dst image
std::unique_ptr<OFX::Image> dst(dstClip_->fetchImage(args.time));
OFX::BitDepthEnum dstBitDepth = dst->getPixelDepth();
OFX::PixelComponentEnum dstComponents = dst->getPixelComponents();
// fetch main input image
std::unique_ptr<OFX::Image> src(srcClip_->fetchImage(args.time));
// make sure bit depths are sane
if(src.get()) {
OFX::BitDepthEnum srcBitDepth = src->getPixelDepth();
OFX::PixelComponentEnum srcComponents = src->getPixelComponents();
// see if they have the same depths and bytes and all
if(srcBitDepth != dstBitDepth || srcComponents != dstComponents)
throw int(1); // HACK!! need to throw an sensible exception here!
}
std::unique_ptr<OFX::Image> mask;
// do we do masking
if(getContext() != OFX::eContextFilter) {
mask.reset(maskClip_->fetchImage(args.time));
// say we are masking
processor.doMasking(true);
// Set it in the processor
processor.setMaskImg(mask.get());
}
// get the scale parameter values...
int ri = 0;
int gi = 0;
std::string bi;
double r = 0, g = 0, b = 0, a = 0;
red_choice_->getValueAtTime(args.time, ri);
green_choice_->getValueAtTime(args.time, gi);
if (ri == 0)
r = 0;
if (ri == 1)
r = 0.5;
if (ri == 2)
r = 1.0;
// Note that green options are out of order
if (gi == 0)
g = 0;
if (gi == 2)
g = 0.5;
if (gi == 1)
g = 1.0;
if (OFX::getImageEffectHostDescription()->supportsStrChoice) {
blue_choice_->getValueAtTime(args.time, bi);
if (bi == "blue_0.0")
b = 0;
if (bi == "blue_0.5")
b = 0.5;
if (bi == "blue_1.0")
b = 1.0;
} else {
b = 1.0;
}
a = 1.0; // always
// set the images
processor.setDstImg(dst.get());
processor.setSrcImg(src.get());
// set the render window
processor.setRenderWindow(args.renderWindow);
// set the scales
processor.setScales((float)r, (float)g, (float)b, (float)a);
// Call the base class process member, this will call the derived templated process code
processor.process();
}
// override the rod call
bool
ChoiceParamsPlugin::getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod)
{
// our RoD is the same as the 'Source' clip's, we are not interested in the mask
rod = srcClip_->getRegionOfDefinition(args.time);
// say we set it
return true;
}
// override the roi call
void
ChoiceParamsPlugin::getRegionsOfInterest(const OFX::RegionsOfInterestArguments &args, OFX::RegionOfInterestSetter &rois)
{
// we don't actually need to do this as this is the default, but do it for examples sake
rois.setRegionOfInterest(*srcClip_, args.regionOfInterest);
// set it on the mask only if we are in an interesting context
if(getContext() != OFX::eContextFilter)
rois.setRegionOfInterest(*maskClip_, args.regionOfInterest);
}
// the overridden render function
void
ChoiceParamsPlugin::render(const OFX::RenderArguments &args)
{
// instantiate the render code based on the pixel depth of the dst clip
OFX::BitDepthEnum dstBitDepth = dstClip_->getPixelDepth();
OFX::PixelComponentEnum dstComponents = dstClip_->getPixelComponents();
// do the rendering
if(dstComponents == OFX::ePixelComponentRGBA) {
switch(dstBitDepth) {
case OFX::eBitDepthUByte : {
ImageScaler<unsigned char, 4, 255> fred(*this);
setupAndProcess(fred, args);
}
break;
case OFX::eBitDepthUShort : {
ImageScaler<unsigned short, 4, 65535> fred(*this);
setupAndProcess(fred, args);
}
break;
case OFX::eBitDepthFloat : {
ImageScaler<float, 4, 1> fred(*this);
setupAndProcess(fred, args);
}
break;
default :
OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
}
}
else {
switch(dstBitDepth) {
case OFX::eBitDepthUByte : {
ImageScaler<unsigned char, 1, 255> fred(*this);
setupAndProcess(fred, args);
}
break;
case OFX::eBitDepthUShort : {
ImageScaler<unsigned short, 1, 65535> fred(*this);
setupAndProcess(fred, args);
}
break;
case OFX::eBitDepthFloat : {
ImageScaler<float, 1, 1> fred(*this);
setupAndProcess(fred, args);
}
break;
default :
OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
}
}
}
// overridden is identity
bool
ChoiceParamsPlugin:: isIdentity(const OFX::IsIdentityArguments &args, OFX::Clip * &identityClip, double &identityTime)
{
return false;
}
// we have changed a param
void
ChoiceParamsPlugin::changedParam(const OFX::InstanceChangedArgs &/*args*/, const std::string &paramName)
{
}
// we have changed a param
void
ChoiceParamsPlugin::changedClip(const OFX::InstanceChangedArgs &/*args*/, const std::string &clipName)
{
}
////////////////////////////////////////////////////////////////////////////////
// stuff for the interact
// draw the interact
bool ChoiceParamsInteract::draw(const OFX::DrawArgs &args)
{
OfxRGBColourF col;
switch(_state)
{
case eInActive : col.r = col.g = col.b = 0.0f; break;
case ePoised : col.r = col.g = col.b = 0.5f; break;
case ePicked : col.r = col.g = col.b = 1.0f; break;
}
// make the box a constant size on screen by scaling by the pixel scale
float dx = (float)(kBoxSize.x * args.pixelScale.x);
float dy = (float)(kBoxSize.y * args.pixelScale.y);
// Draw a cross hair, the current coordinate system aligns with the image plane.
glPushMatrix();
// draw the bo
glColor3f(col.r, col.g, col.b);
glTranslated(_position.x, _position.y, 0);
glBegin(GL_POLYGON);
glVertex2f(-dx, -dy);
glVertex2f(-dx, dy);
glVertex2f( dx, dy);
glVertex2f( dx, -dy);
glEnd();
glPopMatrix();
glPushMatrix();
// draw a complementary outline
glColor3f(1.0f - col.r, 1.0f - col.g, 1.0f - col.b);
glTranslated(_position.x, _position.y, 0);
glBegin(GL_LINE_LOOP);
glVertex2f(-dx, -dy);
glVertex2f(-dx, dy);
glVertex2f( dx, dy);
glVertex2f( dx, -dy);
glEnd();
glPopMatrix();
return true;
}
// overridden functions from OFX::Interact to do things
bool
ChoiceParamsInteract::penMotion(const OFX::PenArgs &args)
{
// figure the size of the box in cannonical coords
float dx = (float)(kBoxSize.x * args.pixelScale.x);
float dy = (float)(kBoxSize.y * args.pixelScale.y);
// pen position is in cannonical coords
OfxPointD penPos = args.penPosition;
switch(_state) {
case eInActive :
case ePoised :
{
// are we in the box, become 'poised'
StateEnum newState;
penPos.x -= _position.x;
penPos.y -= _position.y;
if(Absolute(penPos.x) < dx &&
Absolute(penPos.y) < dy) {
newState = ePoised;
}
else {
newState = eInActive;
}
if(_state != newState) {
// we have a new state
_state = newState;
// and force an overlay redraw
_effect->redrawOverlays();
}
}
break;
case ePicked :
{
// move our position
_position = penPos;
// and force an overlay redraw
_effect->redrawOverlays();
}
break;
}
// we have trapped it only if the mouse ain't over it or we are actively dragging
return _state != eInActive;
}
bool
ChoiceParamsInteract::penDown(const OFX::PenArgs &args)
{
// this will refigure the state
penMotion(args);
// if poised means we were over it when the pen went down, so pick it
if(_state == ePoised) {
// we are now picked
_state = ePicked;
// move our position
_position = args.penPosition;
// and request a redraw just incase
_effect->redrawOverlays();
}
return _state == ePicked;
}
bool
ChoiceParamsInteract::penUp(const OFX::PenArgs &args)
{
if(_state == ePicked) {
// reset to poised for a moment
_state = ePoised;
// this will refigure the state
penMotion(args);
// and redraw for good measure
_effect->redrawOverlays();
// we did trap it
return true;
}
// we didn't trap it
return false;
}
using namespace OFX;
mDeclarePluginFactory(ChoiceParamsExamplePluginFactory, {}, {});
class ChoiceParamsExampleOverlayDescriptor : public DefaultEffectOverlayDescriptor<ChoiceParamsExampleOverlayDescriptor, ChoiceParamsInteract> {};
void ChoiceParamsExamplePluginFactory::describe(OFX::ImageEffectDescriptor& desc)
{
// basic labels
desc.setLabels("Choice Params (Support)", "ChoiceParams(spt)", "Choice Params (Support)");
desc.setPluginGrouping("OFX Example (Support)");
// add the supported contexts, only filter at the moment
desc.addSupportedContext(eContextFilter);
desc.addSupportedContext(eContextGeneral);
desc.addSupportedContext(eContextPaint);
// add supported pixel depths
desc.addSupportedBitDepth(eBitDepthUByte);
desc.addSupportedBitDepth(eBitDepthUShort);
desc.addSupportedBitDepth(eBitDepthFloat);
// set a few flags
desc.setSingleInstance(false);
desc.setHostFrameThreading(false);
desc.setSupportsMultiResolution(true);
desc.setSupportsTiles(true);
desc.setTemporalClipAccess(false);
desc.setRenderTwiceAlways(false);
desc.setSupportsMultipleClipPARs(false);
desc.setOverlayInteractDescriptor( new ChoiceParamsExampleOverlayDescriptor);
}
void ChoiceParamsExamplePluginFactory::describeInContext(OFX::ImageEffectDescriptor& desc, OFX::ContextEnum context)
{
// Source clip only in the filter context
// create the mandated source clip
ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
srcClip->addSupportedComponent(ePixelComponentRGBA);
srcClip->addSupportedComponent(ePixelComponentAlpha);
srcClip->setTemporalClipAccess(false);
srcClip->setSupportsTiles(true);
srcClip->setIsMask(false);
// if general or paint context, define the mask clip
if(context == eContextGeneral || context == eContextPaint) {
// if paint context, it is a mandated input called 'brush'
ClipDescriptor *maskClip = context == eContextGeneral ? desc.defineClip("Mask") : desc.defineClip("Brush");
maskClip->addSupportedComponent(ePixelComponentAlpha);
maskClip->setTemporalClipAccess(false);
if(context == eContextGeneral)
maskClip->setOptional(true);
maskClip->setSupportsTiles(true);
maskClip->setIsMask(true); // we are a mask input
}
// create the mandated output clip
ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
dstClip->addSupportedComponent(ePixelComponentRGBA);
dstClip->addSupportedComponent(ePixelComponentAlpha);
dstClip->setSupportsTiles(true);
// make some pages and to things in
PageParamDescriptor *page = desc.definePageParam("Controls");
auto *choice1 = desc.defineChoiceParam("red_choice");
choice1->appendOption("red: none");
choice1->appendOption("red: some");
choice1->appendOption("red: lots");
choice1->setDefault(0);
page->addChild(*choice1);
// Note: index 1 is "lots" (even though UI order is 2), index 2 is "some"
// because options are appended in order.
auto *choice2 = desc.defineChoiceParam("green_choice");
choice2->appendOption("green: none", "", 0);
choice2->appendOption("green: lots", "", 2);
choice2->appendOption("green: some", "", 1);
choice2->setDefault(0);
page->addChild(*choice2);
if (getImageEffectHostDescription()->supportsStrChoice) {
auto *choice3 = desc.defineStrChoiceParam("blue_choice");
choice3->appendOption("blue_0.0", "blue: none", 0);
choice3->appendOption("blue_0.5", "blue: some", 1);
choice3->appendOption("blue_1.0", "blue: lots", 2);
choice3->setDefault("blue_0.0");
page->addChild(*choice3);
}
}
ImageEffect *ChoiceParamsExamplePluginFactory::createInstance(OfxImageEffectHandle handle, ContextEnum /*context*/)
{
return new ChoiceParamsPlugin(handle);
}
namespace OFX
{
namespace Plugin
{
void getPluginIDs(OFX::PluginFactoryArray &ids)
{
static ChoiceParamsExamplePluginFactory p("org.openeffects.support.choiceParamsPlugin", 1, 0);
ids.push_back(&p);
}
}
}
+115
View File
@@ -0,0 +1,115 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual C++ Express 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic", "Basic\basic.vcproj", "{F14E0B69-3767-44B1-A28C-326B09350C7E}"
ProjectSection(ProjectDependencies) = postProject
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707} = {257EC9EE-530A-4A6F-8B2E-AAB1C8458707}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ofxsupport", "..\Library\ofxsupport.vcproj", "{257EC9EE-530A-4A6F-8B2E-AAB1C8458707}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "noise", "Generator\noise.vcproj", "{F14EBC69-3767-44B1-A28C-326B59350C7F}"
ProjectSection(ProjectDependencies) = postProject
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707} = {257EC9EE-530A-4A6F-8B2E-AAB1C8458707}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "invert", "Invert\invert.vcproj", "{F14E0B89-3767-88B1-A28C-326B0B350C7E}"
ProjectSection(ProjectDependencies) = postProject
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707} = {257EC9EE-530A-4A6F-8B2E-AAB1C8458707}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "retimer", "Retimer\retimer.vcproj", "{F14E0B89-3767-48B1-A28C-326B0F350C7B}"
ProjectSection(ProjectDependencies) = postProject
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707} = {257EC9EE-530A-4A6F-8B2E-AAB1C8458707}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crossfade", "Transition\crossFade.vcproj", "{C14CCB89-3767-88B1-A28C-326B0B350C7E}"
ProjectSection(ProjectDependencies) = postProject
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707} = {257EC9EE-530A-4A6F-8B2E-AAB1C8458707}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "proptester", "..\PropTester\propTester.vcproj", "{F14E0B69-BD67-4CB1-A28C-326B09350C7B}"
ProjectSection(ProjectDependencies) = postProject
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707} = {257EC9EE-530A-4A6F-8B2E-AAB1C8458707}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MultiBundle", "MultiBundle\multibundle.vcproj", "{F14ECC69-3767-44B1-A28C-32FB09F50C7E}"
ProjectSection(ProjectDependencies) = postProject
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707} = {257EC9EE-530A-4A6F-8B2E-AAB1C8458707}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F14E0B69-3767-44B1-A28C-326B09350C7E}.Debug|Win32.ActiveCfg = Debug|Win32
{F14E0B69-3767-44B1-A28C-326B09350C7E}.Debug|Win32.Build.0 = Debug|Win32
{F14E0B69-3767-44B1-A28C-326B09350C7E}.Debug|x64.ActiveCfg = Debug|x64
{F14E0B69-3767-44B1-A28C-326B09350C7E}.Debug|x64.Build.0 = Debug|x64
{F14E0B69-3767-44B1-A28C-326B09350C7E}.Release|Win32.ActiveCfg = Release|Win32
{F14E0B69-3767-44B1-A28C-326B09350C7E}.Release|Win32.Build.0 = Release|Win32
{F14E0B69-3767-44B1-A28C-326B09350C7E}.Release|x64.ActiveCfg = Release|x64
{F14E0B69-3767-44B1-A28C-326B09350C7E}.Release|x64.Build.0 = Release|x64
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707}.Debug|Win32.ActiveCfg = Debug|Win32
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707}.Debug|Win32.Build.0 = Debug|Win32
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707}.Debug|x64.ActiveCfg = Debug|x64
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707}.Debug|x64.Build.0 = Debug|x64
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707}.Release|Win32.ActiveCfg = Release|Win32
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707}.Release|Win32.Build.0 = Release|Win32
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707}.Release|x64.ActiveCfg = Release|x64
{257EC9EE-530A-4A6F-8B2E-AAB1C8458707}.Release|x64.Build.0 = Release|x64
{F14EBC69-3767-44B1-A28C-326B59350C7F}.Debug|Win32.ActiveCfg = Debug|Win32
{F14EBC69-3767-44B1-A28C-326B59350C7F}.Debug|Win32.Build.0 = Debug|Win32
{F14EBC69-3767-44B1-A28C-326B59350C7F}.Debug|x64.ActiveCfg = Debug|x64
{F14EBC69-3767-44B1-A28C-326B59350C7F}.Debug|x64.Build.0 = Debug|x64
{F14EBC69-3767-44B1-A28C-326B59350C7F}.Release|Win32.ActiveCfg = Release|Win32
{F14EBC69-3767-44B1-A28C-326B59350C7F}.Release|Win32.Build.0 = Release|Win32
{F14EBC69-3767-44B1-A28C-326B59350C7F}.Release|x64.ActiveCfg = Release|x64
{F14EBC69-3767-44B1-A28C-326B59350C7F}.Release|x64.Build.0 = Release|x64
{F14E0B89-3767-88B1-A28C-326B0B350C7E}.Debug|Win32.ActiveCfg = Debug|Win32
{F14E0B89-3767-88B1-A28C-326B0B350C7E}.Debug|Win32.Build.0 = Debug|Win32
{F14E0B89-3767-88B1-A28C-326B0B350C7E}.Debug|x64.ActiveCfg = Debug|x64
{F14E0B89-3767-88B1-A28C-326B0B350C7E}.Debug|x64.Build.0 = Debug|x64
{F14E0B89-3767-88B1-A28C-326B0B350C7E}.Release|Win32.ActiveCfg = Release|Win32
{F14E0B89-3767-88B1-A28C-326B0B350C7E}.Release|Win32.Build.0 = Release|Win32
{F14E0B89-3767-88B1-A28C-326B0B350C7E}.Release|x64.ActiveCfg = Release|x64
{F14E0B89-3767-88B1-A28C-326B0B350C7E}.Release|x64.Build.0 = Release|x64
{F14E0B89-3767-48B1-A28C-326B0F350C7B}.Debug|Win32.ActiveCfg = Debug|Win32
{F14E0B89-3767-48B1-A28C-326B0F350C7B}.Debug|Win32.Build.0 = Debug|Win32
{F14E0B89-3767-48B1-A28C-326B0F350C7B}.Debug|x64.ActiveCfg = Debug|x64
{F14E0B89-3767-48B1-A28C-326B0F350C7B}.Debug|x64.Build.0 = Debug|x64
{F14E0B89-3767-48B1-A28C-326B0F350C7B}.Release|Win32.ActiveCfg = Release|Win32
{F14E0B89-3767-48B1-A28C-326B0F350C7B}.Release|Win32.Build.0 = Release|Win32
{F14E0B89-3767-48B1-A28C-326B0F350C7B}.Release|x64.ActiveCfg = Release|x64
{F14E0B89-3767-48B1-A28C-326B0F350C7B}.Release|x64.Build.0 = Release|x64
{C14CCB89-3767-88B1-A28C-326B0B350C7E}.Debug|Win32.ActiveCfg = Debug|Win32
{C14CCB89-3767-88B1-A28C-326B0B350C7E}.Debug|Win32.Build.0 = Debug|Win32
{C14CCB89-3767-88B1-A28C-326B0B350C7E}.Debug|x64.ActiveCfg = Debug|x64
{C14CCB89-3767-88B1-A28C-326B0B350C7E}.Debug|x64.Build.0 = Debug|x64
{C14CCB89-3767-88B1-A28C-326B0B350C7E}.Release|Win32.ActiveCfg = Release|Win32
{C14CCB89-3767-88B1-A28C-326B0B350C7E}.Release|Win32.Build.0 = Release|Win32
{C14CCB89-3767-88B1-A28C-326B0B350C7E}.Release|x64.ActiveCfg = Release|x64
{C14CCB89-3767-88B1-A28C-326B0B350C7E}.Release|x64.Build.0 = Release|x64
{F14E0B69-BD67-4CB1-A28C-326B09350C7B}.Debug|Win32.ActiveCfg = Debug|Win32
{F14E0B69-BD67-4CB1-A28C-326B09350C7B}.Debug|Win32.Build.0 = Debug|Win32
{F14E0B69-BD67-4CB1-A28C-326B09350C7B}.Debug|x64.ActiveCfg = Debug|x64
{F14E0B69-BD67-4CB1-A28C-326B09350C7B}.Debug|x64.Build.0 = Debug|x64
{F14E0B69-BD67-4CB1-A28C-326B09350C7B}.Release|Win32.ActiveCfg = Release|Win32
{F14E0B69-BD67-4CB1-A28C-326B09350C7B}.Release|Win32.Build.0 = Release|Win32
{F14E0B69-BD67-4CB1-A28C-326B09350C7B}.Release|x64.ActiveCfg = Release|x64
{F14E0B69-BD67-4CB1-A28C-326B09350C7B}.Release|x64.Build.0 = Release|x64
{F14ECC69-3767-44B1-A28C-32FB09F50C7E}.Debug|Win32.ActiveCfg = Debug|Win32
{F14ECC69-3767-44B1-A28C-32FB09F50C7E}.Debug|Win32.Build.0 = Debug|Win32
{F14ECC69-3767-44B1-A28C-32FB09F50C7E}.Debug|x64.ActiveCfg = Debug|Win32
{F14ECC69-3767-44B1-A28C-32FB09F50C7E}.Release|Win32.ActiveCfg = Release|Win32
{F14ECC69-3767-44B1-A28C-32FB09F50C7E}.Release|Win32.Build.0 = Release|Win32
{F14ECC69-3767-44B1-A28C-32FB09F50C7E}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>field.ofx</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.0.1d1</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
</plist>
+286
View File
@@ -0,0 +1,286 @@
#ifdef _WINDOWS
#include <windows.h>
#endif
#include <iostream>
#include <stdio.h>
#include "ofxsImageEffect.h"
#include "ofxsMultiThread.h"
#include "../include/ofxsProcessing.H"
// Base class for the RGBA and the Alpha processor
class FieldBase : public OFX::ImageProcessor {
protected :
OFX::Image *_srcImg;
OFX::FieldEnum _field;
public :
/** @brief no arg ctor */
FieldBase(OFX::ImageEffect &instance, OFX::FieldEnum field)
: OFX::ImageProcessor(instance)
, _srcImg(0), _field(field)
{
}
/** @brief set the src image */
void setSrcImg(OFX::Image *v) {_srcImg = v;}
};
// template to do the RGBA processing
template <class PIX, int nComponents, int max>
class ImageFielder : public FieldBase {
public :
// ctor
ImageFielder(OFX::ImageEffect &instance, OFX::FieldEnum field)
: FieldBase(instance, field)
{}
// and do some processing
void multiThreadProcessImages(OfxRectI procWindow)
{
//eFieldLower only the spatially lower field is present
//eFieldUpper only the spatially upper field is present
for(int y = procWindow.y1; y < procWindow.y2; y++) {
if(_effect.abort()) break;
PIX *dstPix = (PIX *) _dstImg->getPixelAddress(procWindow.x1, y);
for(int x = procWindow.x1; x < procWindow.x2; x++) {
PIX *srcPix = (PIX *) (_srcImg ? _srcImg->getPixelAddress(x, y) : 0);
// do we have a source image to scale up
if(srcPix) {
for(int c = 0; c < nComponents; c++) {
if((_field == OFX::eFieldLower) && (c==0))
dstPix[c] = max;
else if((_field == OFX::eFieldUpper) && (c==2))
dstPix[c] = max;
else
dstPix[c] = max - srcPix[c];
}
}
else {
// no src pixel here, be black and transparent
for(int c = 0; c < nComponents; c++) {
if((_field == OFX::eFieldLower) && (c==0))
dstPix[c] = max;
else if((_field == OFX::eFieldUpper) && (c==2))
dstPix[c] = max;
else
dstPix[c] = 0;
}
}
// increment the dst pixel
dstPix += nComponents;
}
}
}
};
////////////////////////////////////////////////////////////////////////////////
/** @brief The plugin that does our work */
class FieldPlugin : public OFX::ImageEffect {
protected :
// do not need to delete these, the ImageEffect is managing them for us
OFX::Clip *dstClip_;
OFX::Clip *srcClip_;
public :
/** @brief ctor */
FieldPlugin(OfxImageEffectHandle handle)
: ImageEffect(handle)
, dstClip_(0)
, srcClip_(0)
{
dstClip_ = fetchClip(kOfxImageEffectOutputClipName);
srcClip_ = fetchClip(kOfxImageEffectSimpleSourceClipName);
}
/* Override the render */
virtual void render(const OFX::RenderArguments &args);
/* set up and run a processor */
void setupAndProcess(FieldBase &, const OFX::RenderArguments &args);
};
////////////////////////////////////////////////////////////////////////////////
/** @brief render for the filter */
////////////////////////////////////////////////////////////////////////////////
// basic plugin render function, just a skelington to instantiate templates from
/* set up and run a processor */
void
FieldPlugin::setupAndProcess(FieldBase &processor, const OFX::RenderArguments &args)
{
// get a dst image
std::unique_ptr<OFX::Image> dst(dstClip_->fetchImage(args.time));
OFX::BitDepthEnum dstBitDepth = dst->getPixelDepth();
OFX::PixelComponentEnum dstComponents = dst->getPixelComponents();
// fetch main input image
std::unique_ptr<OFX::Image> src(srcClip_->fetchImage(args.time));
// make sure bit depths are sane
if(src.get()) {
OFX::BitDepthEnum srcBitDepth = src->getPixelDepth();
OFX::PixelComponentEnum srcComponents = src->getPixelComponents();
// see if they have the same depths and bytes and all
if(srcBitDepth != dstBitDepth || srcComponents != dstComponents)
throw int(1); // HACK!! need to throw an sensible exception here!
}
// set the images
processor.setDstImg(dst.get());
processor.setSrcImg(src.get());
// set the render window
processor.setRenderWindow(args.renderWindow);
// Call the base class process member, this will call the derived templated process code
processor.process();
}
// the overridden render function
void
FieldPlugin::render(const OFX::RenderArguments &args)
{
// instantiate the render code based on the pixel depth of the dst clip
OFX::BitDepthEnum dstBitDepth = dstClip_->getPixelDepth();
OFX::PixelComponentEnum dstComponents = dstClip_->getPixelComponents();
double time = args.time;
std::cout << "Rendering at time " << time << std::endl;
OFX::FieldEnum field = args.fieldToRender;
// do the rendering
if(dstComponents == OFX::ePixelComponentRGBA)
{
switch(dstBitDepth)
{
case OFX::eBitDepthUByte :
{
ImageFielder<unsigned char, 4, 255> fred(*this, field);
setupAndProcess(fred, args);
}
break;
case OFX::eBitDepthUShort :
{
ImageFielder<unsigned short, 4, 65535> fred(*this, field);
setupAndProcess(fred, args);
}
break;
case OFX::eBitDepthFloat :
{
ImageFielder<float, 4, 1> fred(*this, field);
setupAndProcess(fred, args);
}
break;
default :
OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
}
}
else
{
switch(dstBitDepth)
{
case OFX::eBitDepthUByte :
{
ImageFielder<unsigned char, 1, 255> fred(*this, field);
setupAndProcess(fred, args);
}
break;
case OFX::eBitDepthUShort :
{
ImageFielder<unsigned short, 1, 65535> fred(*this, field);
setupAndProcess(fred, args);
}
break;
case OFX::eBitDepthFloat :
{
ImageFielder<float, 1, 1> fred(*this, field);
setupAndProcess(fred, args);
}
break;
default :
OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
}
}
}
mDeclarePluginFactory(FieldExamplePluginFactory, {}, {});
using namespace OFX;
void FieldExamplePluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
// basic labels
desc.setLabels("Field", "Field", "Field");
desc.setPluginGrouping("OFX Example (Support)");
// add the supported contexts, only filter at the moment
desc.addSupportedContext(eContextFilter);
// add supported pixel depths
desc.addSupportedBitDepth(eBitDepthUByte);
desc.addSupportedBitDepth(eBitDepthUShort);
desc.addSupportedBitDepth(eBitDepthFloat);
// set a few flags
desc.setSingleInstance(false);
desc.setHostFrameThreading(false);
desc.setSupportsMultiResolution(true);
desc.setSupportsTiles(true);
desc.setTemporalClipAccess(false);
desc.setRenderTwiceAlways(true);
desc.setSupportsMultipleClipPARs(false);
}
void FieldExamplePluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, OFX::ContextEnum /*context*/)
{
// Source clip only in the filter context
// create the mandated source clip
ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
srcClip->addSupportedComponent(ePixelComponentRGBA);
srcClip->addSupportedComponent(ePixelComponentAlpha);
srcClip->setTemporalClipAccess(false);
srcClip->setSupportsTiles(true);
srcClip->setIsMask(false);
srcClip->setFieldExtraction(eFieldExtractSingle);
// create the mandated output clip
ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
dstClip->addSupportedComponent(ePixelComponentRGBA);
dstClip->addSupportedComponent(ePixelComponentAlpha);
dstClip->setSupportsTiles(true);
}
OFX::ImageEffect* FieldExamplePluginFactory::createInstance(OfxImageEffectHandle handle, OFX::ContextEnum /*context*/)
{
return new FieldPlugin(handle);
}
namespace OFX
{
namespace Plugin
{
void getPluginIDs(OFX::PluginFactoryArray &ids)
{
static FieldExamplePluginFactory p("net.sf.openfx.fieldPlugin", 1, 0);
ids.push_back(&p);
}
}
}
+464
View File
@@ -0,0 +1,464 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="field"
ProjectGUID="{F14E0B89-3767-88B1-A28C-326B0B350C7E}"
RootNamespace="field"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\$(ConfigurationName)-$(PlatformName)"
IntermediateDirectory=".\$(ConfigurationName)-$(PlatformName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Debug/$(InputName).tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../include,../../../include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PROPTESTER_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
PrecompiledHeaderFile=".\$(ConfigurationName)-$(PlatformName)/$(InputName).pch"
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="2057"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib opengl32.lib"
OutputFile="../$(OutDir)/$(InputName).ofx.bundle/Contents/Win32/$(InputName).ofx"
LinkIncremental="1"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(IntDir)/$(InputName).pdb"
ImportLibrary="$(IntDir)/$(InputName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/$(InputName).bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory=".\$(ConfigurationName)-$(PlatformName)"
IntermediateDirectory=".\$(ConfigurationName)-$(PlatformName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="3"
TypeLibraryName=".\Debug/$(InputName).tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../include,../../../include"
PreprocessorDefinitions="WIN64;_DEBUG;_WINDOWS;_USRDLL;"
MinimalRebuild="false"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
PrecompiledHeaderFile=".\$(ConfigurationName)-$(PlatformName)/$(InputName).pch"
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="2057"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib opengl32.lib"
OutputFile="../$(OutDir)/$(InputName).ofx.bundle/Contents/Win64/$(InputName).ofx"
LinkIncremental="1"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/$(InputName).pdb"
ImportLibrary="$(OutDir)/$(InputName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/$(InputName).bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\$(ConfigurationName)-$(PlatformName)"
IntermediateDirectory=".\$(ConfigurationName)-$(PlatformName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Release/$(InputName).tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="../../include,../../../include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PROPTESTER_EXPORTS"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\$(ConfigurationName)-$(PlatformName)/$(InputName).pch"
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="2057"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib opengl32.lib"
OutputFile="../$(OutDir)/$(InputName).ofx.bundle/Contents/Win32/$(InputName).ofx"
LinkIncremental="1"
SuppressStartupBanner="true"
ProgramDatabaseFile="$(IntDir)/$(InputName).pdb"
ImportLibrary="$(IntDir)/$(InputName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/$(InputName).bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory=".\$(ConfigurationName)-$(PlatformName)"
IntermediateDirectory=".\$(ConfigurationName)-$(PlatformName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="3"
TypeLibraryName=".\Release/$(InputName).tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="../../include,../../../include"
PreprocessorDefinitions="WIN64;NDEBUG;_WINDOWS;_USRDLL;"
StringPooling="false"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\$(ConfigurationName)-$(PlatformName)/$(InputName).pch"
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="2057"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib opengl32.lib"
OutputFile="../$(OutDir)/$(InputName).ofx.bundle/Contents/Win64/$(InputName).ofx"
LinkIncremental="1"
SuppressStartupBanner="true"
ProgramDatabaseFile="$(OutDir)/$(InputName).pdb"
ImportLibrary="$(OutDir)/$(InputName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/$(InputName).bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="field.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,26 @@
__global__ void GainAdjustKernel(int p_Width, int p_Height, float p_GainR, float p_GainG, float p_GainB, float p_GainA, const float* p_Input, float* p_Output)
{
const int x = blockIdx.x * blockDim.x + threadIdx.x;
const int y = blockIdx.y * blockDim.y + threadIdx.y;
if ((x < p_Width) && (y < p_Height))
{
const int index = ((y * p_Width) + x) * 4;
p_Output[index + 0] = p_Input[index + 0] * p_GainR;
p_Output[index + 1] = p_Input[index + 1] * p_GainG;
p_Output[index + 2] = p_Input[index + 2] * p_GainB;
p_Output[index + 3] = p_Input[index + 3] * p_GainA;
}
}
void RunCudaKernel(void* p_Stream, int p_Width, int p_Height, float* p_Gain, const float* p_Input, float* p_Output)
{
dim3 threads(128, 1, 1);
dim3 blocks(((p_Width + threads.x - 1) / threads.x), p_Height, 1);
cudaStream_t stream = static_cast<cudaStream_t>(p_Stream);
GainAdjustKernel<<<blocks, threads, 0, stream>>>(p_Width, p_Height, p_Gain[0], p_Gain[1], p_Gain[2], p_Gain[3], p_Input, p_Output);
}
+462
View File
@@ -0,0 +1,462 @@
#include "GPUGain.h"
#include <stdio.h>
#include "ofxsImageEffect.h"
#include "ofxsMultiThread.h"
#include "ofxsProcessing.h"
#include "ofxsLog.h"
#define kPluginName "GPU Gain"
#define kPluginGrouping "OFX Example (Support)"
#define kPluginDescription "Apply separate RGB gain adjustments to each channels; CUDA/OpenCL Buffers/OpenCL Images/Metal"
#define kPluginIdentifier "com.OpenFXSample.GPUGain"
#define kPluginVersionMajor 1
#define kPluginVersionMinor 0
#define kSupportsTiles false
#define kSupportsMultiResolution false
#define kSupportsMultipleClipPARs false
////////////////////////////////////////////////////////////////////////////////
class GainExample : public OFX::ImageProcessor
{
public:
explicit GainExample(OFX::ImageEffect& p_Instance);
virtual void processImagesCuda();
virtual void processImagesOpenCL();
virtual void processImagesMetal();
virtual void multiThreadProcessImages(OfxRectI p_ProcWindow);
void setSrcImg(OFX::Image* p_SrcImg);
void setScales(float p_ScaleR, float p_ScaleG, float p_ScaleB, float p_ScaleA);
private:
OFX::Image* _srcImg;
float _scales[4];
};
GainExample::GainExample(OFX::ImageEffect& p_Instance)
: OFX::ImageProcessor(p_Instance)
{
}
#ifdef OFX_SUPPORTS_CUDARENDER
extern void RunCudaKernel(void* p_Stream, int p_Width, int p_Height, float* p_Gain, const float* p_Input, float* p_Output);
#endif
void GainExample::processImagesCuda()
{
#ifdef OFX_SUPPORTS_CUDARENDER
const OfxRectI& bounds = _srcImg->getBounds();
const int width = bounds.x2 - bounds.x1;
const int height = bounds.y2 - bounds.y1;
float* input = static_cast<float*>(_srcImg->getPixelData());
float* output = static_cast<float*>(_dstImg->getPixelData());
RunCudaKernel(_pCudaStream, width, height, _scales, input, output);
#endif
}
#ifdef __APPLE__
extern void RunMetalKernel(void* p_CmdQ, int p_Width, int p_Height, float* p_Gain, const float* p_Input, float* p_Output);
#endif
void GainExample::processImagesMetal()
{
#ifdef __APPLE__
const OfxRectI& bounds = _srcImg->getBounds();
const int width = bounds.x2 - bounds.x1;
const int height = bounds.y2 - bounds.y1;
float* input = static_cast<float*>(_srcImg->getPixelData());
float* output = static_cast<float*>(_dstImg->getPixelData());
RunMetalKernel(_pMetalCmdQ, width, height, _scales, input, output);
#endif
}
extern void RunOpenCLKernelBuffers(void* p_CmdQ, int p_Width, int p_Height, float* p_Gain, const float* p_Input, float* p_Output);
extern void RunOpenCLKernelImages(void* p_CmdQ, int p_Width, int p_Height, float* p_Gain, const float* p_Input, float* p_Output);
void GainExample::processImagesOpenCL()
{
#ifdef OFX_SUPPORTS_OPENCLRENDER
const OfxRectI& bounds = _srcImg->getBounds();
const int width = bounds.x2 - bounds.x1;
const int height = bounds.y2 - bounds.y1;
float* input = static_cast<float*>(_srcImg->getOpenCLImage());
float* output = static_cast<float*>(_dstImg->getOpenCLImage());
// if a plugin supports both OpenCL Buffers and Images, the host decides which is used and
// the plugin must determine which based on whether kOfxImageEffectPropOpenCLImage or kOfxImagePropData is set
if (input || output)
{
RunOpenCLKernelImages(_pOpenCLCmdQ, width, height, _scales, input, output);
}
else
{
input = static_cast<float*>(_srcImg->getPixelData());
output = static_cast<float*>(_dstImg->getPixelData());
RunOpenCLKernelBuffers(_pOpenCLCmdQ, width, height, _scales, input, output);
}
#endif
}
void GainExample::multiThreadProcessImages(OfxRectI p_ProcWindow)
{
for (int y = p_ProcWindow.y1; y < p_ProcWindow.y2; ++y)
{
if (_effect.abort()) break;
float* dstPix = static_cast<float*>(_dstImg->getPixelAddress(p_ProcWindow.x1, y));
for (int x = p_ProcWindow.x1; x < p_ProcWindow.x2; ++x)
{
float* srcPix = static_cast<float*>(_srcImg ? _srcImg->getPixelAddress(x, y) : 0);
// do we have a source image to scale up
if (srcPix)
{
for(int c = 0; c < 4; ++c)
{
dstPix[c] = srcPix[c] * _scales[c];
}
}
else
{
// no src pixel here, be black and transparent
for (int c = 0; c < 4; ++c)
{
dstPix[c] = 0;
}
}
// increment the dst pixel
dstPix += 4;
}
}
}
void GainExample::setSrcImg(OFX::Image* p_SrcImg)
{
_srcImg = p_SrcImg;
}
void GainExample::setScales(float p_ScaleR, float p_ScaleG, float p_ScaleB, float p_ScaleA)
{
_scales[0] = p_ScaleR;
_scales[1] = p_ScaleG;
_scales[2] = p_ScaleB;
_scales[3] = p_ScaleA;
}
////////////////////////////////////////////////////////////////////////////////
/** @brief The plugin that does our work */
class GPUGain : public OFX::ImageEffect
{
public:
explicit GPUGain(OfxImageEffectHandle p_Handle);
/* Override the render */
virtual void render(const OFX::RenderArguments& p_Args);
/* Override is identity */
virtual bool isIdentity(const OFX::IsIdentityArguments& p_Args, OFX::Clip*& p_IdentityClip, double& p_IdentityTime);
/* Override changedParam */
virtual void changedParam(const OFX::InstanceChangedArgs& p_Args, const std::string& p_ParamName);
/* Override changed clip */
virtual void changedClip(const OFX::InstanceChangedArgs& p_Args, const std::string& p_ClipName);
/* Set the enabledness of the component scale params depending on the type of input image and the state of the scaleComponents param */
void setEnabledness();
/* Set up and run a processor */
void setupAndProcess(GainExample &p_GainExample, const OFX::RenderArguments& p_Args);
private:
// Does not own the following pointers
OFX::Clip* m_DstClip;
OFX::Clip* m_SrcClip;
OFX::DoubleParam* m_Scale;
OFX::DoubleParam* m_ScaleR;
OFX::DoubleParam* m_ScaleG;
OFX::DoubleParam* m_ScaleB;
OFX::DoubleParam* m_ScaleA;
OFX::BooleanParam* m_ComponentScalesEnabled;
};
GPUGain::GPUGain(OfxImageEffectHandle p_Handle)
: ImageEffect(p_Handle)
{
m_DstClip = fetchClip(kOfxImageEffectOutputClipName);
m_SrcClip = fetchClip(kOfxImageEffectSimpleSourceClipName);
m_Scale = fetchDoubleParam("scale");
m_ScaleR = fetchDoubleParam("scaleR");
m_ScaleG = fetchDoubleParam("scaleG");
m_ScaleB = fetchDoubleParam("scaleB");
m_ScaleA = fetchDoubleParam("scaleA");
m_ComponentScalesEnabled = fetchBooleanParam("scaleComponents");
// Set the enabledness of our RGBA sliders
setEnabledness();
}
void GPUGain::render(const OFX::RenderArguments& p_Args)
{
if ((m_DstClip->getPixelDepth() == OFX::eBitDepthFloat) && (m_DstClip->getPixelComponents() == OFX::ePixelComponentRGBA))
{
GainExample imageScaler(*this);
setupAndProcess(imageScaler, p_Args);
}
else
{
OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
}
}
bool GPUGain::isIdentity(const OFX::IsIdentityArguments& p_Args, OFX::Clip*& p_IdentityClip, double& p_IdentityTime)
{
double rScale = 1.0, gScale = 1.0, bScale = 1.0, aScale = 1.0;
if (m_ComponentScalesEnabled->getValueAtTime(p_Args.time))
{
rScale = m_ScaleR->getValueAtTime(p_Args.time);
gScale = m_ScaleG->getValueAtTime(p_Args.time);
bScale = m_ScaleB->getValueAtTime(p_Args.time);
aScale = m_ScaleA->getValueAtTime(p_Args.time);
}
const double scale = m_Scale->getValueAtTime(p_Args.time);
rScale *= scale;
gScale *= scale;
bScale *= scale;
if ((rScale == 1.0) && (gScale == 1.0) && (bScale == 1.0) && (aScale == 1.0))
{
p_IdentityClip = m_SrcClip;
p_IdentityTime = p_Args.time;
return true;
}
return false;
}
void GPUGain::changedParam(const OFX::InstanceChangedArgs& p_Args, const std::string& p_ParamName)
{
if (p_ParamName == "scaleComponents")
{
setEnabledness();
}
}
void GPUGain::changedClip(const OFX::InstanceChangedArgs& p_Args, const std::string& p_ClipName)
{
if (p_ClipName == kOfxImageEffectSimpleSourceClipName)
{
setEnabledness();
}
}
void GPUGain::setEnabledness()
{
// the component enabledness depends on the clip being RGBA and the param being true
const bool enable = (m_ComponentScalesEnabled->getValue() && (m_SrcClip->getPixelComponents() == OFX::ePixelComponentRGBA));
m_ScaleR->setEnabled(enable);
m_ScaleG->setEnabled(enable);
m_ScaleB->setEnabled(enable);
m_ScaleA->setEnabled(enable);
}
void GPUGain::setupAndProcess(GainExample& p_GainExample, const OFX::RenderArguments& p_Args)
{
// Get the dst image
std::unique_ptr<OFX::Image> dst(m_DstClip->fetchImage(p_Args.time));
OFX::BitDepthEnum dstBitDepth = dst->getPixelDepth();
OFX::PixelComponentEnum dstComponents = dst->getPixelComponents();
// Get the src image
std::unique_ptr<OFX::Image> src(m_SrcClip->fetchImage(p_Args.time));
OFX::BitDepthEnum srcBitDepth = src->getPixelDepth();
OFX::PixelComponentEnum srcComponents = src->getPixelComponents();
// Check to see if the bit depth and number of components are the same
if ((srcBitDepth != dstBitDepth) || (srcComponents != dstComponents))
{
OFX::throwSuiteStatusException(kOfxStatErrValue);
}
double rScale = 1.0, gScale = 1.0, bScale = 1.0, aScale = 1.0;
if (m_ComponentScalesEnabled->getValueAtTime(p_Args.time))
{
rScale = m_ScaleR->getValueAtTime(p_Args.time);
gScale = m_ScaleG->getValueAtTime(p_Args.time);
bScale = m_ScaleB->getValueAtTime(p_Args.time);
aScale = m_ScaleA->getValueAtTime(p_Args.time);
}
const double scale = m_Scale->getValueAtTime(p_Args.time);
rScale *= scale;
gScale *= scale;
bScale *= scale;
// Set the images
p_GainExample.setDstImg(dst.get());
p_GainExample.setSrcImg(src.get());
// Setup OpenCL and CUDA Render arguments
p_GainExample.setGPURenderArgs(p_Args);
// Set the render window
p_GainExample.setRenderWindow(p_Args.renderWindow);
// Set the scales
p_GainExample.setScales(rScale, gScale, bScale, aScale);
// Call the base class process member, this will call the derived templated process code
p_GainExample.process();
}
////////////////////////////////////////////////////////////////////////////////
using namespace OFX;
GPUGainFactory::GPUGainFactory()
: OFX::PluginFactoryHelper<GPUGainFactory>(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor)
{
}
void GPUGainFactory::describe(OFX::ImageEffectDescriptor& p_Desc)
{
// Basic labels
p_Desc.setLabels(kPluginName, kPluginName, kPluginName);
p_Desc.setPluginGrouping(kPluginGrouping);
p_Desc.setPluginDescription(kPluginDescription);
// Add the supported contexts, only filter at the moment
p_Desc.addSupportedContext(eContextFilter);
p_Desc.addSupportedContext(eContextGeneral);
// Add supported pixel depths
p_Desc.addSupportedBitDepth(eBitDepthFloat);
// Set a few flags
p_Desc.setSingleInstance(false);
p_Desc.setHostFrameThreading(false);
p_Desc.setSupportsMultiResolution(kSupportsMultiResolution);
p_Desc.setSupportsTiles(kSupportsTiles);
p_Desc.setTemporalClipAccess(false);
p_Desc.setRenderTwiceAlways(false);
p_Desc.setSupportsMultipleClipPARs(kSupportsMultipleClipPARs);
// Setup OpenCL render capability flags
p_Desc.setSupportsOpenCLBuffersRender(true);
p_Desc.setSupportsOpenCLImagesRender(true);
// Setup CUDA render capability flags on non-Apple system
#ifndef __APPLE__
p_Desc.setSupportsCudaRender(true);
p_Desc.setSupportsCudaStream(true);
#endif
// Setup Metal render capability flags only on Apple system
#ifdef __APPLE__
p_Desc.setSupportsMetalRender(true);
#endif
}
static DoubleParamDescriptor* defineScaleParam(OFX::ImageEffectDescriptor& p_Desc, const std::string& p_Name, const std::string& p_Label,
const std::string& p_Hint, GroupParamDescriptor* p_Parent)
{
DoubleParamDescriptor* param = p_Desc.defineDoubleParam(p_Name);
param->setLabels(p_Label, p_Label, p_Label);
param->setScriptName(p_Name);
param->setHint(p_Hint);
param->setDefault(1);
param->setRange(0, 10);
param->setIncrement(0.1);
param->setDisplayRange(0, 10);
param->setDoubleType(eDoubleTypeScale);
if (p_Parent)
{
param->setParent(*p_Parent);
}
return param;
}
void GPUGainFactory::describeInContext(OFX::ImageEffectDescriptor& p_Desc, OFX::ContextEnum /*p_Context*/)
{
// Source clip only in the filter context
// Create the mandated source clip
ClipDescriptor* srcClip = p_Desc.defineClip(kOfxImageEffectSimpleSourceClipName);
srcClip->addSupportedComponent(ePixelComponentRGBA);
srcClip->setTemporalClipAccess(false);
srcClip->setSupportsTiles(kSupportsTiles);
srcClip->setIsMask(false);
// Create the mandated output clip
ClipDescriptor* dstClip = p_Desc.defineClip(kOfxImageEffectOutputClipName);
dstClip->addSupportedComponent(ePixelComponentRGBA);
dstClip->addSupportedComponent(ePixelComponentAlpha);
dstClip->setSupportsTiles(kSupportsTiles);
// Make some pages and to things in
PageParamDescriptor* page = p_Desc.definePageParam("Controls");
// Group param to group the scales
GroupParamDescriptor* componentScalesGroup = p_Desc.defineGroupParam("componentScales");
componentScalesGroup->setHint("Scales on the individual component");
componentScalesGroup->setLabels("Components", "Components", "Components");
// Make overall scale params
DoubleParamDescriptor* param = defineScaleParam(p_Desc, "scale", "scale", "Scales all component in the image", 0);
page->addChild(*param);
// Add a boolean to enable the component scale
BooleanParamDescriptor* boolParam = p_Desc.defineBooleanParam("scaleComponents");
boolParam->setDefault(true);
boolParam->setHint("Enables scales on individual components");
boolParam->setLabels("Scale Components", "Scale Components", "Scale Components");
boolParam->setParent(*componentScalesGroup);
page->addChild(*boolParam);
// Make the four component scale params
param = defineScaleParam(p_Desc, "scaleR", "red", "Scales the red component of the image", componentScalesGroup);
page->addChild(*param);
param = defineScaleParam(p_Desc, "scaleG", "green", "Scales the green component of the image", componentScalesGroup);
page->addChild(*param);
param = defineScaleParam(p_Desc, "scaleB", "blue", "Scales the blue component of the image", componentScalesGroup);
page->addChild(*param);
param = defineScaleParam(p_Desc, "scaleA", "alpha", "Scales the alpha component of the image", componentScalesGroup);
page->addChild(*param);
}
ImageEffect* GPUGainFactory::createInstance(OfxImageEffectHandle p_Handle, ContextEnum /*p_Context*/)
{
return new GPUGain(p_Handle);
}
void OFX::Plugin::getPluginIDs(PluginFactoryArray& p_FactoryArray)
{
static GPUGainFactory gainPlugin;
p_FactoryArray.push_back(&gainPlugin);
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "ofxsImageEffect.h"
class GPUGainFactory : public OFX::PluginFactoryHelper<GPUGainFactory>
{
public:
GPUGainFactory();
virtual void load() {}
virtual void unload() {}
virtual void describe(OFX::ImageEffectDescriptor& p_Desc);
virtual void describeInContext(OFX::ImageEffectDescriptor& p_Desc, OFX::ContextEnum p_Context);
virtual OFX::ImageEffect* createInstance(OfxImageEffectHandle p_Handle, OFX::ContextEnum p_Context);
};
+21
View File
@@ -0,0 +1,21 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GPUGain", "GPUGain.vcxproj", "{88405F0E-918E-4523-8627-1380BC83A605}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{88405F0E-918E-4523-8627-1380BC83A605}.Debug|x64.ActiveCfg = Debug|x64
{88405F0E-918E-4523-8627-1380BC83A605}.Debug|x64.Build.0 = Debug|x64
{88405F0E-918E-4523-8627-1380BC83A605}.Release|x64.ActiveCfg = Release|x64
{88405F0E-918E-4523-8627-1380BC83A605}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{88405F0E-918E-4523-8627-1380BC83A605}</ProjectGuid>
<RootNamespace>GPUGain</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(VCTargetsPath)\BuildCustomizations\CUDA 8.0.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>12.0.30501.0</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(CUDA_INC_PATH);$(AMDAPPSDKROOT)/include;../OpenFX-1.4/include;../Support/include</IncludePath>
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(CUDA_LIB_PATH);$(AMDAPPSDKROOT)/lib/x86_64</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(CUDA_INC_PATH);$(AMDAPPSDKROOT)/include;../OpenFX-1.4/include;../Support/include</IncludePath>
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(CUDA_LIB_PATH);$(AMDAPPSDKROOT)/lib/x86_64</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PreBuildEvent>
<Command />
</PreBuildEvent>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;cuda.lib;cudart.lib;OpenCL.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Message>Creating bundle...</Message>
<Command>if not exist "$(OutDir)GPUGain.ofx.bundle\Contents\Resources" mkdir "$(OutDir)GPUGain.ofx.bundle\Contents\Resources"
if not exist "$(OutDir)GPUGain.ofx.bundle\Contents\Win64" mkdir "$(OutDir)GPUGain.ofx.bundle\Contents\Win64"
copy /Y "$(TargetPath)" /B "$(OutDir)GPUGain.ofx.bundle\Contents\Win64\GPUGain.ofx" /B
</Command>
</PostBuildEvent>
<CudaCompile>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX64</TargetMachine>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;cuda.lib;cudart.lib;OpenCL.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Message>Creating bundle...</Message>
<Command>if not exist "$(OutDir)GPUGain.ofx.bundle\Contents\Resources" mkdir "$(OutDir)GPUGain.ofx.bundle\Contents\Resources"
if not exist "$(OutDir)GPUGain.ofx.bundle\Contents\Win64" mkdir "$(OutDir)GPUGain.ofx.bundle\Contents\Win64"
copy /Y "$(TargetPath)" /B "$(OutDir)GPUGain.ofx.bundle\Contents\Win64\GPUGain.ofx" /B
</Command>
</PostBuildEvent>
<CudaCompile>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Support\Library\ofxsCore.cpp" />
<ClCompile Include="..\Support\Library\ofxsImageEffect.cpp" />
<ClCompile Include="..\Support\Library\ofxsInteract.cpp" />
<ClCompile Include="..\Support\Library\ofxsLog.cpp" />
<ClCompile Include="..\Support\Library\ofxsMultiThread.cpp" />
<ClCompile Include="..\Support\Library\ofxsParams.cpp" />
<ClCompile Include="..\Support\Library\ofxsProperty.cpp" />
<ClCompile Include="..\Support\Library\ofxsPropertyValidation.cpp" />
<ClCompile Include="GPUGain.cpp" />
<ClCompile Include="OpenCLKernel.cpp" />
</ItemGroup>
<ItemGroup>
<CudaCompile Include="CudaKernel.cu" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\CUDA 8.0.targets" />
</ImportGroup>
</Project>
@@ -0,0 +1,225 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXFileReference section */
3DF51C6C1CB741110070CA48 /* CudaKernel.cu */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CudaKernel.cu; sourceTree = "<group>"; };
3DF51C6D1CB741110070CA48 /* GPUGain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GPUGain.cpp; sourceTree = "<group>"; };
3DF51C6E1CB741110070CA48 /* GPUGain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPUGain.h; sourceTree = "<group>"; };
3DF51C701CB741110070CA48 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
3DF51C711CB741110070CA48 /* OpenCLKernel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpenCLKernel.cpp; sourceTree = "<group>"; };
3DF51C721CB7413B0070CA48 /* ofxsCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ofxsCore.cpp; path = ../../Support/Library/ofxsCore.cpp; sourceTree = "<group>"; };
3DF51C731CB7413B0070CA48 /* ofxsImageEffect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ofxsImageEffect.cpp; path = ../../Support/Library/ofxsImageEffect.cpp; sourceTree = "<group>"; };
3DF51C741CB7413B0070CA48 /* ofxsInteract.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ofxsInteract.cpp; path = ../../Support/Library/ofxsInteract.cpp; sourceTree = "<group>"; };
3DF51C751CB7413B0070CA48 /* ofxsLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ofxsLog.cpp; path = ../../Support/Library/ofxsLog.cpp; sourceTree = "<group>"; };
3DF51C761CB7413B0070CA48 /* ofxsMultiThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ofxsMultiThread.cpp; path = ../../Support/Library/ofxsMultiThread.cpp; sourceTree = "<group>"; };
3DF51C771CB7413B0070CA48 /* ofxsParams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ofxsParams.cpp; path = ../../Support/Library/ofxsParams.cpp; sourceTree = "<group>"; };
3DF51C781CB7413B0070CA48 /* ofxsProperty.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ofxsProperty.cpp; path = ../../Support/Library/ofxsProperty.cpp; sourceTree = "<group>"; };
3DF51C791CB7413B0070CA48 /* ofxsPropertyValidation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ofxsPropertyValidation.cpp; path = ../../Support/Library/ofxsPropertyValidation.cpp; sourceTree = "<group>"; };
4F799E1E1EC4662F00E46226 /* MetalKernel.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MetalKernel.mm; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXGroup section */
3D2F26961CBB8F6B00FC8803 /* Support */ = {
isa = PBXGroup;
children = (
3DF51C721CB7413B0070CA48 /* ofxsCore.cpp */,
3DF51C731CB7413B0070CA48 /* ofxsImageEffect.cpp */,
3DF51C741CB7413B0070CA48 /* ofxsInteract.cpp */,
3DF51C751CB7413B0070CA48 /* ofxsLog.cpp */,
3DF51C761CB7413B0070CA48 /* ofxsMultiThread.cpp */,
3DF51C771CB7413B0070CA48 /* ofxsParams.cpp */,
3DF51C781CB7413B0070CA48 /* ofxsProperty.cpp */,
3DF51C791CB7413B0070CA48 /* ofxsPropertyValidation.cpp */,
);
name = Support;
sourceTree = "<group>";
};
3DF51C611CB740BF0070CA48 = {
isa = PBXGroup;
children = (
3D2F26961CBB8F6B00FC8803 /* Support */,
3DF51C6C1CB741110070CA48 /* CudaKernel.cu */,
3DF51C6D1CB741110070CA48 /* GPUGain.cpp */,
3DF51C6E1CB741110070CA48 /* GPUGain.h */,
3DF51C701CB741110070CA48 /* Makefile */,
3DF51C711CB741110070CA48 /* OpenCLKernel.cpp */,
4F799E1E1EC4662F00E46226 /* MetalKernel.mm */,
);
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXLegacyTarget section */
3DF51C661CB740BF0070CA48 /* GPUGain */ = {
isa = PBXLegacyTarget;
buildArgumentsString = "$(ACTION)";
buildConfigurationList = 3DF51C691CB740BF0070CA48 /* Build configuration list for PBXLegacyTarget "GPUGain" */;
buildPhases = (
);
buildToolPath = /usr/bin/make;
dependencies = (
);
name = GPUGain;
passBuildSettingsInEnvironment = 1;
productName = GPUGain;
};
/* End PBXLegacyTarget section */
/* Begin PBXProject section */
3DF51C621CB740BF0070CA48 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0640;
ORGANIZATIONNAME = blackmagicdesign;
TargetAttributes = {
3DF51C661CB740BF0070CA48 = {
CreatedOnToolsVersion = 6.4;
};
};
};
buildConfigurationList = 3DF51C651CB740BF0070CA48 /* Build configuration list for PBXProject "GPUGain" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
);
mainGroup = 3DF51C611CB740BF0070CA48;
projectDirPath = "";
projectRoot = "";
targets = (
3DF51C661CB740BF0070CA48 /* GPUGain */,
);
};
/* End PBXProject section */
/* Begin XCBuildConfiguration section */
3DF51C671CB740BF0070CA48 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
3DF51C681CB740BF0070CA48 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
};
name = Release;
};
3DF51C6A1CB740BF0070CA48 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEBUGGING_SYMBOLS = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
3DF51C6B1CB740BF0070CA48 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
3DF51C651CB740BF0070CA48 /* Build configuration list for PBXProject "GPUGain" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3DF51C671CB740BF0070CA48 /* Debug */,
3DF51C681CB740BF0070CA48 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
3DF51C691CB740BF0070CA48 /* Build configuration list for PBXLegacyTarget "GPUGain" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3DF51C6A1CB740BF0070CA48 /* Debug */,
3DF51C6B1CB740BF0070CA48 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 3DF51C621CB740BF0070CA48 /* Project object */;
}
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>GPUGain.ofx</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.0.1d1</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,108 @@
#import <Metal/Metal.h>
#include <unordered_map>
#include <mutex>
const char* kernelSource = \
"#include <metal_stdlib>\n" \
"using namespace metal; \n" \
"kernel void GainAdjustKernel(constant int& p_Width [[buffer (11)]], constant int& p_Height [[buffer (12)]], constant float& p_GainR [[buffer (13)]], \n" \
" constant float& p_GainG [[buffer (14)]], constant float& p_GainB [[buffer (15)]], constant float& p_GainA [[buffer (16)]], \n" \
" const device float* p_Input [[buffer (0)]], device float* p_Output [[buffer (8)]], uint2 id [[ thread_position_in_grid ]]) \n" \
"{ \n" \
" if ((id.x < p_Width) && (id.y < p_Height)) \n" \
" { \n" \
" const int index = ((id.y * p_Width) + id.x) * 4; \n" \
" p_Output[index + 0] = p_Input[index + 0] * p_GainR; \n" \
" p_Output[index + 1] = p_Input[index + 1] * p_GainG; \n" \
" p_Output[index + 2] = p_Input[index + 2] * p_GainB; \n" \
" p_Output[index + 3] = p_Input[index + 3] * p_GainA; \n" \
" } \n" \
"} \n";
std::mutex s_PipelineQueueMutex;
typedef std::unordered_map<id<MTLCommandQueue>, id<MTLComputePipelineState>> PipelineQueueMap;
PipelineQueueMap s_PipelineQueueMap;
void RunMetalKernel(void* p_CmdQ, int p_Width, int p_Height, float* p_Gain, const float* p_Input, float* p_Output)
{
const char* kernelName = "GainAdjustKernel";
id<MTLCommandQueue> queue = static_cast<id<MTLCommandQueue> >(p_CmdQ);
id<MTLDevice> device = queue.device;
id<MTLLibrary> metalLibrary; // Metal library
id<MTLFunction> kernelFunction; // Compute kernel
id<MTLComputePipelineState> pipelineState; // Metal pipeline
NSError* err;
std::unique_lock<std::mutex> lock(s_PipelineQueueMutex);
const auto it = s_PipelineQueueMap.find(queue);
if (it == s_PipelineQueueMap.end())
{
id<MTLLibrary> metalLibrary; // Metal library
id<MTLFunction> kernelFunction; // Compute kernel
NSError* err;
MTLCompileOptions* options = [MTLCompileOptions new];
options.fastMathEnabled = YES;
if (!(metalLibrary = [device newLibraryWithSource:@(kernelSource) options:options error:&err]))
{
fprintf(stderr, "Failed to load metal library, %s\n", err.localizedDescription.UTF8String);
return;
}
[options release];
if (!(kernelFunction = [metalLibrary newFunctionWithName:[NSString stringWithUTF8String:kernelName]/* constantValues : constantValues */]))
{
fprintf(stderr, "Failed to retrieve kernel\n");
[metalLibrary release];
return;
}
if (!(pipelineState = [device newComputePipelineStateWithFunction:kernelFunction error:&err]))
{
fprintf(stderr, "Unable to compile, %s\n", err.localizedDescription.UTF8String);
[metalLibrary release];
[kernelFunction release];
return;
}
s_PipelineQueueMap[queue] = pipelineState;
//Release resources
[metalLibrary release];
[kernelFunction release];
}
else
{
pipelineState = it->second;
}
id<MTLBuffer> srcDeviceBuf = reinterpret_cast<id<MTLBuffer> >(const_cast<float *>(p_Input));
id<MTLBuffer> dstDeviceBuf = reinterpret_cast<id<MTLBuffer> >(p_Output);
id<MTLCommandBuffer> commandBuffer = [queue commandBuffer];
commandBuffer.label = [NSString stringWithFormat:@"GainAdjustKernel"];
id<MTLComputeCommandEncoder> computeEncoder = [commandBuffer computeCommandEncoder];
[computeEncoder setComputePipelineState:pipelineState];
int exeWidth = [pipelineState threadExecutionWidth];
MTLSize threadGroupCount = MTLSizeMake(exeWidth, 1, 1);
MTLSize threadGroups = MTLSizeMake((p_Width + exeWidth - 1)/exeWidth, p_Height, 1);
[computeEncoder setBuffer:srcDeviceBuf offset: 0 atIndex: 0];
[computeEncoder setBuffer:dstDeviceBuf offset: 0 atIndex: 8];
[computeEncoder setBytes:&p_Width length:sizeof(int) atIndex:11];
[computeEncoder setBytes:&p_Height length:sizeof(int) atIndex:12];
[computeEncoder setBytes:&p_Gain[0] length:sizeof(float) atIndex:13];
[computeEncoder setBytes:&p_Gain[1] length:sizeof(float) atIndex:14];
[computeEncoder setBytes:&p_Gain[2] length:sizeof(float) atIndex:15];
[computeEncoder setBytes:&p_Gain[3] length:sizeof(float) atIndex:16];
[computeEncoder dispatchThreadgroups:threadGroups threadsPerThreadgroup: threadGroupCount];
[computeEncoder endEncoding];
[commandBuffer commit];
}

Some files were not shown because too many files have changed in this diff Show More