diff --git a/SConstruct b/SConstruct index 31278e22b..355f2b941 100644 --- a/SConstruct +++ b/SConstruct @@ -251,7 +251,7 @@ def defineBuildTargets(env, artifacts): artifacts['plugins'] = env.SharedLibrary('$BINDIR/lumiera-plugin', plugobj) # call subdir SConscript(s) for independent components - SConscript(dirs=[SRCDIR+'/tool'], exports='env artifacts') + SConscript(dirs=[SRCDIR+'/tool'], exports='env artifacts core') SConscript(dirs=[TESTDIR], exports='env artifacts core') @@ -264,7 +264,7 @@ def definePostBuildTargets(env, artifacts): il = env.Alias('install-lib', '$DESTDIR/lib') env.Alias('install', [ib, il]) - build = env.Alias('build', artifacts['lumiera']+artifacts['plugins']) + build = env.Alias('build', artifacts['lumiera']+artifacts['plugins']+artifacts['tools']) allbu = env.Alias('allbuild', build+artifacts['testsuite']) env.Default('build') # additional files to be cleaned when cleaning 'build' diff --git a/doc/devel/.gitignore b/doc/devel/.gitignore new file mode 100644 index 000000000..96886436c --- /dev/null +++ b/doc/devel/.gitignore @@ -0,0 +1,2 @@ +,doxylog +html/* diff --git a/doc/devel/uml/class139653.html b/doc/devel/uml/class139653.html index cfdc8392a..641046544 100644 --- a/doc/devel/uml/class139653.html +++ b/doc/devel/uml/class139653.html @@ -21,7 +21,8 @@
Operation currEDL

Declaration :

The EDL currently in focus. In most cases, Session and EDL are almost the same, just EDL emphasizes the collection aspect. But generally (for larger editing projects) one Session can contain several EDLs, which may even be nested. At any given time, only one of these EDLs has focus and recieves the editing commands.

Operation getFixture

Declaration :

While the session can be comprised of several EDLs,
there is only one Fixture, which represents the actual
configuration of all Objects to be rendered

-
Relation current (<unidirectional association>)

Declaration :

Standard access path to get at the current session via the Session Manager, which acts as a "PImpl" smart pointer

+
Relation current (<unidirectional association>)

Declaration :

Standard access path to get at the current session via the Session Manager, which acts as a "PImpl" smart pointer

+
Relation defaults (<unidirectional association>)

Declaration :

All public operations : currEDL , getFixture

diff --git a/doc/devel/uml/class140549.html b/doc/devel/uml/class140549.html new file mode 100644 index 000000000..9366aa42a --- /dev/null +++ b/doc/devel/uml/class140549.html @@ -0,0 +1,26 @@ + + + + + + +Class ConfigRules + + + + + +
Class ConfigRules
+

+ + + + +

Declaration :

Directly inherited by : ResolverBase

+

public acces point for running Config Queries

+ +
Relation <association>

Declaration :

+
Relation <association>

Declaration :

+

All public operations : resolve

+ + diff --git a/doc/devel/uml/class140677.html b/doc/devel/uml/class140677.html new file mode 100644 index 000000000..6b32a5b25 --- /dev/null +++ b/doc/devel/uml/class140677.html @@ -0,0 +1,27 @@ + + + + + + +Class QueryHandler + + + + + +
Class QueryHandler
+

+ + + + +

Declaration :

Directly inherited by : ConfigRules

+
+ +
Relation <association>

Declaration :

+
Relation <association>

Declaration :

+
Operation resolve

Declaration :

+

All public operations : resolve

+ + diff --git a/doc/devel/uml/class140805.html b/doc/devel/uml/class140805.html new file mode 100644 index 000000000..a9f18e933 --- /dev/null +++ b/doc/devel/uml/class140805.html @@ -0,0 +1,26 @@ + + + + + + +Class TypeHandler + + + + + +
Class TypeHandler
+

+ + + + +

Declaration :

Directly inherited by : TypeHandler<Pipe>

+
+ +
Operation find

Declaration :

+
Operation make

Declaration :

+

All public operations : find , make

+ + diff --git a/doc/devel/uml/class140933.html b/doc/devel/uml/class140933.html new file mode 100644 index 000000000..60883f3f2 --- /dev/null +++ b/doc/devel/uml/class140933.html @@ -0,0 +1,24 @@ + + + + + + +Class ResolverBase + + + + + +
Class ResolverBase
+

+ + + + +

Declaration :

Directly inherited by : QueryHandlerImpl

+
+
+

All public operations : resolve

+ + diff --git a/doc/devel/uml/class141061.html b/doc/devel/uml/class141061.html new file mode 100644 index 000000000..db362df0b --- /dev/null +++ b/doc/devel/uml/class141061.html @@ -0,0 +1,22 @@ + + + + + + +Class YAP_Prolog + + + + + +
Class YAP_Prolog
+

+ + + + +

Declaration :

+
+ + diff --git a/doc/devel/uml/class141189.html b/doc/devel/uml/class141189.html new file mode 100644 index 000000000..ae8237f18 --- /dev/null +++ b/doc/devel/uml/class141189.html @@ -0,0 +1,31 @@ + + + + + + +Class QueryHandlerImpl + + + + + +
Class QueryHandlerImpl
+

+ + + + +

Declaration :

+ +
Relation <association>

Declaration :

+
Relation <association>

Declaration :

+
Relation <association>

Declaration :

+
Relation <association>

Declaration :

+
Operation resolve

Declaration :

+
Relation <unidirectional association>

Declaration :

+
Relation <unidirectional association>

Declaration :

+
Relation <unidirectional association>

Declaration :

+

All public operations : resolve , resolve

+ + diff --git a/doc/devel/uml/class141317.html b/doc/devel/uml/class141317.html new file mode 100644 index 000000000..96e49881c --- /dev/null +++ b/doc/devel/uml/class141317.html @@ -0,0 +1,24 @@ + + + + + + +Class TypeHandler<Pipe> + + + + + +
Class TypeHandler<Pipe>
+

+ + + + +

Declaration :

+ +
Relation <unidirectional association>

Declaration :

+

All public operations : find , make

+ + diff --git a/doc/devel/uml/class141445.html b/doc/devel/uml/class141445.html new file mode 100644 index 000000000..0f69494d7 --- /dev/null +++ b/doc/devel/uml/class141445.html @@ -0,0 +1,23 @@ + + + + + + +Class DefaultsManager + + + + + +
Class DefaultsManager
+

+ + + + +

Declaration :

+ +
Relation <association>

Declaration :

+ + diff --git a/doc/devel/uml/class141573.html b/doc/devel/uml/class141573.html new file mode 100644 index 000000000..8417d6b5b --- /dev/null +++ b/doc/devel/uml/class141573.html @@ -0,0 +1,23 @@ + + + + + + +Class DefaultsRegistry + + + + + +
Class DefaultsRegistry
+

+ + + + +

Declaration :

+ +
Relation <association>

Declaration :

+ + diff --git a/doc/devel/uml/class141701.html b/doc/devel/uml/class141701.html new file mode 100644 index 000000000..232cf2aed --- /dev/null +++ b/doc/devel/uml/class141701.html @@ -0,0 +1,20 @@ + + + + + + +Class User + + + + + +
Class User
+

+ + + + +

Declaration :

+ diff --git a/doc/devel/uml/class141829.html b/doc/devel/uml/class141829.html new file mode 100644 index 000000000..d6c42943f --- /dev/null +++ b/doc/devel/uml/class141829.html @@ -0,0 +1,20 @@ + + + + + + +Class Serializer + + + + + +
Class Serializer
+

+ + + + +

Declaration :

+ diff --git a/doc/devel/uml/classdiagrams.html b/doc/devel/uml/classdiagrams.html index 03c862119..4cf5416cc 100644 --- a/doc/devel/uml/classdiagrams.html +++ b/doc/devel/uml/classdiagrams.html @@ -27,6 +27,7 @@ Media-Asset Relations Proc-Asset Relations Render Entities +Rules access Session structure Struct-Asset Relations diff --git a/doc/devel/uml/classes.html b/doc/devel/uml/classes.html index d2f240eb9..23162b8f6 100644 --- a/doc/devel/uml/classes.html +++ b/doc/devel/uml/classes.html @@ -39,11 +39,14 @@ CompoundMediacompound of several elementary media tracks,
e.g. the individual media streams found in one media file ConditionI provided a reworked Condition class in my Cinelerra2 repository Config +ConfigRulesinterfacepublic acces point for running Config Queries ConManagerConnection Manager, used to build the connections between render engine nodes, if these nodes need to cooperate besides the normal "data pull" operation. Esp., the Connection Manager knows how to wire up the effect's parameters with the corresponding ParamProviders (autmation) in the Session Constraint ControllerFacadeboundaryProvides unified access to the Proc-Subsystem Controller. Especially, this Facade class provides the functions to get a render engine to carry out actual renderings. Datasetmeta asset describing a collection of control data DBImplementation of the registry holding all Asset instances known to the Asset Manager subsystem. As of 8/2007 implemented by a hashtable. +DefaultsManager +DefaultsRegistry DoAttach DoRecurse EDL @@ -102,13 +105,17 @@ ProcNodeinterfaceKey abstraction of the Render Engine: A Data processing Node ProcPattspecial type of structural Asset representing information how to build some part of the render engine's processing nodes network. ProjectorSpecial video processing node used to scale and translate image data. +QueryHandlerinterface +QueryHandlerImpl RelativeLocation RelTypeenumthe possible kinds of RelativePlacements RenderEngine RenderStateEncapsulates the logic used to get a "current render process" in accordance to the currentyl applicable controller settings. The provided StateProxy serves to hold any mutalbe state used in the render process, so the rest of the render engine can be stateless. +ResolverBase Scheduler Segment SegmentationToolTool implementation for deriving a partitioning of the current timeline such, that each segement has a constant configuration. "Constant" means here, that any remaining changes over time can be represented by automation solely, without the need to change the node connections. +Serializeractor SessionPrimary 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. SessionImplImplementation class for the Session interface SessManager @@ -126,13 +133,17 @@ Trackstructural asset holding the configuration of a track in the EDL Track Trafo +TypeHandlerinterface +TypeHandler<Pipe> Unknownplaceholder for unknown or unavailable media source +Useractor VFrame Visitable VRenderRepresentation of a Video render process. (Encapsulates the video buffers for the actual calculations) Wish WriteBuffer WriteBufferPool +YAP_Prolog diff --git a/doc/devel/uml/classes_list.html b/doc/devel/uml/classes_list.html index 41655bf32..6f3005da9 100644 --- a/doc/devel/uml/classes_list.html +++ b/doc/devel/uml/classes_list.html @@ -40,11 +40,14 @@ CompoundMedia
Condition
Config
+ConfigRules
ConManager
Constraint
ControllerFacade
Dataset
DB
+DefaultsManager
+DefaultsRegistry
DoAttach
DoRecurse
EDL
@@ -103,13 +106,17 @@ ProcNode
ProcPatt
Projector
+QueryHandler
+QueryHandlerImpl
RelativeLocation
RelType
RenderEngine
RenderState
+ResolverBase
Scheduler
Segment
SegmentationTool
+Serializer
Session
SessionImpl
SessManager
@@ -127,13 +134,17 @@ Track
Track
Trafo
+TypeHandler
+TypeHandler<Pipe>
Unknown
+User
VFrame
Visitable
VRender
Wish
WriteBuffer
WriteBufferPool
+YAP_Prolog
diff --git a/doc/devel/uml/collaborationdiagrams.html b/doc/devel/uml/collaborationdiagrams.html index 37350c3f2..2d8ab627d 100644 --- a/doc/devel/uml/collaborationdiagrams.html +++ b/doc/devel/uml/collaborationdiagrams.html @@ -16,6 +16,7 @@ +
"default" object
build processThis figure shows the process of building and starting a RenderEngine
diff --git a/doc/devel/uml/componentdiagrams.html b/doc/devel/uml/componentdiagrams.html index 967828869..46ed24795 100644 --- a/doc/devel/uml/componentdiagrams.html +++ b/doc/devel/uml/componentdiagrams.html @@ -17,6 +17,7 @@ +
backend-components
components
OverviewThis drawing shows the top level compoents and relations
proc-components
diff --git a/doc/devel/uml/fig131461.png b/doc/devel/uml/fig131461.png new file mode 100644 index 000000000..87241bcda Binary files /dev/null and b/doc/devel/uml/fig131461.png differ diff --git a/doc/devel/uml/fig131589.png b/doc/devel/uml/fig131589.png new file mode 100644 index 000000000..14e160602 Binary files /dev/null and b/doc/devel/uml/fig131589.png differ diff --git a/doc/devel/uml/fig131717.png b/doc/devel/uml/fig131717.png new file mode 100644 index 000000000..b45afa0c1 Binary files /dev/null and b/doc/devel/uml/fig131717.png differ diff --git a/doc/devel/uml/fig131845.png b/doc/devel/uml/fig131845.png new file mode 100644 index 000000000..da87ab8cb Binary files /dev/null and b/doc/devel/uml/fig131845.png differ diff --git a/doc/devel/uml/index.html b/doc/devel/uml/index.html index 406fc303d..bbecbcbc0 100644 --- a/doc/devel/uml/index.html +++ b/doc/devel/uml/index.html @@ -112,7 +112,7 @@ Documentation
Artifact Lumiera

Depends on common

Depends on gui

Depends on proc

Depends on backend

the main executable to be built

-

executable associated with : exitnode, pathmanager, track, paramprovider, mask, main, conmanager, clip, meta, fixedlocation, relativelocation, 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, vrender

+

executable associated with : 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, vrender, exitnode, pathmanager, track, paramprovider, mask, main, conmanager, clip, meta, fixedlocation, relativelocation, mobject, source, frame, placement, sessionimpl, builderfacade, controllerfacade, processor, pluginadapter, effect, buildertool, segmentationtool

Artifact main

Artifact source

@@ -1137,8 +1137,71 @@ reuse exiting Engine

Selection :

Transformation

GUI is here just a container to hold any entities considered to be User Interface related, which is not in focus for this Design draft

5 Package CommonLib

+ +

5.1 Package ConfigQuery

+
+ +

5.1.1 Component View Query System overview

+
+ +

+

components



+ +
Component ConfigRules
+

A system for accessing various kinds of preconfigured objects by querying for capabilities.

+ +
Component Resolver
+ +
Component Rule Base
+ +
Component DefaultsManager
+
+ +

5.1.2 Class View query

+
+ +

+

Rules access



+
+
+
+
+
+
+
+
+
+
+ +

5.1.3 Use Case View query use

+
+ +

+

when to query



+ +

5.1.3.1 Use Case create specific object

+ +

5.1.3.2 Use Case use "default" object

+
+
+ +

5.1.3.3 Use Case load object from session

+ +

5.1.3.4 Use Case add new object to session

+
Class User
+
+ +

5.1.3.5 Use Case ConfigQuery

+ +

5.1.3.6 Use Case need sub object

+ +

+

"default" object



+ +
Class instance predicate impl

type :TypeHandler

+
-

5.1 Class View error

+

5.2 Class View error

@@ -1152,7 +1215,7 @@ reuse exiting Engine

Selection :

Transformation

-

5.2 Class View Service Components

+

5.3 Class View Service Components

Class Tool
@@ -1162,7 +1225,7 @@ reuse exiting Engine

Selection :

Transformation
Class Appconfig

-

5.3 Class View Posix Threads Abstraction

+

5.4 Class View Posix Threads Abstraction

C++ wrapers for pthreads

Class Thread
@@ -1170,7 +1233,7 @@ reuse exiting Engine

Selection :

Transformation
Class Mutex

-

5.4 Class View SmartPointers

+

5.5 Class View SmartPointers

diff --git a/doc/devel/uml/index_34.html b/doc/devel/uml/index_34.html new file mode 100644 index 000000000..54f1d1d1f --- /dev/null +++ b/doc/devel/uml/index_34.html @@ -0,0 +1,23 @@ + + + + + + +" + + + + + +
"
+

+ + + + + + +
NameKindDescription
"default" objectcollaboration diagram
+ + diff --git a/doc/devel/uml/index_60.html b/doc/devel/uml/index_60.html index a873c25b0..4909e634c 100644 --- a/doc/devel/uml/index_60.html +++ b/doc/devel/uml/index_60.html @@ -30,8 +30,8 @@ <flow>transition <flow>transition <flow>transition -<flow>transition <flow>transition +<flow>transition <flow>transition <flow>transition <flow>transition diff --git a/doc/devel/uml/index_65.html b/doc/devel/uml/index_65.html index cb80221e6..3fce72879 100644 --- a/doc/devel/uml/index_65.html +++ b/doc/devel/uml/index_65.html @@ -23,6 +23,7 @@ access Fileuse case activity finalactivity final activity finalactivity final +add new object to sessionuse case AFrameclass aframeartifacta buffer and render process holding a Audio frame allocationartifact @@ -55,8 +56,8 @@ aud_aclass instance audioclass instance audio1class instance -audio1class instance audio1class instance +audio1class instance autoartifactMedia Object holding automation data AutoclassAutomation data for some parameter (i.e. a time varying function) Automation Entitiesclass diagram diff --git a/doc/devel/uml/index_67.html b/doc/devel/uml/index_67.html index 93dc372e2..08c04b765 100644 --- a/doc/devel/uml/index_67.html +++ b/doc/devel/uml/index_67.html @@ -23,42 +23,42 @@ Categoryclasstree like classification of Assets categoryartifacttree like classification of Assets causeattributea copy of the first exception encountered in this exception chain -chainoperationcreate and add another Placement for this media object, thus increasingly constraining the (possible) position of this object. chainrelationChain of additional Placements further constraining the position of this MObject +chainoperationcreate and add another Placement for this media object, thus increasingly constraining the (possible) position of this object. checked_inrelationchecked_in objects are subject of cache aging and must be not in use checked_outrelationthis list keeps all mappings which are in use, and thus prevents them from Cache aging -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. -clipartifacta Media Clip clipartifactbookkeeping (asset) view of a media clip. +clipartifacta Media Clip Clipclass clipsrelation Codecclassdescription of some media data decoder or encoder facility @@ -71,6 +71,7 @@ CommonLibpackage complete Render Engineactivity object componentsrelation +componentscomponent diagram compoundclipartifactcompound of several clips (multichannel) CompoundClipclassClip MObject which is actually a compound of several elementary clips,
e.g. the several streams found within multichannels media. CompoundMediaclasscompound of several elementary media tracks,
e.g. the individual media streams found in one media file @@ -78,6 +79,10 @@ ConditionclassI provided a reworked Condition class in my Cinelerra2 repository Configclass config examplesuse case view +ConfigQuerypackage +ConfigQueryuse case +ConfigRulesclasspublic acces point for running Config Queries +ConfigRulescomponentA system for accessing various kinds of preconfigured objects by querying for capabilities. configureoperation configure Renderactivity configure Toolsopaque activity action @@ -88,14 +93,15 @@ constraintartifactLocatingPin representing an directive by the user that
must not be violated Constraintclass Controllercomponent -controllerpackagesourcecode package

The Processing and Render Controller,
located within the MObject Subsystem Controllerpackage +controllerpackagesourcecode package

The Processing and Render Controller,
located within the MObject Subsystem Controller Entitiesclass diagram Controller Workingsclass view ControllerFacadeclassProvides unified access to the Proc-Subsystem Controller. Especially, this Facade class provides the functions to get a render engine to carry out actual renderings. controllerfacadeartifactFacade and service access point for the Proc Layer Controller ControllerFacadecomponent create ProcNodeopaque activity action +create specific objectuse case createClipoperationcreate a (possibly compound) Clip refering to this media, ready to be added to the EDL. currEDLoperationThe EDL currently in focus. In most cases, Session and EDL are almost the same, just EDL emphasizes the collection aspect. But generally (for larger editing projects) one Session can contain several EDLs, which may even be nested. At any given time, only one of these EDLs has focus and recieves the editing commands. currentrelationStandard access path to get at the current session via the Session Manager, which acts as a "PImpl" smart pointer diff --git a/doc/devel/uml/index_68.html b/doc/devel/uml/index_68.html index 68da1dfbd..90bc7ba4d 100644 --- a/doc/devel/uml/index_68.html +++ b/doc/devel/uml/index_68.html @@ -22,14 +22,18 @@ datasrcrelationThe predecessor in a processing pipeline, i.e. a source to get data to be processed DBclassImplementation of the registry holding all Asset instances known to the Asset Manager subsystem. As of 8/2007 implemented by a hashtable. dbartifactregistry holding known Asset instances. +defaultsrelation +DefaultsManagerclass +DefaultsManagercomponent +DefaultsRegistryclass define segmentopaque activity action descriptorrelationtype of this frame descriptorrelation 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 Paramsopaque activity action determine Render Paramsexpansion region +determine Render Paramsopaque activity action devnullclass instance Dispatchercomponent dispatchOpoperation diff --git a/doc/devel/uml/index_69.html b/doc/devel/uml/index_69.html index 1f6fd3f19..6c17d406d 100644 --- a/doc/devel/uml/index_69.html +++ b/doc/devel/uml/index_69.html @@ -24,8 +24,8 @@ 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 diff --git a/doc/devel/uml/index_70.html b/doc/devel/uml/index_70.html index b36d60aff..78b986b1b 100644 --- a/doc/devel/uml/index_70.html +++ b/doc/devel/uml/index_70.html @@ -29,12 +29,13 @@ FileProviderclassThis is the Factory for Files, whenever something wants to use some file (or temporary storage), This Factory will hand out some smart/shared pointer to a File object which will be used to retrieve Frames. FileReferenceclass filesrelation +findoperation fixedlocationartifactimplements fixed placement of a MObject 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 diff --git a/doc/devel/uml/index_72.html b/doc/devel/uml/index_72.html index bf8262c8c..0abaaac68 100644 --- a/doc/devel/uml/index_72.html +++ b/doc/devel/uml/index_72.html @@ -24,8 +24,8 @@ howtoProcoperation@return descriptor how to build a render pipeline corresponding to this media Hubclass hubartifactspecial ProcNode used to build data distributing connections -HUEclass instance HUEclass instance +HUEclass instance diff --git a/doc/devel/uml/index_73.html b/doc/devel/uml/index_73.html index 27e37a604..798945020 100644 --- a/doc/devel/uml/index_73.html +++ b/doc/devel/uml/index_73.html @@ -20,9 +20,9 @@ idattributeAsset primary key. In Memory Databaseclass diagram inFixtureactivity action pin -inputclass instance inputclass instance inputclass instance +inputclass instance instanceoperation instructionsrelation Interfaceclass view diff --git a/doc/devel/uml/index_76.html b/doc/devel/uml/index_76.html index 0b4ef97db..75cbabe50 100644 --- a/doc/devel/uml/index_76.html +++ b/doc/devel/uml/index_76.html @@ -25,6 +25,7 @@ linkartifactforwarding, adapting or connecting ProcNode loadoperationreplace the current session by a new
session loaded from serialized state. load Mediause case +load object from sessionuse case locatingpinartifactChaining and constraining the Placement of a Media Object LocatingPinclassAn element with value semantics, which actually implements the placement of some MObject by positioning it in some way. Lockclass diff --git a/doc/devel/uml/index_77.html b/doc/devel/uml/index_77.html index 3e0b915cc..e6d8e8031 100644 --- a/doc/devel/uml/index_77.html +++ b/doc/devel/uml/index_77.html @@ -18,6 +18,7 @@ + diff --git a/doc/devel/uml/index_78.html b/doc/devel/uml/index_78.html index eeaf4b78d..1cf51971d 100644 --- a/doc/devel/uml/index_78.html +++ b/doc/devel/uml/index_78.html @@ -18,6 +18,7 @@
NameKindDescription
mainartifact
makeoperation
mappingrelation
mappingsrelationweak pointers
Maskclass
+ diff --git a/doc/devel/uml/index_79.html b/doc/devel/uml/index_79.html index d1fdc83c0..4ac4c3b33 100644 --- a/doc/devel/uml/index_79.html +++ b/doc/devel/uml/index_79.html @@ -19,9 +19,9 @@ - + diff --git a/doc/devel/uml/index_80.html b/doc/devel/uml/index_80.html index 2b01f816d..ba34ae763 100644 --- a/doc/devel/uml/index_80.html +++ b/doc/devel/uml/index_80.html @@ -40,6 +40,7 @@ + diff --git a/doc/devel/uml/index_81.html b/doc/devel/uml/index_81.html new file mode 100644 index 000000000..5a521bd2f --- /dev/null +++ b/doc/devel/uml/index_81.html @@ -0,0 +1,27 @@ + + + + + + +Q + + + + + +
Q
+

+ + + +
NameKindDescription
nameattributeelement ID, comprehensible but sanitized. The tuple (category, name, org) is unique.
need sub objectuse case
nextrelationnext additional LocatingPin, if any
nodecreatertoolartifactcentral Tool implementing the Renderengine building
NodeCreatorToolclassThis Tool implementation plays the central role in the buld process: given a MObject from Session, it is able to attach ProcNodes to the render engine under construction such as to reflect the properties of the MObject in the actual render.
NameKindDescription
offsetattributeOffset the actual position by this (time) value relative to the anchor point. TODO: Representation?
orgattributeorigin or authorship id. Can be a project abbreviation, a package id or just the authors nickname or UID. This allows for the compnent name to be more generic (e.g. "blur"). Default for all assets provided by the core Lumiera codebase is "lumi".
ouputclass instance
ouputclass instance
ouputclass instance
ouputclass instance
outPortrelationthe Port this MObject wants to be conected to
outputrelation
Overviewcomponent diagramThis drawing shows the top level compoents and relations
pnodenode
pointattributeidentifying the point where the nodes should be attached
Posix Threads Abstractionclass viewC++ wrapers for pthreads
predicate implclass instance
Prefetchclass
Previewclassalternative version of the media data, probably with lower resolution
previewartifactalternative version of the media data, probably with lower resolution
+ + + + + + +
NameKindDescription
queryclass view
Query System overviewcomponent view
query useuse case view
QueryHandlerclass
QueryHandlerImplclass
+ + diff --git a/doc/devel/uml/index_82.html b/doc/devel/uml/index_82.html index a76e8f590..1bade53e8 100644 --- a/doc/devel/uml/index_82.html +++ b/doc/devel/uml/index_82.html @@ -22,8 +22,8 @@ registryrelation@internal Table or DB holding all registered asset instances. relativelocationartifactPlacement implemnetaion providing various ways of attaching a MObject to another one RelativeLocationclass -relTypeattributethe kind of relation denoted by this Placement RelTypeclassthe possible kinds of RelativePlacements +relTypeattributethe kind of relation denoted by this Placement removeoperationremove the given asset <i>together with all its dependants</i> from the internal DB Render Entitiesclass diagram Render Requestactivity parameter @@ -38,7 +38,13 @@ reprattributehuman readable representation of the condition characterizing this allocaton, e.g. "t >= 10" resetoperationreset all session config and
start with a pristine default session. resolveoperationcreate an actual (explicit) placement while trying to satisfy the network of adjacent objects and placements. +resolveoperation +resolveoperation +Resolvercomponent +ResolverBaseclass rootCauseoperationIf this exception was caused by a chain of further exceptions,
return the first one registered in this throw sequence.
This works only, if every exceptions thrown as a consequence
of another exception is propperly constructed by passing
the original exception to the constructor +Rule Basecomponent +Rules accessclass diagram diff --git a/doc/devel/uml/index_83.html b/doc/devel/uml/index_83.html index 18c49405b..e2f2fcea3 100644 --- a/doc/devel/uml/index_83.html +++ b/doc/devel/uml/index_83.html @@ -28,11 +28,12 @@ segmentsactivity object segmentsactivity object segmentsrelationthe partitioning of the Timeline to be created by this tool. +Serializerclass Service Componentsclass view Sessioncomponent sessionartifactInterface: the session edited by the user -sessionpackagesourcecode package

Everything concerning the EDL and Session, within the MObject Subsystem Sessionclass view +sessionpackagesourcecode package

Everything concerning the EDL and Session, within the MObject Subsystem 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 diff --git a/doc/devel/uml/index_84.html b/doc/devel/uml/index_84.html index 692cb2cac..14d928057 100644 --- a/doc/devel/uml/index_84.html +++ b/doc/devel/uml/index_84.html @@ -34,21 +34,23 @@ trackrelation trackattribute trackrelation -trackartifactstructural asset holding the configuration of a track in the EDL 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.
+trackartifactstructural asset holding the configuration of a track in the EDL 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 +TypeHandlerclass +TypeHandler<Pipe>class diff --git a/doc/devel/uml/index_85.html b/doc/devel/uml/index_85.html index 6075e15d1..dafc717cb 100644 --- a/doc/devel/uml/index_85.html +++ b/doc/devel/uml/index_85.html @@ -20,7 +20,9 @@ Unknownclassplaceholder for unknown or unavailable media source unknownartifactplaceholder for unknown or unavailable media source usageuse case view +use "default" objectuse case useFileoperationAnnounces that the application intends to use this file with mode (READ|WRITE|READWRITE) +Userclass useTemporaryStorageoperationProvides a pool for interminate frames diff --git a/doc/devel/uml/index_86.html b/doc/devel/uml/index_86.html index f75b93690..e3c5f01a9 100644 --- a/doc/devel/uml/index_86.html +++ b/doc/devel/uml/index_86.html @@ -20,23 +20,23 @@ versionattributeversion number of the thing or concept represented by this asset. Of each unique tuple (name, category, org) there will be only one version in the whole system. Version 0 is reserved for internal purposes. Versions are considered to be ordered, and any higher version is supposed to be fully backwards compatible to all previous versions. VFrameclass vframeartifacta buffer and render process holding a Video frame -vid1class instance vid1class instance -vid_aclass instance -vid_aclass instance -vid_Aclass instance +vid1class 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 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 748f57b37..bd2bf3399 100644 --- a/doc/devel/uml/index_87.html +++ b/doc/devel/uml/index_87.html @@ -19,6 +19,7 @@ NameKindDescription whatoperation whatoperationthe base class of all exceptions thrown by the standard library +when to queryuse case diagram wiringTemplaterelation wishartifactLocatingPin representing a low-priority directive by the user,
to be fulfilled only if possible (and after satisfying the
more important LocatingPins) Wishclass diff --git a/doc/devel/uml/index_89.html b/doc/devel/uml/index_89.html new file mode 100644 index 000000000..bb8528187 --- /dev/null +++ b/doc/devel/uml/index_89.html @@ -0,0 +1,23 @@ + + + + + + +Y + + + + + +
Y
+

+ + + + + + +
NameKindDescription
YAP_Prologclass
+ + diff --git a/doc/devel/uml/navig.html b/doc/devel/uml/navig.html index 74b812388..fd08b1b7d 100644 --- a/doc/devel/uml/navig.html +++ b/doc/devel/uml/navig.html @@ -12,6 +12,6 @@

-Top- -Classes- -Public Operations- -Public properties- -Packages- -Use Cases- -Activities- -Class Diagrams- -Object Diagrams- -Activity Diagrams- -Use Case Diagrams- -Collaboration Diagrams- -Component Diagrams- -Deployment Diagrams-

-

< A B C D E F G H I K L M N O P R S T U V W ~

+

" < A B C D E F G H I K L M N O P Q R S T U V W Y ~

diff --git a/doc/devel/uml/packages.html b/doc/devel/uml/packages.html index c9321815b..49c0f4f80 100644 --- a/doc/devel/uml/packages.html +++ b/doc/devel/uml/packages.html @@ -25,6 +25,7 @@ codegenThis package is used to organize code generation by BOUML. It is considered useless after having generated the initial code skeleton. commonsrcsourcecode package

Common library and helper classes CommonLib +ConfigQuery Controller controllersrcsourcecode package

The Processing and Render Controller,
located within the MObject Subsystem design diff --git a/doc/devel/uml/public_operations.html b/doc/devel/uml/public_operations.html index d0aedd4c7..697d67b52 100644 --- a/doc/devel/uml/public_operations.html +++ b/doc/devel/uml/public_operations.html @@ -29,6 +29,7 @@ currEDLSessionThe EDL currently in focus. In most cases, Session and EDL are almost the same, just EDL emphasizes the collection aspect. But generally (for larger editing projects) one Session can contain several EDLs, which may even be nested. At any given time, only one of these EDLs has focus and recieves the editing commands. dispatchOpVisitable enableAssetchange the enabled status of this asset. Note the corresponding #isActive predicate may depend on the enablement status of parent assets as well +findTypeHandler getAppconfigaccess the configuation value for a given key.
@return empty string for unknown keys, else the corresponding configuration value get_reprAllocation getAssetAssetManagerfind and return corresponging object @@ -48,20 +49,23 @@ isActiveAssetweather this asset is swithced on and consequently included in the fixture and participates in rendering knownAssetManager@return true if the given id is registered in the internal asset DB loadSessManagerreplace the current session by a new
session loaded from serialized state. +makeTypeHandler playRenderEngineTODO: will probably be handled differently (see Cehteh) removeAssetManagerremove the given asset <i>together with all its dependants</i> from the internal DB resetSessManagerreset all session config and
start with a pristine default session. resolvePlacementcreate an actual (explicit) placement while trying to satisfy the network of adjacent objects and placements. +resolveQueryHandler +resolveQueryHandlerImpl rootCauseErrorIf this exception was caused by a chain of further exceptions,
return the first one registered in this throw sequence.
This works only, if every exceptions thrown as a consequence
of another exception is propperly constructed by passing
the original exception to the constructor saveSessManagercreate a complete, serialized representation
of the current session config and contents.
@todo how to serialize, prameters, return value? treatApplicable treatBuilderToolThis operation is to be overloaded for the specific MObject subclasses to be treated. +treatNodeCreatorTool treatNodeCreatorTool treatNodeCreatorTool treatNodeCreatorTool -treatNodeCreatorTool -treatSegmentationTool treatSegmentationTool +treatSegmentationTool treatSegmentationTool useFileFileProviderAnnounces that the application intends to use this file with mode (READ|WRITE|READWRITE) useTemporaryStorageFileProviderProvides a pool for interminate frames diff --git a/doc/devel/uml/usecasediagrams.html b/doc/devel/uml/usecasediagrams.html index 62cd42a0e..c6ce03c64 100644 --- a/doc/devel/uml/usecasediagrams.html +++ b/doc/devel/uml/usecasediagrams.html @@ -17,6 +17,7 @@ +
backend use cases
when to query
diff --git a/doc/devel/uml/usecases.html b/doc/devel/uml/usecases.html index d55241488..9b7d44a88 100644 --- a/doc/devel/uml/usecases.html +++ b/doc/devel/uml/usecases.html @@ -18,8 +18,14 @@ + + + + + +
access Channel
access File
add new object to session
ConfigQuery
create specific object
detect Channels
load Media
load object from session
need sub object
use "default" object
diff --git a/src/common/appconfig.cpp b/src/common/appconfig.cpp index 612376022..17a245cdf 100644 --- a/src/common/appconfig.cpp +++ b/src/common/appconfig.cpp @@ -37,13 +37,6 @@ using util::isnil; namespace lumiera { - /** This internal pointer to the single instance is deliberately - * not initialized (i.e. rely on implicit initialisation to 0), - * because when static init reaches this definition, the - * Appconfig::instance() probably already has been called - * by another compilation unit. This is ugliy, but preferable - * to beeing dependant on inclusion order of headers. */ -// scoped_ptr Appconfig::theApp_; #ifndef LUMIERA_VERSION #define LUMIERA_VERSION 3++devel diff --git a/src/common/configrules.cpp b/src/common/configrules.cpp new file mode 100644 index 000000000..3a1ae1bdd --- /dev/null +++ b/src/common/configrules.cpp @@ -0,0 +1,71 @@ +/* + ConfigRules - interface for rule based configuration + + Copyright (C) Lumiera.org + 2008, 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/configrules.hpp" +#include "common/query/mockconfigrules.hpp" +//#include "common/util.hpp" +#include "nobugcfg.h" + + + +namespace lumiera + { + + namespace query + { + + LUMIERA_ERROR_DEFINE (CAPABILITY_QUERY, "unresolvable capability query"); + + + + } // 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 query + { + namespace // local definitions: implementing a backdoor for tests + { + string fakeBypass; + } + + void setFakeBypass(string const& q) { fakeBypass = q; } + bool isFakeBypass (string const& q) { return q == fakeBypass; } + + } // namespace query + + + +} // namespace lumiera diff --git a/src/common/configrules.hpp b/src/common/configrules.hpp new file mode 100644 index 000000000..81da041ae --- /dev/null +++ b/src/common/configrules.hpp @@ -0,0 +1,240 @@ +/* + CONFIGRULES.hpp - interface for rule based configuration + + Copyright (C) Lumiera.org + 2008, 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 configrules.hpp + ** Interface for accessing rule based configuration. + ** By using the Query template, you can pose a query in prolog syntax and get some + ** existing or newly created object fulfilling the requested predicates. The actual + ** implementation is hidden behind the #instance (Singleton factory). As of 1/2008, + ** it is \e planned to use an embedded YAP Prolog system at some point in the future, + ** for now we use a \link MockConfigRules mock implementation \endlink employing a + ** preconfigured Map. + ** + ** Fully implementing this facility would require the participating objects to register capabilities + ** 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 lumiera::Query + ** @see mobject::session::DefsManager + ** @see asset::StructFactory + ** + */ + + +#ifndef LUMIERA_CONFIGRULES_H +#define LUMIERA_CONFIGRULES_H + +#include "common/query.hpp" +#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 convenient...) +#include "proc/mobject/session/track.hpp" +#include "proc/asset/procpatt.hpp" +#include "proc/asset/pipe.hpp" +#include "proc/asset/track.hpp" + +#include +#include + + + +namespace lumiera + { + using std::string; + using std::tr1::shared_ptr; + + + + + namespace query + { + // The intention is to support the following style of Prolog code + // + // resolve(O, Cap) :- find(O), capabilities(Cap). + // resolve(O, Cap) :- make(O), capabilities(Cap). + // capabilities(Q) :- call(Q). + // + // stream(T, mpeg) :- type(T, track), type(P, pipe), resolve(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 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 + { + + }; + + + template + < const Symbol SYM, // Predicate symbol + typename SIG = bool(string) // Signature + > + class Pred + { + + }; + + /** + * 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. + * @todo it can't be done exactly this way, but I leave it in + * as a reminder for later, to show the intention + */ + template + class TypeHandler + { + static const TY NIL; + + template + TY find (Pred capability); + + 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. + * (this code works and is already used 2/2008) + * @see lumiera::query::LookupPreconfigured + * @see lumiera::query::MockTable + */ + template + class QueryHandler + { + protected: + virtual ~QueryHandler() { } + public: + /** try to find or create an object of type TY + * fulfilling the given query. + * @param solution object fulfilling the query. Will be bound or + * unified (in case it's already bound) with the first solution. + * @query any goals to be fulfilled by the solution. + * @return false if resolution failed. In this case, solution ptr is empty. + */ + virtual bool resolve (shared_ptr& solution, const Query& q) = 0; + }; + + // 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. + // Of course then the definitions need to be split up in separate headers. + + + + + + /** + * Generic query interface for retrieving objects matching + * some capability query. To be instantiated using a typelist, + * thus inheriting from the Handler classes for each type. In + * the (future) version using YAP Prolog, this will drive the + * generation and registration of the necessary predicate + * implementations for each concrete type, using the speicalisations + * given alongside with the types. For now it just serves to generate + * the necessary resolve(Query) virtual functions (implemented + * by MockConfigRules) + */ + template + class ConfigRules + : public typelist::InstantiateForEach + { + protected: + ConfigRules () {} + virtual ~ConfigRules() {} + + public: + // TODO: find out what operations we need to support here for the »real solution« (using Prolog) + }; + + + + + LUMIERA_ERROR_DECLARE (CAPABILITY_QUERY); ///< unresolvable capability query. + + } // namespace query + + + + + + /* ============= global configuration ==================== */ + + /** + * the list of all concrete types participating in the + * rule based config query system + */ + typedef lumiera::typelist::Types < mobject::session::Track + , asset::Track + , asset::Pipe + , const asset::ProcPatt + > ::List + InterfaceTypes; + + /** + * user-visible Interface to the ConfigRules subsystem. + * Configured as Singleton (with hidden Implementation class) + */ + class ConfigRules + : public query::ConfigRules + { + + public: + static SingletonSub instance; + + }; + + + + + namespace query + { + + /** backdoor for tests: the next config query with this query string + * will magically suceed with every candidate object provided. This + * is currently necessary to get objects into the defaults manager, + * as the query system is not able to do real query resolution */ + void setFakeBypass(string const& q); + bool isFakeBypass (string const& q); + + } // namespace query + +} // namespace lumiera +#endif diff --git a/src/common/error.hpp b/src/common/error.hpp index 4ccb8b1d7..71e5f79dc 100644 --- a/src/common/error.hpp +++ b/src/common/error.hpp @@ -162,10 +162,10 @@ namespace lumiera */ #ifdef NOBUG_ABORT #undef NOBUG_ABORT -#define CIN_NOBUG_LOCATION \ +#define LUMIERA_NOBUG_LOCATION \ std::string (NOBUG_BASENAME(__FILE__)) +":"+ NOBUG_STRINGIZE(__LINE__) + ", function " + __func__ #define NOBUG_ABORT \ - lumiera::error::assertion_terminate (CIN_NOBUG_LOCATION); + lumiera::error::assertion_terminate (LUMIERA_NOBUG_LOCATION); #endif diff --git a/src/common/multithread.hpp b/src/common/multithread.hpp index 1dbbac519..0e936964c 100644 --- a/src/common/multithread.hpp +++ b/src/common/multithread.hpp @@ -27,6 +27,7 @@ #define LUMIERA_MULTITHREAD_H #include "nobugcfg.h" +#include "common/util.hpp" namespace lumiera diff --git a/src/common/p.hpp b/src/common/p.hpp new file mode 100644 index 000000000..d4cc2f11c --- /dev/null +++ b/src/common/p.hpp @@ -0,0 +1,128 @@ +/* + P.hpp - customized shared_ptr with ordering and type relationships + + Copyright (C) Lumiera.org + 2008, 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 p.hpp + ** customized refcounting smart pointer. + ** Template derived from std::tr1::shared_ptr adding total ordering and + ** type relationships implemented by forwarding to the pointees. In all other + ** respects, it should behave exactly as shared_ptr and is able to cooperate + ** and share ownership with other shared_ptr instantiations. + ** + ** By default different instantiations of shared_ptr are completely unrelated types, + ** even if using inherintance related type parameters for instantiation: a shared_ptr + ** isn't some kind-of shared_ptr -- we need to do an explicit static_ptr_cast. Another + ** common problem is the definition of equality and ordering relations for shared_ptr: + ** equality is based on the equality of the managed pointers, while ordering is built upon + ** the ref count. While generally this may be a good compromise, in our case it hinders treating + ** the smart ptrs within the application almost as if they were the objects themselfs and proved + ** an obstacle for writing generic helper functions. + ** + ** the P template resolves these problems by implementing the ordering operators in terms of + ** the corresponding operators on the pointee and by allowing to specify a base class smart-ptr + ** as template parameter. + ** + ** @see asset.hpp + ** @see customsharedptrtest.cpp + ** @see orderingofassetstest.cpp + */ + + +#ifndef LUMIERA_P_H +#define LUMIERA_P_H + + +#include + + +namespace lumiera + { + using std::tr1::shared_ptr; + using std::tr1::weak_ptr; + + /** + * customized refcounting smart pointer template, built upon + * std::tr1::shared_ptr, but forwarding type relationships and + * ordering operators to the pointee objects. + * @param TAR the visible pointee type + * @param the shared-ptr type used as implementation + * @note if the BASE smart-ptr type used as implementation + * implies another pointer type than the one used on + * the interface (=type TAR), then every access to the + * pointee causes an dynamic cast. Thus the pointee types + * need to support RTTI. + */ + template > + class P + : public BASE + { + public: + P ( ) : BASE() {} + template explicit P (Y* p) : BASE(p) {} + template P (Y* p, D d) : BASE(p,d){} + + P (P const& r) : BASE(r) {} + template P (shared_ptr const& r) : BASE(r) {} + template explicit P (weak_ptr const& wr) : BASE(wr) {} + template explicit P (std::auto_ptr & ar) : BASE(ar) {} + + + P& operator= (P const& r) { BASE::operator= (r); return *this; } + template P& operator=(shared_ptr const& sr) { BASE::operator= (sr); return *this; } + template P& operator=(std::auto_ptr & ar) { BASE::operator= (ar); return *this; } + + TAR* get() const { return dynamic_cast (BASE::get()); } + TAR& operator*() const { return *get(); } + TAR* operator->() const { return get(); } + + void swap(P& b) { BASE::swap (b);} + + + private: /* === friend operators injected into enclosing namespace for ADL === */ + template + friend inline bool + operator== (P const& p, P<_O_> const& q) { return (p && q)? (*p == *q) : (!p && !q); } + + template + friend inline bool + operator!= (P const& p, P<_O_> const& q) { return (p && q)? (*p != *q) : !(!p && !q); } + + template + friend inline bool + operator< (P const& p, P<_O_> const& q) { return (p && q) && (*p < *q); } + + template + friend inline bool + operator> (P const& p, P<_O_> const& q) { return (p && q) && (*q < *p); } + + template + friend inline bool + operator<= (P const& p, P<_O_> const& q) { return (p && q)? (*p <= *q) : (!p && !q); } + + template + friend inline bool + operator>= (P const& p, P<_O_> const& q) { return (p && q)? (*p >= *q) : (!p && !q); } + + }; + + +} // namespace lumiera +#endif diff --git a/src/common/query.cpp b/src/common/query.cpp new file mode 100644 index 000000000..67873a5e8 --- /dev/null +++ b/src/common/query.cpp @@ -0,0 +1,150 @@ +/* + Query - interface for capability queries + + Copyright (C) Lumiera.org + 2008, 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/query.hpp" +#include "common/util.hpp" +#include "nobugcfg.h" + +#include +#include +#include + +using std::map; +using boost::regex; +using boost::smatch; +using boost::regex_search; +using boost::sregex_iterator; + +using util::contains; +using util::isnil; + + +namespace lumiera + { + + namespace query + { + + namespace // local definitions + { + typedef boost::function ChPredicate; + + ChPredicate is_alpha = boost::algorithm::is_alpha(); + ChPredicate is_upper = boost::algorithm::is_upper(); + } // local defs + + + void + normalizeID (string& id) + { + id = util::sanitize(id); + if (isnil(id) || !is_alpha (id[0])) + id.insert(0, "o"); + + + REQUIRE (!isnil(id)); + REQUIRE (is_alpha (id[0])); + + char first = id[0]; + if (is_upper (first)) + id[0] = std::tolower (first); + } + + + + + namespace // Implementation details + { + map regexTable; + + Symbol matchArgument = "\\(\\s*([\\w_\\.\\-]+)\\s*\\),?\\s*"; + regex findPredicate (string("(\\w+)")+matchArgument); + + inline regex& + getTermRegex (Symbol sym) + { + if (!contains (regexTable, sym)) + regexTable[sym] = regex (string(sym)+=matchArgument); + return regexTable[sym]; + } + } + + /** (preliminary) helper: instead of really parsing and evaluating the terms, + * just do a regular expression match to extract the literal argument + * behind the given predicate symbol. e.g calling + * queryID ("stream", "id(abc), stream(mpeg)") + * yields "mpeg" + */ + const string + extractID (Symbol sym, const string& termString) + { + smatch match; + if (regex_search (termString, match, getTermRegex (sym))) + return (match[1]); + else + return ""; + } + + + /** (preliminary) helper: cut a term with the given symbol. + * The term is matched, removed from the original string and returned + * @note parameter termString will be modified! + */ + const string + removeTerm (Symbol sym, string& termString) + { + smatch match; + if (regex_search (termString, match, getTermRegex (sym))) + { + string res (sym); res += "("+match[1]+")"; + termString.erase (match.position(), match[0].length()); + return res; + } + else + return ""; + } + + + /** @note this is a very hackish preliminary implementation. + * The regex used will flounder when applied to nested terms. + * We need a real parser for predicate logic terms (which we + * probably get for free when we embed a prolog system)... + */ + uint + countPraed (const string& q) + { + uint cnt (0); + sregex_iterator end; + for (sregex_iterator i (q.begin(),q.end(), findPredicate); + i != end; ++i) + ++cnt; + return cnt; + } + + } // namespace query + + + /** */ + + +} // namespace lumiera diff --git a/src/common/query.hpp b/src/common/query.hpp new file mode 100644 index 000000000..db76259db --- /dev/null +++ b/src/common/query.hpp @@ -0,0 +1,89 @@ +/* + QUERY.hpp - interface for capability queries + + Copyright (C) Lumiera.org + 2008, 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. + +*/ + + +#ifndef LUMIERA_QUERY_H +#define LUMIERA_QUERY_H + + +#include +#include + +#include + + +namespace lumiera + { + using std::string; + using boost::format; + + /* ==== comon definitions for rule based queries ==== */ + + typedef const char * const Symbol; + + + /** + * Generic query interface for retrieving objects matching + * some capability query + */ + template + class Query : public std::string + { + public: + explicit Query (const string& predicate="") : string(predicate) {} + explicit Query (format& pattern) : string(str(pattern)) {} + + const string asKey() const + { + return string(typeid(OBJ).name())+": "+*this; + } + + operator string& () { return *this; } // TODO: needed temporarily by mockconfigrules + }; // for calling removeTerm on the string-ref.... + + + namespace query + { + + /** ensure standard format for a given id string. + * Trim, sanitize and ensure the first letter is lower case. + * @note modifies the given string ref in place + */ + void normalizeID (string& id); + + + /** count the top-level predicates in the query string. + * usable for ordering queries, as more predicates usually + * mean more conditions, i.e. more constriction + */ + uint countPraed (const string&); + + + const string extractID (Symbol, const string& termString); + + const string removeTerm (Symbol, string& termString); + + + } // namespace query + +} // namespace lumiera +#endif diff --git a/src/common/query/mockconfigrules.cpp b/src/common/query/mockconfigrules.cpp new file mode 100644 index 000000000..c8b9f774b --- /dev/null +++ b/src/common/query/mockconfigrules.cpp @@ -0,0 +1,202 @@ +/* + MockConfigRules - mock implementation of the config rules system + + Copyright (C) Lumiera.org + 2008, 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/query/mockconfigrules.hpp" + +#include "proc/mobject/session/track.hpp" +#include "proc/asset/procpatt.hpp" +#include "proc/asset/pipe.hpp" + + +#include "common/util.hpp" +#include "nobugcfg.h" + +using util::isnil; + + +namespace lumiera + { + + namespace query + { + using asset::Struct; + using asset::Pipe; + using asset::PPipe; + + 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.asKey(), obj); + } + + /** shortcut for simply accessing a table entry */ + template + any& + item (PTAB& table, const string& query) + { + return (*table)[Query(query).asKey()]; + } + + } + + + /** 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 + + typedef const ProcPatt cPP; + + + // for baiscpipetest.cpp --------- + answer_->insert (entry_Struct ("stream(video)")); + answer_->insert (entry_Struct ("stream(teststream)")); + item (answer_, "stream(default)") = item (answer_,"stream(video)"); // set up a default stream + + answer_->insert (entry_Struct ("pipe(master), stream(video)")); + item (answer_, "") = item(answer_,"pipe(master), stream(video)");// use as default + } + + + + + /* under some circumstances we need to emulate the behaviour * + * of a real resolution engine in a more detailed manner. * + * These case are hard wired in code below */ + + /** special case: create a new pipe with matching pipe and stream IDs on the fly when referred... */ + bool + MockTable::fabricate_matching_new_Pipe (Query& q, string const& pipeID, string const& streamID) + { + typedef WrapReturn::Wrapper Ptr; + + Ptr newPipe (Struct::create (pipeID, streamID)); + answer_->insert (entry (q, newPipe)); + return true; // denotes query will now succeed... + } + /** special case: create a new pipe for a specific stream ID */ + bool + MockTable::fabricate_just_new_Pipe (Query& q ) + { + typedef WrapReturn::Wrapper Ptr; + + Ptr newPipe (Struct::create (Query ("make(PP), "+q))); + answer_->insert (entry (q, newPipe)); + return true; + } + /** special case: create/retrieve new rocessing pattern for given stream ID... */ + bool + MockTable::fabricate_ProcPatt_on_demand (Query& q, string const& streamID) + { + typedef const ProcPatt cPP; + typedef WrapReturn::Wrapper Ptr; + + Ptr newPP (Struct::create (Query ("make(PP), "+q))); + answer_->insert (entry (q, newPP)); + return true; + } + + /** for entering "valid" solutions on-the-fly from tests */ + template + bool + MockTable::set_new_mock_solution (Query& q, typename WrapReturn::Wrapper& obj) + { + answer_->erase (q.asKey()); + answer_->insert (entry (q, obj)); + return true; + } + // generate the necessary specialisations----------------------------- + template bool MockTable::set_new_mock_solution (Query&, PPipe&); + + + + + + MockConfigRules::MockConfigRules () + { + WARN (config, "using a mock implementation of the ConfigQuery interface"); + } + + + MockTable::MockTable () + : answer_(new Tab()), + isInit_(false) + { } + + + + + /** 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 relpies based + * 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) + { + static const any NOTFOUND; + if (!isInit_) fill_mock_table(); + + Tab::iterator i = answer_->find (queryStr); + if (i == answer_->end()) + return NOTFOUND; + else + return i->second; + } + + + + } // namespace query + +} // namespace lumiera diff --git a/src/common/query/mockconfigrules.hpp b/src/common/query/mockconfigrules.hpp new file mode 100644 index 000000000..f5bea3264 --- /dev/null +++ b/src/common/query/mockconfigrules.hpp @@ -0,0 +1,252 @@ +/* + MOCKCONFIGRULES.hpp - mock implementation of the config rules system + + Copyright (C) Lumiera.org + 2008, 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 mockconfigrules.hpp + ** Mock/Test/Debugging Implementation of the config rules system. + ** Instead of actually parsing/analyzing/resolving queries, this implementation + ** uses a Table of hard wired queries together with preconfigured object instances + ** as answer values. As of 1/2008 it is used to "keep the implementation work going" + ** -- later on, when we use a real Prolog interpreter, it still may be useful for + ** testing and debugging. + ** + ** @see lumiera::Query + ** @see lumiera::ConfigRules + ** + */ + + +#ifndef LUMIERA_MOCKCONFIGRULES_H +#define LUMIERA_MOCKCONFIGRULES_H + +#include "proc/mobject/session.hpp" +#include "common/configrules.hpp" +#include "common/util.hpp" + +#include +#include +#include +#include + + + +namespace lumiera + { + + + namespace query + { + using asset::Pipe; + using asset::ProcPatt; + using asset::PProcPatt; + using mobject::Session; + + using util::isnil; + + using boost::any; + using boost::any_cast; + + + + + + namespace // internal details + { + + /** 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; }; + + + /** helper detecting if a query actually intended to retrieve a "default" object. + * This implementation is quite crude, of cours it would be necessary to actually + * parse and evaluate the query. @note query is modified if "default" ... */ + inline bool + is_defaults_query (string& query) + { + return !isnil (removeTerm ("default", query)); + } + } // details (end) + + + /** + * the actual table holding preconfigured answers + * packaged as boost::any objects. + */ + class MockTable : public lumiera::ConfigRules + { + typedef std::map Tab; + typedef boost::scoped_ptr PTab; + + PTab answer_; + bool isInit_; + + protected: + MockTable (); + const any& fetch_from_table_for (const string& queryStr); + + // special cases.... + template + bool detect_case (typename WrapReturn::Wrapper&, Query& q); + bool fabricate_matching_new_Pipe (Query& q, string const& pipeID, string const& streamID); + bool fabricate_just_new_Pipe (Query& q); + bool fabricate_ProcPatt_on_demand (Query& q, string const& streamID); + + template + bool set_new_mock_solution (Query& q, typename WrapReturn::Wrapper& candidate); + + + private: + void fill_mock_table (); + }; + + + /** + * building block defining how to do + * the mock implementation for \e one type. + * We simply access a table holding pre-created objects. + */ + template + class LookupPreconfigured : public BASE + { + typedef typename WrapReturn::Wrapper Ret; + + public: + /** (dummy) implementation of the QueryHandler interface */ + virtual bool + resolve (Ret& solution, const Query& q) + { + const any& entry = fetch_from_table_for (q.asKey()); + if (!isnil (entry)) + { + const Ret& candidate (any_cast (entry)); + if (! solution + ||(solution && solution == candidate) // simulates a real unification + ) + return solution = candidate; + } + return try_special_case(solution, q); + } + + private: + bool + try_special_case (Ret& solution, const Query& q) + { + if (solution && isFakeBypass(q)) // backdoor for tests + return solution; + + Query newQuery = q; + if (is_defaults_query (newQuery)) // modified query.. + return solution = Session::current->defaults (newQuery); + // may cause recursion + if (detect_case (solution, newQuery)) + return resolve (solution, newQuery); + + return solution = Ret(); // fail: return default-constructed empty smart ptr + } + }; + + + /** Hook for treating very special cases for individual types only */ + template + inline bool + MockTable::detect_case (typename WrapReturn::Wrapper&, Query& q) + { + q.clear(); // end recursion + return false; + } + template<> + inline bool + MockTable::detect_case (WrapReturn::Wrapper& candidate, Query& q) + { + if (!isnil (extractID("make", q))) + return false; // let the query fail here, + // so the invoking factory will go ahead + // and create a new object. + + const string pipeID = extractID("pipe", q); + const string streamID = extractID("stream", q); + + if (candidate && pipeID == candidate->getPipeID()) + return set_new_mock_solution (q, candidate); // "learn" this solution to be "valid" + + if (!isnil(pipeID) && !isnil(streamID)) + return fabricate_matching_new_Pipe (q, pipeID, streamID); + + if (!candidate && (!isnil(streamID) || !isnil(pipeID))) + return fabricate_just_new_Pipe (q); + + q.clear(); + return false; + } + template<> + inline bool + MockTable::detect_case (WrapReturn::Wrapper& candidate, Query& q) + { + if (!isnil (extractID("make", q))) + return false; // failure triggers creation... + + const string streamID = extractID("stream", q); + if (!candidate && !isnil(streamID)) + return fabricate_ProcPatt_on_demand (q, streamID); + + q.clear(); + return false; + } + + + + + + + /** + * Facade: 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 typelist::InstantiateChained < InterfaceTypes + , LookupPreconfigured // building block used for each of the types + , MockTable // for implementing the base class (interface) + > + { + protected: + MockConfigRules (); ///< to be used only by the singleton factory + friend class lumiera::singleton::StaticCreate; + + virtual ~MockConfigRules() {} + + public: + + // TODO: implementation of any additional functions on the ConfigRules inteface goes here + }; + + + + + } // namespace query + +} // namespace lumiera +#endif diff --git a/src/common/singletonfactory.hpp b/src/common/singletonfactory.hpp index 026b6990e..9fdf21d21 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 lumiera @@ -53,10 +52,10 @@ namespace lumiera * @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..a7e800487 --- /dev/null +++ b/src/common/singletonsubclass.hpp @@ -0,0 +1,179 @@ +/* + SINGLETONSUBCLASS.hpp - variant of the singleton (factory) creating a subclass + + Copyright (C) Lumiera.org + 2008, 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 LUMIERA_SINGLETONSUBCLASS_H +#define LUMIERA_SINGLETONSUBCLASS_H + + +#include "common/singleton.hpp" + +#include +#include + + +namespace lumiera + { + using boost::scoped_ptr; + + + namespace singleton + { + /** + * Helper template to use the general policy classes of the lumiera::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)); } + }; + + + 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 \e later, when the singleton factory + * is actually created, to point at the desired implementation subclass. + */ + static My_scoped_ptr link; + + /** Forwarding Template used 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> + typename Adapter::My_scoped_ptr Adapter::link; // note: use special ctor (due to stati init order!) + + + /** 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 + } + }; + + + /** + * 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 lumiera + +#endif diff --git a/src/common/test/run.hpp b/src/common/test/run.hpp index b38729d8a..529896d0b 100644 --- a/src/common/test/run.hpp +++ b/src/common/test/run.hpp @@ -85,7 +85,7 @@ namespace test { public: Launch (string testID, string groups) { Suite::enroll (this,testID,groups); }; - virtual auto_ptr operator() () { return auto_ptr (new TEST ); }; + virtual auto_ptr operator() () { return auto_ptr (new TEST ); }; }; } // namespace test diff --git a/src/common/test/testoption.cpp b/src/common/test/testoption.cpp index aaaff32b8..8b1199887 100644 --- a/src/common/test/testoption.cpp +++ b/src/common/test/testoption.cpp @@ -1,5 +1,5 @@ /* - Suite - helper class for running collections of tests + Suite - handle cmdline for invoking Testsuite Copyright (C) Lumiera.org 2008, Hermann Vosseler @@ -45,6 +45,7 @@ namespace test * \code * --help * --group + * --describe * \endcode */ TestOption::TestOption (util::Cmdline& cmdline) diff --git a/src/common/typelistutil.hpp b/src/common/typelistutil.hpp new file mode 100644 index 000000000..4e382df3d --- /dev/null +++ b/src/common/typelistutil.hpp @@ -0,0 +1,147 @@ +/* + TYPELISTUTIL.hpp - metaprogramming utilities for lists-of-types + + Copyright (C) Lumiera.org + 2008, 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 lumiera::typelist::Types (i.e. lists-of-types). + ** + ** @see lumiera::query::ConfigRules usage example + ** @see typelist.hpp + ** + */ + + +#ifndef LUMIERA_TYPELISTUTIL_H +#define LUMIERA_TYPELISTUTIL_H + +#include "common/typelist.hpp" + + + +namespace lumiera + { + namespace typelist + { + + /** + * Apply a template to a collection of types. + * The resulting class ends up inheriting from an instantiation + * 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 + , 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 lumiera +#endif diff --git a/src/common/util.hpp b/src/common/util.hpp index 4687bd7f4..7f8704554 100644 --- a/src/common/util.hpp +++ b/src/common/util.hpp @@ -91,6 +91,14 @@ namespace util return set.end() != set.find (val); } + /** shortcut for string value containment test */ + template + inline bool + contains (std::string& str, const T& val) + { + return str.find (val) != std::string::npos; + } + /** shortcut for brute-force containment test * in any sequencial container */ template @@ -116,6 +124,39 @@ namespace util } + /** remove all elements fulfilling a given predicate + * from a (sorted) set. + * @return true if anything has been removed. */ + template + bool remove_if (SET& set, PRD test) + { + typedef typename SET::iterator Itor; + bool found = false; + Itor end = set.end(); + Itor begin = set.begin(); + Itor pos = begin; + while (pos!=end) + { + if (!test (*pos)) ++pos; + else + { + found = true; + if (pos==begin) + { + set.erase(pos); + pos = begin = set.begin(); + } + else + { + set.erase(pos--); + ++pos; + } + end = set.end(); + } } + return found; + } + + /** shortcut for operating on all elements of a container. * Isn't this already defined somewhere? It's so obvious.. */ @@ -156,8 +197,8 @@ namespace util "trailing Withespace \t \n" --> 'trailing_Withespace' "with a lot \nof Whitespace" --> 'with_a_lot_of_Whitespace' "with\"much (punctuation)[]!" --> 'withmuch_(punctuation)' - "§&Ω%€ leading garbarge" --> 'leading_garbarge' - "mixed Ω garbarge" --> 'mixed_garbarge' + "§&Ω%€ leading garbage" --> 'leading_garbage' + "mixed Ω garbage" --> 'mixed_garbage' "Bääääh!!" --> 'Bh' \endverbatim */ diff --git a/src/proc/asset.cpp b/src/proc/asset.cpp index 99fd50670..923b61248 100644 --- a/src/proc/asset.cpp +++ b/src/proc/asset.cpp @@ -163,7 +163,7 @@ namespace asset void Asset::defineDependency (PAsset parent) { - PAsset p_this (AssetManager::getPtr(*this)); + PAsset p_this (AssetManager::wrap(*this)); REQUIRE (!contains (parent->dependants, p_this)); REQUIRE (!contains (this->parents, parent)); parents.push_back (parent); @@ -173,7 +173,7 @@ namespace asset void Asset::defineDependency (Asset& parent) { - PAsset p_parent (AssetManager::getPtr(parent)); + PAsset p_parent (AssetManager::wrap(parent)); ASSERT (p_parent); defineDependency (p_parent); } diff --git a/src/proc/asset.hpp b/src/proc/asset.hpp index 0387e85ba..7088b8324 100644 --- a/src/proc/asset.hpp +++ b/src/proc/asset.hpp @@ -39,7 +39,7 @@ ** value. For example the asset::Media#getID returns an ID. By using the ** templated query function AssetManager#getAsset, we can get at references to the more ** specific subinterface asset::media just by using the ID value in a typesafe manner. - ** This helps avoiding dynamic typing and switch-on-type, leading to much more robust, + ** This helps avoiding dynamic typing and switch-on-type, leading to more robust, ** extensible and clear code. ** ** (Implementation detail: as g++ is not able to handle member function template @@ -59,13 +59,16 @@ #include "proc/asset/category.hpp" #include "common/error.hpp" +#include "common/p.hpp" + +#include +#include +#include #include #include #include #include -#include -#include using std::string; @@ -79,6 +82,9 @@ namespace asset using std::size_t; using std::tr1::shared_ptr; + using std::tr1::static_pointer_cast; + + using lumiera::P; /** @@ -107,8 +113,8 @@ namespace asset class Asset; class AssetManager; typedef const ID& IDA; - typedef shared_ptr PAsset; - typedef shared_ptr PcAsset; + typedef P PAsset; + typedef P PcAsset; @@ -116,7 +122,7 @@ namespace asset /** * Superinterface describing especially bookeeping properties. - * As of 09/2008, there are four Kinds of Assets, each + * As of 09/2007, there are four Kinds of Assets, each * comprising a sub-Interface of the Asset Interface: *
-
+
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]]
+&rarr; [[accessing and integrating configuration queries|ConfigQueryIntegration]]
 
-
+
+
* planning to embed a YAP Prolog engine
+* currently just integrated by a table driven mock
+* the baseline is a bit more clear by now (4/08)
+
+&rarr; see also ConfigRules
+&rarr; see also DefaultsManagement
+
+!Use cases
+[<img[when to run config queries|uml/fig131717.png]]
+
+The key idea is that there is a Rule Base &mdash; partly contained in the session (building on a stock of standard rules supplied with the application). Now, whenever there is the need to get a new object, for adding it to the session or for using associated with another object &mdash; then instead of creating it by a direct hard wired ctor call, we issue a ConfigQuery requesting an object of the given type with some //capabilities// defined by predicates. The same holds true when loading an existing session: some objects won't be loaded back blindly, rather they will be re-created by issuing the config queries again. Especially important is the case of (re)creating a [[processing pattern|ProcPatt]] guiding how to wire up the processing pipeline for some given media.
+
+At various places, instead of requiring a fixed set of capabilities, it is possible to request a "default configured" object instead, specifying just those capabilities we really need to be configured in a specific way. This is done by using the [[Defaults Manager|DefaultsManagement]] accessible on the [[Session]] interface. Such a default object query may either retrieve an already existing object instance, run further config queries, and finally result in the invocation of a factory for creating new objects &mdash; just as necessary and guarded by the rules.
+
+@@clear(left):display(block):@@
+
+!Components and Relations
+[>img[participating classes|uml/fig131461.png]]
+
+<br/>
+<br/>
+<br/>
+<br/>
+<br/>
+<br/>
+<br/>
+
+Access point is the interface {{{ConfigRules}}}, which allowes to resolve a ConfigQuery resulting in an object with properties condigured such as to fulfill the query. This whole subsystem employes quite some generic programming, because actually we don't deal with "objects", but rather with similar instantiations of the same functionality for a collection of different object types. For the purpose of resolving these queries, the actual kind of object is not so much of importance, but on the caller sinde, of course we want to deal with the result of the queries in a typesafe manner.
+Examples for //participating object kinds// are [[pipes|Pipe]], [[processing patterns|ProcPatt]], effect instances, [[tags|Tag]], [[labels|Label]], [[automation data sets|AutomationData]],...
+@@clear(right):display(block):@@
+For this to work, we need each of the //participating object types// to implement a generic interface {{{TypeHandler}}}, which will provide actual C/C++ implementations for the predicates usable on objects of this type within the Prolog rules. The implementation has to make sure that alongside with each config query, there are additional //type constraints// to be regarded. For example, if the client code runs a {{{Query<Pipe>}}}, an additional //type guard// (implemented by a predicate {{{type(pipe)}}} has to be inserted, so only rules and facts in accordance with this type will be used for resolution.
+
+
+!when querying for a [["default"|DefaultsManagement]] object
+[<img[colaboration when issuing a defaults query|uml/fig131845.png]]
+
+@@clear(left):display(block):@@
+
+
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 Lumiera 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 Lumiera'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.
@@ -808,7 +848,7 @@ Error: #f88
!anatomy of a Configuration Query The query is given as a number of logic predicates, which are required to be true. Syntactically, it is a string in prolog syntax, e.g. {{{stream(mpeg)}}}, where "stream" is the //predicate, // meaning here "the stream type is...?" and "mpeg" is a //term // denoting an actual property, object, thing, number etc &mdash; the actual kind of stream in the given example. Multible comma separated predicates are combined with logical "and". Terms may be //variable // at start, which is denoted syntactically by starting them with a uppercase letter. But any variable term need to be //bound // to some known value while computing the solution to the query, otherwise the query fails. A failed query is treated as a local failure, which may cause some operation being aborted or just some other possibility being chosen. -Queries are represented by instantiations of the {{{Query<TYPE>}}} template, because their actual meaning is "retrieve or create an object of TYPE, configured such that...!". At the C++ side, this ensures type safety and fosters programming against interfaces, while being implemented rule-wise by silently prepending the query with the predicate "{{{object(tYPE)}}}" +Queries are represented by instantiations of the {{{Query<TYPE>}}} template, because their actual meaning is "retrieve or create an object of TYPE, configured such that...!". At the C++ side, this ensures type safety and fosters programming against interfaces, while being implemented rule-wise by silently prepending the query with the predicate "{{{object(TYPE)}}}" !executing a Configuration Query Actually posing such an configuration query, for example to the [[Defaults Manager in the Sessison|DefaultsManagement]], may trigger several actions: First it is checked against internal object registries (depending on the target object type), which may cause the delivery of an already existing object (as reference, clone, or smart pointer). Otherwise, the system tries to figure out an viable configuration for a newly created object instance, possibly by issuing recursive queries. In the most general case this may silently impose additional decisions onto the //execution context // of the query &mdash; by default the session. @@ -816,8 +856,12 @@ 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; [[accessing and integrating configuration queries|ConfigQueryIntegration]] &rarr; see {{{src/common/query/mockconfigrules.cpp}}} for the table with the hard wired (mock) answers + +{{red{WARN}}} there is an interference with the (planned) Undo function: a totally correct implementation of "Undo" would need to remember and restore the internal state of the query system (similar to backtracking). But, more generally, such an correct implementation is not achievable, because we are never able to capture and control the whole state of a real world system doing such advanced things like video and sound processing. Seemingly we have to accept that after undoing an action, there is no guarantee we can re-do it the same way as it was first time. +
@@ -839,10 +883,36 @@ This is an very important external Interface, because it links together all thre
[[ProcLayer and Engine]]
 
-
-
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]]
+
+
As detailed in the [[definition|DefaultsManagement]], {{{default(Obj)}}} is sort of a Joker along the lines "give me a suitable Object and I don't care for further details". Actually, default objects are implemented by the {{{mobject::session::DefsManager}}}, which remembers and keeps track of anything labeled as "default". This defaults manager is a singleton and can be accessed via the [[Session]] interface, meaning that the memory track regarding defaults is part of the session state. Accessing an object via the query for an default actually //tagges// this object (storing a weak ref in the ~DefsManager). Alongside with each object successfully queried via "default", the degree of constriction is remembered, i.e. the number of additional conditions contained in the query. This enables us to search for default objects starting with the most unspecific.
+
+!Skeleton
+# ''search'': using the predicate {{{default(X)}}} enumerates existing objects of suitable type
+#* candidates are delivered starting with the least constrained default
+#* the argument is unified
+#** if the rest of the query succeeds we've found our //default object// and are happy.
+#** otherwise, if all enumerated solutions are exhausted without success, we enter
+# ''default creation'': try to get an object fulfilling the conditions and remember this situation
+#* we issue an ConfigQuery with the query terms //minus// the {{{default(X)}}} predicate
+#* it depends on the circumstances how this query is handled. Typically the query resolution first searches existing objects and then creates a new instance to match the required capabilities. Usually, this process succeeds, but there can be configurations leading to failure.
+#** failing the ~ConfigQuery is considered an (non-critical) exception (throws), as defaults queries are supposed to succeed
+#** otherwise, the newly created object is remembered (tagged) as new default, together with the degree of constriction
+
+!!!Implementation details
+Taken precisely, the "degree of constriction" yields only a partial ordering &mdash; but as the "default"-predicate is sort of a existential quantification anyways, its sole purpose is to avoid polluting the session with unnecessary default objects, and we don't need to care for absolute precision. A suitable approximation is to count the number of predicates terms in the query and use a (sorted) set (separate for each Type) to store weak refs to the the objects tagged as "default"
+{{red{WARN}}} there is an interference with the (planned) Undo function. This is a general problem of the config queries; just ignoring this issue seems reasonable.
+
+!!!Problems with the (preliminary) mock implementation
+As we don't have a Prolog interpreter on board yet, we utilize a mock store with preconfigured answers. (see {{{MockConfigQuery}}}). As this preliminary solution is lacking the ability to create new objects, we need to resort to some trickery here (please look away). The overall logic is quite broken, because the system isn't capable to do any real resolution &mdash; if we ignore this fact, the rest of the algorithm can be implemented, tested and used right now.
 
+
+
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. This query mechanism is implemented by [[configuration rules|ConfigRules]]
+
+!!!!what is denoted by {{{default}}}?
+{{{default(Obj)}}} is a predicate expressing that the object {{{Obj}}} can be considered the default setup under the given conditions. Using the //default// can be considered as a shortcut for actually finding a exact and unique solution. The latter would require to specify all sorts of detailed properties up to the point where only one single object can satisfy all conditions. On the other hand, leaving some properties unspecified would yield a set of solutions (and the user code issuing the query had to provide means for selecting one soltution from this set). Just falling back on the //default// means that the user code actually doesn't care for any additional properties (as long as the properties he //does// care for are satisfied). Nothing is said specifically on //how//&nbsp; this default gets configured; actually there can be rules //somewhere,// and, additionally, anything encountered once while asking for a default can be re-used as default under similar circumstances.
+&rarr; [[implementing defaults|DefaultsImplementation]]
+
Along the way of working out various [[implementation details|ImplementationDetails]], decisions need to be made on how to understand the different facilities and entities and how to tackle some of the problems. This page is mainly a collection of keywords, summaries and links to further the discussion. And the various decisions should allways be read as proposals to solve some problem at hand...
 
@@ -932,8 +1002,9 @@ After beeing processed by the Builder, we get the following Render Engine config
 [img[Example1: generated Render Engine|uml/fig129029.png]]
 
-
-
This Example showes the //high level// EDL as well. This needs to be transformed into a Fixture by some facility still to be designed. Basically, each [[Placement]] needs to be queried for this to get the corresponding ExplicitPlacement. The difficult part is to handle possible Placement constraints, e.g. one clip can't be placed at a timespan covered by another clip on the same track. In the current Cinelerra2, all of this is done directly by the GUI actions.
+
+
{{red{TODO: seemingly this example is slightly outdated, as the implementation of placements is now indirect via LocatingPin objects}}}
+This Example showes the //high level// EDL as well. This needs to be transformed into a Fixture by some facility still to be designed. Basically, each [[Placement]] needs to be queried for this to get the corresponding ExplicitPlacement. The difficult part is to handle possible Placement constraints, e.g. one clip can't be placed at a timespan covered by another clip on the same track. In the current Cinelerra2, all of this is done directly by the GUI actions.
 
 The &raquo;Timeline&laquo; is a sequence of ~MObjects -- note: using the same Object instances -- but now with the calculated ExplicitPlacement, locating the clip at a given time and track. The effect is located absolutely in time as well, but because it is the same Instance, it has the pointer to the ~RelativePlacement, wich basically attaches the effect to the clip. This structure may look complicated, but is easy to process if we go "backward" and just rely on the information contained in the ExplicitPlacement.
 [img[Example2: Clip with Effect and generated Fixture for this EDL|uml/fig128901.png]]
@@ -1111,7 +1182,7 @@ For this Lumiera design, we could consider making GOP just another raw media dat
 &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 Lumiera Renderengine, the Builder and the related parts.
 
 * [[Packages, Interfaces and Namespaces|InterfaceNamespaces]]
@@ -1125,6 +1196,7 @@ For this Lumiera design, we could consider making GOP just another raw media dat
 * [[using the Visitor pattern?|VisitorUse]] &mdash; resulting in [[»Visiting-Tool« library implementation|VisitingToolImpl]]
 * [[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]]
+* [[integrating the Config Query system|ConfigQueryIntegration]]
 * [[identifying the basic Builder operations|BasicBuildingOperations]] and [[planning the Implementation|PlanningNodeCreatorTool]]
 * [[how to handle »attached placement«|AttachedPlacementProblem]]
 
@@ -2226,6 +2298,33 @@ DAMAGE. <html><sub><a href="javascript:;" onclick="scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html> ***/
+
+
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 ports|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)
+
+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 Pipes|PipeHandling]]
+
+
+
+
+
!Identification
+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 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 a 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]]. Note that creating a new pipe implies using a [[processing pattern|ProcPatt]], which will be queried from the [[Defaults Manager|DefaultsManagement]] (resulting in the use of some preconfigured pattern or maybe the creation of a new ProcPatt object if necessary)
+
+!removal
+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 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
+
+
A Placement represents a //relation:// it is always linked to a //Subject// (this being a [[Media Object|MObject]]) and has the meaning to //place// this Subject in some manner, either relatively to other Media Objects, or by some Constraint or simply absolute at (time,track). The latter case is especially important and represented by a special [[Sub-Interface|ExplicitPlacement]]
 
@@ -2351,34 +2450,6 @@ We need a way of addressing existing [[pipes|Pipe]]. Besides, as the Pipes 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//
 
-
-
-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)
-
-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 Pipes|PipeHandling]]
-
-
-
-
-
!Identification
-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 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 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 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
-
-
Open issues, Things to be worked out, Problems still to be solved... 
 
@@ -2437,12 +2508,13 @@ Besides, they provide an important __inward interface__ for the [[ProcNode]]s, w
 
 
-
+
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 implementing the foundations and main structures in C++
 * basic AssetManager working
 * currently impmenenting the Builder (&rarr;[[more|PlanningNodeCreatorTool]])
+* intermittently working out how to deal with &rarr; [[ConfigQueries / default objects|ConfigQueryIntegration]])
 <<<
 
 !Summary
@@ -2458,7 +2530,7 @@ The system is ''open'' inasmuch every part mirrors the structure of correspondin
 &rarr; [[Overview Render Engine|OverviewRenderEngine]]
 &rarr; BuildProcess and RenderProcess
 &rarr; [[Two Examples|Examples]] (Object diagrams) 
-&rarr; how [[Automation]] works  {{red{to be defined in more detail}}}
+&rarr; how [[Automation]] works
 &rarr; [[Problems|ProblemsTodo]] to be solved and notable [[design decisions|DesignDecisions]]
 &rarr; [[Implementation Details|ImplementationDetails]] {{red{WIP}}}
 
@@ -2467,13 +2539,13 @@ The system is ''open'' inasmuch every part mirrors the structure of correspondin
A data processing node within the Render Engine. Its key feature is the possibility to pull from it one (freely addressable) [[Frame]] of calculated data. Further, each ~ProcNode has the ability to be wired with other nodes and [[Parameter Providers|ParamProvider]]
 
-
+
This special type of [[structural Asset|StructAsset]] represents information how to build some part of the render engine's processing nodes network. It can be thought of as a template or blueprint for construction. Most notably, it is used for creating nodes reading, decoding and delivering source media material to the render network. Each [[media Asset|MediaAsset]] has associated processing patterns describing the codecs and other transformations needed to get at the media data of this asset. (and because media assets are typically compound objects, the referred ~ProcPatt will be compound too). Obviously, the possibilities opened by using processing patterns go far beyond.
 
 Technically, a processing pattern is a list of building instructions, which will be //executed// by the [[Builder]] on the render node network under construction. This implies the possibility to define further instruction kinds when needed in future; at the moment the relevant sorts of instructions are
 * attach the given sequence of nodes to the specified point
 * recursively execute a nested ~ProcPatt
-More specifically, a sequence of nodes is given by a sequence of prototypical effect and codec assets (and from each of them we can create the corresponding render node). And the point to attach these nodes is given by an identifier &mdash; in most cases just "{{current}}", denoting the point the builder was just working at, when he treated some MObject which in turn yielded this processing pattern in question.
+More specifically, a sequence of nodes is given by a sequence of prototypical effect and codec assets (and from each of them we can create the corresponding render node). And the point to attach these nodes is given by an identifier &mdash; in most cases just "{{{current}}}", denoting the point the builder was just working at, when he treated some MObject which in turn yielded this processing pattern in question.
 
 Like all [[structural assets|StructAsset]], ~ProcPatt employs a special naming scheme within the asset name field, which directly mirrors its purpose and allows to bind to existing processing pattern instances when needed. The idea is letting all assets in need of a similar processing pattern refer to one shared ~ProcPatt instance. For example, within a MPEG video media asset, at some point there will be a ~ProcPatt labeled "{{{stream(mpeg)}}}". In consequence, all MPEG video will use the same pattern of node wiring. And, of course, this pattern could be changed, either globally, or by binding a single clip to some other processing pattern (for making a punctual exception from the general rule)
 
@@ -2484,21 +2556,21 @@ 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.
+The intention is to get much more readable ("declarative") and changeable configuration as by programming the decision logic literately within the implementation of some object.
 
 !Draft
 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).
+resolve(O, Cap) :- find(O), capabilities(Cap).
+resolve(O, Cap) :- make(O), capabilities(Cap).
 capabilities(Q) :- call(Q).
 
-stream(T, mpeg) :- type(T, track), type(P, pipe), retrieve(P, stream(P,mpeg)), place_to(P, T).
+stream(T, mpeg) :- type(T, track), type(P, pipe), resolve(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 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.
+Then, running the goal {{{:-resolve(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).
 
@@ -4064,6 +4136,38 @@ Of course, we can place other ~MObjects relative to some track (that's the main
 &rarr; [[Handling of Pipes|PipeHandling]]
 
+
+
What //exactly&nbsp;// is denoted by &raquo;Track&laquo; &mdash; //basically&nbsp;// a working area to group media objects placed at this track at various time positions &mdash; varies depending on context:
+* viewed as [[structural asset|StructAsset]], tracks are nothing but global identifiers (possibly with attached tags and description)
+* regarding the structure //within each [[EDL]],// tracks form a tree-like grid, the individual track being attached to this tree by a [[Placement]], thus setting up properties of placement (time reference origin, output connection, layer, pan) which will be inherited down to any objects located on this track and on child tracks, if not overridden more locally.
+* with respect to //object identity,// a given track-ID can have an incarnation or manifestation as real track-object within several [[EDLs|EDL]] (meaning you could select, disable or choose for rendering all objects in any EDL placed onto this track). Moreover, the track-//object// and the //placement&nbsp;// of this track within the tree of tracks of a given EDL are two distinguishable entities (meaning a given track &mdash; with a couple of objects located on it &mdash; could be placed differently several times within the same EDL, for example with different start offset or with different layering, output mode or pan position)
+
+!Identification
+Tracks thus represent a blend of several concepts, but depending on the context it is allways clear which aspect is meant. Seen as [[assets|Asset]], tracks are known by a unique track-ID, which can be either [[queried|ConfigQuery]], or directly refered to by use of the asset-ID (which is a globally known hash). Usually, all referrals are via track-ID, including when you [[place|Placement]] an object onto a track. 
+Under some cincumstances though, especially from within the [[Builder]], we refer to a {{{Placement<Track>}}} rather, denoting a specific instantiation located at a distinct node within the tree of tracks of a given EDL. These latter referrals are always done by direct object reference, e.g. while traversing the track tree (generally there is no way to refer to a placement by name).
+
+!creating tracks
+Similar to [[pipes|Pipe]] and [[processing patterns|ProcPatt]], track-assets need not be created, but rather leap into existence on first referral. On the contrary, you need to explicitly create the {{{Placement<Track>}}} for attaching it to some node within the tree of tracks of an EDL. The public access point for creating such a placement is {{{asset::Struct::create(trackID}}} (i.e. the {{{asset::StructFactory}}}), which, as a convenience shortcut, can also be accessed from the interface of the track-objects within the EDL for adding new child tracks to a given track.
+
+!removal
+Deleting a Track is an operation with drastic consequences, as it will cause the removal of all child tracks and the deletion of //all object placements to this track,// which could cause the resepctive objects to go out of scope (being deleted automatically by the placements or other smart pointer classes in charge of them). On the contrary, removing a {{{Placement<Track>}}} from the tree of tracks of an EDL will just cause all objects placed onto this track to disappear (because they are no longer reachable for the build process). On re-adding it, they will show up again. (This is how things behave based on how we defined the relations of the entities to be. Another question is if we want to make this functionality available to the user. Judging from the use of Ardour's &laquo;Playlists&raquo;, such a feature may be quite helpful).
+
+!using Tracks
+The '''Track Asset''' is a rather static object with limited capabilities. It's main purpose is to be a point of referral. Track assets have a description field and you may assign a list of [[tags|Tag]] to them (which could be used for binding ConfigRules).  Note that track assets are globally known within the session, they can't be limited to just one EDL (but you are allways free not to refer to some track from a given EDL). By virtue of this global nature, you can utilize the track assets to enable/disable a bunch of objects irrespective of what EDL they are located in, and probably it's a good idea to allow the selection of specific tracks for rendering.
+Matters are quite different for the placement of a Track within the tree of tracks of a given EDL, and for placing some media object onto a given track. The track placement defines properties which will be inherited to all objects on this track and on all child tracks and thus plays a key role for wiring the objects up to some output pipe. Typically, the top level track of each EDL has a placement-to "the" video and "the" audio master pipe.
+
+!!!!details to note
+* Tracks are global, but the placement of a track is local within one EDL
+* when objects are placed onto a track, this is done by referal to the global track asset ID. But because this placement of some media object is allways inherently contained within one EDL, the //meaning&nbsp;// of such a placement is to connect to the properties of any track-placement of this given track //within this EDL.//
+* thus tracks-as-ID appear as something global, but tracks-as-propperty-carrier appear to the user as something local and object-like.
+* in an extreme case, you'll add two different placements of a track at different points within the track tree of an EDL. And because the objects placed onto a track refer to the global track-ID, every object "on" this track //within this EDL&nbsp;// will show up two times independently and possibly with different inherited properties (output pipe, layering mode, pan, temporal position)
+* an interesting configuration results from the fact that you can use an EDL as a [["meta clip" or "virtual clip"|VirtualClip]] within another EDL. In this case, you'll probably configure the tracks of the "inner" EDL such as to send their output not to a global pipe but rather to the [[source ports|ClipSourcePort]] of the virtual clip (which are effectively local pipes). Thus, within the "outer" EDL, you could attach effects to the virutal clip, combine it with transitions and place it onto another track, and any missing properties of this latter placement are to be resolved within the "outer" EDL <br/>(it would be perfectly legal to construct a contrieved example when using the same track-ID within "inner" and the "outer" EDL. Because the Placement of this track will probably be different in the both ~EDLs, the behaviour of this placement could be quite different in the "inner" and the "outer" EDL. All of this may seem weird when discussed here in a textual and logical manner, but when viewed within the context and meaning of the various entities of the application, it's rather the way you'd expect it to be: you work locally and things behave as defined locally)
+* note further, the root of the tree of tracks within each EDL //is itself again a //{{{Placement<Track>}}}. There is no necessitiy for doing it this way, but it seemed more stright forward and logical to Ichthyo, as it allowes for an easy way of configuring some things (like ouput connections) as a default within one EDL. As every track can have a list of child tracks, you'll get the "list of tracks" you'd expect.
+* a nice consequence of the latter is: if you create a new EDL, it automatically gets one top-level track to start with, and this track will get a default configured placement (according to what is defined as [[default|DefaultsManagement]] within the current ConfigRules) &mdash; typically starting at t=0 and being plugged into the master video and master audio pipe
+* nothing prevents us from putting several objects at the same temporal location within one track. If the builder can't derive any additional layering information (which could be provided by some other configuration rules), then //there is no layering precedence// &mdash; simply the object encountered first (or last) wins.
+* obviously, one wants the __edit function__ used to create such an overlapping placement&nbsp; also to create an [[transition|TransitionsHandling]] between the overlapping objects. Meaning this edit function will automatically create an transition processor object and provide it with a placement such as to attach it to the region of overlap.
+
+
''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.
 
@@ -4107,6 +4211,14 @@ 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 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]])
 
+
+
A ''~Meta-Clip'' or ''Virtual Clip'' (both are synonymous) denotes a clip which doesn't just pull media streams out of a source media asset, but rather provides the results of rendering a complete sub-network. In all other respects it behaves exactly like a "real" clip, i.e. it has [[source ports|ClipSourcePort]], can have attached effects (thus forming a local render pipe) and can be placed and combined with other clips. Depending on what is wired to the source ports, we get two flavours:
+* a __placeholder clip__ has no "embedded" content. Rather, by virtue of placements and wiring requests, the output of some other pipe somewhere in the session will be wired to the clip's source ports. Thus, pulling data from this clip will effectively pull from these source pipes wired to it.
+* a __nested EDL__ is like the other ~EDLs in the Session, just that any missing placement properties will be derived from the Virtual Clip, which is thought as to "contain" the objects of the nested EDL. Typically, you'd also [[configure the tracks|TrackHandling]] of the "inner" EDL such as to connect any output to the source ports of the Virtual Clip.
+
+Like any "real" clip, Virtual Clips have a start offset and a length, which will simply translate into an offset of the frame number pulled from the Virtual Clip's source connection or embedded EDL, making it possible to cut, splice, trim and roll them as usual. This of course implies we can have several instances of the same virtual clip with different start offset and length placed differently. The only limitation is that we can't handle cyclic dependencies for pulling data (which has to be detected and flagged as an error by the builder)
+
+
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]]