From c3b1048fc4aba19ecda0e31bccb93f6306894b9d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 27 Jan 2008 03:58:24 +0100 Subject: [PATCH 01/14] merge buildsystem improvements --- .gitignore | 1 + SConstruct | 24 ++++-- admin/scons/Buildhelper.py | 19 +++++ src/common/test/run.hpp | 9 ++- src/common/util.hpp | 1 - src/pre.hpp | 51 +++++++++++++ src/proc/asset.hpp | 2 + src/proc/asset/media.cpp | 1 + src/proc/mobject/mobject.hpp | 2 + src/proc/mobject/placement.hpp | 2 +- src/tool/try.cpp | 75 +++---------------- tests/SConscript | 6 +- tests/components/backend/mediaaccessmock.cpp | 1 - .../backend/mediaaccessmocktest.cpp | 1 - tests/components/common/appconfigtest.cpp | 1 - .../components/common/factoryspecialtest.cpp | 1 - .../common/sanitizedidentifiertest.cpp | 2 - tests/components/common/singletontest.cpp | 1 - .../common/singletontestmocktest.cpp | 1 - .../common/test/cmdlinewrappertest.cpp | 6 +- 20 files changed, 118 insertions(+), 89 deletions(-) create mode 100644 src/pre.hpp diff --git a/.gitignore b/.gitignore index d55b1ba9f..ef277c1a1 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.tar.* .[^.]* *.os +*.gch Buildhelper.pyc optcache Makefile.in diff --git a/SConstruct b/SConstruct index 126e40a8d..88c5dcb97 100644 --- a/SConstruct +++ b/SConstruct @@ -65,13 +65,14 @@ def setupBasicEnvironment(): , CCFLAGS='-Wall ' # -fdiagnostics-show-option ) + RegisterPrecompiledHeader_Builder(env) handleNoBugSwitches(env) appendCppDefine(env,'DEBUG','DEBUG', 'NDEBUG') appendCppDefine(env,'OPENGL','USE_OPENGL') appendVal(env,'ARCHFLAGS', 'CCFLAGS') # for both C and C++ appendVal(env,'OPTIMIZE', 'CCFLAGS', val=' -O3') - appendVal(env,'DEBUG', 'CCFLAGS', val=' -g') + appendVal(env,'DEBUG', 'CCFLAGS', val=' -ggdb') prepareOptionsHelp(opts,env) opts.Save(OPTIONSCACHEFILE, env) @@ -91,9 +92,13 @@ def appendVal(env,var,targetVar,val=None): def handleNoBugSwitches(env): """ set the build level for NoBug. Release builds imply no DEBUG + wheras ALPHA and BETA require DEBUG """ level = env['BUILDLEVEL'] if level in ['ALPHA', 'BETA']: + if not env['DEBUG']: + print 'NoBug: ALPHA or BETA builds without DEBUG not possible, exiting.' + Exit(1) env.Replace( DEBUG = 1 ) env.Append(CPPDEFINES = 'EBUG_'+level) elif level == 'RELEASE': @@ -128,7 +133,7 @@ def defineCmdlineOptions(): def prepareOptionsHelp(opts,env): prelude = """ -USAGE: scons [-c] [OPTS] [key=val,...] [TARGETS] +USAGE: scons [-c] [OPTS] [key=val [key=val...]] [TARGETS] Build and optionally install Cinelerra. Without specifying any target, just the (re)build target will run. Add -c to the commandline to clean up anything a given target would produce @@ -228,20 +233,26 @@ def defineBuildTargets(env, artifacts): setup sub-environments with special build options if necessary. We use a custom function to declare a whole tree of srcfiles. """ + cinobj = ( srcSubtree(env,'$SRCDIR/backend') + srcSubtree(env,'$SRCDIR/proc') + srcSubtree(env,'$SRCDIR/common') + srcSubtree(env,'$SRCDIR/lib') ) plugobj = srcSubtree(env,'$SRCDIR/plugin', isShared=True) - corelib = env.StaticLibrary('$BINDIR/core.la', cinobj) + core = env.StaticLibrary('$BINDIR/core.la', cinobj) + #core = cinobj # use this for linking directly - artifacts['cinelerra'] = env.Program('$BINDIR/cinelerra', ['$SRCDIR/main.cpp']+ corelib ) + # use PCH to speed up building + precomp = env.PrecompiledHeader('$SRCDIR/pre') + env.Depends(cinobj, precomp) + + artifacts['cinelerra'] = env.Program('$BINDIR/cinelerra', ['$SRCDIR/main.cpp']+ core ) artifacts['plugins'] = env.SharedLibrary('$BINDIR/cinelerra-plugin', plugobj) # call subdir SConscript(s) for independent components SConscript(dirs=[SRCDIR+'/tool'], exports='env artifacts') - SConscript(dirs=[TESTDIR], exports='env artifacts corelib') + SConscript(dirs=[TESTDIR], exports='env artifacts core') @@ -257,7 +268,8 @@ def definePostBuildTargets(env, artifacts): allbu = env.Alias('allbuild', build+artifacts['testsuite']) env.Default('build') # additional files to be cleaned when cleaning 'build' - env.Clean ('build', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log']) + env.Clean ('build', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log' ]) + env.Clean ('build', [ '$SRCDIR/pre.gch' ]) # Doxygen documentation # Note: at the moment we only depend on Doxyfile diff --git a/admin/scons/Buildhelper.py b/admin/scons/Buildhelper.py index 81d501424..419de6e68 100644 --- a/admin/scons/Buildhelper.py +++ b/admin/scons/Buildhelper.py @@ -90,6 +90,25 @@ def globRootdirs(roots): +def RegisterPrecompiledHeader_Builder(env): + """ Registeres an Custom Builder for generating a precompiled Header. + Note you should define a dependency to the PCH file + """ + def genCmdline(source, target, env, for_signature): + return '$CXXCOM -x c++-header %s' % source[0] + def fixSourceDependency(target, source, env): + print "precompiled header: %s --> %s" % (source[0],target[0]) + return (target, source) + + gchBuilder = env.Builder( generator = genCmdline + , emitter = fixSourceDependency + , suffix = '.gch' + , src_suffix = '.hpp' + ) + env.Append(BUILDERS = {'PrecompiledHeader' : gchBuilder}) + + + def Tarball(env,location,dirs,suffix=''): """ Custom Command: create Tarball of some subdirs location: where to create the tar (optionally incl. filename.tar.gz) diff --git a/src/common/test/run.hpp b/src/common/test/run.hpp index 668f29645..0cee56674 100644 --- a/src/common/test/run.hpp +++ b/src/common/test/run.hpp @@ -25,12 +25,17 @@ #ifndef TESTHELPER_RUN_H #define TESTHELPER_RUN_H -#include -#include +#include "pre.hpp" + + +#include "nobugcfg.h" #include "common/test/suite.hpp" #include "common/util.hpp" +#include +#include + namespace test { diff --git a/src/common/util.hpp b/src/common/util.hpp index 6ca7f75d8..6b3a35096 100644 --- a/src/common/util.hpp +++ b/src/common/util.hpp @@ -29,7 +29,6 @@ #include #include -#include "nobugcfg.h" ///////////////////TODO: just temporarily!!!! namespace util diff --git a/src/pre.hpp b/src/pre.hpp new file mode 100644 index 000000000..af83dd9a2 --- /dev/null +++ b/src/pre.hpp @@ -0,0 +1,51 @@ +/* + PRE.hpp - precompiled header collection + + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + Hermann Vosseler + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file pre.hpp + ** Precompiled Header Collection. + ** Assortment of standard util, error handling and basic lib-boost components, + ** frequently used in conjunction. Precompiling these can speedup building + ** significantly. When used, this header should be included prior to any other + ** headers (and it needs to be compiled by gcc into a "pre.gch" file prior to + ** building the object files including this header). + ** + ** @see mobject.hpp usage example + */ + +#ifndef CINELERRA_PRE_HPP +#define CINELERRA_PRE_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include "cinelerra.h" + + + +#endif /*CINELERRA_PRE_HPP*/ diff --git a/src/proc/asset.hpp b/src/proc/asset.hpp index d9e2e5833..f6f8a8d98 100644 --- a/src/proc/asset.hpp +++ b/src/proc/asset.hpp @@ -55,6 +55,8 @@ #define PROC_INTERFACE_ASSET_H +#include "pre.hpp" + #include "proc/asset/category.hpp" #include "common/error.hpp" diff --git a/src/proc/asset/media.cpp b/src/proc/asset/media.cpp index 82ba763be..769863ff3 100644 --- a/src/proc/asset/media.cpp +++ b/src/proc/asset/media.cpp @@ -21,6 +21,7 @@ * *****************************************************/ +#include "pre.hpp" #include "proc/assetmanager.hpp" #include "proc/asset/media.hpp" #include "proc/asset/clip.hpp" diff --git a/src/proc/mobject/mobject.hpp b/src/proc/mobject/mobject.hpp index b051a49ec..634322470 100644 --- a/src/proc/mobject/mobject.hpp +++ b/src/proc/mobject/mobject.hpp @@ -24,6 +24,8 @@ #ifndef MOBJECT_MOBJECT_H #define MOBJECT_MOBJECT_H +#include "pre.hpp" + #include #include diff --git a/src/proc/mobject/placement.hpp b/src/proc/mobject/placement.hpp index 21c4aada8..ab29878de 100644 --- a/src/proc/mobject/placement.hpp +++ b/src/proc/mobject/placement.hpp @@ -57,7 +57,7 @@ #ifndef MOBJECT_PLACEMENT_H #define MOBJECT_PLACEMENT_H -#include "cinelerra.h" +#include "pre.hpp" #include "proc/mobject/mobject.hpp" #include "proc/mobject/session/locatingpin.hpp" #include "proc/asset/port.hpp" diff --git a/src/tool/try.cpp b/src/tool/try.cpp index 6aa45243a..349ca7db0 100644 --- a/src/tool/try.cpp +++ b/src/tool/try.cpp @@ -6,87 +6,32 @@ // 8/07 - how to control NOBUG?? // execute with NOBUG_LOG='ttt:TRACE' bin/try // 1/08 - working out a static initialisation problem for Visitor (Tag creation) +// 1/08 - check 64bit longs #include #include +#include + + using std::string; using std::cout; NOBUG_CPP_DEFINE_FLAG(test); - template class Tag; - - - template - class TagTypeRef - { - public: - static Tag tag; - }; - - - template - class Tag - { - size_t tagID; - static size_t lastRegisteredID; - - public: - Tag(size_t tt=0) : tagID(tt) {} - operator size_t() const { return tagID; } - - template - static Tag& - get (TOOLImpl* const concreteTool=0) - { - INFO (test,"getTag"); - Tag& t = TagTypeRef::tag; - if (!t) - t.tagID = ++Tag::lastRegisteredID; - return t; - } - - }; - - - - - /** storage for the Tag registry for each concrete tool */ - template - Tag TagTypeRef ::tag (0); - - template - size_t Tag::lastRegisteredID (0); - - - - - - class TT - { - - }; - - class TI : public TT - { - - }; - class TII : public TT - { - - }; int main (int argc, char* argv[]) { NOBUG_INIT; - size_t xxx = Tag::get(); - - cout << "created Tag=" << xxx <<"\n"; - cout << "created Tag=" << Tag::get () <<"\n"; + int64_t lol (1); + cout << sizeof(lol)<< "\n"; + + cout << "long: "<< std::numeric_limits::max() + <<" 64: " << std::numeric_limits::max() + <<"\n"; return 0; } diff --git a/tests/SConscript b/tests/SConscript index 31bd607e2..7f66b6284 100644 --- a/tests/SConscript +++ b/tests/SConscript @@ -7,7 +7,7 @@ from os import path from Buildhelper import srcSubtree from Buildhelper import globRootdirs -Import('env','artifacts','corelib') +Import('env','artifacts','core') def testExecutable(env,tree, exeName=None, obj=None): @@ -24,7 +24,7 @@ def testExecutable(env,tree, exeName=None, obj=None): obj = srcSubtree(env,tree) # use all sourcefiles found in subtree if not exeName: exeName = 'test-%s' % tree - return env.Program('#$BINDIR/'+exeName, obj + corelib) + return env.Program('#$BINDIR/'+exeName, obj + core) def treatPluginTestcase(env): @@ -38,7 +38,7 @@ def treatPluginTestcase(env): testplugin = ( env.SharedLibrary('#$BINDIR/.libs/example_plugin', oC, SHLIBPREFIX='') + env.SharedLibrary('#$BINDIR/.libs/example_plugin_cpp', oCPP, SHLIBPREFIX='') ) - testExe = env.Program('#$BINDIR/test-plugin', ['plugin/plugin_main.c'] + corelib) + testExe = env.Program('#$BINDIR/test-plugin', ['plugin/plugin_main.c'] + core) env.Depends(testExe, testplugin) return testExe #-- it depentds (at the moment) on a specific isolated test-plugin, diff --git a/tests/components/backend/mediaaccessmock.cpp b/tests/components/backend/mediaaccessmock.cpp index cd87399bb..d980c83d5 100644 --- a/tests/components/backend/mediaaccessmock.cpp +++ b/tests/components/backend/mediaaccessmock.cpp @@ -36,7 +36,6 @@ #include "backend/mediaaccessmock.hpp" #include "common/util.hpp" -#include "nobugcfg.h" #include #include diff --git a/tests/components/backend/mediaaccessmocktest.cpp b/tests/components/backend/mediaaccessmocktest.cpp index 2e4a71ec5..110d2b3cd 100644 --- a/tests/components/backend/mediaaccessmocktest.cpp +++ b/tests/components/backend/mediaaccessmocktest.cpp @@ -26,7 +26,6 @@ #include "common/test/run.hpp" //#include "common/util.hpp" -#include "nobugcfg.h" //#include #include diff --git a/tests/components/common/appconfigtest.cpp b/tests/components/common/appconfigtest.cpp index c76817712..49266c4ae 100644 --- a/tests/components/common/appconfigtest.cpp +++ b/tests/components/common/appconfigtest.cpp @@ -21,7 +21,6 @@ * *****************************************************/ -#include "nobugcfg.h" #include "common/appconfig.hpp" diff --git a/tests/components/common/factoryspecialtest.cpp b/tests/components/common/factoryspecialtest.cpp index 39066d952..e9848c599 100644 --- a/tests/components/common/factoryspecialtest.cpp +++ b/tests/components/common/factoryspecialtest.cpp @@ -26,7 +26,6 @@ #include "common/test/run.hpp" #include "common/util.hpp" -#include "nobugcfg.h" #include #include diff --git a/tests/components/common/sanitizedidentifiertest.cpp b/tests/components/common/sanitizedidentifiertest.cpp index b066ec03c..a6dba2c79 100644 --- a/tests/components/common/sanitizedidentifiertest.cpp +++ b/tests/components/common/sanitizedidentifiertest.cpp @@ -21,8 +21,6 @@ * *****************************************************/ -#include "nobugcfg.h" - #include "common/test/run.hpp" #include "common/util.hpp" diff --git a/tests/components/common/singletontest.cpp b/tests/components/common/singletontest.cpp index 1fa5e0209..ce88d5245 100644 --- a/tests/components/common/singletontest.cpp +++ b/tests/components/common/singletontest.cpp @@ -26,7 +26,6 @@ #include "common/test/run.hpp" #include "common/singleton.hpp" #include "common/util.hpp" -#include "nobugcfg.h" #include #include diff --git a/tests/components/common/singletontestmocktest.cpp b/tests/components/common/singletontestmocktest.cpp index eab73eba6..b33dda5d2 100644 --- a/tests/components/common/singletontestmocktest.cpp +++ b/tests/components/common/singletontestmocktest.cpp @@ -25,7 +25,6 @@ #include "common/test/run.hpp" #include "common/singleton.hpp" #include "common/util.hpp" -#include "nobugcfg.h" #include #include diff --git a/tests/components/common/test/cmdlinewrappertest.cpp b/tests/components/common/test/cmdlinewrappertest.cpp index 4ab8b28be..84b0780c1 100644 --- a/tests/components/common/test/cmdlinewrappertest.cpp +++ b/tests/components/common/test/cmdlinewrappertest.cpp @@ -21,8 +21,6 @@ * *****************************************************/ -#include "nobugcfg.h" - #include "common/test/run.hpp" #include "common/cmdline.hpp" #include "common/util.hpp" @@ -32,7 +30,6 @@ #include -using namespace boost::lambda; using std::cout; @@ -41,6 +38,9 @@ namespace util { namespace test { + using boost::lambda::_1; + using boost::lambda::var; + /** @test for util::Cmdline, wrapping various example cmdlines */ From 000538f6effa0f49ca8c7b2c80d4baa55580cbbf Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 27 Jan 2008 23:40:45 +0100 Subject: [PATCH 02/14] add stubs to make it link, add some typelist utils --- src/common/typelistutil.hpp | 146 +++++++++++++++++++ src/proc/asset.hpp | 28 ++-- src/proc/asset/port.cpp | 6 + src/proc/asset/port.hpp | 2 +- src/proc/asset/struct.cpp | 27 ++++ src/proc/mobject/session/defsmanager.cpp | 17 ++- tests/50components.tests | 21 +++ tests/components/common/typelistutiltest.cpp | 140 ++++++++++++++++++ wiki/renderengine.html | 10 +- 9 files changed, 379 insertions(+), 18 deletions(-) create mode 100644 src/common/typelistutil.hpp create mode 100644 tests/components/common/typelistutiltest.cpp diff --git a/src/common/typelistutil.hpp b/src/common/typelistutil.hpp new file mode 100644 index 000000000..6aeae1870 --- /dev/null +++ b/src/common/typelistutil.hpp @@ -0,0 +1,146 @@ +/* + TYPELISTUTIL.hpp - metaprogramming utilities for lists-of-types + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +==================================================================== +This code is heavily inspired by + The Loki Library (loki-lib/trunk/include/loki/Sequence.h) + Copyright (c) 2001 by Andrei Alexandrescu + Copyright (c) 2005 by Peter Kümmel + This Loki code accompanies the book: + Alexandrescu, Andrei. "Modern C++ Design: Generic Programming + and Design Patterns Applied". + Copyright (c) 2001. Addison-Wesley. ISBN 0201704315 + + Loki Copyright Notice: + Permission to use, copy, modify, distribute and sell this software for any + purpose is hereby granted without fee, provided that the above copyright + notice appear in all copies and that both that copyright notice and this + permission notice appear in supporting documentation. + The author makes no representations about the suitability of this software + for any purpose. It is provided "as is" without express or implied warranty. +*/ + + +/** @file typelistutil.hpp + ** Helpers for working with cinelerra::typelist::Types (i.e. lists-of-types). + ** + ** @see cinelerra::query::ConfigRules usage example + ** @see typelist.hpp + ** + */ + + +#ifndef CINELERRA_TYPELISTUTIL_H +#define CINELERRA_TYPELISTUTIL_H + +#include "common/typelist.hpp" + + + +namespace cinelerra + { + namespace typelist + { + + /** + * Apply a template to a collection of types. + * The resulting class ends up inheriting from an instantiation + * of the templace for each of the types in the list. + */ + template + < class TYPES // List of Types + , template class _X_ // your-template-goes-here + , class BASE = NullType // Base class at end of chain + > + class InstantiateForEach; + + + template class _X_, class BASE> + class InstantiateForEach + : public BASE + { + public: + typedef BASE Unit; + typedef NullType Next; + }; + + + template + < class TY, typename TYPES + , template class _X_ + , class BASE + > + class InstantiateForEach, _X_, BASE> + : public _X_, + public InstantiateForEach + { + public: + typedef _X_ Unit; + typedef InstantiateForEach Next; + }; + + + + /** + * Build a single inheritance chain of template instantiations. + * Needs the help of the user provided Template, which now has + * to take a second parameter and use this as Base class. + * The resulting class ends up (single) inheriting from an + * instantiation of the templace for each of the types, while + * overrideing/implementing the provided base class. + */ + template + < class TYPES // List of Types + , template class _X_ // your-template-goes-here + , class BASE = NullType // Base class at end of chain + > + class InstantiateChained; + + + template class _X_, class BASE> + class InstantiateChained + : public BASE + { + public: + typedef BASE Unit; + typedef NullType Next; + }; + + + template + < class TY, typename TYPES + , template class _X_ + , class BASE + > + class InstantiateChained, _X_, BASE> + : public _X_< TY + , InstantiateChained + > + { + public: + typedef InstantiateChained Next; + typedef _X_ Unit; + }; + + + } // namespace typelist + +} // namespace cinelerra +#endif diff --git a/src/proc/asset.hpp b/src/proc/asset.hpp index f6f8a8d98..7375d25af 100644 --- a/src/proc/asset.hpp +++ b/src/proc/asset.hpp @@ -291,8 +291,19 @@ namespace asset }; + + + /** promote subtype-ptr to PAsset, e.g. for comparing */ + template + inline const PcAsset + pAsset (const shared_ptr& subPtr) + { + return static_pointer_cast (subPtr); + } + /** ordering of Asset smart ptrs based on Ident tuple. - * @todo currently supporting only smart_ptr. */ + * @todo currently supporting only smart_ptr. + * @todo should better be done using boost::operator */ inline bool operator== (const PcAsset& a1, const PcAsset& a2) { return a1 && a2 && ( 0==a1->ident.compare(a2->ident));} inline bool operator< (const PcAsset& a1, const PcAsset& a2) { return a1 && a2 && (-1==a1->ident.compare(a2->ident));} inline bool operator> (const PcAsset& a1, const PcAsset& a2) { return a2 < a1; } @@ -300,6 +311,13 @@ namespace asset inline bool operator<= (const PcAsset& a1, const PcAsset& a2) { return !(a1 > a2); } inline bool operator!= (const PcAsset& a1, const PcAsset& a2) { return !(a1== a2); } + inline bool operator== (const PAsset& a1, const PAsset& a2) { return pAsset(a1) == pAsset(a2); } + inline bool operator< (const PAsset& a1, const PAsset& a2) { return pAsset(a1) < pAsset(a2); } + inline bool operator> (const PAsset& a1, const PAsset& a2) { return pAsset(a1) > pAsset(a2); } + inline bool operator>= (const PAsset& a1, const PAsset& a2) { return pAsset(a1) >= pAsset(a2); } + inline bool operator<= (const PAsset& a1, const PAsset& a2) { return pAsset(a1) <= pAsset(a2); } + inline bool operator!= (const PAsset& a1, const PAsset& a2) { return pAsset(a1) != pAsset(a2); } + /** ordering of Asset Ident tuples. * @note version is irrelevant */ inline int @@ -311,14 +329,6 @@ namespace asset return name.compare (oi.name); } - /** promote to PAsset, e.g. for comparing */ - template - inline PcAsset - pAsset (shared_ptr& subPtr) - { - return static_pointer_cast (subPtr); - } - /** convienient for debugging */ inline string str (const PcAsset& a) diff --git a/src/proc/asset/port.cpp b/src/proc/asset/port.cpp index f574dbd39..08b7dd38f 100644 --- a/src/proc/asset/port.cpp +++ b/src/proc/asset/port.cpp @@ -54,6 +54,12 @@ namespace asset + PPort + Port::query (string properties) + { + return Struct::create (Query (properties)); + } + void Port::switchProcPatt (PProcPatt& another) { diff --git a/src/proc/asset/port.hpp b/src/proc/asset/port.hpp index 8784b629b..8bb359789 100644 --- a/src/proc/asset/port.hpp +++ b/src/proc/asset/port.hpp @@ -78,7 +78,7 @@ namespace asset void switchProcPatt (PProcPatt& another); /** convienience shortcut for retrieving default configured ports */ - static PPort query (string properties) { return Struct::create (Query (properties)); } + static PPort query (string properties) ; }; diff --git a/src/proc/asset/struct.cpp b/src/proc/asset/struct.cpp index 3f9a911f5..dd8f71aa5 100644 --- a/src/proc/asset/struct.cpp +++ b/src/proc/asset/struct.cpp @@ -25,6 +25,7 @@ #include "proc/asset/struct.hpp" #include "proc/asset/procpatt.hpp" #include "proc/asset/track.hpp" +#include "proc/asset/port.hpp" #include "proc/mobject/session.hpp" #include "common/query.hpp" @@ -37,6 +38,9 @@ using cinelerra::query::normalizeID; namespace asset { + /****** NOTE: not implemented yet. What follows is a hack to build simple tests *******/ + + namespace // common Struct Asset implementation details { /** @internal derive a sensible asset ident tuple when creating @@ -51,6 +55,16 @@ namespace asset Category category (STRUCT,"tracks"); return Asset::Ident (name, category ); } + + typedef std::pair PortIDs; + + PortIDs + createPortIdent (const Query& query) + { + string name ("port-" + query); // TODO get some more sensible dummy values + TODO ("port naming scheme??"); + return PortIDs (name, "mpeg"); // dummy stream type + } } @@ -74,6 +88,19 @@ namespace asset } + /** Similar instance for Port Query.... + * @todo better a generic implementation utilizing ConfigQuery.... + */ + template<> + shared_ptr + StructFactory::operator() (const Query& query) + { + TODO ("actually evaluate the query..."); + PortIDs ids (createPortIdent (query)); + return operator() (ids.first, ids.second); + } + + /** Factory method for creating Ports explicitly. * Normalizes port- and streamID, then retrieves the * default processing pattern (ProcPatt) for this streamID. diff --git a/src/proc/mobject/session/defsmanager.cpp b/src/proc/mobject/session/defsmanager.cpp index 305db5cab..291233ce0 100644 --- a/src/proc/mobject/session/defsmanager.cpp +++ b/src/proc/mobject/session/defsmanager.cpp @@ -22,10 +22,12 @@ #include "proc/mobject/session/defsmanager.hpp" +#include "proc/asset/procpatt.hpp" #include "proc/asset/port.hpp" using asset::Query; using asset::Port; +using asset::ProcPatt; namespace mobject { @@ -40,13 +42,22 @@ namespace mobject /** create or retrieve a default-configured port asset. - * @param */ template<> shared_ptr - DefsManager::operator() (const Query& properties) + DefsManager::operator() (const Query& capabilities) { - + UNIMPLEMENTED ("query for default port with capabilities"); + } + + + /** create or retrieve a default-configured processing pattern. + */ + template<> + shared_ptr + DefsManager::operator() (const Query& capabilities) + { + UNIMPLEMENTED ("query for default processing pattern with capabilities"); } diff --git a/tests/50components.tests b/tests/50components.tests index 7737d7fce..c0addaf23 100644 --- a/tests/50components.tests +++ b/tests/50components.tests @@ -189,6 +189,27 @@ return: 0 END +TEST "TypeListUtil_test" TypeListUtil_test < > +out: ctor DoIt > +out: ctor DoIt > +out: ctor DoIt > +out: ctor DoIt > +out: ctor DoIt > +out: Block< 2>::eat(..) +out: Block< 5>::eat(..) +out: Block<13>::eat(..) +out: gulp! +out: dtor DoIt > +out: dtor DoIt > +out: dtor DoIt > +out: dtor DoIt > +out: dtor DoIt > +out: dtor DoIt > +return: 0 +END + + TEST "VisitingTool_test" VisitingTool_test < + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "common/test/run.hpp" +#include "common/typelistutil.hpp" + +#include +#include +#include + +using std::string; +using std::cout; + + +namespace cinelerra + { + namespace typelist + { + namespace test + { + + /** template for generating lots of different test types */ + template + struct Block + { + static string name; + string talk() { return name+"::eat(..)"; } + }; + + + boost::format fmt ("Block<%2i>"); + + template + string Block::name = str (fmt % I); + + + + /** Use this building block for assembling an abstract interface */ + template + class TakeIt + { + public: + virtual void eat (X& x) = 0; + virtual ~TakeIt() { } + }; + + /** Use this building block for chaining corresponding implementation classes. */ + template + class DoIt + : public BASE + { + protected: + DoIt () { cout << "ctor DoIt<"<< X::name << " >\n";} + virtual ~DoIt() { cout << "dtor DoIt<"<< X::name << " >\n";} + public: + void eat (X& x) { cout << x.talk() << "\n";} + using BASE::eat; // prevent shaddowing + }; + + typedef Types< Block<1> + , Block<2> + , Block<3> + , Block<5> + , Block<8> + , Block<13> + >::List TheTypes; + + typedef InstantiateForEach TheInterface; + + + struct BaseImpl : public TheInterface + { + void eat() { cout << "gulp!\n"; } + }; + + typedef InstantiateChained NumberBabbler; + + + /************************************************************************* + * @test check the helpers for dealing with lists-of-types. + *
  • build an interface and an implementation class + * by inheriting template instantiations + * for a collection of classes
  • + *
+ */ + class TypeListUtil_test : public Test + { + virtual void run(Arg arg) + { + NumberBabbler me_can_has_more_numberz; + + ASSERT (INSTANCEOF (TheInterface, &me_can_has_more_numberz)); + + TheTypes::Tail::Head b2; // Block<2> + TheTypes::Tail::Tail::Tail::Head b5; // Block<5> + TheTypes::Tail::Tail::Tail::Tail::Tail::Head b13; // Block<13> + + me_can_has_more_numberz.eat (b2); + me_can_has_more_numberz.eat (b5); + + TakeIt >& subInterface = me_can_has_more_numberz; + + subInterface.eat (b13); + me_can_has_more_numberz.eat(); + + INFO (test, "SizeOf = %i", sizeof(me_can_has_more_numberz)); + } + }; + + + /** Register this test class... */ + LAUNCHER (TypeListUtil_test, "unit common"); + + + + } // namespace test + + } // namespace typelist + +} // namespace cinelerra diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 8d57363ad..a066a89cc 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -2450,26 +2450,26 @@ Like all [[structural assets|StructAsset]], ~ProcPatt employs a special naming s
a given Render Engine configuration is a list of Processors. Each Processor in turn contains a Graph of ProcNode.s to do the acutal data processing. In order to cary out any calculations, the Processor needs to be called with a StateProxy containing the state information for this RenderProcess
 
-
+
//obviously, getting this one to work requires quite a lot of technical details to be planned and implemented.// This said...
 The intention is to get much more readable ("declarative") and changeable configuration as by programming it directly within the implementation of some object.
 
 !Draft
 As an example, specifying how a Track can be configured for connecting automatically to some "mpeg" bus (=port)
 {{{
-retrieve(O, Cap) :- find(T), capabilities(Cap).
-retrieve(O, Cap) :- make(T), capabilities(Cap).
+retrieve(O, Cap) :- find(O), capabilities(Cap).
+retrieve(O, Cap) :- make(O), capabilities(Cap).
 capabilities(Q) :- call(Q).
 
 stream(T, mpeg) :- type(T, track), type(P, port), retrieve(P, stream(P,mpeg)), place_to(P, T).
 }}}
 
-Then, running the goal {{{:-retrieve(T, stream(T,mpeg)).}}} would search a Track object, try to retrieve a port object with stream-type=mpeg and associate the track with this Port. This relies on a predicate "stream(P,mpeg)" implemented (natively) for the port object. So, "Cap" is the query issued from calling code &mdash; here {{{stream(T,mpeg)}}}, the type guard {{{type(T, track)}}} will probably be handled or inserted inserted automatically, while the predicate implementations for find/1, make/1, stream/2, and place_to/2 are to be provided by the target types.
+Then, running the goal {{{:-retrieve(T, stream(T,mpeg)).}}} would search a Track object, try to retrieve a port object with stream-type=mpeg and associate the track with this Port. This relies on a predicate "stream(P,mpeg)" implemented (natively) for the port object. So, "Cap" is the query issued from calling code &mdash; here {{{stream(T,mpeg)}}}, the type guard {{{type(T, track)}}} will probably be handled or inserted automatically, while the predicate implementations for find/1, make/1, stream/2, and place_to/2 are to be provided by the target types.
 * __The supporting system__ had to combine several code snippets into one rule system to be used for running queries, with some global base rules, rules injected by each individual participating object kind and finally user provided rules added by the current session. The actual query is bound to "Cap" (and consequently run as a goal by {{{call(Q)}}}). The implementation needs to provide a symbol table associating variable terms (like "T" or "P") to C/C++ object types, enabling the participating object kinds to register their specific predicate implementations. This is crucial, because there can be no general scheme of object-provided predicates (for each object kind different predicates make sense, e.g. [[ports|PortHandling]] have other possibilities than [[wiring requests|WiringRequest]]). Basically, a query issues a Prolog goal, which in turn evaluates domain specific predicates provided by the participating objects and thus calls back into C/C++ code. The supporting system maintains the internal connection (via the "type" predicate) such that from Prolog viewpoint it looks as if we were binding Variables directly to object instances. (there are some nasty technical details because of the backtracking nature of Prolog evaluations which need to be hidden away)
 * Any __participating object kind__ needs a way to declare domain specific predicates, thus triggering the registration of the necessary hooks within the supporting system. Moreover, it should be able to inject further prolog code (as shown in the example above with the {{{strem(T, mpeg)}}} predicate. For each of these new domain specific predicates, there needs to be a functor which can be invoked when the C implementation of the predicate is called from Prolog (in some cases even later, when the final solution is "executed", e.g. a new instance has been created and now some properties need to be set).
 
 !!a note on Plugins
-In the design of the Cinelerra-3 Proc Layer done thus far, we provide //no possibility to introduce a new object kind// into the system via plugin interface. The system uses a fixed collection of classes intended to cover all needs (Clip, Effect, Track, Port, Label, Automation, ~Macro-Clips). Thus, plugins will only be able to provide new parametrisations of existing classes. This should not be any real limitation, because the whole system is designed to achieve most of its functionality by freely combining rather basic object kinds. As a plus, it plays nicely with any plain-C based plugin interface. For example, we will have C++ adapter classes for the most common sorts of effect plugin (pull system and synchronous frame-by-frame push with buffering) with a thin C adaptation layer for the specific external plugin systems used.
+In the design of the Cinelerra-3 Proc Layer done thus far, we provide //no possibility to introduce a new object kind// into the system via plugin interface. The system uses a fixed collection of classes intended to cover all needs (Clip, Effect, Track, Port, Label, Automation, ~Macro-Clips). Thus, plugins will only be able to provide new parametrisations of existing classes. This should not be any real limitation, because the whole system is designed to achieve most of its functionality by freely combining rather basic object kinds. As a plus, it plays nicely with any plain-C based plugin interface. For example, we will have C++ adapter classes for the most common sorts of effect plugin (pull system and synchronous frame-by-frame push with buffering) with a thin C adaptation layer for the specific external plugin systems used. Everything beyond this point can be considered "condiguration data" (including the actual plugin implementation to be loaded)
 
From 1614769664728713df48b258d8190a05d7db5551 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 28 Jan 2008 06:05:46 +0100 Subject: [PATCH 03/14] WIP start implementing the DefaultsManager by the (Mock)ConfigRules. pass compiler, but loooots of undefined linker refs.... --- src/common/configrules.cpp | 3 +- src/common/configrules.hpp | 13 ++++++- src/common/query/mockconfigrules.cpp | 5 +++ src/common/query/mockconfigrules.hpp | 7 +++- src/proc/asset/struct.cpp | 2 +- src/proc/mobject/session/defsmanager.cpp | 47 ++++++++++++++++-------- src/proc/mobject/session/defsmanager.hpp | 10 +++-- 7 files changed, 61 insertions(+), 26 deletions(-) diff --git a/src/common/configrules.cpp b/src/common/configrules.cpp index 09b46d51e..2eeca2649 100644 --- a/src/common/configrules.cpp +++ b/src/common/configrules.cpp @@ -34,7 +34,8 @@ namespace cinelerra namespace query { - + CINELERRA_ERROR_DEFINE (CAPABILITY_QUERY, "unresolvable capability query"); + } // namespace query diff --git a/src/common/configrules.hpp b/src/common/configrules.hpp index 2c2c52d7c..80ba8df3c 100644 --- a/src/common/configrules.hpp +++ b/src/common/configrules.hpp @@ -34,6 +34,8 @@ ** they want to provide, together with functors carrying out the neccessary configuration steps. ** All details and consequences of this approach still have to be worked out... ** + ** @note this is rather a scrapbook and in flux... don't take this code too literal! + ** ** @see cinelerra::Query ** @see mobject::session::DefsManager ** @see asset::StructFactory @@ -49,17 +51,21 @@ #include "common/typelist.hpp" #include "proc/mobject/session/track.hpp" +#include "proc/asset/procpatt.hpp" #include "proc/asset/port.hpp" #include +#include namespace cinelerra { using std::string; - namespace query { class MockConfigRules; } + using std::tr1::shared_ptr; + + namespace query { class MockConfigRules; } // TODO: need a better way to return a sub-type from a singleton @@ -114,7 +120,7 @@ namespace cinelerra protected: virtual ~QueryHandler(); public: - virtual TY resolve (Query q); + virtual shared_ptr resolve (Query q); }; // TODO: the Idea is to provide specialisations for the concrete types @@ -179,6 +185,8 @@ namespace cinelerra cinelerra::Singleton ConfigRules::instance; + + CINELERRA_ERROR_DECLARE (CAPABILITY_QUERY); ///< unresolvable capability query. } // namespace query @@ -194,6 +202,7 @@ namespace cinelerra */ typedef cinelerra::typelist::Types < mobject::session::Track , asset::Port + , const asset::ProcPatt > InterfaceTypes; diff --git a/src/common/query/mockconfigrules.cpp b/src/common/query/mockconfigrules.cpp index 7a938728e..915e20ba8 100644 --- a/src/common/query/mockconfigrules.cpp +++ b/src/common/query/mockconfigrules.cpp @@ -33,6 +33,11 @@ namespace cinelerra namespace query { + MockConfigRules::MockConfigRules () + { + + } + } // namespace query diff --git a/src/common/query/mockconfigrules.hpp b/src/common/query/mockconfigrules.hpp index 856d283c3..07fc98831 100644 --- a/src/common/query/mockconfigrules.hpp +++ b/src/common/query/mockconfigrules.hpp @@ -53,6 +53,8 @@ namespace cinelerra { using mobject::session::Track; using asset::Port; + using asset::ProcPatt; + using asset::PProcPatt; /** * Dummy Implementation of the query interface. @@ -67,8 +69,9 @@ namespace cinelerra public: - virtual Track resolve (Query q); - virtual Port resolve (Query q); + virtual shared_ptr resolve (Query q); + virtual shared_ptr resolve (Query q); + virtual PProcPatt resolve (Query q); }; diff --git a/src/proc/asset/struct.cpp b/src/proc/asset/struct.cpp index dd8f71aa5..ad1191045 100644 --- a/src/proc/asset/struct.cpp +++ b/src/proc/asset/struct.cpp @@ -115,7 +115,7 @@ namespace asset { normalizeID (portID); normalizeID (streamID); - PProcPatt processingPattern = Session::current->defaults (Query("stream("+streamID+")")); + PProcPatt processingPattern = Session::current->defaults (Query("stream("+streamID+")")); Port* pP = new Port (processingPattern, portID); return AssetManager::instance().wrap (*pP); } diff --git a/src/proc/mobject/session/defsmanager.cpp b/src/proc/mobject/session/defsmanager.cpp index 291233ce0..2851ea235 100644 --- a/src/proc/mobject/session/defsmanager.cpp +++ b/src/proc/mobject/session/defsmanager.cpp @@ -24,10 +24,21 @@ #include "proc/mobject/session/defsmanager.hpp" #include "proc/asset/procpatt.hpp" #include "proc/asset/port.hpp" +#include "common/configrules.hpp" +#include "common/query/mockconfigrules.hpp" // TODO: better way to handle the includes (rework singleton template?) +#include "common/error.hpp" + +#include + +using boost::format; using asset::Query; using asset::Port; using asset::ProcPatt; +using asset::PProcPatt; + +using cinelerra::ConfigRules; +using cinelerra::query::CINELERRA_ERROR_CAPABILITY_QUERY; namespace mobject { @@ -40,27 +51,31 @@ namespace mobject } - - /** create or retrieve a default-configured port asset. - */ - template<> - shared_ptr - DefsManager::operator() (const Query& capabilities) + + template + shared_ptr + DefsManager::operator() (const Query& capabilities) { - UNIMPLEMENTED ("query for default port with capabilities"); + shared_ptr res = cinelerra::ConfigRules::instance().resolve (capabilities); + + if (!res) + throw cinelerra::error::Config ( str(format("The following Query could not be resolved: %s.") + % capabilities) + , CINELERRA_ERROR_CAPABILITY_QUERY ); + else + return res; } + + + /***************************************************************/ + /* explicit template instantiations for querying various Types */ + /***************************************************************/ - /** create or retrieve a default-configured processing pattern. - */ - template<> - shared_ptr - DefsManager::operator() (const Query& capabilities) - { - UNIMPLEMENTED ("query for default processing pattern with capabilities"); - } - + template shared_ptr DefsManager::operator ()(const Query&); + template PProcPatt DefsManager::operator ()(const Query&); } // namespace mobject::session } // namespace mobject + diff --git a/src/proc/mobject/session/defsmanager.hpp b/src/proc/mobject/session/defsmanager.hpp index ccc75d6ac..b48411058 100644 --- a/src/proc/mobject/session/defsmanager.hpp +++ b/src/proc/mobject/session/defsmanager.hpp @@ -27,10 +27,6 @@ #include "common/query.hpp" -//#include -//#include - -//using std::vector; #include @@ -63,6 +59,12 @@ namespace mobject template shared_ptr operator() (const cinelerra::Query&); +// template +// < class TAR, ///< the target to query for +// template class SMP ///< smart pointer class to wrap the result +// > +// SMP operator() (const cinelerra::Query&); + }; From 706589d4226ee855a67a8cd927537b2f31a61ab2 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 29 Jan 2008 05:39:32 +0100 Subject: [PATCH 04/14] WIP yet more stubs to make it link... --- src/common/configrules.cpp | 3 +++ src/common/configrules.hpp | 4 ++-- src/common/query/mockconfigrules.cpp | 24 ++++++++++++++++++++++++ src/common/query/mockconfigrules.hpp | 2 ++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/common/configrules.cpp b/src/common/configrules.cpp index 2eeca2649..d72608035 100644 --- a/src/common/configrules.cpp +++ b/src/common/configrules.cpp @@ -36,6 +36,9 @@ namespace cinelerra CINELERRA_ERROR_DEFINE (CAPABILITY_QUERY, "unresolvable capability query"); + + ConfigRulesInterface::~ConfigRulesInterface() + { }; } // namespace query diff --git a/src/common/configrules.hpp b/src/common/configrules.hpp index 80ba8df3c..e17914187 100644 --- a/src/common/configrules.hpp +++ b/src/common/configrules.hpp @@ -118,9 +118,9 @@ namespace cinelerra class QueryHandler { protected: - virtual ~QueryHandler(); + virtual ~QueryHandler() { } public: - virtual shared_ptr resolve (Query q); + virtual shared_ptr resolve (Query q) = 0; }; // TODO: the Idea is to provide specialisations for the concrete types diff --git a/src/common/query/mockconfigrules.cpp b/src/common/query/mockconfigrules.cpp index 915e20ba8..068f6bdbd 100644 --- a/src/common/query/mockconfigrules.cpp +++ b/src/common/query/mockconfigrules.cpp @@ -22,6 +22,12 @@ #include "common/query/mockconfigrules.hpp" + +#include "proc/mobject/session/track.hpp" +#include "proc/asset/procpatt.hpp" +#include "proc/asset/port.hpp" + + //#include "common/util.hpp" #include "nobugcfg.h" @@ -37,6 +43,24 @@ namespace cinelerra { } + + shared_ptr + MockConfigRules::resolve (Query q) + { + UNIMPLEMENTED ("solve for Track"); + } + + shared_ptr + MockConfigRules::resolve (Query q) + { + UNIMPLEMENTED ("solve for Port"); + } + + PProcPatt + MockConfigRules::resolve (Query q) + { + UNIMPLEMENTED ("solve for ProcPatt"); + } } // namespace query diff --git a/src/common/query/mockconfigrules.hpp b/src/common/query/mockconfigrules.hpp index 07fc98831..17f9b6f95 100644 --- a/src/common/query/mockconfigrules.hpp +++ b/src/common/query/mockconfigrules.hpp @@ -66,6 +66,8 @@ namespace cinelerra protected: MockConfigRules (); friend class cinelerra::singleton::StaticCreate; + + virtual ~MockConfigRules() {} public: From 250954bb5fa3995f78e1788943c92df6aa89cfb0 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 1 Feb 2008 03:38:29 +0100 Subject: [PATCH 05/14] oops... causes the exception type to be upcasted (from Fatal to Error) --- src/common/error.cpp | 7 ++++--- src/common/error.hpp | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/common/error.cpp b/src/common/error.cpp index 94f7ca3ed..505e6e130 100644 --- a/src/common/error.cpp +++ b/src/common/error.cpp @@ -183,9 +183,10 @@ namespace cinelerra void assertion_terminate (const string& location) { - throw Fatal (location, CINELERRA_ERROR_ASSERTION) - .setUsermsg("Program terminated because of violating " - "an internal consistency check."); + Fatal exception (location, CINELERRA_ERROR_ASSERTION); + exception.setUsermsg("Program terminated because of violating " + "an internal consistency check."); + throw exception; } diff --git a/src/common/error.hpp b/src/common/error.hpp index 3251752df..82a388e50 100644 --- a/src/common/error.hpp +++ b/src/common/error.hpp @@ -122,7 +122,7 @@ namespace cinelerra /** Macro for creating derived exception classes properly * integrated into cinelerra's exception hierarchy. Using - * this macro asures that the new class will get the full + * this macro ensures that the new class will get the full * set of constructors and behaviour common to all exception * classes, so it should be used when creating an derived * exception type for more then stricly local purposes From e2ee8f081b8698130e517d762409149cd8d3d172 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 1 Feb 2008 03:48:09 +0100 Subject: [PATCH 06/14] augment the singleton factory to create a subclass. Helps avoiding dependency problems, because client code is no longer coupled to the implementation class --- .gitignore | 1 + src/common/singletonfactory.hpp | 9 +- src/common/singletonsubclass.hpp | 161 +++++++++++++++++ tests/50components.tests | 10 +- .../common/singletonsubclasstest.cpp | 163 ++++++++++++++++++ tests/components/common/typelistutiltest.cpp | 1 - 6 files changed, 338 insertions(+), 7 deletions(-) create mode 100644 src/common/singletonsubclass.hpp create mode 100644 tests/components/common/singletonsubclasstest.cpp diff --git a/.gitignore b/.gitignore index ef277c1a1..5dc912d9e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .[^.]* *.os *.gch +,valgrind.log* Buildhelper.pyc optcache Makefile.in diff --git a/src/common/singletonfactory.hpp b/src/common/singletonfactory.hpp index ba2151584..a0f63c978 100644 --- a/src/common/singletonfactory.hpp +++ b/src/common/singletonfactory.hpp @@ -40,7 +40,6 @@ This code is heavily inspired by #include "common/util.hpp" #include "nobugcfg.h" -//#include namespace cinelerra @@ -53,10 +52,10 @@ namespace cinelerra * @note internally uses static fields, so all functor instances share pInstance_ */ template - < class SI, // the class to make Singleton - template class Create = singleton::StaticCreate, // how to create/destroy the instance - template class Life = singleton::AutoDestroy, // how to manage Singleton Lifecycle - template class Threading = singleton::IgnoreThreadsafety //TODO use Multithreaded!!! + < class SI // the class of the Singleton instance + , template class Create = singleton::StaticCreate // how to create/destroy the instance + , template class Life = singleton::AutoDestroy // how to manage Singleton Lifecycle + , template class Threading = singleton::IgnoreThreadsafety //TODO use Multithreaded!!! > class SingletonFactory { diff --git a/src/common/singletonsubclass.hpp b/src/common/singletonsubclass.hpp new file mode 100644 index 000000000..90b26a6b5 --- /dev/null +++ b/src/common/singletonsubclass.hpp @@ -0,0 +1,161 @@ +/* + SINGLETONSUBCLASS.hpp - variant of the singleton (factory) creating a subclass + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file singletonsubclass.hpp + ** Spezialized SingletonFactory creating sublcasses of the nominal type. + ** The rationale is to be able to defer the decision what type to create + ** down to the point where the singleton factory is actualy created. + ** Thus the code using the singleton need not know the implementation + ** class, but nevertheless gets an non-virtual access function to the + ** singleton instance (which can be inlined), and the compiler is + ** still able to spot type errors. Maybe someone knows a less + ** contrieved solution fulfilling the same criteria....? + ** + ** @see configrules.cpp usage example + ** @see SingletonSubclass_test + */ + + +#ifndef CINELERRA_SINGLETONSUBCLASS_H +#define CINELERRA_SINGLETONSUBCLASS_H + + +#include "common/singleton.hpp" + +#include +#include + + +namespace cinelerra + { + using boost::scoped_ptr; + + + namespace singleton + { + /** + * Helper template to use the general policy classes of the cinelerra::Singleton, + * but change the way they are parametrized on-the-fly. + */ + template class POL, class I> + struct Adapter + { + + struct Link + { + virtual ~Link() {} + virtual I* create () = 0; ///< @note compiler will check the actual type is asignable... + virtual void destroy (I* pSi) = 0; + }; + + template + struct TypedLink : Link + { + virtual S* create () { return POL::create (); } // covariance checked! + virtual void destroy (I* pSi) { POL::destroy (static_cast (pSi)); } + }; + + /** we configure this link \i later, when the singleton factory + * is actually created, to point at the desired implementation subclass. + */ + static scoped_ptr link; + + /** Forwarding Template to configure the basic SingletonFactory */ + template + struct Adapted + { + static II* create () { return link->create (); } + static void destroy (II* pSi) { link->destroy (pSi); } + }; + }; + + template class A, class I> + scoped_ptr::Link> Adapter::link (0); + + + /** type-information used to configure the factory instance + * with the concrete implementation type to be created. */ + template + struct UseSubclass + { }; + + } // namespace singleton + + + + + /** + * Special variant of the SingletonFactory with the option of actually creating + * a subclass or wrap the product in some way. For the user code, it should behave + * exactly like the standard SingletonFactory. The configuration of the product + * actually to be created is delayed until the ctor call, so it can be hidden + * away to the implementaton of a class using the SingletonFactory. + * + * @see configrules.cpp usage example + */ + template + < class SI // the class to use as Interface for the Singleton + , template class Create = singleton::StaticCreate // how to create/destroy the instance + , template class Life = singleton::AutoDestroy // how to manage Singleton Lifecycle + , template class Threading = singleton::IgnoreThreadsafety //TODO use Multithreaded!!! + > + class SingletonSubclassFactory + : public SingletonFactory< SI + , singleton::Adapter::template Adapted + , Life + , Threading + > + { + public: + /** The singleton-factory ctor configures what concrete type to create. + * It takes type information passed as dummy parameter and installes + * a trampoline object in the static field of class Adapter to perform + * the necessary up/downcasts. This allows to use whatever policy + * class ist wanted, but parametrizes this policy template with + * the concrete type to be created. (only the "create" policy + * needs to know the actual class, because it allocates storage) + */ + template + SingletonSubclassFactory (singleton::UseSubclass) + { + typedef typename singleton::Adapter Adapter; + typedef typename Adapter::template TypedLink TypedLink; + + if (!Adapter::link) + Adapter::link.reset (new TypedLink); + +#ifdef DEBUG + else + REQUIRE ( typeid(*Adapter::link) == typeid(new TypedLink), + "If using several instances of the sub-class-creating " + "singleton factory, all *must* be configured to create " + "objects of exactly the same implementation type!"); +#endif + } + }; + + + + +} // namespace cinelerra + +#endif diff --git a/tests/50components.tests b/tests/50components.tests index c0addaf23..12e0fb0c3 100644 --- a/tests/50components.tests +++ b/tests/50components.tests @@ -118,6 +118,15 @@ out: '§&Ω%€' --> '' END +TEST "SingletonSubclass_test" SingletonSubclass_test 13 < + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "common/testtargetobj.hpp" +#include "common/singletonsubclass.hpp" + +#include "common/test/run.hpp" +#include "common/util.hpp" + +#include +#include +#include + +using boost::lexical_cast; +using boost::format; +using util::isnil; +using std::string; +using std::cout; + + +namespace cinelerra + { + namespace test + { + + + /** + * Target object to be instantiated as Singleton + * Allocates a variable amount of additional heap memory + * and prints diagnostic messages. + */ + class Interface : public TestTargetObj + { + public: + static int cnt; + static void setCountParam (uint c) { Interface::cnt = c; } + + virtual string identify() { return "Interface"; } + + protected: + Interface () : TestTargetObj(cnt) {} + virtual ~Interface() {} + + friend class singleton::StaticCreate; + friend class singleton::HeapCreate; + }; + + int Interface::cnt = 0; + + + class Impl : public Interface + { + public: + virtual string identify() { return "Implementation"; } + }; + + + // for checking the safety..... + class Impl_XXX : public Impl { }; + class Unrelated { }; + + + + + /******************************************************************* + * @test spezialized variant of the Singleton Factory, for creating + * subclasses (implementation classes) without coupling the + * caller to the concrete class type. + * Expected results: an instance of the subclass is created. + * @see cinelerra::Singleton + * @see cinelerra::SingletonSubclassFactory + * @see cinelerra::singleton::Adapter + */ + class SingletonSubclass_test : public Test + { + + virtual void run(Arg arg) + { + uint num= isnil(arg)? 1 : lexical_cast(arg[1]); + + cout << format("using the Singleton should create TargetObj(%d)...\n") % num; + + Interface::setCountParam(num); + + // marker to declare the concrete type to be created + singleton::UseSubclass typeinfo; + + // define an instance of the Singleton factory, + // spezialized to create the concrete Type passed in + SingletonSubclassFactory instance (typeinfo); + + // Now use the Singleton factory... + // Note: we get the Base type + Interface& t1 = instance(); + Interface& t2 = instance(); + + ASSERT ( &t1 == &t2, "not a Singleton, got two different instances." ); + + cout << "calling a non-static method on the Singleton-" + << t1.identify() << "\n" + << string (t1) << "\n"; + +#ifdef DEBUG + verify_error_detection (); +#endif + } + + + + void verify_error_detection () + { + + singleton::UseSubclass more_special_type; + + try + { + SingletonSubclassFactory instance (more_special_type); + cout << "was able to re-configure the SingletonSubclassFactory " + "with another type. This should be detected in debug mode\n"; + } + catch (...) + { + ASSERT (cinelerra_error () == error::CINELERRA_ERROR_ASSERTION); + } + + + // Note: the following won't compile, because the "subclass" isn't a subclass... + // + // singleton::UseSubclass yet_another_type; + // SingletonSubclassFactory instance (yet_another_type); + } + }; + + + + /** Register this test class... */ + LAUNCHER (SingletonSubclass_test, "unit common"); + + + + } // namespace test + +} // namespace cinelerra diff --git a/tests/components/common/typelistutiltest.cpp b/tests/components/common/typelistutiltest.cpp index 0d5fcabd1..d91edfe60 100644 --- a/tests/components/common/typelistutiltest.cpp +++ b/tests/components/common/typelistutiltest.cpp @@ -26,7 +26,6 @@ #include #include -#include using std::string; using std::cout; From edbf5fd7337bf94ca653e31a6f70ae967021c65d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 1 Feb 2008 15:35:33 +0100 Subject: [PATCH 07/14] ConfigRules dependency problems solved by using the new SingletonSubclassFactory --- src/common/configrules.cpp | 11 ++++++++- src/common/configrules.hpp | 31 ++++++++++++------------ src/common/singletonsubclass.hpp | 15 ++++++++++-- src/proc/mobject/session/defsmanager.cpp | 5 ++-- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/common/configrules.cpp b/src/common/configrules.cpp index d72608035..244e88d5f 100644 --- a/src/common/configrules.cpp +++ b/src/common/configrules.cpp @@ -40,9 +40,18 @@ namespace cinelerra ConfigRulesInterface::~ConfigRulesInterface() { }; + } // namespace query - + + namespace + { + /** type of the actual ConfigRules implementation to use */ + singleton::UseSubclass typeinfo; + } + + /** Singleton factory instance, parametrized to actual impl. type. */ + SingletonSub ConfigRules::instance (typeinfo); } // namespace cinelerra diff --git a/src/common/configrules.hpp b/src/common/configrules.hpp index e17914187..ed682e140 100644 --- a/src/common/configrules.hpp +++ b/src/common/configrules.hpp @@ -47,8 +47,8 @@ #define CINELERRA_CONFIGRULES_H #include "common/query.hpp" -#include "common/singleton.hpp" #include "common/typelist.hpp" +#include "common/singletonsubclass.hpp" #include "proc/mobject/session/track.hpp" #include "proc/asset/procpatt.hpp" @@ -65,7 +65,6 @@ namespace cinelerra using std::string; using std::tr1::shared_ptr; - namespace query { class MockConfigRules; } // TODO: need a better way to return a sub-type from a singleton @@ -163,26 +162,18 @@ namespace cinelerra { }; - template - < typename TYPES, - class IMPL - > + template class ConfigRules : public ConfigRulesInterface { protected: ConfigRules () {} virtual ~ConfigRules() {} - - public: - static cinelerra::Singleton instance; + public: // TODO: find out what operations we need to support here for the »real solution« (using Prolog) }; - /** storage for the Singleton instance factory */ - template - cinelerra::Singleton ConfigRules::instance; @@ -206,10 +197,18 @@ namespace cinelerra > InterfaceTypes; - typedef query::ConfigRules< InterfaceTypes, // List of Types to generate interface functions - query::MockConfigRules // actual Implementation to use - > - ConfigRules; // user-visible Interface to the ConfigRules subsystem. + /** + * user-visible Interface to the ConfigRules subsystem. + * Configured as Singleton (with hidden Implementation class) + */ + class ConfigRules + : public query::ConfigRules + { + + public: + static SingletonSub instance; + + }; } // namespace cinelerra diff --git a/src/common/singletonsubclass.hpp b/src/common/singletonsubclass.hpp index 90b26a6b5..8877ba6bf 100644 --- a/src/common/singletonsubclass.hpp +++ b/src/common/singletonsubclass.hpp @@ -135,7 +135,7 @@ namespace cinelerra * needs to know the actual class, because it allocates storage) */ template - SingletonSubclassFactory (singleton::UseSubclass) + SingletonSubclassFactory (singleton::UseSubclass&) { typedef typename singleton::Adapter Adapter; typedef typename Adapter::template TypedLink TypedLink; @@ -154,7 +154,18 @@ namespace cinelerra }; - + /** + * Default Singleton configuration (subclass creating factory) + * @note all Policy template parameters taking default values + */ + template + struct SingletonSub + : public SingletonSubclassFactory + { + template + SingletonSub (TY ref) : SingletonSubclassFactory(ref) {} + }; + } // namespace cinelerra diff --git a/src/proc/mobject/session/defsmanager.cpp b/src/proc/mobject/session/defsmanager.cpp index 2851ea235..5880bc1b3 100644 --- a/src/proc/mobject/session/defsmanager.cpp +++ b/src/proc/mobject/session/defsmanager.cpp @@ -25,7 +25,6 @@ #include "proc/asset/procpatt.hpp" #include "proc/asset/port.hpp" #include "common/configrules.hpp" -#include "common/query/mockconfigrules.hpp" // TODO: better way to handle the includes (rework singleton template?) #include "common/error.hpp" #include @@ -38,6 +37,7 @@ using asset::ProcPatt; using asset::PProcPatt; using cinelerra::ConfigRules; +using cinelerra::query::QueryHandler; using cinelerra::query::CINELERRA_ERROR_CAPABILITY_QUERY; namespace mobject @@ -56,7 +56,8 @@ namespace mobject shared_ptr DefsManager::operator() (const Query& capabilities) { - shared_ptr res = cinelerra::ConfigRules::instance().resolve (capabilities); + QueryHandler& typeHandler = ConfigRules::instance(); + shared_ptr res = typeHandler.resolve (capabilities); if (!res) throw cinelerra::error::Config ( str(format("The following Query could not be resolved: %s.") From 0d50639d708942216a19fcb6636e8eeae0bfb56f Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 2 Feb 2008 14:52:23 +0100 Subject: [PATCH 08/14] Fix problem with static initialisation order --- src/common/singletonsubclass.hpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/common/singletonsubclass.hpp b/src/common/singletonsubclass.hpp index 8877ba6bf..e779b820e 100644 --- a/src/common/singletonsubclass.hpp +++ b/src/common/singletonsubclass.hpp @@ -73,13 +73,20 @@ namespace cinelerra virtual S* create () { return POL::create (); } // covariance checked! virtual void destroy (I* pSi) { POL::destroy (static_cast (pSi)); } }; - + + + struct My_scoped_ptr : scoped_ptr ///< implementation detail: defeat static initialisation + { + using scoped_ptr::get; + My_scoped_ptr() : scoped_ptr (get()? get() : 0) {} ///< bypass if already configured + }; + /** we configure this link \i later, when the singleton factory * is actually created, to point at the desired implementation subclass. */ - static scoped_ptr link; + static My_scoped_ptr link; - /** Forwarding Template to configure the basic SingletonFactory */ + /** Forwarding Template used to configure the basic SingletonFactory */ template struct Adapted { @@ -89,7 +96,7 @@ namespace cinelerra }; template class A, class I> - scoped_ptr::Link> Adapter::link (0); + typename Adapter::My_scoped_ptr Adapter::link; // note: use special ctor (due to stati init order!) /** type-information used to configure the factory instance From e08fc6cdc867e09b6dda14e36d005859f7cba30e Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 3 Feb 2008 19:47:33 +0100 Subject: [PATCH 09/14] reviewed, small additions --- wiki/index.html | 18 ++++++----- wiki/renderengine.html | 68 +++++++++++++++++++++++++----------------- 2 files changed, 51 insertions(+), 35 deletions(-) diff --git a/wiki/index.html b/wiki/index.html index 43202dd25..34493fc01 100755 --- a/wiki/index.html +++ b/wiki/index.html @@ -1032,7 +1032,7 @@ cinelerra3/mob is an anonymous account at pipapo.org where everyone can commit c * on the question who decides what to do after a cache miss, we tend to put the decision into the render node (because this seems to be the simpler aproach), but still have to work out the details.
-
+
! 1. feb.2008 on #openvideo
 21:00 -23:30 GMT. __Participants__:
 * hermanr
@@ -1047,17 +1047,18 @@ cinelerra3/mob is an anonymous account at pipapo.org where everyone can commit c
 * Velmont
 
 !! Discuss the open points in http://www.pipapo.org/pipawiki/Cinelerra3/DesignProcess &mdash; do we need this formalism?
-At start of the project last summer, Cehteh made a [[design process proposal|http://www.pipapo.org/pipawiki/Cinelerra3/DesignProcess]]. We will keeping this up, not for every implementation detail, but for mayor plans, wishes and design decisions. One point in the agenda of future meetings will be to work through proposals in the queue
+At start of the project last summer, Cehteh made a [[design process proposal|http://www.pipapo.org/pipawiki/Cinelerra3/DesignProcess]]. We will keeping this up, not for every implementation detail, but for major plans, wishes and design decisions. One point in the agenda of future meetings will be to work through proposals in the queue
 * proposals in the "idea" state are not complete, can be just brainstorming or need further discussion. Comments please to the proposal page.
 * proposals in the "draft" state are ready for conclusive discussion and will be treated in one of the next meetings
 * "final" proposals are either "accepted" or "dropped". We don't differentiate the latter, but should write a short note why it was dropped.
+* if there is need for more or finer grained categories, we'll extend the page and the template as needed or provide different views
 
 !! The development model
 We employ a distributed model based on GIT. We want this repository to be as complete as possible, including documentation in embedded ~TiddlyWikis and Bug reports. Each dev has its own GIT repo, devs are pulling from each other, they are free to cherry pick and try to make the combined version work. Point is that everyone can clone the git, negotiate with the others what s(he) wants to do, and hack on. Every dev signs off his branch with an standardized signature. For small changes we provide a "Mob GIT", i.e. anonymously pushable git (which is untrusted of course). Cehteh is currently working on a git web frontend which makes the codebase in the mob-repo web-editable like a wiki.
 Will we need a stable version or an official branch?  not yet &mdash; as long as the team is small it will work more painless without. At some point, when the project is more mature, we will define an official branch. Later on we will have automated builds and regression test runs. As we do test-driven development anyways, it's just a question of someone setting up all the infrastructure, then we'll do it.
 Ichthyo proposes a new requirement: All devs should ensure the "master" branch of their respective repositories always passes the compiler and the test suite. ~Work-In-Progress should be done on branches. Rationale: it is sufficient to pull from the master branches, and you can be sure the version you pulled worked for the originator.
-A note on dependencies: it will be hard to target minimal dependencies for such a project, but we shall try not bloat it unnecessarily. Sometimes it can be sensible to rather re-invent a feature &mdash; esp. when it fits into the core focus of the project &mdash; instead of depending on difficult to build and not sufficiently maintained external project. But we should avoid reinventing things like GUI toolkits.
-And, pretty much obvious, we try to stick to modern programming standards. That means, modules have interfaces, interfaces need some (minimal) documentation, and it is not allowed to bypass the interfaces and tangle everything in a wild fashion.
+A note on dependencies: it will be hard to target minimal dependencies for such a project, but we shall try not to bloat it unnecessarily. Sometimes it can be sensible to rather re-invent a feature &mdash; esp. when it fits into the core focus of the project &mdash; instead of depending on difficult to build and not sufficiently maintained external projects. But we should avoid reinventing things like GUI toolkits.
+And, pretty much obvious, we try to stick to modern programming standards. Read: modules have interfaces, interfaces need some (minimal) documentation, and it is not allowed to bypass the interfaces and tangle everything in a wild fashion.
 Currently, the project can be separated into three layers, which could evolve into sub-projects: Backend, ~Proc-Layer, GUI. For each part, the dev most deeply involved and most knowledgeable will take on the sometimes necessary leadership and have the last word in case of quarrels. Currently, Cehteh cares for the Backend and Ichthyo headed for the ~Proc-Layer. We have postponed any work on the GUI for now and don't participate in GUI toolkit discussions. If there is a dev willing to care for the GUI, collect proposals, care for usability and the users needs and finally code it up, then he will the one to decide what toolkit to use.
 We plan to make the discussion about GPL v3 a point on the agenda of the next meeting.
 
@@ -1067,25 +1068,28 @@ We plan to make the discussion about GPL v3 a point on the agenda of the next me
 * write a short status report for each mayor part //prior// to the meeting (saves us time). Maybe add an TODO list there
 * go through the open issues for the design process drafts
 * publish a protocol of each meeting on the (~Cinelerra-CV, ~LibOpenvideo) Mailinglists, in the TiddlyWiki and on pipapo.org
+* News, Protocols and the agenda of the next meeting can be found at the [[pipawiki-page|http://www.pipapo.org/pipawiki/Cinelerra3/MonthlyMeetings]]
 * next meeting on first Thursday in March (6.3.2008)
 
 !! Who works on what, what are the short term goals, what tasks are open?
 ''Ichthyo'' works on the processing layer. Current goal is to get the core of the builder fleshed out. Next goal is to create a clip object (dummy), add it to the EDL, hand the EDL over to the builder and let the builder make the first (preliminary) render nodes. (note: left many details for later).
-Ichthyo started coding his design draft and things seem to work out as intended. Some Keywords: Have a high-level model and a low level model. The former are the objects in the Session edited by the user, the latter is a network of completely configured render nodes, employing the same pull model as in Cinelerra-2. In between sits the Builder, translating high-level into low-level. This translation is done on demand (not for every frame).
+Ichthyo started coding his design draft and things seem to work out as intended. Some Keywords: Have a high-level model and a low level model. The former is comprised of the objects in the Session edited by the user, the latter is a network of completely configured render nodes, employing the same pull model as in Cinelerra-2. In between sits the Builder, translating high-level into low-level. This translation is done on demand (not for every frame).
 Current state in this part is: basic asset manager is done, asset objects (forming a hierarchy) can be created and will be registered automatically, it is possible to create a clip-"~MediaObject" from a media asset (without caring for any details regarding multichannel clips). Some support lib components are written, Session and data holders start up on demand and shutdown cleanly. The test suite is the only interesting executable, and this will remain so for quite some time. Currently writing the first parts of the Builder.
 Further plans/ideas: Ichthyo is rather determined to embed a Prolog interpreter (YAP Prolog) to handle all sorts of configuration queries in a rule-driven fashion. Things Ichthyo can't do in the near future: caring for session loading/saving serialisation plus storage backends, caring for a DB based implementation of the asset manager and integration with production support software, target the scheduler which will receive any edit operations initiated from the GUI.
 
 ''Cehteh'' is currently working on webgit, which is somewhat related inasmuch it will make small contributions to the mob repository much simpler. Previously he started with some foundation and support facilities. He plans to come back to the Backend implementation in about two weeks. The Backend is intended to handle all media (and even meta-)data as generalized frames. The render nodes network created by the ~Proc-Layer is completely stateless and all data is served from below. While it will be possible to address and access individual data within a frame (e.g. audio samples), frames are the smallest unit for memory and cache management. No plans to use a tiled memory model or to support frames larger than aprox. 20-40% of the available RAM.
-Cehteh's design plan includes a scheduler to organize the access to the raw data, monitor the timings and prefetch data as needed. This scheduler will be configurable via quality preferences ("need realtime", "need perfect quality"). Further, there will be an elaborate caching scheme trying hard to avoid re-rendering any frames already calculated previously. Temporary data will be backed by files and thus swapped out &mdash; this swapout and size of temporary data is to be monitored and adjusted on load &mdash; and all temporary data is kept as most-recent-used cache discipline. Incoming and outgoing footage shall mostly be handled by using mmaped buffers. The rationale is to avoid unnecessary copy from kernel to user space and wasting memory for an additional in-kernel buffer. Writing via a mmapped buffer is little more tricky; there will be a in-place writing which is used for indices and other precalculated data which needs updates, and the processing layer can query write buffers which are actually a small cache/ring and then comited to the file. Basically, mmapping is a clean solution if you can design for it, and it's portable (posix)
+Cehteh's design plan includes a scheduler to organize the access to the raw data, monitor the timings and prefetch data as needed. This scheduler will be configurable via quality preferences ("need realtime", "need perfect quality"). Further, there will be an elaborate caching scheme trying hard to avoid re-rendering any frames already calculated previously. Temporary data will be backed by files and thus swapped out &mdash; this swapout and size of temporary data is to be monitored and adjusted according to the current load &mdash; and all temporary data is kept as most-recent-used cache discipline. Incoming and outgoing footage shall mostly be handled by using mmaped buffers. The rationale is to avoid unnecessary copy from kernel to user space and wasting memory for an additional in-kernel buffer. Writing via a mmapped buffer is little more tricky; there will be a in-place writing which is used for indices and other precalculated data which needs updates, and the processing layer can query write buffers which are actually a small cache/ring and then comited to the file. Basically, mmapping is a clean solution if you can design for it, and it's portable (posix)
 Things to do: object serialisation backend is sometime on Cehteh's schedule, but that's ahead and if someone else helps or takes over it would be OK. Even more true for a DB based backend for the asset manager.
 
+''Gmerlin'' plans to implement grayscale support for GAVL, so the upper layers can store arbitrary data in it.
+
 __about multithreading__: since the render nodes are stateless they can be driven in multiple threads (but inter frame dependencies need to be resolved/serialized). Mostly the backend manages threads and does that quite conservatively (compared to Cinelerra-2 which massively creates separate threads for small tasks). Any edit operations initiated from GUI go to a scheduler in the middle layer, which enqueues and effectively serializes operations done to the "media objects" in the high-level model. The editing operations themselves are //not threadsafe // by design, they rely on being scheduled correctly. The builder is triggered from this ~Proc-Layer scheduler and starts in one separate thread, and when done, we swap whole parts of the render nodes network and then the backend can re(start) rendering as needed.
 
 !!The naming discussion
 The discussion looks healthy so far... People can add new proposals on the [[pipawiki|http://www.pipapo.org/pipawiki/Cinelerra3/Names]]. intersting names are still coming in, so we should just let the name-choosing game go on for a while. And, btw, we //can// depart from beeing similar to "Cinelerra" ;-) 
 Let's say, we need a person volonteering to guide/moderate the selection, going over the list and scratching inammprobiate ones. Criteria for good names being:
 * should not be an existing project
-* should be "googeable"
+* should be "googleable"
 * should not be offensive
 * should have one of the free top level domains (.net, .org)
 * should be compatible with educational institutions (sorry, no pr0nedit :)
diff --git a/wiki/renderengine.html b/wiki/renderengine.html
index ded8d9eb3..8ab162beb 100644
--- a/wiki/renderengine.html
+++ b/wiki/renderengine.html
@@ -833,8 +833,8 @@ This is an very important external Interface, because it links together all thre
 * completely hide the Session object behind a ''~PImpl'' smart pointer, so the session object can be switched when reloading.
 * the [[Fixture]] acts as isolation layer, and all objects refered from the Fixture are refcounting smart pointers. So, even when the session gets switched, the old objects remain valid as long as needed.
-
-
RenderEngine
+
+
[[ProcLayer and Engine]]
 
@@ -957,7 +957,7 @@ To make the intended use of the classes more clear, consider the following two e
A special kind (subclass) of [[Placement]]. As such it is always linked to a //Subject//, i.e. a MObject. In addition to the properties of a (unspecific) Placement, the ExplicitPlacement specifies a absolute time and track position for locating the Subject
 
-
+
We use Factories
 * for centralizing [[memory management|MemoryManagement]]
 * to support polymorphism (of course...)
@@ -1109,7 +1109,7 @@ For this Cinelerra3 design, we could consider making GOP just another raw media
 &rarr;see in [[Wikipedia|http://en.wikipedia.org/wiki/Group_of_pictures]]
 
-
+
This wiki page is the entry point to detail notes covering some technical decisions, details and problems encountered in the course of the implementation of the Cinelerra Renderengine, the Builder and the related parts.
 
 * [[Packages, Interfaces and Namespaces|InterfaceNamespaces]]
@@ -1123,7 +1123,7 @@ For this Cinelerra3 design, we could consider making GOP just another raw media
 * [[using the Visitor pattern?|VisitorUse]] &mdash; resulting in [[»Visiting-Tool« library implementation|VisitingToolImpl]]
 * [[Handling of Tracks and Ports in the EDL|TrackPortEDL]]. [[Handling of Tracks|TrackHandling]] and [[Ports|PortHandling]]
 * [[getting default configured|DefaultsManagement]] Objects relying on [[rule-based Configuration Queries|ConfigRules]]
-* [[identifying the basic Builder operations|BasicBuildingOperations]] and [[planning the Implementation|PlanningNodeCreaterTool]]
+* [[identifying the basic Builder operations|BasicBuildingOperations]] and [[planning the Implementation|PlanningNodeCreatorTool]]
 * [[how to handle »attached placement«|AttachedPlacementProblem]]
 
@@ -1524,9 +1524,9 @@ This Design strives to achieve a StrongSeparation between the low-level Structur [img[Classess related to the EDL|uml/fig128133.png]]
-
+
''[[Cinelerra3|index.html]]''
-[[RenderEngine]]
+[[Proc-Layer|ProcLayer and Engine]]
 [[MObjects]]
 [[Implementation|ImplementationDetails]]
 [[Admin]]
@@ -2298,7 +2298,7 @@ afterwards.
 <<tasksum end>>
 
-
+
//This page is a scrapbook for working out the implementation of the builder//
 
 * NodeCreaterTool is a [[visiting tool|VisitorUse]]
@@ -2412,10 +2412,34 @@ We need to work out guidelines for dealing with operations going on simultaneous
 * all EditingOperations are not threadsafe intentionally, because they are [[scheduled|ProcLayerScheduler]]
 
-
+
+
The current Cinelerra-3 architecture separates functionality into three Layers: __GUI__, __Proc__ and __Backend__.
+
+While the Backend is responsible for Data access and management and for carrying out the computation intensive media opteratons, the middle Layer or ~Proc-Layer contains [[assets|Asset]] and [[Session]], i.e. the user-visible data model and provides configuration and behaviour for these entities. Besides, he is responsible for [[building and configuring|Builder]] the [[render engine|RenderEngine]] based on the current Session state.
+
+
+
All Assets of kind asset::Proc represent //processing algorithms// in the bookkeeping view. They enable loading, browsing and maybe even parametrizing all the Effects, Plugins and Codecs available for use within the Cinelerra Session.
+
+Besides, they provide an important __inward interface__ for the [[ProcNode]]s, which will use these asset entries to dispatch the actual processing call when rendering. 
+
+{{red{todo: the naming scheme??}}}
+
+[img[Asset Classess|uml/fig131077.png]]
+
+
+
+
The middle Layer of our current Architecture plan, i.e. the layer managing all processing and manipulation, while the actual data handling is done in the backend and the user interaction belongs to the GUI Layer.
+
+&rarr; see the [[Overview]]
+
+
+
+
The Render Engine is the part of the application doing the actual video calculations. Its operations are guided by the Objects and Parameters edited by the user in [[the EDL|EDL]] and it retrieves the raw audio and video data from the [[Data backend|backend.html]]. Because the inner workings of the Render Engine are closely related to the structures used in the EDL, this design covers [[the aspect of objects placed into the EDL|MObjects]] as well.
 <<<
-''Status'': started out as design draft in summer '07, Ichthyo is now in the middle of a //first, draft, prototypical// implementation in C++
+''Status'': started out as design draft in summer '07, Ichthyo is now in the middle of a implementing the foundations and main structures in C++
+* basic AssetManager working
+* currently impmenenting the Builder (&rarr;[[more|PlanningNodeCreatorTool]])
 <<<
 
 !Summary
@@ -2434,23 +2458,6 @@ The system is ''open'' inasmuch every part mirrors the structure of correspondin
 &rarr; how [[Automation]] works  {{red{to be defined in more detail}}}
 &rarr; [[Problems|ProblemsTodo]] to be solved and notable [[design decisions|DesignDecisions]]
 &rarr; [[Implementation Details|ImplementationDetails]] {{red{WIP}}}
-
-
-
-
All Assets of kind asset::Proc represent //processing algorithms// in the bookkeeping view. They enable loading, browsing and maybe even parametrizing all the Effects, Plugins and Codecs available for use within the Cinelerra Session.
-
-Besides, they provide an important __inward interface__ for the [[ProcNode]]s, which will use these asset entries to dispatch the actual processing call when rendering. 
-
-{{red{todo: the naming scheme??}}}
-
-[img[Asset Classess|uml/fig131077.png]]
-
-
-
-
The middle Layer of our current Architecture plan, i.e. the layer managing all processing and manipulation, while the actual data handling is done in the backend and the user interaction belongs to the GUI Layer.
-
-&rarr; see the [[Overview]]
-
 
@@ -2726,6 +2733,11 @@ The link between ~MObject and Asset should be {{{const}}}, so the clip can't cha At first sight the link between asset and clip-MO is a simple logical relation between entities, but it is not strictly 1:1 because typical media are [[multichannel|MultichannelMedia]]. Even if the media is compound, there is //only one asset::Clip//, because in the logical view we have only one "clip-thing". On the other hand, in the Session/EDL, we have a compound clip ~MObject comprised of several elementary clip objects, each of which will refer to its own sub-media (channel) within the compound media (and don't forget, this structure can be tree-like) {{red{open question:}}} do the clip-MO's of the individual channels refer directly to asset::Media? does this mean the relation is different from the top level, where we have a relation to a asset::Clip??
+
+
Conceptually, the Render Engine is the core of the application. But &mdash; surprisingly &mdash; we don't even have a distinct »~RenderEngine« component in our design. Rather, the engine is formed by the cooperation of several components spread over two layers (Backend and Proc-Layer): The [[Builder]] creates a network of [[render nodes|ProcNode]], which is used by the Backend to pull individual Frames.
+&rarr; OverviewRenderEngine
+
+
The Render Engine only carries out the low-level and performance critical tasks. All configuration and decision concerns are to be handled by [[Builder]] and [[Controller]]. While the actual connection of the Render Nodes can be highly complex, basically each Segment of the Timeline with uniform characteristics is handled by one Processor, which is a graph of [[Processing Nodes|ProcNode]] discharging into a ExitNode. The Render Engine Components as such are //stateless// themselves; for the actual calculations they are combined with a StateProxy object generated by and connected internally to the [[Controller]], while at the same time holding the Data Buffers (Frames) for the actual calculations.
 
@@ -4091,7 +4103,7 @@ Using transitions is a very basic task and thus needs viable support by the GUI.
 Because of this experience, ichthyo wants to support a more general case of transitions, which have N output connections, behave similar to their "simple" counterpart, but leave out the mixing step. As a plus, such transitions can be inserted at the source ports of N clips or between any intermediary or final output ports as well. Any transition processor capable of handling this situation should provide some flag, in order to decide if he can be placed in such a manner. (wichin the builder, encountering a  inconsistently placed transition is just an [[building error|BuildingError]])
 
-
+
The ''Visitor Pattern'' is a special form of //double dispatch// &mdash; selecting the function actually to be executed at runtime based both on the concrete type of some tool object //and // the target this tool is applied to. The rationale is to separate some specific implementation details from the basic infrastructure and the global interfaces, which can be limited to describe the fundamental properties and operations, while all details relevant only for some specific sub-problem can be kept together encapsulated in a tool implementation class. Typically, there is some iteration mechanism, allowing to apply these tools to all objects in a given container, a collection or object graph, without knowing the exact type of the target and tool objects. See the [[Visitor Pattern design discussion|VisitorUse]]
 
 !Problems with Visitor

From 531d432f025265bf9b5e9d7047e344b9c3847d35 Mon Sep 17 00:00:00 2001
From: Ichthyostega 
Date: Wed, 6 Feb 2008 05:34:19 +0100
Subject: [PATCH 10/14] continue with the mock impl for ConfigRules. probably
 using a table of pre stored boost::any records

---
 src/common/configrules.cpp                   |  3 -
 src/common/configrules.hpp                   | 27 ++-------
 src/common/query/mockconfigrules.cpp         | 17 ++----
 src/common/query/mockconfigrules.hpp         | 60 +++++++++++++++++---
 src/common/typelistutil.hpp                  |  3 +-
 tests/components/common/typelistutiltest.cpp | 16 ++++++
 6 files changed, 81 insertions(+), 45 deletions(-)

diff --git a/src/common/configrules.cpp b/src/common/configrules.cpp
index 244e88d5f..c74f70b6a 100644
--- a/src/common/configrules.cpp
+++ b/src/common/configrules.cpp
@@ -37,9 +37,6 @@ namespace cinelerra
     CINELERRA_ERROR_DEFINE (CAPABILITY_QUERY, "unresolvable capability query");
 
     
-    ConfigRulesInterface::~ConfigRulesInterface()
-      { };
-  
       
   } // namespace query
 
diff --git a/src/common/configrules.hpp b/src/common/configrules.hpp
index ed682e140..94dbc8c48 100644
--- a/src/common/configrules.hpp
+++ b/src/common/configrules.hpp
@@ -47,7 +47,7 @@
 #define CINELERRA_CONFIGRULES_H
 
 #include "common/query.hpp"
-#include "common/typelist.hpp"
+#include "common/typelistutil.hpp"
 #include "common/singletonsubclass.hpp"
 
 #include "proc/mobject/session/track.hpp"
@@ -119,7 +119,7 @@ namespace cinelerra
       protected:
         virtual ~QueryHandler()  { }
       public:
-        virtual shared_ptr resolve (Query q) = 0;
+        virtual shared_ptr resolve (const Query& q) = 0;
       };
 
     // TODO: the Idea is to provide specialisations for the concrete types
@@ -131,8 +131,6 @@ namespace cinelerra
       
       
       
-    using cinelerra::typelist::Node;
-    using cinelerra::typelist::NullType;
       
     /** 
      * Generic query interface for retrieving objects matching
@@ -145,26 +143,9 @@ namespace cinelerra
      * the necessary resolve(Query) virtual functions (implemented
      * by MockConfigRules) 
      */
-    template
-    class ConfigRulesInterface;
-      
-    template<>
-    class ConfigRulesInterface 
-      {
-      protected:
-        virtual ~ConfigRulesInterface();
-      };
-      
-    template
-    class ConfigRulesInterface > 
-      : public QueryHandler,
-        public ConfigRulesInterface
-      { };
-      
-    
     template
     class ConfigRules
-      : public ConfigRulesInterface 
+      : public typelist::InstantiateForEach
       {
       protected:
         ConfigRules ()         {}
@@ -194,7 +175,7 @@ namespace cinelerra
   typedef cinelerra::typelist::Types < mobject::session::Track
                                      , asset::Port
                                      , const asset::ProcPatt
-                                     >
+                                     > ::List
                                        InterfaceTypes;
   
   /** 
diff --git a/src/common/query/mockconfigrules.cpp b/src/common/query/mockconfigrules.cpp
index 068f6bdbd..f761cbc0f 100644
--- a/src/common/query/mockconfigrules.cpp
+++ b/src/common/query/mockconfigrules.cpp
@@ -44,23 +44,18 @@ namespace cinelerra
       
     }
     
-    shared_ptr 
-    MockConfigRules::resolve (Query q)
+    MockTable::MockTable () 
     {
-      UNIMPLEMENTED ("solve for Track");
+      TODO ("build the preconfigured table");
     }
     
-    shared_ptr  
-    MockConfigRules::resolve (Query q)
+    
+    const any& 
+    MockTable::fetch_from_table_for (const string& queryStr)
     {
-      UNIMPLEMENTED ("solve for Port");
+      UNIMPLEMENTED ("fetch a preconfigured object from the table");
     }
     
-    PProcPatt
-    MockConfigRules::resolve (Query q)
-    {
-      UNIMPLEMENTED ("solve for ProcPatt");
-    }
 
   
   } // namespace query
diff --git a/src/common/query/mockconfigrules.hpp b/src/common/query/mockconfigrules.hpp
index 17f9b6f95..dfcfde39d 100644
--- a/src/common/query/mockconfigrules.hpp
+++ b/src/common/query/mockconfigrules.hpp
@@ -40,6 +40,7 @@
 
 #include "common/configrules.hpp"
 
+#include 
 #include 
 
 
@@ -51,30 +52,75 @@ namespace cinelerra
   
   namespace query
     {
-    using mobject::session::Track;
-    using asset::Port;
     using asset::ProcPatt;
     using asset::PProcPatt;
     
+    using boost::any;
+    using boost::any_cast;
+    
+    
+    /** a traits-class to define the smart-ptr to wrap the result */
+    template
+    struct WrapReturn                   { typedef shared_ptr Wrapper;  };
+    
+    template<>
+    struct WrapReturn   { typedef PProcPatt Wrapper;  };
+    
+    
+    /** 
+     * the actual table holding preconfigured answers
+     * packaged as boost::any objects. 
+     */
+    class MockTable : public cinelerra::ConfigRules
+      {
+      protected:
+        MockTable ();
+        const any& fetch_from_table_for (const string& queryStr);
+      };
+    
+    
+    /** 
+     * building block defining how to do 
+     * the mock implementation for \i one type.
+     * We simply access a table holding pre-created objects.
+     */
+    template
+    class LookupPreconfigured : public BASE
+      {
+        typedef typename WrapReturn::Wrapper Ret;
+        
+      public:
+        virtual Ret 
+        resolve (const Query& q)
+          {
+            TODO ("handle mismatch and not-found case");
+            return any_cast (fetch_from_table_for (q));
+          }
+      };
+    
+    
     /** 
      * Dummy Implementation of the query interface.
      * Provides an explicit implementation using hard wired
      * values for some types of interest for testing and debugging.
      */
-    class MockConfigRules : public cinelerra::ConfigRules
+    class MockConfigRules 
+      : public typelist::InstantiateChained < InterfaceTypes           
+                                            , LookupPreconfigured  // building block used for each of the types
+                                            , MockTable           //  for implementing the base class (interface) 
+                                            >
       {
       protected:
-        MockConfigRules ();
+        MockConfigRules ();                                   ///< to be used only by the singleton factory
         friend class cinelerra::singleton::StaticCreate;
 
         virtual ~MockConfigRules() {}
         
       public:
         
-        virtual shared_ptr resolve (Query q);
-        virtual shared_ptr  resolve (Query q);
-        virtual PProcPatt         resolve (Query q);
+        // TODO: implementation of any additional functions on the ConfigRules inteface goes here
       };
+      
     
     
   
diff --git a/src/common/typelistutil.hpp b/src/common/typelistutil.hpp
index 6aeae1870..3f3ec1a02 100644
--- a/src/common/typelistutil.hpp
+++ b/src/common/typelistutil.hpp
@@ -62,7 +62,8 @@ namespace cinelerra
     /** 
      * Apply a template to a collection of types. 
      * The resulting class ends up inheriting from an instantiation
-     * of the templace for each of the types in the list.
+     * of the template for each of the types in the list. The iheritance
+     * graph is built in a "mixin" (multiple inheritance) style. 
      */
     template
       < class TYPES                  // List of Types 
diff --git a/tests/components/common/typelistutiltest.cpp b/tests/components/common/typelistutiltest.cpp
index d91edfe60..842a1c5ec 100644
--- a/tests/components/common/typelistutiltest.cpp
+++ b/tests/components/common/typelistutiltest.cpp
@@ -21,6 +21,22 @@
 * *****************************************************/
 
 
+/** @file typelistutiltest.cpp
+ ** \par what are we doing here??
+ **
+ ** the following test composes both an interface and the corresponding implementation
+ ** by instantiating "building block" templates over a collection of types. The resulting
+ ** class ends up inheriting a \i virtual function instantiated for each of the types 
+ ** in the list. (remember: normally the number and signature of all virtual functions
+ ** need to be absolutely fixed in the class definition)
+ **
+ ** @see typelisttest.cpp
+ ** @see typelistutil.hpp
+ ** @see cinelerra::query::ConfigRules  a real world usage example
+ **
+ */
+
+
 #include "common/test/run.hpp"
 #include "common/typelistutil.hpp"
 

From d33242b8cb1d759cb464dbefa620cf730998d034 Mon Sep 17 00:00:00 2001
From: Ichthyostega 
Date: Sun, 10 Feb 2008 17:23:16 +0100
Subject: [PATCH 11/14] filled in lots of daunting details regarding structural
 assets. StructFactury still very preliminary. Now able to fill the table with
 mock queries. TODO: fix assertion failure...

---
 src/common/configrules.hpp               |  34 ++++-
 src/common/query.hpp                     |  15 ++-
 src/common/query/mockconfigrules.cpp     |  69 +++++++++-
 src/common/query/mockconfigrules.hpp     |  23 +++-
 src/proc/asset/buildinstruct.cpp         |  35 -----
 src/proc/asset/buildinstruct.hpp         |  93 +++++++++----
 src/proc/asset/db.hpp                    |   4 +-
 src/proc/asset/port.hpp                  |   1 +
 src/proc/asset/proc.hpp                  |   3 +
 src/proc/asset/procpatt.cpp              |  66 +++++++++-
 src/proc/asset/procpatt.hpp              |  23 +++-
 src/proc/asset/struct.cpp                | 105 ++++++++-------
 src/proc/asset/struct.hpp                |  17 ++-
 src/proc/asset/structfactoryimpl.hpp     | 161 +++++++++++++++++++++++
 src/proc/asset/track.hpp                 |   2 +-
 src/proc/mobject/session/defsmanager.cpp |   2 +-
 wiki/renderengine.html                   |   6 +-
 17 files changed, 518 insertions(+), 141 deletions(-)
 delete mode 100644 src/proc/asset/buildinstruct.cpp
 create mode 100644 src/proc/asset/structfactoryimpl.hpp

diff --git a/src/common/configrules.hpp b/src/common/configrules.hpp
index 94dbc8c48..d5189bbbe 100644
--- a/src/common/configrules.hpp
+++ b/src/common/configrules.hpp
@@ -50,10 +50,11 @@
 #include "common/typelistutil.hpp"
 #include "common/singletonsubclass.hpp"
 
+//TODO: is it sensible to bring in the types explicitly here? (it's not necessary, but may be convienient...)
 #include "proc/mobject/session/track.hpp"
 #include "proc/asset/procpatt.hpp"
 #include "proc/asset/port.hpp"
-
+#include "proc/asset/track.hpp"
 
 #include 
 #include 
@@ -89,9 +90,8 @@ namespace cinelerra
       {
         
       };
-      
-    typedef const char * const Symbol;  
-      
+    
+    
     template
       < const Symbol SYM,            // Predicate symbol
         typename SIG = bool(string) //  Signature
@@ -101,6 +101,17 @@ namespace cinelerra
         
       };
       
+    /**
+     * the "backside" interface towards the classes participating
+     * in the configuration system (the config system will be
+     * delivering instances of these classes for a given query). 
+     * This one currently is just brainstorming. The idea is that
+     * a participating class would provide such  and TypeHandler
+     * implementing the predicates which make sense for this special
+     * type of object. Registering  such a TypeHandler should create
+     * the necessary handler functions to be installed into 
+     * the Prolog system.
+     */  
     template
     class TypeHandler
       {
@@ -112,13 +123,25 @@ namespace cinelerra
         template
         TY make (Pred capability, TY& refObj =NIL);
       };
-      
+    
+    /** 
+     * the "frontside" interface: the Proc-Layer code can
+     * use this QueryHandler to retrieve instances of the
+     * type TY fulfilling the given Query. To start with,
+     * we use a mock implementation-
+     * @see cinelerra::query::LookupPreconfigured
+     * @see cinelerra::query::MockTable
+     */
     template
     class QueryHandler
       {
       protected:
         virtual ~QueryHandler()  { }
       public:
+        /** try to find or create an object of type TY 
+         *  fulfilling the given query.
+         *  @return empty shared-ptr if not found,
+         */
         virtual shared_ptr resolve (const Query& q) = 0;
       };
 
@@ -173,6 +196,7 @@ namespace cinelerra
    *  rule based config query system
    */
   typedef cinelerra::typelist::Types < mobject::session::Track
+                                     , asset::Track
                                      , asset::Port
                                      , const asset::ProcPatt
                                      > ::List
diff --git a/src/common/query.hpp b/src/common/query.hpp
index 85172d965..b5575f0da 100644
--- a/src/common/query.hpp
+++ b/src/common/query.hpp
@@ -26,22 +26,33 @@
 
 
 #include 
+#include 
 
 
 
 namespace cinelerra
   {
   using std::string;
+
+  /* ==== comon definitions for rule based queries ==== */
   
+  typedef const char * const Symbol;  
+      
+
   /** 
    * Generic query interface for retrieving objects matching
    * some capability query
    */
-  template
+  template
   class Query : public std::string
     {
     public:
-      Query (string predicate="") : string(predicate) {}
+      Query (const string& predicate="") : string(predicate) {}
+      
+      const string asKey()  const
+        {
+          return string(typeid(OBJ).name())+": "+*this;
+        }
     };
 
     
diff --git a/src/common/query/mockconfigrules.cpp b/src/common/query/mockconfigrules.cpp
index f761cbc0f..15181c24e 100644
--- a/src/common/query/mockconfigrules.cpp
+++ b/src/common/query/mockconfigrules.cpp
@@ -38,22 +38,83 @@ namespace cinelerra
   
   namespace query
     {
+    using asset::Struct;
+    using asset::Port;
+    using asset::PPort;
+    
+    using asset::ProcPatt;
+    using asset::PProcPatt;
+    
+    namespace
+      {
+      typedef std::pair AnyPair;
+      
+      /** helper to simplify creating mock table entries, wrapped correctly */
+      template
+      AnyPair entry (const string& query, typename WrapReturn::Wrapper& obj)
+      {
+        return AnyPair ( Query (query).asKey()
+                       , any(obj)); 
+      }
+      
+      /** helper especially for creating structural assets from a capability query */
+      template
+      AnyPair entry_Struct(Symbol caps)
+      {
+        typedef typename WrapReturn::Wrapper Ptr;
+        
+        Query query(caps); 
+        Ptr obj = Struct::create (query);
+        return AnyPair(query, obj);
+      }
+    
+    }
+    
+    
+    /** hard coded answers to configuration queries */
+    void
+    MockTable::fill_mock_table ()
+    {
+      // for baiscporttest.cpp ---------
+      answer_->insert (entry_Struct ("stream(teststream)"));
+    }
+
+    
     
     MockConfigRules::MockConfigRules () 
     {
-      
+      WARN (config, "using a mock implementation of the ConfigQuery interface");
     }
     
-    MockTable::MockTable () 
+    MockTable::MockTable ()
+      : answer_(new Tab())
     {
-      TODO ("build the preconfigured table");
+      fill_mock_table ();
     }
+
     
+
     
+    /** this is the (preliminary/mock) implementation
+     *  handling queries for objects of a specific type
+     *  and with capabilities or properties defined by
+     *  the query. The real implementation would require
+     *  a rule based system (Ichthyo plans to use YAP Prolog),
+     *  while this dummy implementation simply relies on a
+     *  table of pre-fabricated objects. Never fails.
+     *  @return smart ptr (or similar) holding the object,
+     *          maybe an empty smart ptr if not found
+     */
     const any& 
     MockTable::fetch_from_table_for (const string& queryStr)
     {
-      UNIMPLEMENTED ("fetch a preconfigured object from the table");
+      static const any NOTFOUND;
+      
+      Tab::iterator i = answer_->find (queryStr);
+      if (i == answer_->end())
+        return NOTFOUND;
+      else
+        return i->second;
     }
     
 
diff --git a/src/common/query/mockconfigrules.hpp b/src/common/query/mockconfigrules.hpp
index dfcfde39d..5e256a3b5 100644
--- a/src/common/query/mockconfigrules.hpp
+++ b/src/common/query/mockconfigrules.hpp
@@ -39,15 +39,18 @@
 #define CINELERRA_MOCKCONFIGRULES_H
 
 #include "common/configrules.hpp"
+#include "common/util.hpp"
 
+#include 
 #include 
 #include 
+#include 
 
 
 
 namespace cinelerra
   {
-  using std::string;
+  //using std::string;
   
   
   namespace query
@@ -55,10 +58,13 @@ namespace cinelerra
     using asset::ProcPatt;
     using asset::PProcPatt;
     
+    using util::isnil;
+    
     using boost::any;
     using boost::any_cast;
     
     
+    
     /** a traits-class to define the smart-ptr to wrap the result */
     template
     struct WrapReturn                   { typedef shared_ptr Wrapper;  };
@@ -73,9 +79,17 @@ namespace cinelerra
      */
     class MockTable : public cinelerra::ConfigRules
       {
+        typedef std::map Tab;
+        typedef boost::scoped_ptr PTab;
+        
+        PTab answer_;
+        
       protected:
         MockTable ();
         const any& fetch_from_table_for (const string& queryStr);
+        
+      private:
+        void fill_mock_table ();
       };
     
     
@@ -93,8 +107,11 @@ namespace cinelerra
         virtual Ret 
         resolve (const Query& q)
           {
-            TODO ("handle mismatch and not-found case");
-            return any_cast (fetch_from_table_for (q));
+            const any& entry = fetch_from_table_for (q.asKey());
+            if (!isnil (entry))
+              return any_cast (entry);
+            else
+              return Ret(); // default-constructed empty smart ptr
           }
       };
     
diff --git a/src/proc/asset/buildinstruct.cpp b/src/proc/asset/buildinstruct.cpp
deleted file mode 100644
index de19c647e..000000000
--- a/src/proc/asset/buildinstruct.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-  BuildInstruct  -  Instructions for building some configuration of render nodes.
- 
-  Copyright (C)         CinelerraCV
-    2007,               Hermann Vosseler 
- 
-  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 2 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, write to the Free Software
-  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- 
-* *****************************************************/
-
-
-#include "proc/asset/buildinstruct.hpp"
-#include "proc/asset/procpatt.hpp"
-#include "proc/asset/proc.hpp"
-
-namespace asset
-  {
-  
-  /** */
-
-
-
-} // namespace asset
diff --git a/src/proc/asset/buildinstruct.hpp b/src/proc/asset/buildinstruct.hpp
index 0a0062e25..d6eeaec0d 100644
--- a/src/proc/asset/buildinstruct.hpp
+++ b/src/proc/asset/buildinstruct.hpp
@@ -21,9 +21,18 @@
 */
 
 
+/** @file buildinstruct.hpp
+ ** Helper classes used by asset::ProcPatt to represent the processing informations.
+ ** Consider these classes as owned by ProcPatt. Non-inline functions go to procpatt.cpp 
+ **
+ */
+
+
 #ifndef ASSET_BUILDINSTRUCT_H
 #define ASSET_BUILDINSTRUCT_H
 
+
+#include 
 #include 
 
 using std::string;
@@ -36,36 +45,74 @@ namespace asset
   class Proc;
   class ProcPatt;
 
+  typedef shared_ptr PProc;
+  typedef shared_ptr PProcPatt;
 
-  /**
-   * (Interface) building instructions to be executed by the Builder
-   *  on the render node network under construction.
-   */
-  class BuildInstruct
+  
+  static Symbol CURRENT = "current";
+  
+  struct DoAttach
     {
-    };
-    
-    
-    
-  class DoRecurse : public BuildInstruct
-    {
-    protected:
-      const ProcPatt* subPattern;
-
-    };
-    
-    
-  class DoAttach : public BuildInstruct
-    {
-    public:
-      const Proc* nodes;
+      vector nodes;
 
       /** identifying the point where the nodes should be attached */
-      const string point;
-
+      string point;
+      
+      DoAttach (Symbol where = CURRENT) 
+        : point(where) 
+        { }
+      
+      DoAttach (PProc& node, Symbol where = CURRENT) 
+        : point(where) 
+        { 
+          nodes.push_back(node); 
+        }
+      
     };
     
     
+  struct DoRecurse
+    {
+      PProcPatt subPattern_;
+
+      explicit DoRecurse (PProcPatt& pattern) : subPattern_(pattern) {}
+    };
+    
+    
+    
+  class DoConditional
+    {
+      // How to do this? we need some context to test the condition...
+    };
+
+    
+  typedef boost::variant< DoAttach, DoRecurse, DoConditional > InstructEntry;
+    
+  /**
+   * (Interface) building instructions to be executed by the Builder
+   * on the render node network under construction. The purpose of this
+   * "micro language" is to be able to store in the configuration or session
+   * how certain parts of the model should be assembled. One important example
+   * is how to build a source reading chain to read and decode frames from a
+   * media file. Another example being a global audio Pipe, comprised of an
+   * EQ plugin, a fader and a panner.
+   * \par
+   * Build instructions are tightliy coupled to asset::ProcPatt and always
+   * created from there.
+   * @see ProcPatt::attach
+   * @see ProcPatt::operator+=  
+   * 
+   */
+  struct BuildInstruct
+    : public InstructEntry 
+    {
+      template
+      BuildInstruct (T& instr) : InstructEntry(instr) {}
+    };
+    
+    
+    
+    
     
 } // namespace asset
 #endif
diff --git a/src/proc/asset/db.hpp b/src/proc/asset/db.hpp
index 8f228d01b..8de442102 100644
--- a/src/proc/asset/db.hpp
+++ b/src/proc/asset/db.hpp
@@ -118,8 +118,8 @@ namespace asset
         {
           try
             {
-              IdHashtable::const_iterator i = table.begin(); 
-              IdHashtable::const_iterator e = table.end(); 
+              IdHashtable::iterator i = table.begin(); 
+              IdHashtable::iterator e = table.end(); 
               for ( ; i!=e ; ++i )
                 i->second->dependants.clear();
               
diff --git a/src/proc/asset/port.hpp b/src/proc/asset/port.hpp
index 8bb359789..c42af656b 100644
--- a/src/proc/asset/port.hpp
+++ b/src/proc/asset/port.hpp
@@ -69,6 +69,7 @@ namespace asset
     protected:
       Port (PProcPatt& wiring, string portID="", wstring shortDesc =wstring(), wstring longDesc =wstring()) ;
       friend class StructFactory;
+      friend class StructFactoryImpl;
 
     public:
       const string& getPortID()       const { return portID_; }
diff --git a/src/proc/asset/proc.hpp b/src/proc/asset/proc.hpp
index fb9d2f494..f2a72cecd 100644
--- a/src/proc/asset/proc.hpp
+++ b/src/proc/asset/proc.hpp
@@ -46,6 +46,9 @@ namespace asset
   class Proc;
   class ProcFactory;
   
+  typedef shared_ptr PProc;
+  
+  
   
   template<>
   class ID : public ID
diff --git a/src/proc/asset/procpatt.cpp b/src/proc/asset/procpatt.cpp
index 3b267f1e4..ec9ecb781 100644
--- a/src/proc/asset/procpatt.cpp
+++ b/src/proc/asset/procpatt.cpp
@@ -22,8 +22,12 @@
 
 
 #include "proc/asset/procpatt.hpp"
-#include "proc/asset/buildinstruct.hpp"
+#include "proc/asset/proc.hpp"
 #include "proc/assetmanager.hpp"
+#include "proc/asset/buildinstruct.hpp"
+#include "common/util.hpp"
+
+using util::isnil;
 
 namespace asset
   {
@@ -45,14 +49,20 @@ namespace asset
     } 
   
   /** */
-  ProcPatt::ProcPatt (const string& properties, const vector& instr)
+  ProcPatt::ProcPatt (const string& properties)
     : Struct (createPatternIdent (properties)),
-      propDescriptor_ (properties),
-      instructions (instr)
+      propDescriptor_ (properties)
   {
     TODO ("verify building instructions, maybe preprocess...");
   }
 
+  /** @internal used for creating a clone */
+  ProcPatt::ProcPatt (const string& props, const InstructionSequence& instructs)
+    : Struct (createPatternIdent (props)),
+      propDescriptor_ (props),
+      instructions_ (instructs)
+  { }
+
   
   /** query the currently defined properties of this
       processing pattern for a stream-ID predicate */
@@ -67,17 +77,59 @@ namespace asset
   /** create a new ProcPatt asset as a literal copy
    *  of this one. The new ProcPatt can then be customized
    *  independently of the original one. This allows using
-   *  some ProcPatt as a template for creatind more
+   *  some ProcPatt as a template for creating more
    *  spezialized patterns. 
    */
   shared_ptr 
   ProcPatt::newCopy (string newID)  const
   {
     TODO ("implement the Pattern-ID within the propDescriptor!");
-    ProcPatt* pP = new ProcPatt (this->propDescriptor_, this->instructions);
+    ProcPatt* pP = new ProcPatt (this->propDescriptor_, this->instructions_);
     return AssetManager::instance().wrap (*pP);
   }
-
+  
+  
+  /** extend the processing instructions to add some Effect
+   *  @param where denotes the insertion point where to attach the Effect
+   *  @param node  prototype of the Effect to be inserted when building.
+   */
+  ProcPatt& 
+  ProcPatt::attach(Symbol where, PProc& node)
+  {
+    DoAttach *last (0);
+    if ( !isnil (instructions_) 
+       && (last = boost::get (&(instructions_.back())))
+       && last->point==where
+       )
+       // instead of adding a new build instruct entry, 
+      //  we can extend the list in the last "DoAttach" entry.
+      last->nodes.push_back(node);
+    else
+      {
+        DoAttach entry(node, where);
+        instructions_.push_back(BuildInstruct(entry));
+      }
+    TODO ("declare dependency??");
+    return *this;
+  }
+  
+  
+  /** extend the processing instructions by reference to another
+   *  ProcPatt, which will be "executed" at this point while building.
+   *  This allowes for using simple PorcPatt instances as building blocks
+   *  to define more complicated patterns.
+   */
+  ProcPatt& 
+  ProcPatt::operator+= (PProcPatt& toReuse)
+  {
+    DoRecurse entry(toReuse);
+    instructions_.push_back(BuildInstruct (entry));
+    TODO ("declare dependency??");
+    
+    return *this;
+  }
+  
+  
 
 
 } // namespace asset
diff --git a/src/proc/asset/procpatt.hpp b/src/proc/asset/procpatt.hpp
index 2a786027b..5cd22e1e1 100644
--- a/src/proc/asset/procpatt.hpp
+++ b/src/proc/asset/procpatt.hpp
@@ -24,6 +24,7 @@
 #ifndef ASSET_PROCPATT_H
 #define ASSET_PROCPATT_H
 
+#include "common/query.hpp"
 #include "proc/asset/struct.hpp"
 
 #include 
@@ -34,26 +35,38 @@ using std::vector;
 
 namespace asset
   {
-  
-  class BuildInstruct;
+  using cinelerra::Symbol;
 
+  class Proc;
+  class ProcPatt;
+  class BuildInstruct; 
+  typedef shared_ptr PProc;
+  typedef shared_ptr PProcPatt;
+  
+  typedef vector InstructionSequence;    
 
   /**
-   * special type of structural Asset 
+   * "Processing Pattern" is a structural Asset 
    * representing information how to build some part 
    * of the render engine's processing nodes network.
    */
   class ProcPatt : public Struct
     {
       string propDescriptor_;
-      vector instructions;
+      InstructionSequence instructions_;
+      
+      ProcPatt (const string& props, const InstructionSequence& instructs);
       
     protected:
-      ProcPatt (const string& properties, const vector& instr);
+      explicit ProcPatt (const string& propDescriptor);
+      friend class StructFactoryImpl;
       
     public:
       const string& queryStreamID()  const;
       shared_ptr newCopy (string newID) const;
+      
+      ProcPatt& attach (Symbol where, PProc& node);
+      ProcPatt& operator+= (PProcPatt& toReuse);
 
     };
     
diff --git a/src/proc/asset/struct.cpp b/src/proc/asset/struct.cpp
index ad1191045..7aaab7b87 100644
--- a/src/proc/asset/struct.cpp
+++ b/src/proc/asset/struct.cpp
@@ -27,78 +27,64 @@
 #include "proc/asset/track.hpp"
 #include "proc/asset/port.hpp"
 #include "proc/mobject/session.hpp"
+#include "common/configrules.hpp"
+
+#include "proc/asset/structfactoryimpl.hpp"
 
-#include "common/query.hpp"
 #include "common/util.hpp"
 #include "nobugcfg.h"
 
 using mobject::Session;
 using cinelerra::query::normalizeID;
 
+using cinelerra::ConfigRules;
+using cinelerra::query::QueryHandler;
+
+
+
 namespace asset
   {
   
-  /****** NOTE: not implemented yet. What follows is a hack to build simple tests *******/
-  
-  
-  namespace // common Struct Asset implementation details
-    {
-      /** @internal derive a sensible asset ident tuple when creating 
-       *  a track asset based on a query
-       *  @todo define the actual naming scheme of struct assets
-       */
-      const Asset::Ident
-      createTrackIdent (const Query& query)
-        {
-          string name ("track-" + query);  // TODO something sensible here; append number, sanitize etc.
-          TODO ("track naming scheme??");
-          Category category (STRUCT,"tracks");
-          return Asset::Ident (name, category );
-        }
-      
-      typedef std::pair PortIDs;
-      
-      PortIDs
-      createPortIdent (const Query& query)
-        {
-          string name ("port-" + query);   // TODO get some more sensible dummy values
-          TODO ("port naming scheme??");
-          return PortIDs (name, "mpeg"); // dummy stream type
-        }
-    } 
+  /****** NOTE: not really implemented yet. What follows is partially a hack to build simple tests *******/
 
 
   
-  StructFactory Struct::create;  ///< storage for the static StructFactory instance
+  
+  /** storage for the static StructFactory instance */
+  StructFactory Struct::create;
+  
+  
+  /** using private implementation detail class */
+  StructFactory::StructFactory ()
+    : impl_(new StructFactoryImpl(*this)) 
+  { }
   
   
   
-  /** Factory method for Structural Asset instances. ....
+  /** Factory method for Structural Asset instances.
+   *  First tries to relove the asset by issuing an capability query.
+   *  If unsuccessfull, use some internally specialized ctor call.
    *  @todo work out the struct asset naming scheme!
    *  @return an Struct smart ptr linked to the internally registered smart ptr
    *          created as a side effect of calling the concrete Struct subclass ctor.
    */
-  template<>
-  shared_ptr 
-  StructFactory::operator() (const Query& query)
+  template
+  shared_ptr 
+  StructFactory::operator() (const Query& capabilities)
   {
-    TODO ("actually evaluate the query...");
-    Track* pT = new Track (createTrackIdent (query));
-    return AssetManager::instance().wrap (*pT);
+    QueryHandler& typeHandler = ConfigRules::instance();  
+    shared_ptr res = typeHandler.resolve (capabilities);
+    
+    if (res)
+      return res;
+    
+    // create new one, since the 
+    // ConfigQuery didn't yield any result
+    STRU* pS = impl_->fabricate(capabilities);
+    return AssetManager::instance().wrap (*pS);
   }
   
   
-  /** Similar instance for Port Query....
-   *  @todo better a generic implementation utilizing ConfigQuery....
-   */
-  template<>
-  shared_ptr 
-  StructFactory::operator() (const Query& query)
-  {
-    TODO ("actually evaluate the query...");
-    PortIDs ids (createPortIdent (query));
-    return operator() (ids.first, ids.second);
-  }
   
   
   /** Factory method for creating Ports explicitly.
@@ -122,4 +108,27 @@ namespace asset
 
 
 
+} // namespace asset
+
+
+
+
+   /**************************************************/
+   /* explicit instantiations of the factory methods */
+   /**************************************************/
+
+#include "proc/asset/struct.hpp"
+#include "proc/asset/procpatt.hpp"
+#include "proc/asset/track.hpp"
+#include "proc/asset/port.hpp"
+
+
+namespace asset
+  {
+  
+  template shared_ptr     StructFactory::operator() (const Query& query);
+  template shared_ptr    StructFactory::operator() (const Query& query);
+  template PProcPatt            StructFactory::operator() (const Query& query);
+
+  
 } // namespace asset
diff --git a/src/proc/asset/struct.hpp b/src/proc/asset/struct.hpp
index 18554f770..76b8b2e42 100644
--- a/src/proc/asset/struct.hpp
+++ b/src/proc/asset/struct.hpp
@@ -40,11 +40,14 @@
 #include "proc/asset.hpp"
 #include "common/query.hpp"
 #include "common/factory.hpp"
+#include "common/singleton.hpp"
 
-#include
+#include 
+#include 
 
 using std::string;
 using std::wstring;
+using boost::scoped_ptr;
 
 
 namespace asset
@@ -53,6 +56,7 @@ namespace asset
   
   class Struct;
   class StructFactory;
+  class StructFactoryImpl;
   class Port;
   
   
@@ -102,14 +106,21 @@ namespace asset
    */ 
   class StructFactory : public cinelerra::Factory
     {
+      scoped_ptr impl_;
+
+    protected:
+      StructFactory ();
+      friend class Struct;
+
+      
     public:
       typedef shared_ptr PType;
       
       template
-      shared_ptr operator() (const Query& query);      ////////////TODO define actual operation 
+      shared_ptr operator() (const Query& query);      ////////////TODO actually do something sensible here 
       
       shared_ptr operator() (string portID, string streamID);
-
+      
     };
     
     
diff --git a/src/proc/asset/structfactoryimpl.hpp b/src/proc/asset/structfactoryimpl.hpp
new file mode 100644
index 000000000..50b45c21f
--- /dev/null
+++ b/src/proc/asset/structfactoryimpl.hpp
@@ -0,0 +1,161 @@
+/*
+  STRUCTFACTORYIMPL.hpp  -  crating structural assets (impl details)
+ 
+  Copyright (C)         CinelerraCV
+    2007,               Hermann Vosseler 
+ 
+  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 2 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, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ 
+*/
+
+
+/** @file structfactoryimpl.hpp
+ ** Private implementation details of creating various structural assets.
+ ** @internal to be used by struct.cpp
+ **
+ ** @see ConfigQuery
+ **
+ */
+
+
+#ifndef ASSET_STRUCTFACTORYIMPL_H
+#define ASSET_STRUCTFACTORYIMPL_H
+
+
+#include "common/configrules.hpp"
+#include "common/error.hpp"
+
+#include 
+
+using boost::format;
+
+using asset::Query;
+using cinelerra::query::CINELERRA_ERROR_CAPABILITY_QUERY;
+
+
+namespace asset
+  {
+  
+  
+  template
+  struct Traits
+    {
+      static Symbol namePrefix;
+      static Symbol catFolder;
+    };
+  
+  template<> Symbol Traits::namePrefix = "track-";
+  template<> Symbol Traits::catFolder  = "tracks";
+  
+  template<> Symbol Traits::namePrefix = "port-";
+  template<> Symbol Traits::catFolder  = "ports";
+  
+  template<> Symbol Traits::namePrefix = "patt-";
+  template<> Symbol Traits::catFolder  = "build-templates";
+  
+  
+  
+  
+  /** 
+   * Implementation deatils, esp. concerning how configuration
+   * queries are resolved and when to create new objects automatically.
+   * @todo better use a general struct traits class, esp.for creating the Ident
+   */ 
+  class StructFactoryImpl
+    {
+
+      /** @internal derive a sensible asset ident tuple when creating 
+       *  structural asset instances  based on a capability query
+       *  @todo define the actual naming scheme of struct assets
+       */
+      template
+      const Asset::Ident
+      createIdent (const Query& query)
+        {
+          string name (Traits::namePrefix + query);  // TODO something sensible here; append number, sanitize etc.
+          TODO ("struct asset naming scheme??");
+          Category cat (STRUCT, Traits::catFolder);
+          return Asset::Ident (name, cat );
+        }
+      
+      typedef std::pair PortIDs;
+    
+      PortIDs
+      createPortIdent (const Query& query)
+        {
+          string name (Traits::namePrefix + query);  // TODO get some more sensible dummy values
+          TODO ("port naming scheme??");
+          TODO ("actually extract the port stream type from the query...");
+          return PortIDs (name, "data");                // dummy stream type
+        }
+  
+    
+      
+      
+      
+      /** used for issuing recursive create calls to top level */
+      StructFactory& recursive_create_;
+      
+    public:
+      StructFactoryImpl (StructFactory& interface)
+        : recursive_create_(interface)
+        { }
+      
+      
+      
+      /** make a new structural asset instance.
+       *  default/fallback impl. throws.
+       */
+      template
+      STRU* fabricate (const Query& caps)
+        {
+        throw cinelerra::error::Config ( str(format("The following Query could not be resolved: %s.") % caps)
+                                       , CINELERRA_ERROR_CAPABILITY_QUERY );
+        }
+      
+    };
+    
+    
+    /* ============= specialisations =========================== */
+
+    template<>
+    Track* 
+    StructFactoryImpl::fabricate (const Query& caps)
+      {
+        TODO ("actually extract properties/capabilities from the query...");
+        return new Track (createIdent (caps));
+      }
+    
+    template<>
+    ProcPatt* 
+    StructFactoryImpl::fabricate (const Query& caps)
+      {
+        TODO ("actually extract properties/capabilities from the query...");
+        return new ProcPatt (createIdent (caps));
+      }
+    
+    template<>
+    Port* 
+    StructFactoryImpl::fabricate (const Query& caps)
+      {
+        PortIDs ids (createPortIdent (caps));
+        return recursive_create_ (ids.first, ids.second).get();
+      }
+    
+    
+    
+    
+} // namespace asset
+#endif
diff --git a/src/proc/asset/track.hpp b/src/proc/asset/track.hpp
index c4b6886c1..def842250 100644
--- a/src/proc/asset/track.hpp
+++ b/src/proc/asset/track.hpp
@@ -39,7 +39,7 @@ namespace asset
     {
     protected:
       Track (const Asset::Ident& idi);
-      friend class StructFactory;
+      friend class StructFactoryImpl;
     };
     
   
diff --git a/src/proc/mobject/session/defsmanager.cpp b/src/proc/mobject/session/defsmanager.cpp
index 5880bc1b3..71e7f8549 100644
--- a/src/proc/mobject/session/defsmanager.cpp
+++ b/src/proc/mobject/session/defsmanager.cpp
@@ -48,7 +48,7 @@ namespace mobject
     /** initialize the most basic internal defaults. */
     DefsManager::DefsManager ()  throw()
     {
-      
+      TODO ("setup basic defaults of the session");
     }
 
     
diff --git a/wiki/renderengine.html b/wiki/renderengine.html
index 8ab162beb..31914ac20 100644
--- a/wiki/renderengine.html
+++ b/wiki/renderengine.html
@@ -2349,8 +2349,10 @@ We need a way of addressing existing [[ports|Port]]. Besides, as the Ports and T
 //Note, we have yet to specify how exactly the building and rendering will work together with the backend. There are several possibilities how to structure the Playlist//
 
-
-
Ports play an central role within the Proc Layer, because for everything placed and handled within the EDL, the final goal is to get it transformed into data which can be retrieved at some port. Ports are special facilities, rather like inventory, separate and not treated like all the other objects.
+
+
{{red{''NOTE'': I am considering to rename "Port" &rarr; "Pipe"}}}
+
+Ports play an central role within the Proc Layer, because for everything placed and handled within the EDL, the final goal is to get it transformed into data which can be retrieved at some port. Ports are special facilities, rather like inventory, separate and not treated like all the other objects.
 We don't distinguish between "input" and "output" ports &mdash; rather, ports are thought to be ''hooks for making connections to''. By following this line of thought, each port has an input side and an output side and is in itself something like a ''Bus'' or the starting point for building a ''processing chain''. Other processing entities like effects and transitions can be placed (attached) at the port, resulting them to be appended to form this chain. Likewise, we can place [[wiring requests|WiringRequest]] to the port, meaning we want it connected to another destination port. The [[Builder]] may generate further wiring requests to fulfil the placement of other entities.
 Thus Ports are the basic building blocks of the whole render network. We distinguish ''global available'' Ports, which are like the sum groups of a mixing console, and the ''lokal port'' or [[source port|ClipSourcePort]] of the individual clips, which exist only within the duration of the corresponding clip. The design //limits the possible kinds of ports // to these two types &mdash; thus we can build local processing chains at clips and global processing chains at the global ports of the session and that's all we can do. (because of the flexibility which comes with the concept of [[placements|Placement]], this is no real limitation)
 

From c77e245f541f2bac3df20ddf95c2bd1c57150fba Mon Sep 17 00:00:00 2001
From: Ichthyostega 
Date: Wed, 13 Feb 2008 04:41:58 +0100
Subject: [PATCH 12/14] make the MockConfigQuery reentrant. Basic asset::Struct
 factory now running (utilizing the MockConfigQuery). basicporttest.cpp not
 yet running, but get some lines ahead :-P

---
 src/common/query/mockconfigrules.cpp     | 20 ++++++++++++++------
 src/common/query/mockconfigrules.hpp     |  5 +++--
 src/proc/asset/port.cpp                  |  1 +
 src/proc/asset/port.hpp                  |  2 +-
 src/proc/asset/structfactoryimpl.hpp     | 11 ++++++-----
 src/proc/mobject/session/defsmanager.cpp |  2 +-
 wiki/renderengine.html                   |  4 +++-
 7 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/src/common/query/mockconfigrules.cpp b/src/common/query/mockconfigrules.cpp
index 15181c24e..29286e920 100644
--- a/src/common/query/mockconfigrules.cpp
+++ b/src/common/query/mockconfigrules.cpp
@@ -65,16 +65,23 @@ namespace cinelerra
         
         Query query(caps); 
         Ptr obj = Struct::create (query);
-        return AnyPair(query, obj);
+        return AnyPair(query.asKey(), obj);
       }
     
     }
     
     
-    /** hard coded answers to configuration queries */
+    /** hard coded answers to configuration queries.
+     *  @note while filling the table re-entrace
+     *        will be quite common, so the order of
+     *        creating the objects is important.
+     */
     void
     MockTable::fill_mock_table ()
     {
+      INFO (config, "creating mock answers for some config queries...");
+      isInit_ = true; // allow re-entrance
+      
       // for baiscporttest.cpp ---------
       answer_->insert (entry_Struct ("stream(teststream)"));
     }
@@ -86,11 +93,11 @@ namespace cinelerra
       WARN (config, "using a mock implementation of the ConfigQuery interface");
     }
     
+    
     MockTable::MockTable ()
-      : answer_(new Tab())
-    {
-      fill_mock_table ();
-    }
+      : answer_(new Tab()),
+        isInit_(false)
+    { }
 
     
 
@@ -109,6 +116,7 @@ namespace cinelerra
     MockTable::fetch_from_table_for (const string& queryStr)
     {
       static const any NOTFOUND;
+      if (!isInit_) fill_mock_table();
       
       Tab::iterator i = answer_->find (queryStr);
       if (i == answer_->end())
diff --git a/src/common/query/mockconfigrules.hpp b/src/common/query/mockconfigrules.hpp
index 5e256a3b5..7b6ce6374 100644
--- a/src/common/query/mockconfigrules.hpp
+++ b/src/common/query/mockconfigrules.hpp
@@ -67,10 +67,10 @@ namespace cinelerra
     
     /** a traits-class to define the smart-ptr to wrap the result */
     template
-    struct WrapReturn                   { typedef shared_ptr Wrapper;  };
+    struct WrapReturn             { typedef shared_ptr Wrapper;  };
     
     template<>
-    struct WrapReturn   { typedef PProcPatt Wrapper;  };
+    struct WrapReturn   { typedef PProcPatt Wrapper;  };
     
     
     /** 
@@ -83,6 +83,7 @@ namespace cinelerra
         typedef boost::scoped_ptr PTab;
         
         PTab answer_;
+        bool isInit_;
         
       protected:
         MockTable ();
diff --git a/src/proc/asset/port.cpp b/src/proc/asset/port.cpp
index 08b7dd38f..e7a998f40 100644
--- a/src/proc/asset/port.cpp
+++ b/src/proc/asset/port.cpp
@@ -46,6 +46,7 @@ namespace asset
   Port::Port (PProcPatt& wiring, string portID, wstring shortDesc, wstring longDesc) 
     : Struct (createPortIdent (wiring,portID,shortDesc,longDesc)),
       portID_ (portID),
+      wiringTemplate(wiring),
       shortDesc (shortDesc),
       longDesc (longDesc)
   {
diff --git a/src/proc/asset/port.hpp b/src/proc/asset/port.hpp
index c42af656b..7fd23fe32 100644
--- a/src/proc/asset/port.hpp
+++ b/src/proc/asset/port.hpp
@@ -53,8 +53,8 @@ namespace asset
    */
   class Port : public Struct
     {
-      PProcPatt wiringTemplate;
       string portID_;
+      PProcPatt wiringTemplate;
       
     public:
       wstring shortDesc;
diff --git a/src/proc/asset/structfactoryimpl.hpp b/src/proc/asset/structfactoryimpl.hpp
index 50b45c21f..ae53e645a 100644
--- a/src/proc/asset/structfactoryimpl.hpp
+++ b/src/proc/asset/structfactoryimpl.hpp
@@ -62,8 +62,8 @@ namespace asset
   template<> Symbol Traits::namePrefix = "port-";
   template<> Symbol Traits::catFolder  = "ports";
   
-  template<> Symbol Traits::namePrefix = "patt-";
-  template<> Symbol Traits::catFolder  = "build-templates";
+  template<> Symbol Traits::namePrefix = "patt-";
+  template<> Symbol Traits::catFolder  = "build-templates";
   
   
   
@@ -121,7 +121,7 @@ namespace asset
       template
       STRU* fabricate (const Query& caps)
         {
-        throw cinelerra::error::Config ( str(format("The following Query could not be resolved: %s.") % caps)
+        throw cinelerra::error::Config ( str(format("The following Query could not be resolved: %s.") % caps.asKey())
                                        , CINELERRA_ERROR_CAPABILITY_QUERY );
         }
       
@@ -135,12 +135,13 @@ namespace asset
     StructFactoryImpl::fabricate (const Query& caps)
       {
         TODO ("actually extract properties/capabilities from the query...");
+        TODO ("make sure AssetManager detects dublicates (it doesn't currently)");
         return new Track (createIdent (caps));
       }
     
     template<>
-    ProcPatt* 
-    StructFactoryImpl::fabricate (const Query& caps)
+    const ProcPatt* 
+    StructFactoryImpl::fabricate (const Query& caps)
       {
         TODO ("actually extract properties/capabilities from the query...");
         return new ProcPatt (createIdent (caps));
diff --git a/src/proc/mobject/session/defsmanager.cpp b/src/proc/mobject/session/defsmanager.cpp
index 71e7f8549..f5688bbfd 100644
--- a/src/proc/mobject/session/defsmanager.cpp
+++ b/src/proc/mobject/session/defsmanager.cpp
@@ -61,7 +61,7 @@ namespace mobject
       
       if (!res)
         throw cinelerra::error::Config ( str(format("The following Query could not be resolved: %s.") 
-                                                   % capabilities)
+                                                   % capabilities.asKey())
                                        , CINELERRA_ERROR_CAPABILITY_QUERY );
       else
         return res;
diff --git a/wiki/renderengine.html b/wiki/renderengine.html
index 31914ac20..f86d20ff0 100644
--- a/wiki/renderengine.html
+++ b/wiki/renderengine.html
@@ -797,7 +797,7 @@ Error: #f88
&rarr; [[Configuration Rules system|ConfigRules]]
-
+
Many features can be implemented by specifically configuring and wiring some unspecific components. Rather than tie the client code in need of some given feature to these configuration internals, in Cinelerra-3 the client can //query // for some kind of object providing the //needed capabilities. // Right from start (summer 2007), Ichthyo had the intention to implement such a feature using sort of a ''declarative database'', e.g. by embedding a Prolog system. By adding rules to the basic session configuration, users should be able to customize the semi-automatic part of Cinelerra's behaviour to great extent.
 
 [[Configuration Queries|ConfigQuery]] are used at various places, when creating and adding new objects, as well when building or optimizing the render engine node network.
@@ -816,6 +816,8 @@ Actually posing such an configuration query, for example to the [[Defaults Manag
 !Implementation
 At start and for debugging/testing, there is an ''dummy'' implementation using a map with predefined queries and answers. But for the real system, the idea is to embed a ''YAP Prolog'' engine to run the queries. This includes the task of defining and loading a set of custom predicates, so the rule system can interact with the object oriented execution environment, for example by transforming some capability predicate into virtual calls to a corresponding object interface. We need a way for objects to declare some capability predicates, together with a functor that can be executed on an object instance (and further parameters) in the cause of the evaluation of some configuration query. Type safety and diagnostics play an important role here, because effectively the rule base is a pool of code open for arbitray additions from the user session.
 &rarr; [[considerations for a Prolog based implementation|QueryImplProlog]]
+&rarr; see {{{src/common/query/mockconfigrules.cpp}}} for the table with the hard wired (mock) answers
+
 
From 857422f6e2b752176dd727e1b60e1e22bf22f60e Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 14 Feb 2008 03:34:29 +0100 Subject: [PATCH 13/14] Rename 'Port' to 'Pipe' I: UML and documentation. finally I've settled down to the name 'Pipe', because its the best description for this concept... --- doc/devel/uml/class128005.html | 2 +- doc/devel/uml/class130053.html | 2 +- doc/devel/uml/class130181.html | 2 +- doc/devel/uml/class136965.html | 2 +- doc/devel/uml/class138117.html | 6 +- doc/devel/uml/class140421.html | 4 +- doc/devel/uml/classes.html | 2 +- doc/devel/uml/classes_list.html | 2 +- doc/devel/uml/fig128133.png | Bin 67486 -> 67880 bytes doc/devel/uml/fig128389.png | Bin 29325 -> 30399 bytes doc/devel/uml/fig129285.png | Bin 53553 -> 53631 bytes doc/devel/uml/fig130309.png | Bin 40186 -> 40215 bytes doc/devel/uml/fig131205.png | Bin 14369 -> 14434 bytes doc/devel/uml/index.html | 24 +++-- doc/devel/uml/index_67.html | 33 +++---- doc/devel/uml/index_68.html | 2 +- doc/devel/uml/index_69.html | 4 +- doc/devel/uml/index_70.html | 2 +- doc/devel/uml/index_73.html | 2 +- doc/devel/uml/index_79.html | 1 - doc/devel/uml/index_80.html | 6 +- doc/devel/uml/index_83.html | 4 +- doc/devel/uml/index_84.html | 12 +-- doc/devel/uml/index_86.html | 16 ++-- doc/devel/uml/index_87.html | 1 + uml/cinelerra3/128133 | 6 +- uml/cinelerra3/128133.diagram | 8 +- uml/cinelerra3/128261 | 12 +-- uml/cinelerra3/128389 | 2 +- uml/cinelerra3/128389.diagram | 2 + uml/cinelerra3/129285 | 2 +- uml/cinelerra3/130053 | 6 +- uml/cinelerra3/130309.diagram | 2 +- uml/cinelerra3/131205.diagram | 2 +- uml/cinelerra3/5.session | 8 +- uml/cinelerra3/cinelerra3.prj | 2 +- wiki/renderengine.html | 150 ++++++++++++++++---------------- 37 files changed, 173 insertions(+), 158 deletions(-) diff --git a/doc/devel/uml/class128005.html b/doc/devel/uml/class128005.html index 524fbb0ac..06db277ae 100644 --- a/doc/devel/uml/class128005.html +++ b/doc/devel/uml/class128005.html @@ -20,7 +20,7 @@
Relation edls (<directional aggregation by value>)

Declaration :

Relation theFixture (<unidirectional association>)

Declaration :

  • Uml : # theFixture : Fixture, multiplicity : 1
  • C++ : protected: Fixture * theFixture
-
Relation ports (<directional aggregation>)

Declaration :

  • Uml : # ports : Port, multiplicity : *
  • C++ : protected: Port* ports

the global ports (busses) of the session

+
Relation pipes (<directional aggregation>)

Declaration :

  • Uml : # pipes : Pipe, multiplicity : *
  • C++ : protected: Pipe* pipes

the global ports (busses) of the session

All public operations : currEDL , getFixture

diff --git a/doc/devel/uml/class130053.html b/doc/devel/uml/class130053.html index a7a18ffb9..d7b63f4a7 100644 --- a/doc/devel/uml/class130053.html +++ b/doc/devel/uml/class130053.html @@ -17,7 +17,7 @@

Declaration :

Directly inherited by : Plug

-
+

Artifact : wish

All public operations : get_repr

diff --git a/doc/devel/uml/class130181.html b/doc/devel/uml/class130181.html index 1d050e694..5fed79b9b 100644 --- a/doc/devel/uml/class130181.html +++ b/doc/devel/uml/class130181.html @@ -16,7 +16,7 @@ -

Declaration :

+

Declaration :

Artifact : constraint

All public operations : get_repr

diff --git a/doc/devel/uml/class136965.html b/doc/devel/uml/class136965.html index a7c9937ee..b705413c0 100644 --- a/doc/devel/uml/class136965.html +++ b/doc/devel/uml/class136965.html @@ -16,7 +16,7 @@ -

Declaration :

  • C++ : class Struct : public Asset

Directly inherited by : Port ProcPatt Track

+

Declaration :

  • C++ : class Struct : public Asset

Directly inherited by : Pipe ProcPatt Track

key abstraction: structural asset

Artifact : struct

All public operations : enable , getDependant , getParents , isActive

diff --git a/doc/devel/uml/class138117.html b/doc/devel/uml/class138117.html index a635bbfb4..a0c0efcf7 100644 --- a/doc/devel/uml/class138117.html +++ b/doc/devel/uml/class138117.html @@ -4,19 +4,19 @@ -Class Port +Class Pipe -
Class Port
+
Class Pipe

-

Declaration :

  • C++ : class Port : public Struct

structural asset corresponding to some port for building a processing chain and generating media output

Artifact : outport

+

Declaration :

  • C++ : class Pipe : public Struct

structural asset representing a basic building block within the high level model: a port for building a processing chain and generating media output

Artifact : pipe

Relation wiringTemplate (<unidirectional association>)

Declaration :

  • Uml : # wiringTemplate : ProcPatt, multiplicity : 0..1
  • C++ : protected: ProcPatt* wiringTemplate

All public operations : enable , getDependant , getParents , isActive

diff --git a/doc/devel/uml/class140421.html b/doc/devel/uml/class140421.html index 9fefd2ebb..0d3267c6e 100644 --- a/doc/devel/uml/class140421.html +++ b/doc/devel/uml/class140421.html @@ -16,9 +16,9 @@ -

Declaration :

  • C++ : class Plug : public Wish
+

Declaration :

  • C++ : class Plug : public Wish

Artifact : plug

-
Relation outPort (<unidirectional association>)

Declaration :

  • Uml : # outPort : Port
  • C++ : protected: Port* outPort

the Port this MObject wants to be conected to

+
Relation outPort (<unidirectional association>)

Declaration :

  • Uml : # outPort : Pipe
  • C++ : protected: Pipe* outPort

the Port this MObject wants to be conected to

All public operations : get_repr

diff --git a/doc/devel/uml/classes.html b/doc/devel/uml/classes.html index 861c332cc..48c1ea2d6 100644 --- a/doc/devel/uml/classes.html +++ b/doc/devel/uml/classes.html @@ -91,10 +91,10 @@ ParameterDescriptor and access object for a plugin parameter. Parameters may be provided with values from the session, and this values may be automated. ParamProviderinterfaceA facility to get the actual value of a plugin/effect parameter PathManagerWhile building a render engine, this Strategy class decides on the actual render strategy in accordance to the current controller settings (system state) +Pipestructural asset representing a basic building block within the high level model: a port for building a processing chain and generating media output Placementinterfaceused to specify the position of a MObject in the EDL. This can be done in various ways (absolute, relative).
Placement at the same time acts as (refcounting) smart pointer for accessing the MObject. Plug PluginAdapterAdapter used to integrage an effects processor in the render pipeline -Portstructural asset corresponding to some port for building a processing chain and generating media output Prefetch Previewalternative version of the media data, probably with lower resolution Prockey abstraction: data processing asset diff --git a/doc/devel/uml/classes_list.html b/doc/devel/uml/classes_list.html index 9b03604d3..41655bf32 100644 --- a/doc/devel/uml/classes_list.html +++ b/doc/devel/uml/classes_list.html @@ -92,10 +92,10 @@ Parameter
ParamProvider
PathManager
+Pipe
Placement
Plug
PluginAdapter
-Port
Prefetch
Preview
Proc
diff --git a/doc/devel/uml/fig128133.png b/doc/devel/uml/fig128133.png index 8b525effdda2c19eb4a2b9e92f808937b8b1b57e..089545c768e411dfdcb5932e8689a0fab1b558c7 100644 GIT binary patch delta 49317 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 UJddOsQ2v|i@~Ze(S4{8!AJ9Ve=l}o! diff --git a/doc/devel/uml/fig128389.png b/doc/devel/uml/fig128389.png index 36521dc8ad91649b73412fc79681383b1b7ae527..c6a57b8573f2a2faab08cafe49d0c14ed5d6d60b 100644 GIT binary patch literal 30399 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 Oy?ib!Q6Q%4^?v|JGc=$8 delta 29167 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

#?HU^OHI*Xm$hY=n{Z$q%w`VOC=Hu6e&O2he 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≠M*QkfVVi^j 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 S++kP%0000TPC>e)I|Kpg?(XjHJ2#&5 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 diff --git a/doc/devel/uml/fig131205.png b/doc/devel/uml/fig131205.png index 91a2d89e2f0e139862dc72882dfe6d35f7cf1c85..f80a5c619e000a6aa7f76cd2510da831eea07b26 100644 GIT binary patch literal 14434 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 Y{P>EK&$a-(`UiO|sqm;!+~E2D0VsyCt^fc4 diff --git a/doc/devel/uml/index.html b/doc/devel/uml/index.html index e623f8fd7..3853e7c4f 100644 --- a/doc/devel/uml/index.html +++ b/doc/devel/uml/index.html @@ -112,7 +112,7 @@ Documentation
Artifact Cinelerra3

Depends on common

Depends on gui

Depends on proc

Depends on backend

the main executable to be built

-

executable associated with : controllerfacade, processor, pluginadapter, effect, buildertool, segmentationtool, aframe, assembler, trafo, explicitplacement, auto, glrender, link, parameter, renderengine, allocation, vframe, toolfactory, arender, renderstate, label, glbuf, procnode, stateproxy, hub, buildable, abstractmo, nodecreatertool, projector, interpolator, edl, fixture, glpipe, exitnode, pathmanager, track, paramprovider, mask, main, conmanager, clip, meta, fixedlocation, relativelocation, vrender, mobject, source, frame, placement, sessionimpl, builderfacade

+

executable associated with : main, conmanager, clip, meta, fixedlocation, relativelocation, vrender, mobject, source, frame, placement, sessionimpl, builderfacade, controllerfacade, processor, pluginadapter, effect, buildertool, segmentationtool, aframe, assembler, trafo, explicitplacement, auto, glrender, link, parameter, renderengine, allocation, vframe, toolfactory, arender, renderstate, label, glbuf, procnode, stateproxy, hub, buildable, abstractmo, nodecreatertool, projector, interpolator, edl, fixture, glpipe, exitnode, pathmanager, track, paramprovider, mask

Artifact main

Artifact source

@@ -261,9 +261,9 @@ Documentation

description of some media data decoder or encoder facility

Artifact source associated with : Codec

-
Artifact outport
+
Artifact pipe

structural asset corresponding to some port generating media output

-

Artifact source associated with : Port

+

Artifact source associated with : Pipe

Artifact track

structural asset holding the configuration of a track in the EDL

@@ -361,7 +361,7 @@ Documentation

Artifact source associated with : Segment

Artifact track
-

descriptor for one track in the Session

+

A grouping device within the EDL. The corresponding Placement
by which this Track object is refered defines fallback placing
properties to be used by all objects placed on this track in
case they don't specify more concrete placements.
Typically, tracks are used do make default Port connections,
define a layer or pan for sound and for for disabling groups
of clips. Note tracks are grouped in a tree like fashion.

Artifact source associated with : Track

Artifact abstractmo
@@ -402,6 +402,18 @@ Documentation
Artifact allocation

Artifact source associated with : Allocation

+ +
Artifact constraint
+

LocatingPin representing an directive by the user that
must not be violated

+

Artifact source associated with : Constraint

+ +
Artifact wish
+

LocatingPin representing a low-priority directive by the user,
to be fulfilled only if possible (and after satisfying the
more important LocatingPins)

+

Artifact source associated with : Wish

+ +
Artifact plug
+

LocatingPin for requesting connection to some Port

+

Artifact source associated with : Plug

Artifact label

Artifact source associated with : Label

@@ -612,7 +624,7 @@ Documentation
Class Effect
Class Codec
Class Track
-
Class Port
+
Class Pipe
Class ProcPatt
Class Dataset
Class DB
@@ -653,11 +665,11 @@ Documentation
Class Auto
Class Wish
+
Class Plug
Class Parameter
-
Class Plug

2.2.2 Package Builder

diff --git a/doc/devel/uml/index_67.html b/doc/devel/uml/index_67.html index c41be7ee3..dfc4fc2d8 100644 --- a/doc/devel/uml/index_67.html +++ b/doc/devel/uml/index_67.html @@ -29,38 +29,38 @@ checked_outrelationthis list keeps all mappings which are in use, and thus prevents them from Cache aging Cinelerra3artifactthe main executable to be built cinelerra3package -class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance class instanceclass instance -class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance class instanceclass instance class instanceclass instance class instanceclass instance class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance class instanceclass instance class instanceclass instance class instanceclass instance -class instanceclass instance class instanceclass instance -class instanceclass instance class instanceclass instance -class instanceclass instance -class instanceclass instance class instanceclass instance class instanceclass instance +class instanceclass instance +class instanceclass instance clearoperationclear current session contents
without resetting overall session config.
Afterwards, the session will contain only one
empty EDL, while all Assets are retained.
Clipclassbookkeeping (asset) view of a media clip. -clipartifactbookkeeping (asset) view of a media clip. clipartifacta Media Clip +clipartifactbookkeeping (asset) view of a media clip. Clipclass clipsrelation Codecclassdescription of some media data decoder or encoder facility @@ -87,6 +87,7 @@ conmanagerartifactmanages the creation of additional ProcNode connections for the Renderengine ConManagercomponent connectopaque activity action +constraintartifactLocatingPin representing an directive by the user that
must not be violated Constraintclass Controllercomponent Controllerpackage diff --git a/doc/devel/uml/index_68.html b/doc/devel/uml/index_68.html index 8f898d37f..68da1dfbd 100644 --- a/doc/devel/uml/index_68.html +++ b/doc/devel/uml/index_68.html @@ -28,8 +28,8 @@ designpackage designpackageAll things concering the big picture.
Not a real code package, rather a container for design drafts, specifications, decisions. detect Channelsuse case -determine Render Paramsexpansion region determine Render Paramsopaque activity action +determine Render Paramsexpansion region devnullclass instance Dispatchercomponent dispatchOpoperation diff --git a/doc/devel/uml/index_69.html b/doc/devel/uml/index_69.html index caf706b98..6ba353281 100644 --- a/doc/devel/uml/index_69.html +++ b/doc/devel/uml/index_69.html @@ -18,14 +18,14 @@ - + - + diff --git a/doc/devel/uml/index_70.html b/doc/devel/uml/index_70.html index b36d60aff..23907ab84 100644 --- a/doc/devel/uml/index_70.html +++ b/doc/devel/uml/index_70.html @@ -33,8 +33,8 @@ - + diff --git a/doc/devel/uml/index_73.html b/doc/devel/uml/index_73.html index 798945020..93008767f 100644 --- a/doc/devel/uml/index_73.html +++ b/doc/devel/uml/index_73.html @@ -20,8 +20,8 @@ - + diff --git a/doc/devel/uml/index_79.html b/doc/devel/uml/index_79.html index 13aab1740..5446e9730 100644 --- a/doc/devel/uml/index_79.html +++ b/doc/devel/uml/index_79.html @@ -22,7 +22,6 @@ - diff --git a/doc/devel/uml/index_80.html b/doc/devel/uml/index_80.html index 9258e1132..2b01f816d 100644 --- a/doc/devel/uml/index_80.html +++ b/doc/devel/uml/index_80.html @@ -25,18 +25,20 @@ + + + + - - diff --git a/doc/devel/uml/index_83.html b/doc/devel/uml/index_83.html index 847236104..df33c880e 100644 --- a/doc/devel/uml/index_83.html +++ b/doc/devel/uml/index_83.html @@ -31,8 +31,8 @@ - + @@ -46,8 +46,8 @@ - + diff --git a/doc/devel/uml/index_84.html b/doc/devel/uml/index_84.html index b2f672c79..738749c2a 100644 --- a/doc/devel/uml/index_84.html +++ b/doc/devel/uml/index_84.html @@ -35,20 +35,20 @@ - + - - - - - + + + + +
NameKindDescription
edlartifactthe (high level) Edit Decision List within the current Session
EDLcomponent
EDLclass
EDLcomponent
EDL Example1object diagramA simple example showing how the actual objects are placed in the Fixture (=definitive playlist). It shows a Video and Audio clip placed on two tracks
EDL Example2object diagramMore complex example showing the Object graph in the EDL and how it is linked into the Fixture to yield the actual locations. In this example, an HUE Effect is applied on a part of the Clip
edlsrelation
EffectclassEffect or media processing component
effectartifactEffect or media processing component
effectartifactEDL representation of a pluggable and automatable effect.
effectartifactEffect or media processing component
Effectclass
elementsrelationrelevant MObjects comprising this segment. TODO: actually necessary??
enableoperationchange the enabled status of this asset. Note the corresponding #isActive predicate may depend on the enablement status of parent assets as well
FixedLocationclass
Fixtureactivity object
fixtureartifactthe (low level) representation of the EDL with concrete placement data
Fixtureclass
Fixturecomponent
Fixtureclass
fork activity nodefork activity node
FrameclassFrames are just a low level lump of continous memory, most parts are opaque. Frames are memory sensitive, they will be small constant sized structures which can be efficently managed in a pool.
Framenode
idattributeAsset primary key.
In Memory Databaseclass diagram
inFixtureactivity action pin
inputclass instance
inputclass instance
inputclass instance
inputclass instance
instanceoperation
instructionsrelation
ouputclass instance
ouputclass instance
ouputclass instance
outportartifactstructural asset corresponding to some port generating media output
outPortrelationthe Port this MObject wants to be conected to
outputrelation
Overviewcomponent diagramThis drawing shows the top level compoents and relations
paramsrelation
PathManagerclassWhile building a render engine, this Strategy class decides on the actual render strategy in accordance to the current controller settings (system state)
pathmanagerartifactManager for deciding the actual render strategy
Pipeclassstructural asset representing a basic building block within the high level model: a port for building a processing chain and generating media output
pipeartifactstructural asset corresponding to some port generating media output
pipesrelationthe global ports (busses) of the session
placementartifactKey Abstraction: a way to place and locate a Media Object
Placementclassused to specify the position of a MObject in the EDL. This can be done in various ways (absolute, relative).
Placement at the same time acts as (refcounting) smart pointer for accessing the MObject.
playoperationTODO: will probably be handled differently (see Cehteh)
playlistnode
plugartifactLocatingPin for requesting connection to some Port
Plugclass
plugIDattributeIdentifier of the Plugin to be used
PluginAdapterclassAdapter used to integrage an effects processor in the render pipeline
pluginadapterartifactAdapter for integrating various Effect processors in the render pipeline
pnodenode
pointattributeidentifying the point where the nodes should be attached
Portclassstructural asset corresponding to some port for building a processing chain and generating media output
portsrelationthe global ports (busses) of the session
Posix Threads Abstractionclass viewC++ wrapers for pthreads
Prefetchclass
Previewclassalternative version of the media data, probably with lower resolution
Service Componentsclass view
Sessioncomponent
sessionartifactInterface: the session edited by the user
Sessionclass view
sessionpackagesourcecode package

Everything concerning the EDL and Session, within the MObject Subsystem
Sessionclass view
SessionclassPrimary Interface for all editing tasks.
The session contains defaults, all the assets being edited, and a set of EDL with the individual MObjects to be manipulated and rendered.
Session structureclass diagram
sessionimplartifactholds the complete session data to be edited by the user
SimpleClipclassElementary clip consisting of only one media stream
SmartPointerclass
SmartPointersclass view
sourcerelationthe media source this clip referes to
sourcerelationmedia source of this clip
sourcerelationthe media source this clip referes to
SourceclassSource Node: represents a media source to pull data from.
sourceartifactRepresentation of a Media source
Source Overviewdeployment diagram
trackattribute
trackrelation
trackartifactstructural asset holding the configuration of a track in the EDL
trackartifactdescriptor for one track in the Session
trackartifactA grouping device within the EDL. The corresponding Placement
by which this Track object is refered defines fallback placing
properties to be used by all objects placed on this track in
case they don't specify more concrete placements.
Typically, tracks are used do make default Port connections,
define a layer or pan for sound and for for disabling groups
of clips. Note tracks are grouped in a tree like fashion.
Trackclass
tracksrelationelementary media assets comprising this compound
Trafoclass
trafoartifacttransforming processing Node
treatoperation
treatoperationThis operation is to be overloaded for the specific MObject subclasses to be treated.
treatoperation
treatoperation
treatoperation
treatoperation
treatoperation
treatoperation
treatoperation
treatoperation
treatoperation
treatoperation
treatoperation
treatoperation
diff --git a/doc/devel/uml/index_86.html b/doc/devel/uml/index_86.html index 74937c93e..2429dd829 100644 --- a/doc/devel/uml/index_86.html +++ b/doc/devel/uml/index_86.html @@ -22,21 +22,21 @@ vframeartifacta buffer and render process holding a Video frame vid1class instance vid1class instance -vid_aclass instance vid_Aclass instance -vid_Aclass instance -vid_aclass instance +vid_aclass instance vid_Aclass instance +vid_aclass instance +vid_Aclass instance videoclass instance +videoclass instance videoclass instance videoclass instance -videoclass instance -video1class instance -video1class instance -video1class instance -video1class instance video1class instance +video1class instance video1class instance +video1class instance +video1class instance +video1class instance Visitableclass visitorpackagesub-namespace for visitor library implementation visitorartifactAcyclic Visitor library diff --git a/doc/devel/uml/index_87.html b/doc/devel/uml/index_87.html index 54f6d4f8c..748f57b37 100644 --- a/doc/devel/uml/index_87.html +++ b/doc/devel/uml/index_87.html @@ -20,6 +20,7 @@ whatoperation whatoperationthe base class of all exceptions thrown by the standard library wiringTemplaterelation +wishartifactLocatingPin representing a low-priority directive by the user,
to be fulfilled only if possible (and after satisfying the
more important LocatingPins) Wishclass write_bufferrelation WriteBufferclass diff --git a/uml/cinelerra3/128133 b/uml/cinelerra3/128133 index cb48c458d..fe9ce6164 100644 --- a/uml/cinelerra3/128133 +++ b/uml/cinelerra3/128133 @@ -1,6 +1,6 @@ format 40 "Asset" // ProcessingLayer::Asset - revision 17 + revision 18 modified_by 5 "hiv" // class settings //class diagram settings @@ -686,7 +686,7 @@ ${inlines} end end - class 138117 "Port" + class 138117 "Pipe" visibility package cpp_decl "${comment}${template}class ${name}${inherit} { @@ -697,7 +697,7 @@ ${inlines} idl_decl "" explicit_switch_type "" - comment "structural asset corresponding to some port for building a processing chain and generating media output" + comment "structural asset representing a basic building block within the high level model: a port for building a processing chain and generating media output" classrelation 141445 // relation 139653 ---|> a public diff --git a/uml/cinelerra3/128133.diagram b/uml/cinelerra3/128133.diagram index 0aa4daeb2..466c2ad1d 100644 --- a/uml/cinelerra3/128133.diagram +++ b/uml/cinelerra3/128133.diagram @@ -106,7 +106,7 @@ classcanvas 141317 class_ref 139909 // LocatingPin draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 518 239 2000 end -classcanvas 146053 class_ref 138117 // Port +classcanvas 146053 class_ref 138117 // Pipe draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 344 597 2004 end @@ -114,8 +114,8 @@ classcanvas 146437 class_ref 140421 // Plug draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 560 597 2000 end -textcanvas 146821 "global Port Asset" - xyzwh 299 569 2000 90 23 +textcanvas 146821 "global processing Pipe Asset" + xyzwh 271 568 2000 149 24 relationcanvas 128389 relation_ref 128005 // from ref 128005 z 1999 to ref 128133 role_a_pos 200 676 3000 no_role_b @@ -271,7 +271,7 @@ relationcanvas 145925 relation_ref 145413 // relationcanvas 146181 relation_ref 145541 // from ref 128005 z 1999 to point 311 616 line 146309 z 1999 stereotype "<>" xyz 103 649 3000 to ref 146053 - role_a_pos 308 594 3000 no_role_b + role_a_pos 307 594 3000 no_role_b multiplicity_a_pos 329 627 3000 no_multiplicity_b relationcanvas 146565 relation_ref 145669 // from ref 146437 z 1999 to ref 137221 diff --git a/uml/cinelerra3/128261 b/uml/cinelerra3/128261 index aea54b2f1..c30e7ce9e 100644 --- a/uml/cinelerra3/128261 +++ b/uml/cinelerra3/128261 @@ -1,6 +1,6 @@ format 40 "MObject" // ProcessingLayer::MObject - revision 28 + revision 29 modified_by 5 "hiv" // class settings //class diagram settings @@ -145,15 +145,15 @@ ${inlines} b multiplicity "" parent class_ref 139653 // Session end - classrelation 147717 // ports () + classrelation 147717 // pipes () relation 145541 o--> stereotype "vector" - a role_name "ports" multiplicity "*" protected + a role_name "pipes" multiplicity "*" protected comment "the global ports (busses) of the session" cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; " - classrelation_ref 147717 // ports () - b multiplicity "" parent class_ref 138117 // Port + classrelation_ref 147717 // pipes () + b multiplicity "" parent class_ref 138117 // Pipe end end @@ -1020,7 +1020,7 @@ ${inlines} cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; " classrelation_ref 147973 // outPort () - b multiplicity "" parent class_ref 138117 // Port + b multiplicity "" parent class_ref 138117 // Pipe end end diff --git a/uml/cinelerra3/128389 b/uml/cinelerra3/128389 index 35d64e6bd..52c1b5245 100644 --- a/uml/cinelerra3/128389 +++ b/uml/cinelerra3/128389 @@ -1,6 +1,6 @@ format 40 "RenderEngine" // ProcessingLayer::RenderEngine - revision 12 + revision 13 modified_by 5 "hiv" // class settings //class diagram settings diff --git a/uml/cinelerra3/128389.diagram b/uml/cinelerra3/128389.diagram index b031adc09..5a6ad5049 100644 --- a/uml/cinelerra3/128389.diagram +++ b/uml/cinelerra3/128389.diagram @@ -84,6 +84,8 @@ classcanvas 139781 class_ref 135045 // CodecAdapter draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 599 621 2000 end +textcanvas 140037 "the »low level model«" + xyzwh 600 318 2000 105 18 relationcanvas 128261 relation_ref 131845 // from ref 128005 z 1999 stereotype "<>" xyz 178 278 3000 to point 216 200 line 137733 z 1999 to ref 128133 diff --git a/uml/cinelerra3/129285 b/uml/cinelerra3/129285 index 55db3685a..17a54b8b9 100644 --- a/uml/cinelerra3/129285 +++ b/uml/cinelerra3/129285 @@ -1,6 +1,6 @@ format 40 "ProcessingLayer" // ProcessingLayer - revision 11 + revision 12 modified_by 5 "hiv" // class settings //class diagram settings diff --git a/uml/cinelerra3/130053 b/uml/cinelerra3/130053 index 73baabcbc..9e872a275 100644 --- a/uml/cinelerra3/130053 +++ b/uml/cinelerra3/130053 @@ -1,6 +1,6 @@ format 40 "asset" // design::codegen::proc::asset - revision 7 + revision 8 modified_by 5 "hiv" // class settings //class diagram settings @@ -508,7 +508,7 @@ ${namespace_end}" comment "description of some media data decoder or encoder facility" end - artifact 137605 "outport" + artifact 137605 "pipe" stereotype "source" cpp_h "/* ${NAME}.hpp - ${description} @@ -542,7 +542,7 @@ ${namespace_start} ${members} ${namespace_end}" associated_classes - class_ref 138117 // OutPort + class_ref 138117 // Pipe end comment "structural asset corresponding to some port generating media output" end diff --git a/uml/cinelerra3/130309.diagram b/uml/cinelerra3/130309.diagram index 7de6c806f..9a3886bc4 100644 --- a/uml/cinelerra3/130309.diagram +++ b/uml/cinelerra3/130309.diagram @@ -55,7 +55,7 @@ classcanvas 132485 class_ref 137989 // Track draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 614 445 2000 end -classcanvas 132613 class_ref 138117 // Port +classcanvas 132613 class_ref 138117 // Pipe draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 682 445 2000 end diff --git a/uml/cinelerra3/131205.diagram b/uml/cinelerra3/131205.diagram index 6b22db552..822bc1982 100644 --- a/uml/cinelerra3/131205.diagram +++ b/uml/cinelerra3/131205.diagram @@ -15,7 +15,7 @@ classcanvas 128389 class_ref 138757 // ProcPatt draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 408 249 2000 end -classcanvas 128517 class_ref 138117 // Port +classcanvas 128517 class_ref 138117 // Pipe draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 240 168 2000 end diff --git a/uml/cinelerra3/5.session b/uml/cinelerra3/5.session index d8ab0b626..af98eb2ed 100644 --- a/uml/cinelerra3/5.session +++ b/uml/cinelerra3/5.session @@ -3,9 +3,9 @@ diagrams classdiagram_ref 130309 // Asset Kinds 860 633 100 4 158 0 classdiagram_ref 128133 // Session structure - 860 633 100 4 462 0 + 860 633 100 4 289 0 classdiagram_ref 128389 // Render Entities - 743 538 100 4 0 0 + 743 538 100 4 184 0 active classdiagram_ref 131205 // Struct-Asset Relations 555 620 100 4 0 0 end @@ -13,12 +13,10 @@ show_stereotypes selected package_ref 129 // cinelerra3 open - - package_ref 128005 // design + deploymentview_ref 128645 // gen class_ref 137477 // Unknown class_ref 137605 // Preview class_ref 137989 // Track - class_ref 138117 // Port class_ref 128005 // SessionImpl class_ref 128133 // EDL class_ref 128261 // Fixture diff --git a/uml/cinelerra3/cinelerra3.prj b/uml/cinelerra3/cinelerra3.prj index f342468f2..9873f26df 100644 --- a/uml/cinelerra3/cinelerra3.prj +++ b/uml/cinelerra3/cinelerra3.prj @@ -1,6 +1,6 @@ format 40 "cinelerra3" - revision 41 + revision 42 modified_by 5 "hiv" cpp_root_dir "../../src/" diff --git a/wiki/renderengine.html b/wiki/renderengine.html index f86d20ff0..5bc243c00 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -536,7 +536,7 @@ Some software component able to work on media data in the Cinelerra Render engin &rarr; ProcAsset {{red{to be defined}}} !Structural Asset -Some of the building blocks providing the framework for the objects placed into the current Session. Notable examples are Input/Output channels (Ports), Viewer attachment points, Tracks, etc. +Some of the building blocks providing the framework for the objects placed into the current Session. Notable examples are [[processing pipes|Pipe]] within the high-level-model, Viewer attachment points, Tracks, etc. * __outward interface operations__ include... * __inward interface operations__ include... &rarr; StructAsset {{red{to be defined}}} @@ -565,7 +565,7 @@ For every Asset we generate a __Ident tuple__ and a long ID (hash) derived from
The Asset Manager provides an Interface to some internal Database holding all Assets in the current Session and System state. It may be a real Database at some point (and for the moment it's a Hashtable). Each [[Asset]] is registered automatically with the Asset Manager; it can be queried either by it's //identification tuple// or by it's unique ID.
-
Placing an MObject relatively to another object such that it should be handled as //attached // to the latter results in several implementation problems. The typical use case is that of an effect attached to a clip or port.
+
Placing an MObject relatively to another object such that it should be handled as //attached // to the latter results in several implementation problems. The typical use case is that of an effect attached to a clip or processing pipe.
 * this attachment is not a globally fixed relation, rather, it typically exists only for some limited time span (e.g. the duration of the basic clip the effect is attached to)
 * the order of attachment is important and the attached placement may create a fork in the signal flow, so we need a way for specifying reproducibly how the resulting wiring should be
 * when building, we access the information in reversed direction: we have the target object and need to query for all attachements
@@ -579,7 +579,7 @@ The first step towards an solution is to isolate the problem; obviously we //nee
 
-
Starting out from the concepts of Objects, Placement to Tracks, Ports and connection properties (&rarr; see [[here|TrackPortEDL]]) within the EDL, we can identify the elementary operations occuring within the Builder. Overall, the Builder is organized as application of //visiting tools// to a collection of objects, so finally we have to consider some object kind appearing in the working function of the given builder tool, which holds at this moment some //context//. The job now is to organize this context such as to create a predictable build process from this //event driven// approach.
+
Starting out from the concepts of Objects, Placement to Tracks, render Pipes and connection properties (&rarr; see [[here|TrackPipeEDL]]) within the EDL, we can identify the elementary operations occuring within the Builder. Overall, the Builder is organized as application of //visiting tools// to a collection of objects, so finally we have to consider some object kind appearing in the working function of the given builder tool, which holds at this moment some //context//. The job now is to organize this context such as to create a predictable build process from this //event driven// approach.
 
 !Builder working Situations
 # any ''Clip'' (which at this point has been reduced already to a part of a simple elementary media stream &rarr; see [[Fixture]])
@@ -589,31 +589,31 @@ The first step towards an solution is to isolate the problem; obviously we //nee
 ##* effectively this is an application of effects
 ## at this point we have to process (and maybe generate on-the-fly) the [[source port of this clip|ClipSourcePort]]
 ##* the output of the source reading and preprocessing defined thus far is delivered as input to this port, which is done by a ~WiringRequest (see below)
-##* as every port, the source port has a processing pattern, normally inserting the camera (transformation effect) at this point
+##* as every port, it is the entry point to a [[processing pipe|Pipe], thus the source port has a processing pattern, typically inserting the camera (transformation effect) at this point
 ## followed by the application of effects
 ##* separately for every effect chain rooted (placed) directly onto the clip
 ##* and regarding the chaining order
-## next we have to assess the [[ports|Port]] to which the clip has been placed
-## producing a [[wiring request|WiringRequest]] for every pair {{{(chainEndpoint, port)}}}
-# [>img[draw/Proc.builder1.png]]   attaching an ''Effect'' is actually always an //insertion operation// which is done by //prepending// to the previously built nodes. Effects may be placed as attached to clips and ports, which causes them to be included in the processing chain at the given location. Effects may as well be placed at an absolute time, which means they are to be applied to every clip that happens to be at this time &mdash; but this usecase will be reolved when creating the Fixture, causing the effect to be attached to the clips in question. The same holds true for Effects put on tracks.
+## next we have to assess the [[pipes|Pipe]] to which the clip has been placed
+## producing a [[wiring request|WiringRequest]] for every pair {{{(chainEndpoint, pipe)}}}
+# [>img[draw/Proc.builder1.png]]   attaching an ''Effect'' is actually always an //insertion operation// which is done by //prepending// to the previously built nodes. Effects may be placed as attached to clips and pipes, which causes them to be included in the processing chain at the given location. Effects may as well be placed at an absolute time, which means they are to be applied to every clip that happens to be at this time &mdash; but this usecase will be reolved when creating the Fixture, causing the effect to be attached to the clips in question. The same holds true for Effects put on tracks.
 # treating an ''wiring request'' means
 ## detecting possible and impossible connections
 ## deriving additional possible "placement dimensions" generated by executing such an connection (e.g. connecting a mono source to a spatial sound system bus creates panning possibilities)
 ##* deriving parameter sources for this additional degrees of freedom
 ##* fire off insertion of the necessary effects to satisfy this connection request and implement the additional "placement dimensions" (pan, layer order, overlay mode, MIDI channel selection...)
-# processing effects and further placements ''attached to a Port'' behaves identical to the processing done with all attachments to individual clips.
+# processing the effects and further placements ''attached to a Pipe'' is handled identical to the processing done with all attachments to individual clips.
 # ''Transitions'' are to be handled differently according to their placement (&rarr; more on [[Transitions|TransitionsHandling]])
 #* when placed normally to two (or N) clips, they are inserted at the exit node of the clip's complete effect chain.
-#* otherwise, when placed to the source port(s) or when placed to some other ports they are inserted at the exit side of those ports effect chains. (Note: this puts additional requirements on the transition processor, so not every transition can be placed this way)
+#* otherwise, when placed to the source port(s) or when placed to some other pipes they are inserted at the exit side of those pipe's effect chains. (Note: this puts additional requirements on the transition processor, so not every transition can be placed this way)
 After consuming all input objects and satisfying all wiring requests, the result is a set of [[exit nodes|ExitNode]] ready for pulling data. We call the network reachable from such an exit node a [[Processor]], together all processors of all segments and output data types comprise the render engine.
 
 !!!dependencies
-Ports need to be there first, as everything else will be placed to a port at some point. The same holds true for tracks. But, on the other hand, both are optional. We can have ~EDLs with ~MObjects without configuring ports (but won't be able to build any render processor of course). And we could have an EDL without any track, if we place every ~MObject within this EDL directly to some port.
+Pipes need to be there first, as everything else will be plugged (placed) to a pipe at some point. The same holds true for tracks. But, on the other hand, both are optional. We can have ~EDLs with ~MObjects without configuring pipes (but won't be able to build any render processor of course). And we could have an EDL without any track, if we place every ~MObject within this EDL directly to some pipe.
 
-Effects can be attached only to already existing pipelines, starting out at some port or clip. Besides that, all further parts can be built in any order and independent of each other. This is made possible by using [[wiring requests|WiringRequest]], which can be resolved later on. So, as long as we start out with the tracks (to resolve any port they are placed to), and further, if we manage to get any effect placed to some clip-MO //after// setting up and treating the clip, we are fine and can do the building quasi event driven.
+Effects can be attached only to already existing pipelines, starting out at some pipes entry port or the source port of some clip. Besides that, all further parts can be built in any order and independent of each other. This is made possible by using [[wiring requests|WiringRequest]], which can be resolved later on. So, as long as we start out with the tracks (to resolve any pipe they are placed to), and further, if we manage to get any effect placed to some clip-MO //after// setting up and treating the clip, we are fine and can do the building quasi event driven.
 
 !!!building and resolving
-Building the network for the individual objects thus creates a queue of wiring requests. Some of them may be immediately resolvable, but detecting this correctly can be nontrivial, and so it seems better to group all wiring requests based on the port and treat them groupwise. Because &mdash; in the most general case &mdash; connecting includes the use of transforming and joining nodes, which can create additional wiring requests (e.g. for automation parameter data connections). Finally, if the network is complete, we could perform [[optimisations|RenderNetworkOptimisation]]
+Building the network for the individual objects thus creates a queue of wiring requests. Some of them may be immediately resolvable, but detecting this correctly can be nontrivial, and so it seems better to group all wiring requests based on the pipe and treat them groupwise. Because &mdash; in the most general case &mdash; connecting includes the use of transforming and joining nodes, which can create additional wiring requests (e.g. for automation parameter data connections). Finally, if the network is complete, we could perform [[optimisations|RenderNetworkOptimisation]]
 
@@ -756,7 +756,7 @@ As the builder has to create a render node network implementing most of the feat * the [[Proc-Layer-Controller|Controller]] initiates the BuildProcess and does the overall coordination of scheduling edit operations, rebuilding the fixture and triggering the Builder * to carry out the building, we use several tools (SegmentationTool, NodeCreaterTool,...), which are supplied by the [[tool factory|BuilderToolFactory]] * the actual building (i.e. the application of those tools to the timeline) is done by the [[Assembler|BuilderAssembler]], which is basically a collection of functions (but has a small amount of global configuration state) -* any non-trivial wiring of render nodes, tracks, ports and automation is done by the services of the [[connection manager|ConManager]] +* any non-trivial wiring of render nodes, tracks, pipes and automation is done by the services of the [[connection manager|ConManager]]
@@ -793,7 +793,7 @@ TertiaryDark: #667 Error: #f88
-
Configuration Queries are requests to the system to "create or retrieve an object with //this and that // capabilities". They are resolved by a rule based system ({{red{planned feature}}}) and the user can extend the used rules for each Session. Syntactically, they are stated in ''prolog'' syntax as a conjunction (=logical and) of ''predicates'', for example {{{stream(mpeg), port(myPort)}}}. Queries are typed to the kind of expected result object: {{{Query<Port> ("stream(mpeg)")}}} requests a port excepting/delivering mpeg stream data &mdash; and it depends on the current configuration what "mpeg" means. If there is any stream data producing component in the system, which advertises to deliver {{{stream(mpeg)}}}, and a port can be configured or connected with this component, then the [[defaults manager|DefaultsManagement]] will create/deliver a [[Port|PortHandling]] object configured accordingly.
+
Configuration Queries are requests to the system to "create or retrieve an object with //this and that // capabilities". They are resolved by a rule based system ({{red{planned feature}}}) and the user can extend the used rules for each Session. Syntactically, they are stated in ''prolog'' syntax as a conjunction (=logical and) of ''predicates'', for example {{{stream(mpeg), pipe(myPipe)}}}. Queries are typed to the kind of expected result object: {{{Query<Pipe> ("stream(mpeg)")}}} requests a pipe excepting/delivering mpeg stream data &mdash; and it depends on the current configuration what "mpeg" means. If there is any stream data producing component in the system, which advertises to deliver {{{stream(mpeg)}}}, and a pipe can be configured or connected with this component, then the [[defaults manager|DefaultsManagement]] will create/deliver a [[Pipe|PipeHandling]] object configured accordingly.
 &rarr; [[Configuration Rules system|ConfigRules]]
 
@@ -801,8 +801,8 @@ Error: #f88
Many features can be implemented by specifically configuring and wiring some unspecific components. Rather than tie the client code in need of some given feature to these configuration internals, in Cinelerra-3 the client can //query // for some kind of object providing the //needed capabilities. // Right from start (summer 2007), Ichthyo had the intention to implement such a feature using sort of a ''declarative database'', e.g. by embedding a Prolog system. By adding rules to the basic session configuration, users should be able to customize the semi-automatic part of Cinelerra's behaviour to great extent.
 
 [[Configuration Queries|ConfigQuery]] are used at various places, when creating and adding new objects, as well when building or optimizing the render engine node network.
-* Creating a [[port|PortHandling]] queries for a default port or a port with a certain stream type
-* Adding a new [[track|TrackHandling]] queries for some default placement configuration, e.g. the port.
+* Creating a [[pipe|PipeHandling]] queries for a default pipe or a pipe with a certain stream type
+* Adding a new [[track|TrackHandling]] queries for some default placement configuration, e.g. the pipe it will be plugged to.
 * when processing a [[wiring request|WiringRequest]], connection possibilities have to be evaluated.
 * actually building such a connection may create additional degrees of freedom, like panning for sound or layering for video.
 
@@ -840,7 +840,7 @@ This is an very important external Interface, because it links together all thre
 
-
For several components and properties there is an implicit default value or configuration; it is stored alongside with the session. The intention is that defaults never create an error, instead, they are to be extended silently on demand. Objects configured according to this defaults can be retrieved at the [[Session]] interface by a set of overloaded functions {{{Session::current->default(Query<TYPE> ("query string"))}}}, where the //query string // defines a capability query similar to what is employed for ports, stream types, codecs etc. The Queries are implemented by [[configuration rules|ConfigRules]]
+
For several components and properties there is an implicit default value or configuration; it is stored alongside with the session. The intention is that defaults never create an error, instead, they are to be extended silently on demand. Objects configured according to this defaults can be retrieved at the [[Session]] interface by a set of overloaded functions {{{Session::current->default(Query<TYPE> ("query string"))}}}, where the //query string // defines a capability query similar to what is employed for pipes, stream types, codecs etc. The Queries are implemented by [[configuration rules|ConfigRules]]
 
@@ -848,13 +848,13 @@ This is an very important external Interface, because it links together all thre ''Everything is an object'' &mdash; of course, that's a //no-brainer // todays. Rather, important is what is not "an object", meaning it can't be arranged arbitrarily * we have one and only one global [[Session]] which directly contains a collection of multiple [[EDLs|EDL]] and is associated with a globally managed collection of [[assets|Asset]] (no, we don't have scoped variables here; if e.g. a media has been "opened", it is just plain globally known as asset.) -* we have some global [[ports|Port]], which are treated in a unique manner and don't behave like other objects (e.g. effects) +* we have some global [[pipes|Pipe]], which are treated in a unique manner and don't behave like other objects (e.g. effects) * we have a [[Fixture]] which acts as isolation layer towards the render engine and is (re)built automatically. -We ''separate'' processing (rendering) and configuration (building). We have a [[Builder]] which creates a network of [[render nodes|ProcNode]], to be processed by //pulling data // from some [[Port]] +We ''separate'' processing (rendering) and configuration (building). We have a [[Builder]] which creates a network of [[render nodes|ProcNode]], to be processed by //pulling data // from some [[Pipe]] ''Objects are [[placed|Placement]] rather'' than assembled, connected, wired, attached. This is more of a rule-based approach and gives us one central metaphor and abstraction, allowing us to treat everything in an uniform manner. You can place it as you like, and the builder tries to make sense out of it, silently disabling what doesn't make sense. -An [[EDL]] is just a collection of configured and placed objects (and has no additional, fixed structure). [[Tracks|Track]] form a mere organisational grid, they are grouping devices not first-class entities (a track doesn't "have" a port or "is" a video track and the like; it can be configured to behave in such manner by using placements though). [[Ports|Port]] are hooks for making connections and are the only facility to build processing chains. We have global ports, and each clip is built around a lokal [[source port|ClipSourcePort]] &mdash; and that's all. No special "media viewer" and "arranger", no special role for media sources, no commitment to some fixed media stream types (video and audio). All of this is sort of pushed down to be configuration, represented as asset of some kind. For example, we have [[processing pattern|ProcPatt]] assets to represent the way of building the source network for reading from some media file (including codecs treated like effect plugin nodes) +An [[EDL]] is just a collection of configured and placed objects (and has no additional, fixed structure). [[Tracks|Track]] form a mere organisational grid, they are grouping devices not first-class entities (a track doesn't "have" a pipe or "is" a video track and the like; it can be configured to behave in such manner by using placements though). [[Pipes|Pipe]] are hooks for making connections and are the only facility to build processing chains. We have global pipes, and each clip is built around a lokal [[source port|ClipSourcePort]] &mdash; and that's all. No special "media viewer" and "arranger", no special role for media sources, no commitment to some fixed media stream types (video and audio). All of this is sort of pushed down to be configuration, represented as asset of some kind. For example, we have [[processing pattern|ProcPatt]] assets to represent the way of building the source network for reading from some media file (including codecs treated like effect plugin nodes) ''State'' is rigorously ''externalized'' and operations are to be ''scheduled'', to simplify locking and error handling. State is either treated similar to media stream data (as addressable and cacheable data frame), or is represented as "parameter" to be served by some [[parameter provider|ParamProvider]]. Automation is just another kind of parameter, i.e. a function, and how this function is calculated is an encapsulated implementation detail (we don't have "bezier automation", and then maybe a "linear automation", a "mask automation" and yet another way to handle transitions) @@ -892,7 +892,7 @@ In this usage, the EDL in most cases will be almost synonymous to the [[Session| The EDL within the Session is just a //logical grouping//, allowing for lots of flexibility. Actually, we can have several ~EDLs within one Session, and these ~EDLs can be linked together or not, they may be in sequence or may constitue a logical grouping of clips used simultanously in compositional work etc. Multiple ~EDLs can use the same or different tracks, and tracks as well are only an organisational (grouping) device. But at any time, we have exactly one [[Fixture]], derived automatically from all ~EDLs and containing the content actually to be rendered. -&rarr; see considerations about [[the role of Tracks and Ports in conjunction with the EDL|TrackPortEDL]] +&rarr; see considerations about [[the role of Tracks and Pipes in conjunction with the EDL|TrackPipeEDL]]
@@ -1123,7 +1123,7 @@ For this Cinelerra3 design, we could consider making GOP just another raw media * [[Handling of the current Session|CurrentSession]] * [[collecting Ideas for Implementation Guidelines|ImplementationGuidelines]] * [[using the Visitor pattern?|VisitorUse]] &mdash; resulting in [[»Visiting-Tool« library implementation|VisitingToolImpl]] -* [[Handling of Tracks and Ports in the EDL|TrackPortEDL]]. [[Handling of Tracks|TrackHandling]] and [[Ports|PortHandling]] +* [[Handling of Tracks and render Pipes in the EDL|TrackPipeEDL]]. [[Handling of Tracks|TrackHandling]] and [[Pipes|PipeHandling]] * [[getting default configured|DefaultsManagement]] Objects relying on [[rule-based Configuration Queries|ConfigRules]] * [[identifying the basic Builder operations|BasicBuildingOperations]] and [[planning the Implementation|PlanningNodeCreatorTool]] * [[how to handle »attached placement«|AttachedPlacementProblem]] @@ -1632,7 +1632,7 @@ So, when creating a clip out of such a compound media asset, the clip has to be |viewing media|asset::Clip, session::Clip and Placement (on hold)| for the whole Media, if not already existent| |mark selection as clip|asset::Clip, session::Clip, Placement with unspec. LocatingPin| doesn't add to EDL| |loading Plugin|asset::Effect| usually at program startup| -|create Session|asset::Track, asset::OutPort| | +|create Session|asset::Track, asset::Pipe| | &rarr; [[Creating and registering Assets|AssetCreation]] !![[MObjects|MObject]] @@ -2262,7 +2262,7 @@ afterwards. !!!prerequisites * Session and ~EDLs exist. -* Ports exist and are configured +* Pipes exist and are configured !!!postconditions * the Fixture contains one sorted timeline of ExplicitPlacement instances @@ -2270,7 +2270,7 @@ afterwards. * {{red{TODO: how to store and group the effects?}}} * any meta-clips or other funny things have been resolved to normal clips with placement * any multichannel clips has been broken down to elementary clips {{red{TODO: what is "elementary". e.g. stereo sound streams?}}} -* any globally or otherwise strangely placed effects have been attached either to a clip or to some port +* any globally or otherwise strangely placed effects have been attached either to a clip or to some pipe * we have one unified list of tracks <<tasksum start>> @@ -2283,7 +2283,7 @@ afterwards. <<task>>what data collections to build? !!treating a Track -<<task>>work out how to refer to ports and do other config +<<task>>work out how to refer to pipes and do other config <<task>>get some uniqe identifier and get relevant properties !!treating a {{{Placement<Clip>}}} @@ -2307,17 +2307,17 @@ afterwards. * the render engine to be built is contained as state within this tool object while it is passed around !!!prerequisites * Session and ~EDLs exist. -* Ports exist and are configured +* Pipes exist and are configured * Fixture contains ExplicitPlacement for every MObject to be rendered, and nothing else <<tasksum start>> <<taskadder>> !!preparing -We need a way of addressing existing [[ports|Port]]. Besides, as the Ports and Tracks are referred by the Placements we are processing, they are guaranteed to exist. +We need a way of addressing existing [[pipes|Pipe]]. Besides, as the Pipes and Tracks are referred by the Placements we are processing, they are guaranteed to exist. -!!treating a Port -<<task>>get the [[processing pattern|ProcPatt]] of the port by accessing the underlying port asset. +!!treating a Pipe +<<task>>get the [[processing pattern|ProcPatt]] of the pipe by accessing the underlying pipe asset. <<task>>process this ProcPatt recursively !!treating a processing pattern @@ -2328,19 +2328,19 @@ We need a way of addressing existing [[ports|Port]]. Besides, as the Ports and T <<task>>process the ProcPatt recursively <<task>>access the ClipSourcePort (which may be created on-the-fly) <<task>>enqueue an WiringRequest for connecting the source pipeline to the source port -<<task>>process the source port recursively (thus adding the camera etc.) -<<task>>enqueue an WiringRequest for any placement to some port for this clip. +<<task>>process the clip's render pipe recursively (thus adding the camera etc.) +<<task>>enqueue an WiringRequest for any placement to some pipe for this clip. * __note__: we suppose ** all wiring requests will be done after the processing of entities ** all effects placed to this clip will be processed after this clip (but before the wiring requests) !!treating an {{{Placement<Effect>}}} -<<task>>{{red{how to assure that effecs are processed after clips/ports??}}} +<<task>>{{red{how to assure that effecs are processed after clips/pipes??}}} <<task>>find out the application point <<task>>build a transforming node for the effect and insert it there !!postprocessing -<<task>>sort and group the assembled list of [[wiring requests|WiringRequest]] by ports +<<task>>sort and group the assembled list of [[wiring requests|WiringRequest]] by pipes <<tasksum end>> @@ -2351,33 +2351,32 @@ We need a way of addressing existing [[ports|Port]]. Besides, as the Ports and T //Note, we have yet to specify how exactly the building and rendering will work together with the backend. There are several possibilities how to structure the Playlist//
-
-
{{red{''NOTE'': I am considering to rename "Port" &rarr; "Pipe"}}}
+
+
+Pipes play an central role within the Proc Layer, because for everything placed and handled within the EDL, the final goal is to get it transformed into data which can be retrieved at some pipe's exit port. Pipes are special facilities, rather like inventory, separate and not treated like all the other objects.
+We don't distinguish between "input" and "output" ports &mdash; rather, pipes are thought to be ''hooks for making connections to''. By following this line of thought, each pipe has an input side and an output side and is in itself something like a ''Bus'' or ''processing chain''. Other processing entities like effects and transitions can be placed (attached) at the pipe, resulting them to be appended to form this chain. Likewise, we can place [[wiring requests|WiringRequest]] to the pipe, meaning we want it connected so to send it's output to another destination pipe. The [[Builder]] may generate further wiring requests to fulfil the placement of other entities.
+Thus //Pipes are the basic building blocks// of the whole render network. We distinguish ''global available'' Pipes, which are like the sum groups of a mixing console, and the ''lokal pipe'' or [[source port|ClipSourcePort]] of the individual clips, which exist only within the duration of the corresponding clip. The design //limits the possible kinds of pipes // to these two types &mdash; thus we can build local processing chains at clips and global processing chains at the global pipes of the session and that's all we can do. (because of the flexibility which comes with the concept of [[placements|Placement]], this is no real limitation)
 
-Ports play an central role within the Proc Layer, because for everything placed and handled within the EDL, the final goal is to get it transformed into data which can be retrieved at some port. Ports are special facilities, rather like inventory, separate and not treated like all the other objects.
-We don't distinguish between "input" and "output" ports &mdash; rather, ports are thought to be ''hooks for making connections to''. By following this line of thought, each port has an input side and an output side and is in itself something like a ''Bus'' or the starting point for building a ''processing chain''. Other processing entities like effects and transitions can be placed (attached) at the port, resulting them to be appended to form this chain. Likewise, we can place [[wiring requests|WiringRequest]] to the port, meaning we want it connected to another destination port. The [[Builder]] may generate further wiring requests to fulfil the placement of other entities.
-Thus Ports are the basic building blocks of the whole render network. We distinguish ''global available'' Ports, which are like the sum groups of a mixing console, and the ''lokal port'' or [[source port|ClipSourcePort]] of the individual clips, which exist only within the duration of the corresponding clip. The design //limits the possible kinds of ports // to these two types &mdash; thus we can build local processing chains at clips and global processing chains at the global ports of the session and that's all we can do. (because of the flexibility which comes with the concept of [[placements|Placement]], this is no real limitation)
-
-The GUI can connect the viewer(s) to some port (and moreover can use [[probe points|ProbePoint]] placed like effects and connected to some port), and likewise, when starting a ''render'', we get the opportunity to specify the ports to pull the data from. Pulling data from some port is the (only) way to activate the render nodes network reachable from this port.
+The GUI can connect the viewer(s) to some pipe (and moreover can use [[probe points|ProbePoint]] placed like effects and connected to some pipe), and likewise, when starting a ''render'', we get the opportunity to specify the pipes to pull the data from. Pulling data from some pipe is the (only) way to activate the render nodes network reachable from this pipe.
 
 &rarr; [[Handling of Tracks|TrackHandling]]
-&rarr; [[Handling of Ports|PortHandling]]
+&rarr; [[Handling of Pipes|PipeHandling]]
 
 
-
+
!Identification
-Ports are distinct objects and can be identified by their asset ~IDs. Besides, as for all [[structural assets|StructAsset]] there are extended query capabilities, including a symbolic port-id and a media (stream) type id. Any port can accept and deliver exactly one media stream kind (which may be inherently structured though, e.g. spatial sound systems or stereoscopic video)
+Pipes are distinct objects and can be identified by their asset ~IDs. Besides, as for all [[structural assets|StructAsset]] there are extended query capabilities, including a symbolic pipe-id and a media (stream) type id. Any pipe can accept and deliver exactly one media stream kind (which may be inherently structured though, e.g. spatial sound systems or stereoscopic video)
 
-!creating ports
-Port assets are created automatically by being used and referred. The [[Session]] holds a collection of global ports, and further ports can be created by using an new port reference in some placement. Moreover, every clip has an (implicit) [[source port|ClipSourcePort]], which will appear as port asset when first used (referred) while [[building|BuildProcess]].
+!creating pipes
+Pipe assets are created automatically by being used and referred. The [[Session]] holds a collection of global pipes, and further pipes can be created by using an new pipe reference in some placement. Moreover, every clip has an (implicit) [[source port|ClipSourcePort]], which will appear as pipe asset when first used (referred) while [[building|BuildProcess]].
 
 !removal
-Deleting a Port is an advanced operation, because it includes finding and "detaching" all references, otherwise the port will leap back into existence immediately. Thus, global port entries in the Session and port references in [[locating pins|LocatingPin]] within any placement have to be removed, while clips using a given source port will be disabled. {{red{todo: implementation deferred}}}
+Deleting a Pipe is an advanced operation, because it includes finding and "detaching" all references, otherwise the pipe will leap back into existence immediately. Thus, global pipe entries in the Session and pipe references in [[locating pins|LocatingPin]] within any placement have to be removed, while clips using a given source port will be disabled. {{red{todo: implementation deferred}}}
 
-!using Ports
-there is not much you can do directly with a port asset. It is an point of reference, after all. Any connection to some port is only temporarily done by a placement in some part of the timeline, so it isn't stored with the port. You can edit the (user visible) description an you can globally disable a port asset. The port's ID and media stream type of course are fixed, because any connection and referral (via the asset ID) is based on them. Later on, we should provide a {{{rewire(oldPort, newPort)}}} to search any ref to the {{{oldPort}}} and try to rewrite it to use the {{{newPort}}}, possibly with a new media stream type.
-Ports are integrated with the [[management of defaults|DefaultsManagement]]. For example, any port uses implicitly some [[processing pattern|ProcPatt]] &mdash; it may default to the empty pattern. This feature enables to apply some standard wiring to the ports (e.g a fader for audio, similar to the classic mixing consoles). This //is // a global property of the port, but &mdash; contrary to the stream type &mdash; this pattern may be switched
+!using Pipes
+there is not much you can do directly with a pipe asset. It is an point of reference, after all. Any connection to some pipe is only temporarily done by a placement in some part of the timeline, so it isn't stored with the pipe. You can edit the (user visible) description an you can globally disable a pipe asset. The pipe's ID and media stream type of course are fixed, because any connection and referral (via the asset ID) is based on them. Later on, we should provide a {{{rewire(oldPipe, newPipe)}}} to search any ref to the {{{oldPipe}}} and try to rewrite it to use the {{{newPipe}}}, possibly with a new media stream type.
+Pipes are integrated with the [[management of defaults|DefaultsManagement]]. For example, any pipe uses implicitly some [[processing pattern|ProcPatt]] &mdash; it may default to the empty pattern. This feature enables to apply some standard wiring to the pipes (e.g a fader for audio, similar to the classic mixing consoles). This //is // a global property of the pipe, but &mdash; contrary to the stream type &mdash; this pattern may be switched
 
@@ -2407,7 +2406,7 @@ Users accustomed with modern GUI applications typically expect that //everything !!Compound and Multiplicity Simple relations can be hard wired. But, on the contrary, it would be as naive to define a Clip as having a Video track and two audio tracks, as it would be naive to overlook the problem of holding video and corresponding audio together. And, moreover, the default case has to be processed in a //straight forward// fashion, with as few tests and decisions as possible. So, basically each component participating in getting the core processing done has to mirror the structure pattern of the other parts, so that processing can be done without testing and forking. But this leaves us with the problem where to put the initial knowledge about the structural pattern used for building up the compound structures and &mdash; especially &mdash; the problem how to treat different kinds of structural patterns, how to detect the pattern to be applied and how to treat multiple instances of the same structural pattern. -One example of this problem is the [[handling of multichannel media|MultichannelMedia]]. Following the above reasoning, we end with having a [["structural processing pattern"|ProcPatt]], typically one video stream with MPEG decoder and a pair of audio streams which need either to be routed to some "left" and "right" output ports, or have to be passed through a panning filter accordingly. Now the problem is: //create a new instance of this structure for each new media, or detect which media to subsume under a existing pattern instance.// +One example of this problem is the [[handling of multichannel media|MultichannelMedia]]. Following the above reasoning, we end with having a [["structural processing pattern"|ProcPatt]], typically one video stream with MPEG decoder and a pair of audio streams which need either to be routed to some "left" and "right" output pipes, or have to be passed through a panning filter accordingly. Now the problem is: //create a new instance of this structure for each new media, or detect which media to subsume under a existing pattern instance.// !!Parallelism We need to work out guidelines for dealing with operations going on simultaneously. Certainly, this will divide the application in several different regions. As always, the primary goal is to avoid multithread problems altogether. Typically, this can be achieved by making matters explicit: externalizing state, make the processing subsystems stateless, queue and schedule tasks, use isolation layers. @@ -2490,21 +2489,21 @@ Like all [[structural assets|StructAsset]], ~ProcPatt employs a special naming s The intention is to get much more readable ("declarative") and changeable configuration as by programming it directly within the implementation of some object. !Draft -As an example, specifying how a Track can be configured for connecting automatically to some "mpeg" bus (=port) +As an example, specifying how a Track can be configured for connecting automatically to some "mpeg" bus (=pipe) {{{ retrieve(O, Cap) :- find(O), capabilities(Cap). retrieve(O, Cap) :- make(O), capabilities(Cap). capabilities(Q) :- call(Q). -stream(T, mpeg) :- type(T, track), type(P, port), retrieve(P, stream(P,mpeg)), place_to(P, T). +stream(T, mpeg) :- type(T, track), type(P, pipe), retrieve(P, stream(P,mpeg)), place_to(P, T). }}} -Then, running the goal {{{:-retrieve(T, stream(T,mpeg)).}}} would search a Track object, try to retrieve a port object with stream-type=mpeg and associate the track with this Port. This relies on a predicate "stream(P,mpeg)" implemented (natively) for the port object. So, "Cap" is the query issued from calling code &mdash; here {{{stream(T,mpeg)}}}, the type guard {{{type(T, track)}}} will probably be handled or inserted automatically, while the predicate implementations for find/1, make/1, stream/2, and place_to/2 are to be provided by the target types. -* __The supporting system__ had to combine several code snippets into one rule system to be used for running queries, with some global base rules, rules injected by each individual participating object kind and finally user provided rules added by the current session. The actual query is bound to "Cap" (and consequently run as a goal by {{{call(Q)}}}). The implementation needs to provide a symbol table associating variable terms (like "T" or "P") to C/C++ object types, enabling the participating object kinds to register their specific predicate implementations. This is crucial, because there can be no general scheme of object-provided predicates (for each object kind different predicates make sense, e.g. [[ports|PortHandling]] have other possibilities than [[wiring requests|WiringRequest]]). Basically, a query issues a Prolog goal, which in turn evaluates domain specific predicates provided by the participating objects and thus calls back into C/C++ code. The supporting system maintains the internal connection (via the "type" predicate) such that from Prolog viewpoint it looks as if we were binding Variables directly to object instances. (there are some nasty technical details because of the backtracking nature of Prolog evaluations which need to be hidden away) +Then, running the goal {{{:-retrieve(T, stream(T,mpeg)).}}} would search a Track object, try to retrieve a pipe object with stream-type=mpeg and associate the track with this pipe. This relies on a predicate "stream(P,mpeg)" implemented (natively) for the pipe object. So, "Cap" is the query issued from calling code &mdash; here {{{stream(T,mpeg)}}}, the type guard {{{type(T, track)}}} will probably be handled or inserted automatically, while the predicate implementations for find/1, make/1, stream/2, and place_to/2 are to be provided by the target types. +* __The supporting system__ had to combine several code snippets into one rule system to be used for running queries, with some global base rules, rules injected by each individual participating object kind and finally user provided rules added by the current session. The actual query is bound to "Cap" (and consequently run as a goal by {{{call(Q)}}}). The implementation needs to provide a symbol table associating variable terms (like "T" or "P") to C/C++ object types, enabling the participating object kinds to register their specific predicate implementations. This is crucial, because there can be no general scheme of object-provided predicates (for each object kind different predicates make sense, e.g. [[pipes|PipeHandling]] have other possibilities than [[wiring requests|WiringRequest]]). Basically, a query issues a Prolog goal, which in turn evaluates domain specific predicates provided by the participating objects and thus calls back into C/C++ code. The supporting system maintains the internal connection (via the "type" predicate) such that from Prolog viewpoint it looks as if we were binding Variables directly to object instances. (there are some nasty technical details because of the backtracking nature of Prolog evaluations which need to be hidden away) * Any __participating object kind__ needs a way to declare domain specific predicates, thus triggering the registration of the necessary hooks within the supporting system. Moreover, it should be able to inject further prolog code (as shown in the example above with the {{{strem(T, mpeg)}}} predicate. For each of these new domain specific predicates, there needs to be a functor which can be invoked when the C implementation of the predicate is called from Prolog (in some cases even later, when the final solution is "executed", e.g. a new instance has been created and now some properties need to be set). !!a note on Plugins -In the design of the Cinelerra-3 Proc Layer done thus far, we provide //no possibility to introduce a new object kind// into the system via plugin interface. The system uses a fixed collection of classes intended to cover all needs (Clip, Effect, Track, Port, Label, Automation, ~Macro-Clips). Thus, plugins will only be able to provide new parametrisations of existing classes. This should not be any real limitation, because the whole system is designed to achieve most of its functionality by freely combining rather basic object kinds. As a plus, it plays nicely with any plain-C based plugin interface. For example, we will have C++ adapter classes for the most common sorts of effect plugin (pull system and synchronous frame-by-frame push with buffering) with a thin C adaptation layer for the specific external plugin systems used. Everything beyond this point can be considered "condiguration data" (including the actual plugin implementation to be loaded) +In the design of the Cinelerra-3 Proc Layer done thus far, we provide //no possibility to introduce a new object kind// into the system via plugin interface. The system uses a fixed collection of classes intended to cover all needs (Clip, Effect, Track, Pipe, Label, Automation, ~Macro-Clips). Thus, plugins will only be able to provide new parametrisations of existing classes. This should not be any real limitation, because the whole system is designed to achieve most of its functionality by freely combining rather basic object kinds. As a plus, it plays nicely with any plain-C based plugin interface. For example, we will have C++ adapter classes for the most common sorts of effect plugin (pull system and synchronous frame-by-frame push with buffering) with a thin C adaptation layer for the specific external plugin systems used. Everything beyond this point can be considered "condiguration data" (including the actual plugin implementation to be loaded)
@@ -2761,7 +2760,7 @@ At first sight the link between asset and clip-MO is a simple logical relation b The Session object is a singleton &mdash; actually it is a »~PImpl«-Facade object (because the actual implementation object can be swapped for (re)loading Sessions).<br/>The Session is comprised of * a collection of ''EDL'' objects * a ''current EDL'', which can be switched and accessed {{red{TODO not sure if I keep this design...}}} -* a collection of ''global Ports'' +* a collection of ''global Pipes'' * the ''Fixture'' with a possibility to [[(re)build it|PlanningBuildFixture]]
@@ -2774,14 +2773,15 @@ For larger editing projects the simple structure of a session containing "t With all the structural complexities possible within such a session, we need an isolation layer to provide __one__ definitive state where all configuration has been made explicit. Thus the session manages one special object list, the [[Fixture]], which can be seen as all currently active objects placed onto a single timeline. !!!organisational devices -The possibility of having multiple ~EDLs helps organizing larger projects. Each [[EDL]] is just a logical grouping; because all effective properties of any MObject within this EDL are defined by the ~MObject itself and the [[Placement]], by which the object is anchored to some time point, some track, can be connected to some port, or linked to another object. In a similar manner, Tracks are just another organisational aid for grouping objects, disabling them and defining common output ports. +The possibility of having multiple ~EDLs helps organizing larger projects. Each [[EDL]] is just a logical grouping; because all effective properties of any MObject within this EDL are defined by the ~MObject itself and the [[Placement]], by which the object is anchored to some time point, some track, can be connected to some pipe, or linked to another object. In a similar manner, Tracks are just another organisational aid for grouping objects, disabling them and defining common output pipes. -!!!global ports -Any session should contain a number of global [[(destination) ports|Port]], typically video out and audio out. The goal is, to get any content producing or transforming object in some way connected to one of these outputs, either //by [[placing|Placement]] it directly// to some port, or by //placing it to a track// and having the track refer to some port. Besides the global destination ports, we can use internal ports to form busses or subgroups, either on a global (session) level, or attached to individual tracks. Normally, ports just gather and mix data, but of course any port can have an attached effect chain. (&rarr; see [[more on Tracks and Ports within the EDL|TrackPortEDL]]) +!!!global pipes +Any session should contain a number of global [[(destination) pipes|Pipe]], typically video out and audio out. The goal is, to get any content producing or transforming object in some way connected to one of these outputs, either //by [[placing|Placement]] it directly// to some pipe, or by //placing it to a track// and having the track refer to some pipe. Besides the global destination pipes, we can use internal pipes to form busses or subgroups, either on a global (session) level, or by using the processing pipe within a [[virtual clip|VirtualClip]], which can be placed freely within the ~EDLs. Normally, pipes just gather and mix data, but of course any pipe can have an attached effect chain. (&rarr; see [[more on Tracks and Pipes within the EDL|TrackPipeEDL]]) !!!default configuration [>img[draw/Proc.builder1.png]]While all these possibilities may seem daunting, there is a simple default configuration loaded into any pristine new session: -It will contain a global video and audio outport, just one EDL with one track; this track will have a internal video and audio port (bus) configured with one fading device sending to the global output ports. So, by adding some clip with a simple absolute placement to this track and some time position, the clip gets connected and rendered, after [[(re)building|PlanningBuildFixture]] the [[Fixture]] and passing the result to the [[Builder]] &mdash; and using the resulting render nodes network (Render Engine). +It will contain a global video and audio out pipe, just one EDL with one track; this track will have a internal video and audio pipe (bus) configured with one fading device sending to the global output ports. So, by adding some clip with a simple absolute placement to this track and some time position, the clip gets connected and rendered, after [[(re)building|PlanningBuildFixture]] the [[Fixture]] and passing the result to the [[Builder]] &mdash; and using the resulting render nodes network (Render Engine). +
<<search>><<closeAll>><<permaview>><<newTiddler>><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel "options »" "Change TiddlyWiki advanced options">>
@@ -2876,14 +2876,14 @@ Instead, we should try to just connect the various subsystems via Interfaces and
Structural Assets are intended mainly for internal use, but the user should be able to see and query them. They are not "loaded" or "created" direcly, rather they //leap into existance // by creating or extending some other structures in the EDL/Session, hence the name. Some of the structural Asset parametrisation can be modified to control of some aspects of the Proc Layer's (default) behaviour.
 * [[Processing Patterns|ProcPatt]] encode information how to set up some parts of the render network to be created automatically: for example, when building a clip, we use the processing pattern how to decode and preprocess the actual media data.
-* [[Tracks|Track]] are one of the dimensions used for organizing the EDL. They serve as an Anchor to attach parametrisation of output port, overlay mode etc. By [[placing|Placement]] to a track, some media object inherits placement properties from this track.
-* [[Ports|Port]] form &mdash; at least as visible to the user &mdash; the basic building block of the render network, because the latter appears to be a collection of processing pipelines rooted on Ports and interconnected. (this is the //outward view; // in fact the render network consists of [[nodes|ProcNode]] and is [[built|Builder]] from the Ports, clips, effects...)
+* [[Tracks|Track]] are one of the dimensions used for organizing the EDL. They serve as an Anchor to attach parametrisation of output pipe, overlay mode etc. By [[placing|Placement]] to a track, some media object inherits placement properties from this track.
+* [[Pipes|Pipe]] form &mdash; at least as visible to the user &mdash; the basic building block of the render network, because the latter appears to be a collection of interconnected processing pipelines. (this is the //outward view; // in fact the render network consists of [[nodes|ProcNode]] and is [[built|Builder]] from the Pipes, clips, effects...)
 [>img[Asset Classess|uml/fig131205.png]]
 !naming scheme
 The Asset name field of structural Assets utilizes a special naming scheme, which allows to derive the name based on the capabilities of the structural asset. For example, by default all media clips with a given media stream type (e.g. H264) will use the same [[processing Pattern|ProcPatt]] for rendering. {{red{todo: work out the details of this naming scheme??}}}
 
 !querying
-Structural assets can be queried by specifying the specific type (Port, Track, ProcPatt) and a query goal, which means in the current implementation just querying for some predicate defined with the structural asset. For example, you can {{{Query<Port> ("stream(mpeg)")}}}, yieliding the first port found which declares to have stream type "mpeg"
+Structural assets can be queried by specifying the specific type (Pipe, Track, ProcPatt) and a query goal, which means in the current implementation just querying for some predicate defined with the structural asset. For example, you can {{{Query<Pipe> ("stream(mpeg)")}}}, yieliding the first pipe found which declares to have stream type "mpeg"
/*{{{*/
@@ -4054,17 +4054,17 @@ function addKeyDownHandlers(e)
 
-
Tracks are just a structure used to organize the Media Objects within the EDL. They form a grid, and besides that, they have no special meaning. They are grouping devices, not first-class entities. A track doesn't "have" a port or "is" a video track and the like; it can be configured to behave in such manner by using placements.
+
Tracks are just a structure used to organize the Media Objects within the EDL. They form a grid, and besides that, they have no special meaning. They are grouping devices, not first-class entities. A track doesn't "have" a port or pipe or "is" a video track and the like; it can be configured to behave in such manner by using placements.
 
 Tracks are assets on their own, but they can be found within a given EDL. So, several ~EDLs can share a single track or each EDL can have its own, separate tracks. 
 * Like most ~MObjects, tracks have a asset view: you can find a track asset in the asset manager.
 * and they have an object view: there is an track MObject which can be [[placed|Placement]], thus defining properties of this track within one EDL
-Of course, we can place other ~MObjects relative to some track (that's the main reason why we want to have tracks). In this sense, the [[handling of Tracks|TrackHandling]] is somewhat special: the placement of some track can be found directly within the EDL (and not within the general collection of placed objects which form the contents of any EDL). This placement defines properties of the track, which will be inherited if necessary by all ~MObjects placed to this track. For example, if placing a track to some global [[Port]], and if placing a clip to this track, without placing the clip directly to another port, the port information of the track will be fetched by the builder when needed to make the output connection of the clip.
+Of course, we can place other ~MObjects relative to some track (that's the main reason why we want to have tracks). In this sense, the [[handling of Tracks|TrackHandling]] is somewhat special: the placement of some track can be found directly within the EDL (and not within the general collection of placed objects which form the contents of any EDL). This placement defines properties of the track, which will be inherited if necessary by all ~MObjects placed to this track. For example, if placing (=plugging) a track to some global [[Pipe]], and if placing a clip to this track, without placing the clip directly to another pipe, the associated-to-pipe information of the track will be fetched by the builder when needed to make the output connection of the clip.
 &rarr; [[Handling of Tracks|TrackHandling]]
-&rarr; [[Handling of Ports|PortHandling]]
+&rarr; [[Handling of Pipes|PipeHandling]]
 
-
+
''towards a definition of »Track«''. We don't want to tie ourself to some naive and overly simplistic definition, just because it is convenient. For classical (analogue) media, tracks are physical entities dictated by the nature of the process by which the media works. Especially, Tape machines have read/writing heads, which creates fixed tracks to which to route the signals. This is a practical geometric necessity. For digital media, there is no such necessity. We are bound primarily by the editor's habits of working.
 
 !!!Assessment of Properties
@@ -4079,17 +4079,17 @@ Starting with the assumption "everything is just connected processing nodes
 
 !!!the constant part
 there seems to be some non time-varying part in each EDL, that doesn't fit well with the simple model "objects on a timeline". Tracks seen as an organisational grid fall into this category: they are a global property of the given EDL. They could be associated to the Session as a whole, but effectively this would subvert the concept of having [[several EDLs|SessionOverview]]. On the other hand, 
-[[ports|Port]] for Video and Sound output are obviously a global property of the Session. There can be several global ports forming a matrix of subgroup busses. We could add ports to tracks by default as well, but we don't do this, because, again, this would run counter to our attempt of treating tracks as merely organisational entities. We have special [[source ports|ClipSourcePort]] on individual clips though, and we will have ports on meta-clips too.
+[[pipes|Pipe]] for Video and Sound output are obviously a global property of the Session. There can be several global pipes forming a matrix of subgroup busses. We could add ports or pipes to tracks by default as well, but we don't do this, because, again, this would run counter to our attempt of treating tracks as merely organisational entities. We have special [[source ports|ClipSourcePort]] on individual clips though, and we will have ports on [[virtual clips|VirtualClip]] too.
 
 !Design
 [[Tracks|Track]] are just a structure used to organize the Media Objects within the EDL. They form a grid, and besides that, they have no special meaning. It seems convenient to make the tracks not just a list, but allow grouping (tree structure) right from start. __~MObjects__ are ''placed'' rather than wired. The wiring is derived from the __Placement__. Placing can happen in several dimensions:
 * placing in time will define when to activate and show the object.
 * placing onto a track associates the ~MObject with this track; the GUI will show it on this track and the track may be used to resolve other properties of the object.
-* placing to a __Port__ brings the object in conjunction with this Port for the build process. It will be considered when building the render network for this port. Source-like objects (clips and exit nodes of effect chains) will be connected to the port, while transforming objects (effects) are inserted at the port. (you may read "placed to port X" as "plug into port X")
-* depending on the nature of the port and the source, placing to some port may create additional degrees of freedom, demanding the object to be placed in this new, additional dimensions: Connecting to video out e.g. creates an overlay mode and a layer position which need to be specified, while connecting to a spatial sound system creates the necessity of a pan position. On the other hand, placing a mono clip onto a mono Port creates no additional degrees of freedom.
-Placements are __resolved__ resulting in an ExplicitPlacement. In most cases this is just a gathering of properties, but as Placements can be incomplete and relative, there is room for real solving. The resolving mechanism tries to __derive missing properties__ from the __context__: When a clip isn't placed to some port but to a Track, than the Track and its parents will be inspected. If some of them has been placed to a port, the object will be connected to this port. Similar for layers and pan position. This is done by [[Placement]] and LocatingPin; as the [[Builder]] uses ~ExplicitPlacements, he isn't concerned with this resolving and uses just the data they deliver to drive the [[basic building operations|BasicBuildingOperations]]
+* placing to a __Pipe__ brings the object in conjunction with this pipe for the build process. It will be considered when building the render network for this pipe. Source-like objects (clips and exit nodes of effect chains) will be connected to the pipe, while transforming objects (effects) are inserted at the pipe. (you may read "placed to pipe X" as "plug into pipe X")
+* depending on the nature of the pipe and the source, placing to some pipe may create additional degrees of freedom, demanding the object to be placed in this new, additional dimensions: Connecting to video out e.g. creates an overlay mode and a layer position which need to be specified, while connecting to a spatial sound system creates the necessity of a pan position. On the other hand, placing a mono clip onto a mono Pipe creates no additional degrees of freedom.
+Placements are __resolved__ resulting in an ExplicitPlacement. In most cases this is just a gathering of properties, but as Placements can be incomplete and relative, there is room for real solving. The resolving mechanism tries to __derive missing properties__ from the __context__: When a clip isn't placed to some pipe but to a Track, than the Track and its parents will be inspected. If some of them has been placed to a pipe, the object will be connected to this pipe. Similar for layers and pan position. This is done by [[Placement]] and LocatingPin; as the [[Builder]] uses ~ExplicitPlacements, he isn't concerned with this resolving and uses just the data they deliver to drive the [[basic building operations|BasicBuildingOperations]]
 &rarr; [[Definition|Track]] and [[handling of Tracks|TrackHandling]]
-&rarr; [[Definition|Port]] and [[handling of Ports|PortHandling]]
+&rarr; [[Definition|Pipe]] and [[handling of Pipes|PipeHandling]]
 
@@ -4100,11 +4100,11 @@ Placements are __resolved__ resulting in an ExplicitPlacement. In most cases thi * some control data connection to a ParamProvider, because in the most general case the controling curves are treated like automation !!!how much output ports? -The standard case of a transition is sort of mixing together two input streams, like e.g. a simple dissolve. For this to be of any use, this input streams need to be connected to the same ouput port before and after the transition (with regards to the timeline), i.e. the inputs and the transition share placement to the same output destination. In this case, when the transition starts, the direct connections can be suspended and the transition will switch in seamlessly. +The standard case of a transition is sort of mixing together two input streams, like e.g. a simple dissolve. For this to be of any use, this input streams need to be connected to the same ouput destination before and after the transition (with regards to the timeline), i.e. the inputs and the transition share placement to the same output pipe. In this case, when the transition starts, the direct connections can be suspended and the transition will switch in seamlessly. Using transitions is a very basic task and thus needs viable support by the GUI. Handling of transitions need to be very convienient, because it is so important. Because of this, it is compelling to subsume a more complicated situation and treat this more complicated case similar. This is the case, when two (or N) elements have to be combined in the way of a transition, but their further processing in the processing chain //after// the transition needs to be different, maybe they belong to differnent subgroups, have to appear on different layers or with different pan positions. Of courese, the workaround is simple, at least "simple" from the programmers point of view. It is //not// simple from the editor's point of view the moment the editor has to do this simple thing (changing the wiring and add manualy synced fade curves to the individual parts) a dozend or even a hundred times in some larger project. -Because of this experience, ichthyo wants to support a more general case of transitions, which have N output connections, behave similar to their "simple" counterpart, but leave out the mixing step. As a plus, such transitions can be inserted at the source ports of N clips or between any intermediary or final output ports as well. Any transition processor capable of handling this situation should provide some flag, in order to decide if he can be placed in such a manner. (wichin the builder, encountering a inconsistently placed transition is just an [[building error|BuildingError]]) +Because of this experience, ichthyo wants to support a more general case of transitions, which have N output connections, behave similar to their "simple" counterpart, but leave out the mixing step. As a plus, such transitions can be inserted at the source ports of N clips or between any intermediary or final output pipes as well. Any transition processor capable of handling this situation should provide some flag, in order to decide if he can be placed in such a manner. (wichin the builder, encountering a inconsistently placed transition is just an [[building error|BuildingError]])
From 6346723069916081e7d5a2a52c0dcab9f06861f0 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 14 Feb 2008 04:12:30 +0100 Subject: [PATCH 14/14] Rename 'Port' to 'Pipe' II: source code --- src/common/configrules.hpp | 12 +- src/common/query/mockconfigrules.cpp | 8 +- src/proc/asset/{port.cpp => pipe.cpp} | 30 +-- src/proc/asset/{port.hpp => pipe.hpp} | 39 ++-- src/proc/asset/struct.cpp | 22 +- src/proc/asset/struct.hpp | 4 +- src/proc/asset/structfactoryimpl.hpp | 24 +- src/proc/assetmanager.cpp | 4 +- src/proc/mobject/explicitplacement.hpp | 6 +- src/proc/mobject/placement.hpp | 4 +- src/proc/mobject/session/defsmanager.cpp | 6 +- src/proc/mobject/session/locatingpin.cpp | 10 +- src/proc/mobject/session/locatingpin.hpp | 8 +- src/proc/mobject/session/plug.cpp | 4 +- src/proc/mobject/session/plug.hpp | 10 +- src/proc/mobject/session/track.hpp | 2 +- tests/components/proc/asset/basicpipetest.cpp | 208 ++++++++++++++++++ tests/components/proc/asset/basicporttest.cpp | 208 ------------------ 18 files changed, 304 insertions(+), 305 deletions(-) rename src/proc/asset/{port.cpp => pipe.cpp} (67%) rename src/proc/asset/{port.hpp => pipe.hpp} (66%) create mode 100644 tests/components/proc/asset/basicpipetest.cpp delete mode 100644 tests/components/proc/asset/basicporttest.cpp diff --git a/src/common/configrules.hpp b/src/common/configrules.hpp index d5189bbbe..a247eb30d 100644 --- a/src/common/configrules.hpp +++ b/src/common/configrules.hpp @@ -53,7 +53,7 @@ //TODO: is it sensible to bring in the types explicitly here? (it's not necessary, but may be convienient...) #include "proc/mobject/session/track.hpp" #include "proc/asset/procpatt.hpp" -#include "proc/asset/port.hpp" +#include "proc/asset/pipe.hpp" #include "proc/asset/track.hpp" #include @@ -77,14 +77,14 @@ namespace cinelerra // retrieve(O, Cap) :- make(T), capabilities(Cap). // capabilities(Q) :- call(Q). // - // stream(T, mpeg) :- type(T, track), type(P, port), retrieve(P, stream(P,mpeg)), place_to(P, T). + // stream(T, mpeg) :- type(T, track), type(P, pipe), retrieve(P, stream(P,mpeg)), place_to(P, T). // // The type guard is inserted auomatically, while the predicate implementations for // find/1, make/1, stream/2, and place_to/2 are to be provided by the target types. // // As a example, the goal ":-retrieve(T, stream(T,mpeg))." would search a Track object, try to - // retrieve a port object with stream-type=mpeg and associate the track with this Port. The - // predicate "stream(P,mpeg)" needs to be implemented (natively) for the port object. + // retrieve a pipe object with stream-type=mpeg and associate the track with this Pipe. The + // predicate "stream(P,mpeg)" needs to be implemented (natively) for the pipe object. class Resolver { @@ -148,7 +148,7 @@ namespace cinelerra // TODO: the Idea is to provide specialisations for the concrete types // we want to participate in the ConfigRules system.... // Thus we get the possibility to create a specific return type, - // e.g. return a shared_ptr but a Placement, using the appropriate factory. + // e.g. return a shared_ptr but a Placement, using the appropriate factory. // Of course then the definitions need to be split up in separate headers. @@ -197,7 +197,7 @@ namespace cinelerra */ typedef cinelerra::typelist::Types < mobject::session::Track , asset::Track - , asset::Port + , asset::Pipe , const asset::ProcPatt > ::List InterfaceTypes; diff --git a/src/common/query/mockconfigrules.cpp b/src/common/query/mockconfigrules.cpp index 29286e920..52f7f93fd 100644 --- a/src/common/query/mockconfigrules.cpp +++ b/src/common/query/mockconfigrules.cpp @@ -25,7 +25,7 @@ #include "proc/mobject/session/track.hpp" #include "proc/asset/procpatt.hpp" -#include "proc/asset/port.hpp" +#include "proc/asset/pipe.hpp" //#include "common/util.hpp" @@ -39,8 +39,8 @@ namespace cinelerra namespace query { using asset::Struct; - using asset::Port; - using asset::PPort; + using asset::Pipe; + using asset::PPipe; using asset::ProcPatt; using asset::PProcPatt; @@ -82,7 +82,7 @@ namespace cinelerra INFO (config, "creating mock answers for some config queries..."); isInit_ = true; // allow re-entrance - // for baiscporttest.cpp --------- + // for baiscpipetest.cpp --------- answer_->insert (entry_Struct ("stream(teststream)")); } diff --git a/src/proc/asset/port.cpp b/src/proc/asset/pipe.cpp similarity index 67% rename from src/proc/asset/port.cpp rename to src/proc/asset/pipe.cpp index e7a998f40..e15a09254 100644 --- a/src/proc/asset/port.cpp +++ b/src/proc/asset/pipe.cpp @@ -1,5 +1,5 @@ /* - Port - structural asset corresponding to some port generating media output + Pipe - structural asset denoting a processing pipe generating media output Copyright (C) CinelerraCV 2007, Hermann Vosseler @@ -21,31 +21,31 @@ * *****************************************************/ -#include "proc/asset/port.hpp" +#include "proc/asset/pipe.hpp" namespace asset { - namespace // Port Asset implementation details + namespace // Pipe Asset implementation details { /** @internal derive a sensible asset ident tuple when creating - * a port asset based on a query + * a pipe asset based on a query * @todo define the actual naming scheme of struct assets */ const Asset::Ident - createPortIdent (PProcPatt& wiring, string& id, wstring& shortD, wstring& longD) + createPipeIdent (PProcPatt& wiring, string& id, wstring& shortD, wstring& longD) { - string name ("port-" + id); // TODO something sensible here; append number, sanitize etc. - TODO ("Implement port name scheme!!"); - Category category (STRUCT,"ports"); + string name ("pipe-" + id); // TODO something sensible here; append number, sanitize etc. + TODO ("Implement pipe name scheme!!"); + Category category (STRUCT,"pipes"); return Asset::Ident (name, category ); } } /** */ - Port::Port (PProcPatt& wiring, string portID, wstring shortDesc, wstring longDesc) - : Struct (createPortIdent (wiring,portID,shortDesc,longDesc)), - portID_ (portID), + Pipe::Pipe (PProcPatt& wiring, string pipeID, wstring shortDesc, wstring longDesc) + : Struct (createPipeIdent (wiring,pipeID,shortDesc,longDesc)), + pipeID_ (pipeID), wiringTemplate(wiring), shortDesc (shortDesc), longDesc (longDesc) @@ -55,14 +55,14 @@ namespace asset - PPort - Port::query (string properties) + PPipe + Pipe::query (string properties) { - return Struct::create (Query (properties)); + return Struct::create (Query (properties)); } void - Port::switchProcPatt (PProcPatt& another) + Pipe::switchProcPatt (PProcPatt& another) { wiringTemplate = another; TODO ("trigger rebuild fixture"); diff --git a/src/proc/asset/port.hpp b/src/proc/asset/pipe.hpp similarity index 66% rename from src/proc/asset/port.hpp rename to src/proc/asset/pipe.hpp index 7fd23fe32..0761efe65 100644 --- a/src/proc/asset/port.hpp +++ b/src/proc/asset/pipe.hpp @@ -1,5 +1,5 @@ /* - PORT.hpp - structural asset corresponding to some port generating media output + PIPE.hpp - structural asset denoting a processing pipe generating media output Copyright (C) CinelerraCV 2007, Hermann Vosseler @@ -21,8 +21,8 @@ */ -#ifndef ASSET_OUTPORT_H -#define ASSET_OUTPORT_H +#ifndef ASSET_PIPE_H +#define ASSET_PIPE_H #include "proc/asset/struct.hpp" #include "proc/asset/procpatt.hpp" @@ -32,61 +32,60 @@ namespace asset { - class Port; - typedef shared_ptr PPort; + class Pipe; + typedef shared_ptr PPipe; template<> - class ID : public ID + class ID : public ID { public: ID (size_t id); - ID (const Port&); + ID (const Pipe&); }; /** - * structural asset corresponding to some port - * for building a processing chain and - * generating media output + * structural asset corresponding to some + * processing pipe for generating media output */ - class Port : public Struct + class Pipe : public Struct { - string portID_; + string pipeID_; PProcPatt wiringTemplate; public: wstring shortDesc; wstring longDesc; - virtual const ID& getID() const ///< @return ID typed to asset::Port + virtual const ID& getID() const ///< @return ID typed to asset::Pipe { - return static_cast& > (Asset::getID()); + return static_cast& > (Asset::getID()); } protected: - Port (PProcPatt& wiring, string portID="", wstring shortDesc =wstring(), wstring longDesc =wstring()) ; + Pipe (PProcPatt& wiring, string pipeID="", wstring shortDesc =wstring(), wstring longDesc =wstring()) ; friend class StructFactory; friend class StructFactoryImpl; public: - const string& getPortID() const { return portID_; } + const string& getPipeID() const { return pipeID_; } const PProcPatt& getProcPatt() const { return wiringTemplate; } /** use another wiring template. Triggers complete rebuild of the render engine. */ void switchProcPatt (PProcPatt& another); - /** convienience shortcut for retrieving default configured ports */ - static PPort query (string properties) ; + /** convienience shortcut for retrieving default configured pipes */ + static PPipe query (string properties) ; }; // catch up with postponed definition of ID ctors... // - inline ID::ID(size_t id) : ID (id) {}; - inline ID::ID(const Port& port) : ID (port.getID()) {}; + inline ID::ID(size_t id) : ID (id) {}; + inline ID::ID(const Pipe& pipe) : ID (pipe.getID()) {}; diff --git a/src/proc/asset/struct.cpp b/src/proc/asset/struct.cpp index 7aaab7b87..729da826a 100644 --- a/src/proc/asset/struct.cpp +++ b/src/proc/asset/struct.cpp @@ -25,7 +25,7 @@ #include "proc/asset/struct.hpp" #include "proc/asset/procpatt.hpp" #include "proc/asset/track.hpp" -#include "proc/asset/port.hpp" +#include "proc/asset/pipe.hpp" #include "proc/mobject/session.hpp" #include "common/configrules.hpp" @@ -87,22 +87,22 @@ namespace asset - /** Factory method for creating Ports explicitly. - * Normalizes port- and streamID, then retrieves the + /** Factory method for creating Pipes explicitly. + * Normalizes pipe- and streamID, then retrieves the * default processing pattern (ProcPatt) for this streamID. - * The Port ctor will fill out the shortDesc and longDesc - * automatically, based on portID and streamID (and they + * The Pipe ctor will fill out the shortDesc and longDesc + * automatically, based on pipeID and streamID (and they * are editable anyways) * @see ProcPatt * @see DefaultsManager */ - shared_ptr - StructFactory::operator() (string portID, string streamID) + shared_ptr + StructFactory::operator() (string pipeID, string streamID) { - normalizeID (portID); + normalizeID (pipeID); normalizeID (streamID); PProcPatt processingPattern = Session::current->defaults (Query("stream("+streamID+")")); - Port* pP = new Port (processingPattern, portID); + Pipe* pP = new Pipe (processingPattern, pipeID); return AssetManager::instance().wrap (*pP); } @@ -120,13 +120,13 @@ namespace asset #include "proc/asset/struct.hpp" #include "proc/asset/procpatt.hpp" #include "proc/asset/track.hpp" -#include "proc/asset/port.hpp" +#include "proc/asset/pipe.hpp" namespace asset { - template shared_ptr StructFactory::operator() (const Query& query); + template shared_ptr StructFactory::operator() (const Query& query); template shared_ptr StructFactory::operator() (const Query& query); template PProcPatt StructFactory::operator() (const Query& query); diff --git a/src/proc/asset/struct.hpp b/src/proc/asset/struct.hpp index 76b8b2e42..e9cb9de7d 100644 --- a/src/proc/asset/struct.hpp +++ b/src/proc/asset/struct.hpp @@ -57,7 +57,7 @@ namespace asset class Struct; class StructFactory; class StructFactoryImpl; - class Port; + class Pipe; template<> @@ -119,7 +119,7 @@ namespace asset template shared_ptr operator() (const Query& query); ////////////TODO actually do something sensible here - shared_ptr operator() (string portID, string streamID); + shared_ptr operator() (string pipeID, string streamID); }; diff --git a/src/proc/asset/structfactoryimpl.hpp b/src/proc/asset/structfactoryimpl.hpp index ae53e645a..506baea83 100644 --- a/src/proc/asset/structfactoryimpl.hpp +++ b/src/proc/asset/structfactoryimpl.hpp @@ -59,8 +59,8 @@ namespace asset template<> Symbol Traits::namePrefix = "track-"; template<> Symbol Traits::catFolder = "tracks"; - template<> Symbol Traits::namePrefix = "port-"; - template<> Symbol Traits::catFolder = "ports"; + template<> Symbol Traits::namePrefix = "pipe-"; + template<> Symbol Traits::catFolder = "pipes"; template<> Symbol Traits::namePrefix = "patt-"; template<> Symbol Traits::catFolder = "build-templates"; @@ -90,15 +90,15 @@ namespace asset return Asset::Ident (name, cat ); } - typedef std::pair PortIDs; + typedef std::pair PipeIDs; - PortIDs - createPortIdent (const Query& query) + PipeIDs + createPipeIdent (const Query& query) { - string name (Traits::namePrefix + query); // TODO get some more sensible dummy values - TODO ("port naming scheme??"); - TODO ("actually extract the port stream type from the query..."); - return PortIDs (name, "data"); // dummy stream type + string name (Traits::namePrefix + query); // TODO get some more sensible dummy values + TODO ("pipe naming scheme??"); + TODO ("actually extract the pipe stream type from the query..."); + return PipeIDs (name, "data"); // dummy stream type } @@ -148,10 +148,10 @@ namespace asset } template<> - Port* - StructFactoryImpl::fabricate (const Query& caps) + Pipe* + StructFactoryImpl::fabricate (const Query& caps) { - PortIDs ids (createPortIdent (caps)); + PipeIDs ids (createPipeIdent (caps)); return recursive_create_ (ids.first, ids.second).get(); } diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index 4d988aa61..1da043dbc 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -235,7 +235,7 @@ namespace asset #include "proc/asset/proc.hpp" #include "proc/asset/struct.hpp" #include "proc/asset/track.hpp" -#include "proc/asset/port.hpp" +#include "proc/asset/pipe.hpp" #include "proc/asset/meta.hpp" #include "proc/asset/procpatt.hpp" @@ -256,7 +256,7 @@ namespace asset template shared_ptr AssetManager::wrap (const Media& asset); template shared_ptr AssetManager::wrap (const Clip& asset); template shared_ptr AssetManager::wrap (const Track& asset); - template shared_ptr AssetManager::wrap (const Port& asset); + template shared_ptr AssetManager::wrap (const Pipe& asset); template shared_ptr AssetManager::wrap (const ProcPatt& asset); diff --git a/src/proc/mobject/explicitplacement.hpp b/src/proc/mobject/explicitplacement.hpp index 9cc8bd1b7..9cf0917aa 100644 --- a/src/proc/mobject/explicitplacement.hpp +++ b/src/proc/mobject/explicitplacement.hpp @@ -48,9 +48,9 @@ namespace mobject { public: const Time time; - const Port port; + const Pipe pipe; - typedef std::pair SolutionData; //TODO (ichthyo consideres better passing of solution by subclass) + typedef std::pair SolutionData; //TODO (ichthyo consideres better passing of solution by subclass) /** no need to resolve any further, as this ExplicitPlacement * already \i is the result of a resolve()-call. @@ -70,7 +70,7 @@ namespace mobject */ ExplicitPlacement (const Placement& base, const SolutionData found) : Placement(base), - time(found.first), port(found.second) + time(found.first), pipe(found.second) { }; friend ExplicitPlacement Placement::resolve () const; diff --git a/src/proc/mobject/placement.hpp b/src/proc/mobject/placement.hpp index ab29878de..7b326f23d 100644 --- a/src/proc/mobject/placement.hpp +++ b/src/proc/mobject/placement.hpp @@ -60,7 +60,7 @@ #include "pre.hpp" #include "proc/mobject/mobject.hpp" #include "proc/mobject/session/locatingpin.hpp" -#include "proc/asset/port.hpp" +#include "proc/asset/pipe.hpp" #include using std::tr1::shared_ptr; @@ -86,7 +86,7 @@ namespace mobject { protected: typedef cinelerra::Time Time; - typedef asset::shared_ptr Port; + typedef asset::shared_ptr Pipe; diff --git a/src/proc/mobject/session/defsmanager.cpp b/src/proc/mobject/session/defsmanager.cpp index f5688bbfd..bfb505efb 100644 --- a/src/proc/mobject/session/defsmanager.cpp +++ b/src/proc/mobject/session/defsmanager.cpp @@ -23,7 +23,7 @@ #include "proc/mobject/session/defsmanager.hpp" #include "proc/asset/procpatt.hpp" -#include "proc/asset/port.hpp" +#include "proc/asset/pipe.hpp" #include "common/configrules.hpp" #include "common/error.hpp" @@ -32,7 +32,7 @@ using boost::format; using asset::Query; -using asset::Port; +using asset::Pipe; using asset::ProcPatt; using asset::PProcPatt; @@ -73,7 +73,7 @@ namespace mobject /* explicit template instantiations for querying various Types */ /***************************************************************/ - template shared_ptr DefsManager::operator ()(const Query&); + template shared_ptr DefsManager::operator ()(const Query&); template PProcPatt DefsManager::operator ()(const Query&); } // namespace mobject::session diff --git a/src/proc/mobject/session/locatingpin.cpp b/src/proc/mobject/session/locatingpin.cpp index 88456d9a5..5da70e497 100644 --- a/src/proc/mobject/session/locatingpin.cpp +++ b/src/proc/mobject/session/locatingpin.cpp @@ -98,7 +98,7 @@ namespace mobject { LocatingSolution solution; resolve (solution); - return SolutionData (solution.getTime(), solution.getPort()); + return SolutionData (solution.getTime(), solution.getPipe()); } bool @@ -142,11 +142,11 @@ namespace mobject return minTime; } - LocatingPin::Port - LocatingPin::LocatingSolution::getPort() + LocatingPin::Pipe + LocatingPin::LocatingSolution::getPipe() { - UNIMPLEMENTED ("get effective Port of Solution"); - return Port (); + UNIMPLEMENTED ("get effective Pipe of Solution"); + return Pipe (); } diff --git a/src/proc/mobject/session/locatingpin.hpp b/src/proc/mobject/session/locatingpin.hpp index c4e64844a..81b3fa92f 100644 --- a/src/proc/mobject/session/locatingpin.hpp +++ b/src/proc/mobject/session/locatingpin.hpp @@ -51,7 +51,7 @@ using boost::scoped_ptr; -namespace asset { class Port; } +namespace asset { class Pipe; } namespace mobject { @@ -83,8 +83,8 @@ namespace mobject protected: typedef cinelerra::Time Time; typedef Time* Track; //TODO dummy declaration; we don't use Tracks as first-class entity any longer - typedef std::tr1::shared_ptr Port; - typedef std::pair SolutionData; //TODO (ichthyo consideres better passing of solution by subclass) + typedef std::tr1::shared_ptr Pipe; + typedef std::pair SolutionData; //TODO (ichthyo consideres better passing of solution by subclass) struct LocatingSolution; /** next additional Pin, if any */ @@ -141,7 +141,7 @@ namespace mobject { } Time getTime (); - Port getPort (); + Pipe getPipe (); bool is_definite (); bool is_impossible (); diff --git a/src/proc/mobject/session/plug.cpp b/src/proc/mobject/session/plug.cpp index 91c4b9fb9..09fa2dab8 100644 --- a/src/proc/mobject/session/plug.cpp +++ b/src/proc/mobject/session/plug.cpp @@ -1,5 +1,5 @@ /* - Plug - LocatingPin for requesting connection to some Port + Plug - LocatingPin for requesting connection to some Pipe Copyright (C) CinelerraCV 2007, Hermann Vosseler @@ -22,7 +22,7 @@ #include "proc/mobject/session/plug.hpp" -#include "proc/asset/port.hpp" +#include "proc/asset/pipe.hpp" namespace mobject { diff --git a/src/proc/mobject/session/plug.hpp b/src/proc/mobject/session/plug.hpp index 53599ea52..7d45c14ee 100644 --- a/src/proc/mobject/session/plug.hpp +++ b/src/proc/mobject/session/plug.hpp @@ -1,5 +1,5 @@ /* - PLUG.hpp - LocatingPin for requesting connection to some Port + PLUG.hpp - LocatingPin for requesting connection to some Pipe Copyright (C) CinelerraCV 2007, Hermann Vosseler @@ -28,7 +28,7 @@ -namespace asset { class Port; } +namespace asset { class Pipe; } namespace mobject { @@ -36,13 +36,13 @@ namespace mobject { /** - * LocatingPin for requesting connection to some Port + * LocatingPin for requesting connection to some Pipe */ class Plug : public Wish { protected: - /** the Port this MObject wants to be conected to */ - asset::Port* outPort; ////////////////////////////////TODO: shared_ptr + /** the Pipe this MObject wants to be conected to */ + asset::Pipe* outPipe; ////////////////////////////////TODO: shared_ptr }; diff --git a/src/proc/mobject/session/track.hpp b/src/proc/mobject/session/track.hpp index 99c7ae9cb..4429a9189 100644 --- a/src/proc/mobject/session/track.hpp +++ b/src/proc/mobject/session/track.hpp @@ -42,7 +42,7 @@ namespace mobject * The corresponding Placement by which this Track object is refered * defines fallback placing properties to be used by all objects placed on this track * in case they don't specify more concrete placements. - * Typically, tracks are used do make default Port connections, + * Typically, tracks are used do make default processing pipe connections, * define a layer or pan for sound and for for disabling groups * of clips. Note tracks are grouped in a tree like fashion. */ diff --git a/tests/components/proc/asset/basicpipetest.cpp b/tests/components/proc/asset/basicpipetest.cpp new file mode 100644 index 000000000..315ba83a7 --- /dev/null +++ b/tests/components/proc/asset/basicpipetest.cpp @@ -0,0 +1,208 @@ +/* + BasicPipe(Test) - checking the basic properties of Pipe Assets + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "common/test/run.hpp" +#include "common/util.hpp" + +#include "proc/asset/category.hpp" +#include "proc/asset/pipe.hpp" +#include "common/query.hpp" +#include "proc/assetmanager.hpp" +#include "proc/mobject/session.hpp" +#include "proc/asset/assetdiagnostics.hpp" + +#include +#include + +using boost::format; +using util::contains; +using util::isnil; +using std::string; +using std::wstring; +using std::cout; + + +namespace asset + { + namespace test + { + using mobject::Session; + using cinelerra::Query; + using cinelerra::query::normalizeID; + + + + /*********************************************************************** + * @test basic properties of Pipe (structural) Assets. + *
  • created by referral
  • + *
  • access existing pipe by referral
  • + *
  • create with full properties
  • + *
  • access ProcPatt
  • + *
  • check dependency
  • + *
+ */ + class BasicPipe_test : public Test + { + virtual void run(Arg arg) + { + string pipeID = isnil(arg)? "blackHole" : arg[1]; + string streamID = 2>arg.size()? "teststream" : arg[2] ; + + createExplicit (pipeID,streamID); + create_or_ref (pipeID); + dependProcPatt (pipeID); + } + + + + + void createExplicit (string pID, string sID) + { + string pID_sane (pID); + normalizeID (pID_sane); + + PPipe thePipe = asset::Struct::create (pID,sID); + + ASSERT (thePipe); + ASSERT (thePipe->getProcPatt()); + ASSERT (thePipe->getPipeID() == pID_sane); + ASSERT (thePipe->getProcPatt()->queryStreamID() == sID); + ASSERT (thePipe->shortDesc == wstring (pID_sane.begin(), pID_sane.end())); + + Asset::Ident idi = thePipe->ident; + ASSERT (idi.org == "cin3"); + ASSERT (contains (idi.name, thePipe->getPipeID())); + ASSERT (contains (idi.name, thePipe->getProcPatt()->queryStreamID())); + + Category cat (idi.category); + Category refcat (STRUCT,"pipes"); + ASSERT ( cat.hasKind(STRUCT) ); + ASSERT ( cat.isWithin(refcat) ); + } + + + void create_or_ref(string pID) + { + normalizeID (pID); + + PPipe pipe1 = Pipe::query ("pipe("+pID+")"); + ASSERT (pipe1); + ASSERT (pipe1->getPipeID() == pID); + + string pID2 = "another-" + pID; + PPipe pipe2 = Pipe::query ("pipe("+pID2+")"); + ASSERT (pipe2); + ASSERT (pipe2 != pipe1); + Category c1 = pipe1->ident.category; + Category c2 = pipe2->ident.category; + ASSERT (c1 == c2); + + PPipe pipe3 = Pipe::query ("pipe("+pID2+")"); + ASSERT (pipe3 == pipe2); + } + + + void create_using_default() + { + PPipe pipe1 = Pipe::query (""); // "the default pipe" + PPipe pipe2; + ASSERT (pipe1); + ASSERT (pipe1 == Session::current->defaults (Query())); + ASSERT (pipe1->ident.category.hasKind(VIDEO)); + ASSERT (pipe1->getProcPatt()); + PProcPatt popa = Session::current->defaults (Query("pipe()")); + ASSERT (popa == pipe1->getProcPatt()); + + // several variants to query for "the default pipe" + pipe2 = Session::current->defaults(Query ()); + ASSERT (pipe2 == pipe1); + pipe2 = asset::Struct::create (Query ()); + ASSERT (pipe2 == pipe1); + pipe2 = asset::Struct::create (Query ("pipe()")); + ASSERT (pipe2 == pipe1); + + string sID = popa->queryStreamID(); // sort of a "default stream type" + PPipe pipe3 = Pipe::query ("stream("+sID+")"); + ASSERT (pipe3); + ASSERT (pipe3->getProcPatt()->queryStreamID() == sID); + ASSERT (pipe3->getProcPatt() == Session::current->defaults (Query("stream("+sID+")"))); + } + + + void dependProcPatt(string pID) + { + PPipe thePipe = Pipe::query ("pipe("+pID+")"); + ASSERT (thePipe); + PProcPatt thePatt = thePipe->getProcPatt(); + ASSERT (thePatt); + ASSERT (dependencyCheck (thePipe, thePatt)); + + PProcPatt pattern2 = thePatt->newCopy("another"); + ASSERT (thePatt != pattern2); + ASSERT (!dependencyCheck (thePipe, pattern2)); + TODO ("add something to the new pattern, e.g. an effect"); + + // now querying for a pipe using this pattern (created on-the-fly) + // note: because the pattern is new, this new pipe will be used as + // default pipe for this pattern automatically + PPipe pipe2x = Pipe::query ("pattern(another)"); + ASSERT (pattern2 == pipe2x->getProcPatt()); + ASSERT (pipe2x == Session::current->defaults (Query("pattern(another)"))); + + thePipe->switchProcPatt(pattern2); + ASSERT ( dependencyCheck (thePipe, pattern2)); + ASSERT (!dependencyCheck (thePipe, thePatt)); + + AssetManager& aMang = AssetManager::instance(); + ASSERT ( aMang.known (thePipe->getID())); + ASSERT ( aMang.known (thePatt->getID())); + ASSERT ( aMang.known (pattern2->getID())); + aMang.remove (pattern2->getID()); + ASSERT ( aMang.known (thePatt->getID())); + ASSERT (!aMang.known (pattern2->getID())); + ASSERT (!aMang.known (thePipe->getID())); // has been unlinked too, because dependant on pattern2 + + ASSERT (thePipe); + ASSERT (thePipe->getProcPatt()); + ASSERT (thePipe->getProcPatt() == pattern2); // but is still valid, as long as the ref is alive.... + + PPipe pipe3x = Pipe::query ("pattern(another)"); + ASSERT (pipe3x->getProcPatt() != pattern2); // because pattern2 is already unlinked... + ASSERT (pipe3x == Session::current->defaults (Query("pattern(another)"))); + ASSERT (pipe3x != pipe2x); // ..we got a new default pipe for "pattern(another)" too! + + + TRACE (assetmem, "leaving BasicPipe_test::dependProcPatt()"); + // expect now pipe2x and pattern2 to be destroyed... + } + }; + + + /** Register this test class... */ + LAUNCHER (BasicPipe_test, "unit asset"); + + + + } // namespace test + +} // namespace asset diff --git a/tests/components/proc/asset/basicporttest.cpp b/tests/components/proc/asset/basicporttest.cpp deleted file mode 100644 index e68a20738..000000000 --- a/tests/components/proc/asset/basicporttest.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - BasicPort(Test) - checking the basic properties of Port Assets - - Copyright (C) CinelerraCV - 2007, Hermann Vosseler - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -* *****************************************************/ - - -#include "common/test/run.hpp" -#include "common/util.hpp" - -#include "proc/asset/category.hpp" -#include "proc/asset/port.hpp" -#include "common/query.hpp" -#include "proc/assetmanager.hpp" -#include "proc/mobject/session.hpp" -#include "proc/asset/assetdiagnostics.hpp" - -#include -#include - -using boost::format; -using util::contains; -using util::isnil; -using std::string; -using std::wstring; -using std::cout; - - -namespace asset - { - namespace test - { - using mobject::Session; - using cinelerra::Query; - using cinelerra::query::normalizeID; - - - - /*********************************************************************** - * @test basic properties of Port (structural) Assets. - *
  • created by referral
  • - *
  • access existing port by referral
  • - *
  • create with full properties
  • - *
  • access ProcPatt
  • - *
  • check dependency
  • - *
- */ - class BasicPort_test : public Test - { - virtual void run(Arg arg) - { - string portID = isnil(arg)? "blackHole" : arg[1]; - string streamID = 2>arg.size()? "teststream" : arg[2] ; - - createExplicit (portID,streamID); - create_or_ref (portID); - dependProcPatt (portID); - } - - - - - void createExplicit (string pID, string sID) - { - string pID_sane (pID); - normalizeID (pID_sane); - - PPort thePort = asset::Struct::create (pID,sID); - - ASSERT (thePort); - ASSERT (thePort->getProcPatt()); - ASSERT (thePort->getPortID() == pID_sane); - ASSERT (thePort->getProcPatt()->queryStreamID() == sID); - ASSERT (thePort->shortDesc == wstring (pID_sane.begin(), pID_sane.end())); - - Asset::Ident idi = thePort->ident; - ASSERT (idi.org == "cin3"); - ASSERT (contains (idi.name, thePort->getPortID())); - ASSERT (contains (idi.name, thePort->getProcPatt()->queryStreamID())); - - Category cat (idi.category); - Category refcat (STRUCT,"ports"); - ASSERT ( cat.hasKind(STRUCT) ); - ASSERT ( cat.isWithin(refcat) ); - } - - - void create_or_ref(string pID) - { - normalizeID (pID); - - PPort port1 = Port::query ("port("+pID+")"); - ASSERT (port1); - ASSERT (port1->getPortID() == pID); - - string pID2 = "another-" + pID; - PPort port2 = Port::query ("port("+pID2+")"); - ASSERT (port2); - ASSERT (port2 != port1); - Category c1 = port1->ident.category; - Category c2 = port2->ident.category; - ASSERT (c1 == c2); - - PPort port3 = Port::query ("port("+pID2+")"); - ASSERT (port3 == port2); - } - - - void create_using_default() - { - PPort port1 = Port::query (""); // "the default port" - PPort port2; - ASSERT (port1); - ASSERT (port1 == Session::current->defaults (Query())); - ASSERT (port1->ident.category.hasKind(VIDEO)); - ASSERT (port1->getProcPatt()); - PProcPatt popa = Session::current->defaults (Query("port()")); - ASSERT (popa == port1->getProcPatt()); - - // several variants to query for "the default port" - port2 = Session::current->defaults(Query ()); - ASSERT (port2 == port1); - port2 = asset::Struct::create (Query ()); - ASSERT (port2 == port1); - port2 = asset::Struct::create (Query ("port()")); - ASSERT (port2 == port1); - - string sID = popa->queryStreamID(); // sort of a "default stream type" - PPort port3 = Port::query ("stream("+sID+")"); - ASSERT (port3); - ASSERT (port3->getProcPatt()->queryStreamID() == sID); - ASSERT (port3->getProcPatt() == Session::current->defaults (Query("stream("+sID+")"))); - } - - - void dependProcPatt(string pID) - { - PPort thePort = Port::query ("port("+pID+")"); - ASSERT (thePort); - PProcPatt thePatt = thePort->getProcPatt(); - ASSERT (thePatt); - ASSERT (dependencyCheck (thePort, thePatt)); - - PProcPatt pattern2 = thePatt->newCopy("another"); - ASSERT (thePatt != pattern2); - ASSERT (!dependencyCheck (thePort, pattern2)); - TODO ("add something to the new pattern, e.g. an effect"); - - // now querying for a port using this pattern (created on-the-fly) - // note: because the pattern is new, this new port will be used as - // default port for this pattern automatically - PPort port2x = Port::query ("pattern(another)"); - ASSERT (pattern2 == port2x->getProcPatt()); - ASSERT (port2x == Session::current->defaults (Query("pattern(another)"))); - - thePort->switchProcPatt(pattern2); - ASSERT ( dependencyCheck (thePort, pattern2)); - ASSERT (!dependencyCheck (thePort, thePatt)); - - AssetManager& aMang = AssetManager::instance(); - ASSERT ( aMang.known (thePort->getID())); - ASSERT ( aMang.known (thePatt->getID())); - ASSERT ( aMang.known (pattern2->getID())); - aMang.remove (pattern2->getID()); - ASSERT ( aMang.known (thePatt->getID())); - ASSERT (!aMang.known (pattern2->getID())); - ASSERT (!aMang.known (thePort->getID())); // has been unlinked too, because dependant on pattern2 - - ASSERT (thePort); - ASSERT (thePort->getProcPatt()); - ASSERT (thePort->getProcPatt() == pattern2); // but is still valid, as long as the ref is alive.... - - PPort port3x = Port::query ("pattern(another)"); - ASSERT (port3x->getProcPatt() != pattern2); // because pattern2 is already unlinked... - ASSERT (port3x == Session::current->defaults (Query("pattern(another)"))); - ASSERT (port3x != port2x); // ..we got a new default port for "pattern(another)" too! - - - TRACE (assetmem, "leaving BasicPort_test::dependProcPatt()"); - // expect now port2x and pattern2 to be destroyed... - } - }; - - - /** Register this test class... */ - LAUNCHER (BasicPort_test, "unit asset"); - - - - } // namespace test - -} // namespace asset