From 8a7b6cf8690e16d8a1958a2a943318cb7930134f Mon Sep 17 00:00:00 2001 From: Mike Solar Date: Sun, 9 Nov 2025 17:03:56 +0800 Subject: [PATCH] Add OFX plugin support and related infrastructure This commit extends the OFX plugin support in Olive by: - Initializing and scanning for OFX plugins - Updating PluginNode to handle OFX plugin parameters and inputs - Adding necessary methods and properties for OFX plugin integration - Enhancing NodeFactory to include OFX plugin nodes - Refactoring and renaming OliveInstance to OlivePluginInstance - Introducing new classes for parameter handling (ParamInstance) - Adding PluginJob for rendering OFX plugins - Adjusting CMakeLists.txt files to include new source files --- app/CMakeLists.txt | 2 + app/common/Current.h | 24 +++ app/node/factory.cpp | 16 ++ app/node/node.h | 6 +- app/node/plugins/Plugin.cpp | 95 ++++++++--- app/node/plugins/Plugin.h | 56 +++++-- app/node/traverser.cpp | 4 + app/node/value.h | 8 +- app/pluginSupport/CMakeLists.txt | 8 +- app/pluginSupport/OliveHost.cpp | 17 +- app/pluginSupport/OliveHost.h | 5 +- ...veInstance.cpp => OlivePluginInstance.cpp} | 29 ++-- ...{OliveInstance.h => OlivePluginInstance.h} | 12 +- app/pluginSupport/paraminstance.cpp | 22 +++ app/pluginSupport/paraminstance.h | 149 ++++++++++++++++++ app/render/job/CMakeLists.txt | 4 +- app/render/job/acceleratedjob.h | 14 +- app/render/job/pluginjob.cpp | 25 +++ app/render/job/pluginjob.h | 50 ++++++ app/render/plugin/CMakeLists.txt | 1 + app/render/plugin/pluginrenderer.cpp | 33 ++++ app/render/plugin/pluginrenderer.h | 46 ++++++ app/render/renderprocessor.cpp | 9 +- 23 files changed, 545 insertions(+), 90 deletions(-) rename app/pluginSupport/{OliveInstance.cpp => OlivePluginInstance.cpp} (79%) rename app/pluginSupport/{OliveInstance.h => OlivePluginInstance.h} (96%) create mode 100644 app/pluginSupport/paraminstance.cpp create mode 100644 app/pluginSupport/paraminstance.h create mode 100644 app/render/job/pluginjob.cpp create mode 100644 app/render/job/pluginjob.h create mode 100644 app/render/plugin/CMakeLists.txt create mode 100644 app/render/plugin/pluginrenderer.cpp create mode 100644 app/render/plugin/pluginrenderer.h diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 37ccd41ed..f3a57ec33 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -55,6 +55,8 @@ configure_file(ts/translations.qrc.in ts/translations.qrc @ONLY) set(OLIVE_RESOURCES ${OLIVE_RESOURCES} ${CMAKE_CURRENT_BINARY_DIR}/ts/translations.qrc + render/job/pluginjob.cpp + render/job/pluginjob.h ) # Add version object diff --git a/app/common/Current.h b/app/common/Current.h index aee702922..44487a2c0 100644 --- a/app/common/Current.h +++ b/app/common/Current.h @@ -19,7 +19,9 @@ #ifndef CURRENT_H #define CURRENT_H +#include "pluginSupport/OliveHost.h" #include "render/videoparams.h" +#include "render/job/pluginjob.h" class Current { public: @@ -55,10 +57,32 @@ public: { return true; } + + std::shared_ptr pluginHost() + { + return myHost; + } + + void setPluginHost(std::shared_ptr host) + { + myHost = host; + } + + std::shared_ptr pluginCache() + { + return plugin_cache_; + } + + void setPluginCache(std::shared_ptr cache) + { + plugin_cache_ = cache; + } private: static Current current; olive::VideoParams currentVideoParams_; olive::AudioParams currentAudioParams_; + std::shared_ptr myHost; + std::shared_ptr plugin_cache_; }; diff --git a/app/node/factory.cpp b/app/node/factory.cpp index 9529137ab..5d0400bba 100644 --- a/app/node/factory.cpp +++ b/app/node/factory.cpp @@ -29,6 +29,7 @@ #include "block/transition/diptocolor/diptocolortransition.h" #include "color/displaytransform/displaytransform.h" #include "color/ociogradingtransformlinear/ociogradingtransformlinear.h" +#include "common/Current.h" #include "distort/cornerpin/cornerpindistortnode.h" #include "distort/crop/cropdistortnode.h" #include "distort/flip/flipdistortnode.h" @@ -62,6 +63,8 @@ #include "math/trigonometry/trigonometry.h" #include "output/track/track.h" #include "output/viewer/viewer.h" +#include "pluginSupport/OliveHost.h" +#include "plugins/Plugin.h" #include "project/folder/folder.h" #include "project/footage/footage.h" #include "project/sequence/sequence.h" @@ -84,6 +87,19 @@ void NodeFactory::Initialize() library_.append(created_node); } + + std::shared_ptr host=std::make_shared(); + Current::getInstance().setPluginHost(host); + std::shared_ptr plugin_cache=std::make_shared(*host); + plugin_cache->registerInCache(*OFX::Host::PluginCache::getPluginCache()); + OFX::Host::PluginCache::getPluginCache()->scanPluginFiles(); + + + for (auto plugin : OFX::Host::PluginCache::getPluginCache()->getPlugins()) { + plugin::PluginNode *plugin_node=new plugin::PluginNode(dynamic_cast(plugin)); + library_.append(plugin_node); + } + } void NodeFactory::Destroy() diff --git a/app/node/node.h b/app/node/node.h index b2f05d95f..f73de0ee2 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -19,6 +19,8 @@ #ifndef NODE_H #define NODE_H +#include "ofxhImageEffectAPI.h" + #include #include #include @@ -1124,11 +1126,11 @@ public: static const QString kEnabledInput; - std::shared_ptr getPlugin(); + OFX::Host::ImageEffect::ImageEffectPlugin* getPlugin(); protected: // If is set, this is a plugin node. - std::shared_ptr plugin; + OFX::Host::ImageEffect::ImageEffectPlugin* plugin= nullptr; void InsertInput(const QString &id, NodeValue::Type type, const QVariant &default_value, InputFlags flags, diff --git a/app/node/plugins/Plugin.cpp b/app/node/plugins/Plugin.cpp index f1b9b68b8..af663eb71 100644 --- a/app/node/plugins/Plugin.cpp +++ b/app/node/plugins/Plugin.cpp @@ -17,44 +17,89 @@ */ #include "Plugin.h" + +#include "render/rendermanager.h" +#include "render/job/pluginjob.h" +olive::plugin::PluginNode::PluginNode( + OFX::Host::ImageEffect::ImageEffectPlugin *plugin) +{ + this->plugin = plugin; + auto params = plugin->getDescriptor().getParams(); + + for (auto param: params) { + + NodeValue::Type type; + + const std::string &ofxType = param.second->getType(); + if (ofxType == kOfxParamTypeInteger) { + type = NodeValue::kInt; + } else if (ofxType == kOfxParamTypeDouble) { + type = NodeValue::kFloat; + } else if (ofxType == kOfxParamTypeBoolean) { + type = NodeValue::kBoolean; + } else if (ofxType == kOfxParamTypeString) { + type = NodeValue::kText; + } else if (ofxType == kOfxParamTypeRGB || + ofxType == kOfxParamTypeRGBA) { + type = NodeValue::kColor; + } else if (ofxType == kOfxParamTypeChoice) { + type = NodeValue::kCombo; + } else if (ofxType == kOfxParamTypeDouble2D || + ofxType == kOfxParamTypeInteger2D){ + type = NodeValue::kVec2;} + else if (ofxType == kOfxParamTypeDouble3D || + ofxType == kOfxParamTypeInteger3D){ + type = NodeValue::kVec3; + } else if (ofxType == kOfxParamTypeStrChoice){ + type = NodeValue::kStrCombo; + }else if (ofxType == kOfxParamTypeBytes + || ofxType == kOfxParamTypeCustom) { + type = NodeValue::kBinary; + } else { + type = NodeValue::kNone; + } + + if (ofxType == kOfxParamTypePushButton) { + // TODO + } else if (ofxType == kOfxParamTypeGroup) { + // TODO + } else if (ofxType == kOfxParamTypePage) { + // TODO + } + + AddInput(param.second->getName().data(), type); + } + +} QString olive::plugin::PluginNode::Name() const { - if (methods.name) { - char buffer[64]={0}; - bool ok=methods.name(buffer, 64); - if (ok) { - return QString(buffer); - } - } - return ""; + return plugin->getDescriptor() + .getProps() + .getStringProperty(kOfxPropLabel) + .data(); + } QString olive::plugin::PluginNode::Description() const { - if (methods.description) { - char buffer[1024] = { 0 }; - bool ok = methods.description(buffer, 1024); - if (ok) { - return QString(buffer); - } - } - return ""; + return plugin->getDescriptor().getProps().getStringProperty(kOfxPropPluginDescription).data(); + } void olive::plugin::PluginNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - methods.value(&node_ctx_functions); + TexturePtr tex = value[kTextureInput].toTexture(); + if (tex) { + PluginJob job(,value); + table->Push(NodeValue::kTexture, tex->toJob(job), this); + } + + + } QString olive::plugin::PluginNode::id() const { - if (methods.id) { - char buffer[64]={0}; - bool ok=methods.id(buffer, 64); - if (ok) { - return QString(buffer); - } - } - return ""; + return plugin->getIdentifier().data(); } \ No newline at end of file diff --git a/app/node/plugins/Plugin.h b/app/node/plugins/Plugin.h index 5e69358dc..b2ab6b5fd 100644 --- a/app/node/plugins/Plugin.h +++ b/app/node/plugins/Plugin.h @@ -18,36 +18,60 @@ #ifndef PLUGIN_NODES_H #define PLUGIN_NODES_H +#include "ofxhImageEffectAPI.h" +#include "ofxhPluginCache.h" #include "node/node.h" -#include "pluginSupport/Plugin.h" -#include "pluginSupport/OlivePlugin.cpp" + namespace olive { namespace plugin { +const QString kTextureInput = QStringLiteral("tex_in"); class PluginNode : public olive::Node{ public: - PluginNode():Node() - { - memset(&methods, 0, sizeof(olive_node_methods)); - }; - explicit PluginNode(struct olive_node_methods methods):Node() - { - this->methods=methods; - } - void setMethods(struct olive_node_methods methods) - { - this->methods=methods; - } + PluginNode(OFX::Host::ImageEffect::ImageEffectPlugin* plugin) ; + + QString Name() const override; QString id() const override; QVector Category() const override; QString Description() const override; + + void AddPushButton(); + void AddPage(); + Node *copy() const override; + /** + * @brief The main processing function + * + * The node's main purpose is to take values from inputs to set values in outputs. For whatever subclass node you + * create, this is where the code for that goes. + * + * Note that as a video editor, the node graph has to work across time. Depending on the purpose of your node, it may + * output different values depending on the time, and even if not, it will likely be receiving different input + * depending on the time. Most of the difficult work here is handled by NodeInput::get_value() which you should pass + * the `time` parameter to. It will return its value (at that time, if it's keyframed), or pass the time to a + * corresponding output if it's connected to one. If your node doesn't directly deal with time, the default behavior + * of the NodeParam objects will handle everything related to it automatically. + */ void Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const override; -private: - struct olive_node_methods methods; + + /** + * @brief If Value() pushes a ShaderJob, this is the function that will process them. + */ + virtual void ProcessSamples(const NodeValueRow &values, + const SampleBuffer &input, SampleBuffer &output, + int index) const; + + /** + * @brief If Value() pushes a GenerateJob, override this function for the image to create + * + * @param frame + * + * The destination buffer. It will already be allocated and ready for writing to. + */ + virtual void GenerateFrame(FramePtr frame, const GenerateJob &job) const; }; diff --git a/app/node/traverser.cpp b/app/node/traverser.cpp index 401446c85..f31aba4c8 100644 --- a/app/node/traverser.cpp +++ b/app/node/traverser.cpp @@ -387,6 +387,10 @@ QVector2D NodeTraverser::GenerateResolution() const video_params_.height()); } +/** + * Resolve Jobs. I need to add a PluginJob here and move the plugin code here. + * @param val + */ void NodeTraverser::ResolveJobs(NodeValue &val) { if (val.type() == NodeValue::kTexture) { diff --git a/app/node/value.h b/app/node/value.h index 590d5638d..43f370bf4 100644 --- a/app/node/value.h +++ b/app/node/value.h @@ -163,7 +163,13 @@ public: * Resolves to `int` - the index currently selected */ kCombo, - + /** + * ComboBox type + * + * Resolves to `QString` - the text of choice currently selected + * This is to support the OpenFX type kOfxParamTypeStrChoice + */ + kStrCombo, /** * Video Parameters type * diff --git a/app/pluginSupport/CMakeLists.txt b/app/pluginSupport/CMakeLists.txt index 19b62b0f8..23adfb8ad 100644 --- a/app/pluginSupport/CMakeLists.txt +++ b/app/pluginSupport/CMakeLists.txt @@ -1,6 +1,10 @@ target_sources(libolive-editor PRIVATE OliveHost.h OliveHost.cpp - OliveInstance.h - OliveInstance.cpp + OlivePluginInstance.h + OlivePluginInstance.cpp + OliveClip.cpp + OliveClip.h + paraminstance.cpp + paraminstance.h ) \ No newline at end of file diff --git a/app/pluginSupport/OliveHost.cpp b/app/pluginSupport/OliveHost.cpp index d0a0e1355..c0a3c95c9 100644 --- a/app/pluginSupport/OliveHost.cpp +++ b/app/pluginSupport/OliveHost.cpp @@ -26,22 +26,15 @@ #include #include "OliveHost.h" -#include "OliveInstance.h" +#include "OlivePluginInstance.h" #include "common/Current.h" using namespace OFX::Host; using namespace olive::plugin; -void loadPlugins(QString path) + +void olive::plugin::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()); - - } - } + OFX::Host::ImageEffect::PluginCache imageEffectPluginCache(myHost); } - OliveHost::~OliveHost() { for(auto& descriptor:descriptors_){ @@ -82,7 +75,7 @@ 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 OliveInstance(plugin,desc,context,Current::getInstance().interactive()); + ImageEffect::Instance* instance=new OlivePluginInstance(plugin,desc,context,Current::getInstance().interactive()); instances_.append(instance); return instance; }; diff --git a/app/pluginSupport/OliveHost.h b/app/pluginSupport/OliveHost.h index f0d39d633..4fb5f020a 100644 --- a/app/pluginSupport/OliveHost.h +++ b/app/pluginSupport/OliveHost.h @@ -15,6 +15,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#ifndef OLIVE_HOST_H +#define OLIVE_HOST_H #include "ofxhHost.h" #include "ofxhImageEffectAPI.h" #include "ofxCore.h" @@ -66,4 +68,5 @@ private: QList instances_; }; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/app/pluginSupport/OliveInstance.cpp b/app/pluginSupport/OlivePluginInstance.cpp similarity index 79% rename from app/pluginSupport/OliveInstance.cpp rename to app/pluginSupport/OlivePluginInstance.cpp index f653aeeaf..f39110443 100644 --- a/app/pluginSupport/OliveInstance.cpp +++ b/app/pluginSupport/OlivePluginInstance.cpp @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "OliveInstance.h" +#include "OlivePluginInstance.h" #include "OliveClip.h" #include "ofxCore.h" @@ -28,11 +28,12 @@ #include #include #include +#include "paraminstance.h" namespace olive { namespace plugin { -OfxStatus OliveInstance::vmessage(const char *type, const char *id, +OfxStatus OlivePluginInstance::vmessage(const char *type, const char *id, const char *format, va_list args) { char *buffer = new char[1024]; @@ -59,7 +60,7 @@ OfxStatus OliveInstance::vmessage(const char *type, const char *id, return kOfxStatOK; } } -OfxStatus OliveInstance::setPersistentMessage(const char *type, const char *id, +OfxStatus OlivePluginInstance::setPersistentMessage(const char *type, const char *id, const char *format, va_list args) { char *buffer = new char[1024]; @@ -95,66 +96,66 @@ OfxStatus OliveInstance::setPersistentMessage(const char *type, const char *id, } return kOfxStatOK; } -OfxStatus OliveInstance::clearPersistentMessage() +OfxStatus OlivePluginInstance::clearPersistentMessage() { persistentErrors_.clear(); // TODO: tell the shell to remove message. return kOfxStatOK; } -void OliveInstance::getProjectSize(double &xSize, double &ySize) const +void OlivePluginInstance::getProjectSize(double &xSize, double &ySize) const { xSize =params_.width(); ySize =params_.height(); } -void OliveInstance::getProjectOffset(double &xOffset, double &yOffset) const +void OlivePluginInstance::getProjectOffset(double &xOffset, double &yOffset) const { xOffset =params_.x(); yOffset =params_.y(); } -void OliveInstance::getProjectExtent(double &xSize, double &ySize) const +void OlivePluginInstance::getProjectExtent(double &xSize, double &ySize) const { xSize =params_.width(); ySize =params_.height(); // TODO: Ensure this project does not support this. } -double OliveInstance::getProjectPixelAspectRatio() const +double OlivePluginInstance::getProjectPixelAspectRatio() const { return Current::getInstance() .currentVideoParams() .pixel_aspect_ratio() .toDouble(); } -double OliveInstance::getFrameRate() const +double OlivePluginInstance::getFrameRate() const { return params_.frame_rate().toDouble(); } -double OliveInstance::getEffectDuration() const +double OlivePluginInstance::getEffectDuration() const { // Return a default duration value return 100.0; } -double OliveInstance::getFrameRecursive() const +double OlivePluginInstance::getFrameRecursive() const { // Return current frame (this would typically be set by the host during rendering) return 0.0; } -void OliveInstance::getRenderScaleRecursive(double &x, double &y) const +void OlivePluginInstance::getRenderScaleRecursive(double &x, double &y) const { // Return default render scale (1.0, 1.0) x = 1.0; y = 1.0; } OFX::Host::Param::Instance * -OliveInstance::newParam(const std::string &name, +OlivePluginInstance::newParam(const std::string &name, OFX::Host::Param::Descriptor &Descriptor) { } -OFX::Host::ImageEffect::ClipInstance *OliveInstance::newClipInstance( +OFX::Host::ImageEffect::ClipInstance *OlivePluginInstance::newClipInstance( OFX::Host::ImageEffect::Instance *plugin, OFX::Host::ImageEffect::ClipDescriptor *descriptor, int index) diff --git a/app/pluginSupport/OliveInstance.h b/app/pluginSupport/OlivePluginInstance.h similarity index 96% rename from app/pluginSupport/OliveInstance.h rename to app/pluginSupport/OlivePluginInstance.h index 5e2e0178d..db59e04c6 100644 --- a/app/pluginSupport/OliveInstance.h +++ b/app/pluginSupport/OlivePluginInstance.h @@ -15,7 +15,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef OLIVE_INSTANCE_H +#define OLIVE_INSTANCE_H #include "ofxCore.h" #include "ofxImageEffect.h" #include @@ -36,9 +37,9 @@ struct PersistentErrors{ ErrorType type; QString message; }; -class OliveInstance : public OFX::Host::ImageEffect::Instance { +class OlivePluginInstance : public OFX::Host::ImageEffect::Instance { public: - OliveInstance( + OlivePluginInstance( OFX::Host::ImageEffect::ImageEffectPlugin* plugin, OFX::Host::ImageEffect::Descriptor& desc, const std::string& context, @@ -46,7 +47,7 @@ public: : OFX::Host::ImageEffect::Instance(plugin, desc, context, interactive) { } - ~OliveInstance() override = default; + ~OlivePluginInstance() override = default; const std::string &getDefaultOutputFielding() const{ return kOfxImageFieldNone; }; @@ -151,4 +152,5 @@ private: VideoParams params_; }; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/app/pluginSupport/paraminstance.cpp b/app/pluginSupport/paraminstance.cpp new file mode 100644 index 000000000..63b594e04 --- /dev/null +++ b/app/pluginSupport/paraminstance.cpp @@ -0,0 +1,22 @@ +/* + * 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 . + * + */ + + +#include "paraminstance.h" + diff --git a/app/pluginSupport/paraminstance.h b/app/pluginSupport/paraminstance.h new file mode 100644 index 000000000..9a05ecaa5 --- /dev/null +++ b/app/pluginSupport/paraminstance.h @@ -0,0 +1,149 @@ +/* + * 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 . + * + */ + +// Copyright OpenFX and contributors to the OpenFX project. +#ifndef PARAM_INSTANCE_H +#define PARAM_INSTANCE_H + +#include "OlivePluginInstance.h" +#include "ofxhParam.h" +namespace olive +{ +namespace plugin +{ +class PushbuttonInstance : public OFX::Host::Param::PushbuttonInstance { +protected: + OlivePluginInstance* _effect; + OFX::Host::Param::Descriptor *_descriptor; +public: + PushbuttonInstance(OlivePluginInstance *effect, const std::string &name, + OFX::Host::Param::Descriptor &descriptor) + : OFX::Host::Param::PushbuttonInstance( descriptor) + { + _descriptor = &descriptor; + }; +}; + +class IntegerInstance : public OFX::Host::Param::IntegerInstance { +protected: + OlivePluginInstance* _effect; + OFX::Host::Param::Descriptor& _descriptor; +public: + IntegerInstance(OlivePluginInstance* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor); + OfxStatus get(int&); + OfxStatus get(OfxTime time, int&); + OfxStatus set(int); + OfxStatus set(OfxTime time, int); +}; + +class DoubleInstance : public OFX::Host::Param::DoubleInstance { +protected: + OlivePluginInstance* _effect; + OFX::Host::Param::Descriptor& _descriptor; +public: + DoubleInstance(OlivePluginInstance* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor); + OfxStatus get(double&); + OfxStatus get(OfxTime time, double&); + OfxStatus set(double); + OfxStatus set(OfxTime time, double); + OfxStatus derive(OfxTime time, double&); + OfxStatus integrate(OfxTime time1, OfxTime time2, double&); +}; + +class BooleanInstance : public OFX::Host::Param::BooleanInstance { +protected: + OlivePluginInstance* _effect; + OFX::Host::Param::Descriptor& _descriptor; +public: + BooleanInstance(OlivePluginInstance* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor); + OfxStatus get(bool&); + OfxStatus get(OfxTime time, bool&); + OfxStatus set(bool); + OfxStatus set(OfxTime time, bool); +}; + +class ChoiceInstance : public OFX::Host::Param::ChoiceInstance { +protected: + OlivePluginInstance* _effect; + OFX::Host::Param::Descriptor& _descriptor; +public: + ChoiceInstance(OlivePluginInstance* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor); + OfxStatus get(int&); + OfxStatus get(OfxTime time, int&); + OfxStatus set(int); + OfxStatus set(OfxTime time, int); +}; + +class RGBAInstance : public OFX::Host::Param::RGBAInstance { +protected: + OlivePluginInstance* _effect; + OFX::Host::Param::Descriptor& _descriptor; +public: + RGBAInstance(OlivePluginInstance* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor); + OfxStatus get(double&,double&,double&,double&); + OfxStatus get(OfxTime time, double&,double&,double&,double&); + OfxStatus set(double,double,double,double); + OfxStatus set(OfxTime time, double,double,double,double); +}; + + +class RGBInstance : public OFX::Host::Param::RGBInstance { +protected: + OlivePluginInstance* _effect; + OFX::Host::Param::Descriptor& _descriptor; +public: + RGBInstance(OlivePluginInstance* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor); + OfxStatus get(double&,double&,double&); + OfxStatus get(OfxTime time, double&,double&,double&); + OfxStatus set(double,double,double); + OfxStatus set(OfxTime time, double,double,double); +}; + +class Double2DInstance : public OFX::Host::Param::Double2DInstance { +protected: + OlivePluginInstance* _effect; + OFX::Host::Param::Descriptor& _descriptor; +public: + Double2DInstance(OlivePluginInstance* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor); + OfxStatus get(double&,double&); + OfxStatus get(OfxTime time,double&,double&); + OfxStatus set(double,double); + OfxStatus set(OfxTime time,double,double); +}; + +class Integer2DInstance : public OFX::Host::Param::Integer2DInstance { +protected: + OlivePluginInstance* _effect; + OFX::Host::Param::Descriptor& _descriptor; +public: + Integer2DInstance(OlivePluginInstance* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor); + OfxStatus get(int&,int&); + OfxStatus get(OfxTime time,int&,int&); + OfxStatus set(int,int); + OfxStatus set(OfxTime time,int,int); +}; +} +} + + + +#endif // HOST_DEMO_PARAM_INSTANCE_H + + +#endif //PARAMINSTANCE_H diff --git a/app/render/job/CMakeLists.txt b/app/render/job/CMakeLists.txt index 6ad233bbe..350257ee0 100644 --- a/app/render/job/CMakeLists.txt +++ b/app/render/job/CMakeLists.txt @@ -22,5 +22,7 @@ set(OLIVE_SOURCES render/job/generatejob.h render/job/samplejob.h render/job/shaderjob.h - PARENT_SCOPE + render/job/pluginjob.h + render/job/pluginjob.cpp + PARENT_SCOPE ) diff --git a/app/render/job/acceleratedjob.h b/app/render/job/acceleratedjob.h index 1724fa201..1a4f4053c 100644 --- a/app/render/job/acceleratedjob.h +++ b/app/render/job/acceleratedjob.h @@ -33,22 +33,22 @@ public: { } - NodeValue Get(const QString &input) const + virtual NodeValue Get(const QString &input) const { return value_map_.value(input); } - void Insert(const QString &input, const NodeValueRow &row) + virtual void Insert(const QString &input, const NodeValueRow &row) { value_map_.insert(input, row.value(input)); } - void Insert(const QString &input, const NodeValue &value) + virtual void Insert(const QString &input, const NodeValue &value) { value_map_.insert(input, value); } - void Insert(const NodeValueRow &row) + virtual void Insert(const NodeValueRow &row) { #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) value_map_.insert(row); @@ -59,16 +59,16 @@ public: #endif } - const NodeValueRow &GetValues() const + virtual const NodeValueRow &GetValues() const { return value_map_; } - NodeValueRow &GetValues() + virtual NodeValueRow &GetValues() { return value_map_; } -private: +protected: NodeValueRow value_map_; }; diff --git a/app/render/job/pluginjob.cpp b/app/render/job/pluginjob.cpp new file mode 100644 index 000000000..67c4e71d2 --- /dev/null +++ b/app/render/job/pluginjob.cpp @@ -0,0 +1,25 @@ +/* + * 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 . + * + */ + +#include "pluginjob.h" + +namespace olive { +namespace plugin { +} // plugin +} // olive \ No newline at end of file diff --git a/app/render/job/pluginjob.h b/app/render/job/pluginjob.h new file mode 100644 index 000000000..84d945469 --- /dev/null +++ b/app/render/job/pluginjob.h @@ -0,0 +1,50 @@ +/* + * 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 . + * + */ + +#ifndef PLUGINJOB_H +#define PLUGINJOB_H +#include "acceleratedjob.h" +#include "pluginSupport/OlivePluginInstance.h" + +#include + +namespace olive { +namespace plugin { + +class PluginJob :public AcceleratedJob{ +public: + explicit PluginJob(std::shared_ptr pluginInstance, NodeValueRow row): AcceleratedJob() + { + this->pluginInstance = pluginInstance; + + + } + +private: + std::shared_ptr pluginInstance; + + QHash> paramsOnTime; + + QHash params; +}; + +} // plugin +} // olive + +#endif //PLUGINJOB_H diff --git a/app/render/plugin/CMakeLists.txt b/app/render/plugin/CMakeLists.txt new file mode 100644 index 000000000..89d6f2721 --- /dev/null +++ b/app/render/plugin/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(libolive-editor PRIVATE pluginrenderer.cpp pluginrenderer.h) \ No newline at end of file diff --git a/app/render/plugin/pluginrenderer.cpp b/app/render/plugin/pluginrenderer.cpp new file mode 100644 index 000000000..c6b26de69 --- /dev/null +++ b/app/render/plugin/pluginrenderer.cpp @@ -0,0 +1,33 @@ +/* + * 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 . + * + */ + +// +// Created by mikesolar on 25-10-19. +// + +#include "pluginrenderer.h" + +#include "pluginSupport/OlivePluginInstance.h" +void olive::plugin::PluginRenderer::Blit(QVariant shader, ShaderJob job, + Texture *destination, + VideoParams destination_params, + bool clear_destination) +{ + +} \ No newline at end of file diff --git a/app/render/plugin/pluginrenderer.h b/app/render/plugin/pluginrenderer.h new file mode 100644 index 000000000..09e99f846 --- /dev/null +++ b/app/render/plugin/pluginrenderer.h @@ -0,0 +1,46 @@ +/* + * 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 . + * + */ + +// +// Created by mikesolar on 25-10-19. +// + +#ifndef PLUGINRENDERER_H +#define PLUGINRENDERER_H +#include "render/renderer.h" +namespace olive +{ +namespace plugin{ +class PluginRenderer : public olive::Renderer{ + Q_OBJECT +public: + PluginRenderer(QObject *parent=nullptr):Renderer(parent){}; +protected: + void Blit(QVariant shader, + ShaderJob job, + Texture *destination, + VideoParams destination_params, + bool clear_destination) override; +}; +} +} + + + +#endif //PLUGINRENDERER_H diff --git a/app/render/renderprocessor.cpp b/app/render/renderprocessor.cpp index bdec1ceed..73f89d487 100644 --- a/app/render/renderprocessor.cpp +++ b/app/render/renderprocessor.cpp @@ -169,7 +169,7 @@ void RenderProcessor::Run() } // if is a plugin - Node *node=ticket_->property("node").value(); + /*Node *node=ticket_->property("node").value(); if (node && node->getPlugin()) { std::shared_ptr plugin = node->getPlugin(); @@ -214,7 +214,7 @@ void RenderProcessor::Run() int numFramesToRender=ticket_->property("time").value().toDouble() * params.frame_rate().toDouble(); - stat = instance->beginRenderAction(0, numFramesToRender, 1.0, false, renderScale, /*sequential=*/true, /*interactive=*/false + stat = instance->beginRenderAction(0, numFramesToRender, 1.0, false, renderScale, /*sequential=#1#true, /*interactive=#1#false ); if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) { ticket_->Finish(); @@ -239,7 +239,7 @@ void RenderProcessor::Run() assert(stat == kOfxStatOK || stat == kOfxStatReplyDefault); // render a frame - stat = instance->renderAction(t,kOfxImageFieldBoth,renderWindow, renderScale, /*sequential=*/true, /*interactive=*/false, /*draft=*/false); + stat = instance->renderAction(t,kOfxImageFieldBoth,renderWindow, renderScale, /*sequential=#1#true, /*interactive=#1#false, /*draft=#1#false); assert(stat == kOfxStatOK); // get the output image buffer @@ -250,9 +250,10 @@ void RenderProcessor::Run() exportToPPM(ss.str(), outputImage); } - instance->endRenderAction(0, numFramesToRender, 1.0, false, renderScale, /*sequential=*/true, /*interactive=*/false + instance->endRenderAction(0, numFramesToRender, 1.0, false, renderScale, /*sequential=#1#true, /*interactive=#1#false ); } + */ switch (type) { case RenderManager::kTypeVideo: {