diff --git a/src/proc/asset/effect.cpp b/src/proc/asset/effect.cpp index e8203996e..cf795dc08 100644 --- a/src/proc/asset/effect.cpp +++ b/src/proc/asset/effect.cpp @@ -23,8 +23,13 @@ #include "proc/asset/effect.hpp" -namespace asset +namespace asset { + + Proc::ProcFunc* + Effect::resolveProcessor() const { + UNIMPLEMENTED ("do the actual resolution plugin -> callable processing function"); + } diff --git a/src/proc/asset/effect.hpp b/src/proc/asset/effect.hpp index df1472a36..a9b470b17 100644 --- a/src/proc/asset/effect.hpp +++ b/src/proc/asset/effect.hpp @@ -28,8 +28,7 @@ -namespace asset - { +namespace asset { /** * Effect or media processing component @@ -38,22 +37,18 @@ namespace asset { public: - /** resolve any plugin and configuration info - * to yield the actual media data processing function. - * @return a function ready to be invoked; either the - * "real thing" or a suitable placeholder. - * @throw lumiera::error::Fatal if unable to provide - * any usable function or placeholder. This case - * can be considered exceptional and justifies a - * subsystem failure. - */ - ProcFunc* - resolveProcessor(); - + + private: + /** implementation of how to resolve the corresponding plugin + * to yield an actual media data processing function. */ + ProcFunc* + resolveProcessor() const; + + }; - - - + + + } // namespace asset #endif diff --git a/src/proc/asset/proc.hpp b/src/proc/asset/proc.hpp index 406270d09..61ce66cbc 100644 --- a/src/proc/asset/proc.hpp +++ b/src/proc/asset/proc.hpp @@ -82,6 +82,20 @@ namespace asset { typedef void (ProcFunc) (PBuff); + /** resolve any plugin and configuration info + * to yield the actual media data processing function. + * @return a function ready to be invoked; either the + * "real thing" or a suitable placeholder. + * @throw lumiera::error::Fatal if unable to provide + * any usable function or placeholder. This case + * can be considered exceptional and justifies a + * subsystem failure. + */ + virtual ProcFunc* + resolveProcessor() const =0; + + + protected: Proc (const Asset::Ident& idi) : Asset(idi) {} //////////////TODO friend class ProcFactory; diff --git a/src/proc/engine/buffhandle.hpp b/src/proc/engine/buffhandle.hpp index c2602cc96..cdf1135e6 100644 --- a/src/proc/engine/buffhandle.hpp +++ b/src/proc/engine/buffhandle.hpp @@ -30,9 +30,10 @@ ** thus it makes sense to utilise a single large buffer pointer array per pull() calldown ** sequence and dynamically claim small chunks for each node. ** + ** @see nodewiring-def.hpp ** @see nodeoperation.hpp ** @see bufftable.hpp storage for the buffer table - ** @see engine::Invocation + ** @see engine::RenderInvocation */ #ifndef ENGINE_BUFFHANDLE_H @@ -116,7 +117,6 @@ namespace engine { }; - //////TODO: invent an input/output description pattern, which can be passed to the wiring factory } // namespace engine #endif diff --git a/src/proc/engine/nodefactory.cpp b/src/proc/engine/nodefactory.cpp index abdbc4a01..3c7299c21 100644 --- a/src/proc/engine/nodefactory.cpp +++ b/src/proc/engine/nodefactory.cpp @@ -31,45 +31,8 @@ namespace engine { namespace { // Details of node fabrication - using lib::AllocationCluster; - - template - NODE & - makeNode () - { - ////TODO: this is a draft how it /might/ work - ////TODO: of course this can't be hard wired.... - - ProcNode * predecessor1, predecessor2; - - WiringSituation setup; - setup.defineInput (4, predecessor1, 2); - setup.defineInput (2, predecessor2); - - WiringFactory* wFac; - - AllocationCluster allocator; - bool doCache = (2 == 2); // find out Cache should be used for this node - - WiringDescriptor & wDesc = (*wFac)(setup,doCache); - - NODE* newNode = allocator.create (wDesc); - - return *newNode; - - /* - * Problems to be solved: /////////////TODO: see Ticket #247 - * - write a generic allocator, which later on can be augmented to do block wise bulk allocation /////////////DONE: AllocationCluster - * - the allocator needs to keep track of the objects; actually he owns the objects /////////////DONE - * - we need to access the wiring descriptor of the predecessor nodes. Which means, the code - * must be in the body of NodeFactory (because the latter is friend of ProcNode and can access the wiring descriptor) - * - btw reconsider if this level of protection is necessary, or if the const WiringDescriptor cant be just on the public interface of ProcNode - * - find out how the Caching/ReadInput/InPlace detection can work - * - think about a sensible Ctor for NodeFactory. This one must create the WiringFactory and pass the Allocator. - * - all of this will be installed into the ToolFactory, i.e. it is part of the build process - */ - } - + ////////////////////////////////////////////////TODO: still needed? + } // (END) Details of node fabrication @@ -78,10 +41,16 @@ namespace engine { /** create a processing node able to render an effect */ - PTrafo - NodeFactory::operator() (Placement const&) + PNode + NodeFactory::operator() (Placement const& effect, WiringSituation& intendedWiring) { - UNIMPLEMENTED ("create proc node for Effect/Plugin"); + intendedWiring.resolveProcessor(effect->getProcAsset()); + WiringDescriptor& wiring = wiringFac_(intendedWiring); + + PNode newNode = alloc_.create (wiring); + ENSURE (newNode); + ENSURE (newNode->isValid()); + return newNode; } diff --git a/src/proc/engine/nodefactory.hpp b/src/proc/engine/nodefactory.hpp index 112f2ccc7..4c3d9e679 100644 --- a/src/proc/engine/nodefactory.hpp +++ b/src/proc/engine/nodefactory.hpp @@ -26,8 +26,12 @@ #include "proc/engine/procnode.hpp" #include "proc/mobject/placement.hpp" +#include "proc/engine/nodewiring.hpp" + ////////////////////////////////////TODO: make inclusions / forward definitions a bit more orthogonal.... + +namespace lib { class AllocationCluster; } namespace mobject { namespace session { @@ -43,9 +47,13 @@ namespace session { namespace engine { using std::vector; + using lib::AllocationCluster; + ///////////////////////////// TODO: as of 9/09, it seems no longer necessary to use any subclasses of ProcNode class Trafo; - typedef Trafo* PTrafo; ///< @note ProcNode is handled by pointer and bulk allocated/deallocated + typedef Trafo* PTrafo; ///< @note ProcNode is handled by pointer and bulk allocated/deallocated + + class WiringSituation; /** @@ -53,10 +61,17 @@ namespace engine { */ class NodeFactory { + AllocationCluster& alloc_; + WiringFactory wiringFac_; - public: - - PTrafo operator() (mobject::session::PEffect const&); + public: + NodeFactory (AllocationCluster& a) + : alloc_(a) + , wiringFac_(alloc_) + { } + + + PNode operator() (mobject::session::PEffect const&, WiringSituation&); }; diff --git a/src/proc/engine/nodewiring-config.hpp b/src/proc/engine/nodewiring-config.hpp index d1063f8da..47d0eb395 100644 --- a/src/proc/engine/nodewiring-config.hpp +++ b/src/proc/engine/nodewiring-config.hpp @@ -43,6 +43,7 @@ ** @see proc::engine::config::Strategy ** @see nodewiring.hpp ** @see configflags.hpp + ** @see config-flags-test.cpp ** */ diff --git a/src/proc/engine/nodewiring-def.hpp b/src/proc/engine/nodewiring-def.hpp index 0a025f35e..c5f37c2bc 100644 --- a/src/proc/engine/nodewiring-def.hpp +++ b/src/proc/engine/nodewiring-def.hpp @@ -41,6 +41,7 @@ #include "proc/engine/procnode.hpp" +#include "lib/refarray.hpp" #include //#include @@ -50,6 +51,7 @@ namespace engine { + using lib::RefArray; /** @@ -70,6 +72,9 @@ namespace engine { class WiringSituation : boost::noncopyable { + long flags_; + asset::Proc::ProcFunc* function_; + protected: RefArray& makeOutDescriptor() ; RefArray& makeInDescriptor() ; @@ -86,6 +91,8 @@ namespace engine { * with connection informations later on. */ WiringSituation() + : flags_(0) + , function_(0) { UNIMPLEMENTED ("representation of the intended wiring"); } @@ -95,6 +102,8 @@ namespace engine { * of an existing predecessor node */ WiringSituation (PNode predecessor) + : flags_(0) + , function_(0) { UNIMPLEMENTED ("wiring representation; hook up connections 1:1"); REQUIRE (predecessor); @@ -105,6 +114,51 @@ namespace engine { } + /** set up a connection leading to a specific input pin of the new node */ + WiringSituation& + defineInput (uint inPin, PNode pred, uint outPin) + { + UNIMPLEMENTED ("wiring representation; define new connection"); + return *this; + } + + /** set up the next input connection, + * originating at a specific output pin of the predecessor */ + WiringSituation& + defineInput (PNode pred, uint outPin) + { + UNIMPLEMENTED ("wiring representation; define new connection"); + return *this; + } + + /** set up the next input connection to a specific input pin, + * originating at a the next/sole output pin of the predecessor */ + WiringSituation& + defineInput (uint inPin, PNode pred) + { + UNIMPLEMENTED ("wiring representation; define new connection"); + return *this; + } + + + /** set detail flags regarding the desired node operation mode */ + WiringSituation& + setFlag (long code) + { + flags_ |= code; + return *this; + } + + long getFlags () const { return flags_; } + + + /** trigger resolving of the actual processing function */ + WiringSituation& + resolveProcessor (asset::Proc const& procAsset) + { + function_ = procAsset.resolveProcessor(); + ENSURE (function_); + } }; diff --git a/src/proc/engine/nodewiring.cpp b/src/proc/engine/nodewiring.cpp index 41b212af5..f32b02bf3 100644 --- a/src/proc/engine/nodewiring.cpp +++ b/src/proc/engine/nodewiring.cpp @@ -109,7 +109,7 @@ namespace engine { { WiringSelector selector; - WiringFactoryImpl (Alloc& alloc) + WiringFactoryImpl (AllocationCluster& alloc) : selector(config::PossibleConfigs::List(), alloc) { } }; @@ -119,42 +119,40 @@ namespace engine { - /** As the WiringFactory (an all the embedded factories + /** As the WiringFactory (and all the embedded factories * for the specific wiring situations) use the AllocationCluster * of the current build process, we need to create a new instance * for each newly built segment of the low-level model. + * @note As this ctor creates a WiringFactoryImpl instance, + * compiling this invocation actually drives the necessary + * template instantiations for all cases encountered while + * building the node network. */ WiringFactory::WiringFactory (lib::AllocationCluster& a) : alloc_(a), pImpl_(new config::WiringFactoryImpl (alloc_)) { } + + + WiringFactory::~WiringFactory () {} + /** create and configure a concrete wiring descriptor to tie * a ProcNode to its predecessor nodes. This includes selecting - * the actual StateAdapter type, configuring it out of some operation - * control templates (policy classes). Compiling this operator function - * actually drives the necessary template instantiations for all cases - * encountered while building the node network. + * the actual StateAdapter type, configuring it based on operation + * control templates (policy classes). * The created WiringDescriptor object is bulk allocated similar to the ProcNode * objects for a given segment of the Timeline. It should be further configured * with the actual predecessor nodes pointers and can then be used to create * the new processing node to be wired up. */ WiringDescriptor& - WiringFactory::operator() (WiringSituation& setup, bool cache) + WiringFactory::operator() (WiringSituation const& setup) { - UNIMPLEMENTED ("build the actual wiring descriptor based on given operation options"); - - ///////////////////////////////////////////////////////////////////////////////TODO: how to get the WiringSituation into the factory???? - - -// Bits config (FlagInfo::CODE); -// return pImpl_->selector[config](); - //// - /////TODO: change the FunctionType to take an "input/output description pattern" - /////TODO: invent such a pattern ---> buffhandle.hpp + long config = setup.getFlags(); + return pImpl_->selector[config] (setup); } diff --git a/src/proc/engine/nodewiring.hpp b/src/proc/engine/nodewiring.hpp index 64b007ab3..abc369fa2 100644 --- a/src/proc/engine/nodewiring.hpp +++ b/src/proc/engine/nodewiring.hpp @@ -90,9 +90,10 @@ namespace engine { public: WiringFactory (lib::AllocationCluster& a); + ~WiringFactory (); WiringDescriptor& - operator() (WiringSituation& setup, bool cache); //////////////////TODO: of course this will accept *all* the relevant flags (not only "cache") + operator() (WiringSituation const& setup); }; diff --git a/src/proc/engine/procnode.hpp b/src/proc/engine/procnode.hpp index e68f35cf6..be54a32c4 100644 --- a/src/proc/engine/procnode.hpp +++ b/src/proc/engine/procnode.hpp @@ -101,7 +101,8 @@ namespace engine { * holding the actual buffer pointers and issuing the recursive pull() calls * @see NodeWiring#callDown default implementation */ - virtual BuffHandle callDown (State& currentProcess, uint requiredOutputNr) const =0; + virtual BuffHandle + callDown (State& currentProcess, uint requiredOutputNr) const =0; friend class ProcNode; @@ -125,17 +126,20 @@ namespace engine { : wiringConfig_(wd) { } - virtual ~ProcNode() {}; friend class NodeFactory; public: + virtual ~ProcNode() {}; /////////////////////////TODO: do we still intend to build a hierarchy below ProcNode??? + + bool isValid() const; /** output channel count */ uint nrO() { return wiringConfig_.nrO; } + /** Engine Core operation: render and pull output from this node. * On return, currentProcess will hold onto output buffer(s) * containing the calculated result frames. In case this node @@ -156,5 +160,14 @@ namespace engine { }; + + bool + ProcNode::isValid() const + { + UNIMPLEMENTED ("ProcNode validity self-check"); + return false; //////////////////////////TODO + } + + } // namespace engine #endif diff --git a/src/proc/mobject/session/effect.hpp b/src/proc/mobject/session/effect.hpp index 967353e9a..52b21bb54 100644 --- a/src/proc/mobject/session/effect.hpp +++ b/src/proc/mobject/session/effect.hpp @@ -37,6 +37,8 @@ using std::string; namespace mobject { namespace session { + using asset::PProc; + class Effect : public AbstractMO { @@ -45,6 +47,8 @@ namespace session { string pluginID; public: + /** access the underlying processing asset */ + PProc getProcAsset () const; }; diff --git a/tests/components/proc/engine/node-basic-test.cpp b/tests/components/proc/engine/node-basic-test.cpp index 3c1aee4d7..c3b89e802 100644 --- a/tests/components/proc/engine/node-basic-test.cpp +++ b/tests/components/proc/engine/node-basic-test.cpp @@ -77,9 +77,15 @@ namespace test { AllocationCluster alloc; NodeFactory nodeFab(alloc); - PEffect pEffect; /////////////////TODO how to get an simple Effect MObject for Tests??? - WiringSituation setup; + ProcNode * testSource; ///////////TODO: how to fabricate a test-Node??? + + WiringSituation setup(testSource); + + setup.defineInput (4, predecessor1, 2); + setup.defineInput (2, predecessor2); + + PEffect pEffect; /////////////////TODO how to get an simple Effect MObject for Tests??? ProcNode* pNode = nodeFab (pEffect, setup); ASSERT (pNode);