From 66bc601dc8de807568fcdc73fad804581560b9d4 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 7 Jan 2008 00:36:36 +0100 Subject: [PATCH 1/8] continue working out properties of tracks and ports --- wiki/renderengine.html | 94 ++++++++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 26 deletions(-) diff --git a/wiki/renderengine.html b/wiki/renderengine.html index fee468d59..1335e6365 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -514,12 +514,12 @@ ColorPalette SiteUrl -
-
Asset management is a subsystem on its own. Assets are "things" that can be loaded into a session, like Media, Clips, Effects, Transitions. It is the "bookkeeping view", while the EDL is the "manipulation and process view". Some Assets can be //loaded// and a collection of Assets is saved with eatch Session. Besides, there is a collection of basic Assets allways available by default.
+
+
Asset management is a subsystem on its own. Assets are "things" that can be loaded into a session, like Media, Clips, Effects, Transitions. It is the "bookkeeping view", while the EDL is the "manipulation and process view". Some Assets can be //loaded// and a collection of Assets is saved with each Session. Besides, there is a collection of basic Assets always available by default.
 
 The Assets are important reference points holding the information needed to access external resources. For example, an Clip asset can reference a Media asset, which in turn holds the external filename from which to get the media stream. For Effects, the situation is similar. Assets thus serve two quite distinct purposes. One is to load, list, group search and browse them, and to provide an entry point to create new or get at existing MObjects in the EDL, while the other purpose is to provide attribute and property informations to the inner parts of the engine, while at the same time isolating and decoupling them from environmental details. 
 
-We can distinguish several different Kinds of Assets, each one with specific properties. While all these Kinds of Assets implement the basic Asset interface, they themselfs are the __key abstractions__ of the asset management view. Mostly, their interfaces will be used directly, because they are quite different in behaviour. Thus it is common to see asset related operations being templated on the Asset Kind. 
+We can distinguish several different Kinds of Assets, each one with specific properties. While all these Kinds of Assets implement the basic Asset interface, they in turn are the __key abstractions__ of the asset management view. Mostly, their interfaces will be used directly, because they are quite different in behaviour. Thus it is common to see asset related operations being templated on the Asset Kind. 
 → see also [[Creating and registering Assets|AssetCreation]]
 [img[Asset Classess|uml/fig130309.png]]
 
@@ -542,7 +542,7 @@ Some of the building blocks providing the framework for the objects placed into
 → StructAsset {{red{to be defined}}}
 
 !Meta Asset
-Some additional, virtual facilities created in the course of the editing process. Examples are Automation data sets, Lables and reference points, Meta Clips (nested sub-~EDLs)
+Some additional, virtual facilities created in the course of the editing process. Examples are Automation data sets, Labels and reference points, Meta Clips (nested sub-~EDLs)
 * __outward interface operations__ include...
 * __inward interface operations__ include...
 → MetaAsset {{red{to be defined}}}
@@ -570,7 +570,7 @@ For every Asset we generate a __Ident tuple__ and a long ID (hash) derived from
 [img[how to implement Automation|uml/fig129669.png]]
 
-
+
Starting out from the concepts of Objects, Placement to Tracks, Ports and connection properties (→ see [[here|TrackPortEDL]]) within the EDL, we can identify the elementary operations occuring within the Builder. Overall, the Builder is organized as application of //visiting tools// to a collection of objects, so finally we have to consider some object kind appearing in the working function of the given builder tool, which holds at this moment some //context//. The job now is to organize this context such as to create a predictable build process from this //event driven// approach.
 
 !Builder working Situations
@@ -602,7 +602,7 @@ After consuming all input objects and satisfying all wiring requests, the result
 !!!dependencies
 Ports need to be there first, as everything else will be placed to a port at some point. The same holds true for tracks. But, on the other hand, both are optional. We can have ~EDLs with ~MObjects without configuring ports (but won't be able to build any render processor of course). And we could have an EDL without any track, if we place every ~MObject within this EDL directly to some port.
 
-Effects can be attached only to already existing pipelines, starting out at some port or clip. Besides that, all further parts can be built in any order and independent of each other. This is made possible by using [[wiring requests|WiringRequest]], which can be resolved later on. So, as long as we start out with the tracks (to resolve any port they are placed to), and further, if we manage to get any effect placed to some clip-MO //after// treating the clip, we are fine and can do the building quasi event driven.
+Effects can be attached only to already existing pipelines, starting out at some port or clip. Besides that, all further parts can be built in any order and independent of each other. This is made possible by using [[wiring requests|WiringRequest]], which can be resolved later on. So, as long as we start out with the tracks (to resolve any port they are placed to), and further, if we manage to get any effect placed to some clip-MO //after// setting up and treating the clip, we are fine and can do the building quasi event driven.
 
 !!!building and resolving
 Building the network for the individual objects thus creates a queue of wiring requests. Some of them may be immediately resolvable, but detecting this correctly can be nontrivial, and so it seems better to group all wiring requests based on the port and treat them groupwise. Because — in the most general case — connecting includes the use of transforming and joining nodes, which can create additional wiring requests (e.g. for automation parameter data connections). Finally, if the network is complete, we could perform [[optimisations|RenderNetworkOptimisation]]
@@ -803,7 +803,23 @@ This is an very important external Interface, because it links together all thre
 
RenderEngine
 
-
+
+
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...
+
+''Everything is an object'' — of course, that's a //no-brainer // todays. Rather, important is what is not "an object", meaning it can't be arranged arbitrarily
+* we have one and only one global [[Session]] which directly contains a collection of multiple [[EDLs|EDL]] and is associated with a globally managed collection of [[assets|Asset]] (no, we don't have scoped variables here; if e.g. a media has been "opened", it is just plain globally known as asset.)
+* we have some global [[ports|Port]], which are treated in a unique manner and don't behave like other objects (e.g. effects)
+* we have a [[Fixture]] which acts as isolation layer towards the render engine and is (re)built automatically.
+
+We ''separate'' processing (rendering) and configuration (building). We have a [[Builder]] which creates a network of [[render nodes|ProcNode]], to be processed by //pulling data // from some [[Port]]
+
+''Objects are [[placed|Placement]] rather'' than assembled, connected, wired, attached. This is more of a rule-based approach and gives us one central metaphor and abstraction, allowing us to treat everything in an uniform manner. You can place it as you like, and the builder tries to make sense out of it, silently disabling what doesn't make sense.
+An [[EDL]] is just a collection of configured and placed objects (and has no additional, fixed structure). [[Tracks|Track]] form a mere organisational grid, they are grouping devices not first-class entities (a track doesn't "have" a port or "is" a video track and the like; it can be configured to behave in such manner by using placements though). [[Ports|Port]] are hooks for making connections and are the only facility to build processing chains. We have global ports, and each clip is built around a lokal [[source port|ClipSourcePort]] — and that's all. No special "media viewer" and "arranger", no special role for media sources, no commitment to some fixed media stream types (video and audio). All of this is sort of pushed down to be configuration, represented as asset of some kind. For example, we have [[processing pattern|ProcPatt]] assets to represent the way of building the source network for reading from some media file (including codecs treated like effect plugin nodes)
+
+''State'' is rigorously ''externalized'' and operations are to be ''scheduled'', to simplify locking and error handling. State is either treated similar to media stream data (as addressable and cacheable data frame), or is represented as "parameter" to be served by some [[parameter provider|ParamProvider]]. Automation is just another kind of parameter, i.e. a function, and how this function is calculated is an encapsulated implementation detail (we don't have "bezier automation", and then maybe a "linear automation", a "mask automation" and yet another way to handle transitions)
+
+
+
This __proc-Layer__ and ~Render-Engine implementation started out as a design-draft by [[Ichthyo|mailto:Ichthyostega@web.de]] in summer 2007. The key idea of this design-draft is to use the [[Builder Pattern|http://en.wikipedia.org/wiki/Builder_pattern]] for the Render Engine, thus separating completely the //building// of the Render Pipeline from //running,// i.e. doing the actual Render. The Nodes in this Pipeline should process Video/Audio and do nothing else. No more decisions, tests and conditional operations when running the Pipeline. Move all of this out into the configuration of the pipeline, which is done by the Builder.
 
 !Why doesn't the current Cinelerra-2 Design succeed?
@@ -811,10 +827,10 @@ The design of Cinelerra-2 basically follows a similar design, but __fails becaus
 # too much differentiation is put into the class hierarchy instead of configuring Instances differently.<br>This causes overly heavy use of virtual functions and -- in order to ameliorate this -- falling back to hard wired branching
 # far too much coupling and back-coupling to the internals of the EDL, forcing a overly rigid structure on the latter
 
-!Try to learn from this
+!Try to learn from the Problems of the current Cinelerra-2 codebase
 * build up an [[Node Abstraction|ProcNode]] powerful enough to express //all necessary Operations// without the need to recure on the actual object type
-* need to redesign the internals of the EDL in a far more open manner. See MObjects
-* strive at a StrongSeparation between EDL and Render Engine
+* need to redesign the internals of the EDL in a far more open manner. Everything is an [[M-Object|MObjects]] which is [[placed|Placement]] in some manner
+* strive at a StrongSeparation between EDL and Render Engine, encapsulate and allways implement against interfaces
 
 
 !Design Goals
@@ -1055,7 +1071,7 @@ For this Cinelerra3 design, we could consider making GOP just another raw media
 &rarr;see in [[Wikipedia|http://en.wikipedia.org/wiki/Group_of_pictures]]
 
-
+
This wiki page is the entry point to detail notes covering some technical decisions, details and problems encountered in the course of the implementation of the Cinelerra Renderengine, the Builder and the related parts.
 
 * [[Packages, Interfaces and Namespaces|InterfaceNamespaces]]
@@ -1067,7 +1083,7 @@ For this Cinelerra3 design, we could consider making GOP just another raw media
 * [[Handling of the current Session|CurrentSession]]
 * [[collecting Ideas for Implementation Guidelines|ImplementationGuidelines]]
 * [[using the Visitor pattern?|VisitorUse]] &mdash; resulting in [[»Visiting-Tool« library implementation|VisitingToolImpl]]
-* [[Handling of Tracks and Ports in the EDL|TrackPortEDL]]
+* [[Handling of Tracks and Ports in the EDL|TrackPortEDL]]. [[Handling of Tracks|TrackHandling]] and [[Ports|PortHandling]]
 * [[identifying the basic Builder operations|BasicBuildingOperations]] and [[planning the Implementation|PlanningNodeCreaterTool]]
 
@@ -2193,7 +2209,7 @@ Placements have //value semantics,// i.e. we don't stress the identity of a plac
-
+
//This page is a scrapbook for working out the implementation of how to (re)build the [[Fixture]]//
 Structurally, (re)building the Fixture rather belongs to [[Session]]/[[EDLs|EDL]], but it is implemented very similar to the render engine build process: by treating all ~MObjects found in the various ~EDLs with a common [[visiting tool|VisitorUse]], this tool collects a simplified view with everyting made explicit, which can be pulled of as Fixture, i.e. (special kind of) EDL
 afterwards.
@@ -2242,7 +2258,7 @@ afterwards.
 <<tasksum end>>
 
-
+
//This page is a scrapbook for working out the implementation of the builder//
 
 * NodeCreaterTool is a [[visiting tool|VisitorUse]]
@@ -2291,6 +2307,18 @@ We need a way of addressing existing [[ports|Port]]. Besides, as the Ports and T
 
Playlist is a sequence of individual Render Engine Processors able to render a segment of the timeline. So, together these Processors are able to render the whole timeline (or part of the timeline if only a part has to be rendered).
 
 //Note, we have yet to specify how exactly the building and rendering will work together with the backend. There are several possibilities how to structure the Playlist//
+
+
+
+
Ports play an central role within the Proc Layer, because for everything placed and handled within the EDL, the final goal is to get it transformed into data which can be retrieved at some port. Ports are special facilities, rather like inventory, separate and not treated like all the other objects.
+We don't distinguish between "input" and "output" ports &mdash; rather, ports are thought to be ''hooks for making connections to''. By following this line of thought, each port has an input side and an output side and is in itself something like a ''Bus'' or the starting point for building a ''processing chain''. Other processing entities like effects and transitions can be placed (attached) at the port, resulting them to be appended to form this chain. Likewise, we can place [[wiring requests|WiringRequest]] to the port, meaning we want it connected to another destination port. The [[Builder]] may generate further wiring requests to fulfil the placement of other entities.
+Thus Ports are the basic building blocks of the whole render network. We distinguish ''global available'' Ports, which are like the sum groups of a mixing console, and the ''lokal port'' or [[source port|ClipSourcePort]] of the individual clips, which exist only within the duration of the corresponding clip. The design //limits the possible kinds of ports // to these two types &mdash; thus we can build local processing chains at clips and global processing chains at the global ports of the session and that's all we can do. (because of the flexibility which comes with the concept of [[placements|Placement]], this is no real limitation)
+
+The GUI can connect the viewer(s) to some port (and moreover can use [[probe points|ProbePoint]] placed like effects and connected to some port), and likewise, when starting a ''render'', we get the opportunity to specify the ports to pull the data from. Pulling data from some port is the (only) way to activate the render nodes network reachable from this port.
+
+&rarr; [[Handling of Tracks|TrackHandling]]
+&rarr; [[Handling of Ports|PortHandling]]
+
 
@@ -2597,7 +2625,7 @@ The link between ~MObject and Asset should be {{{const}}}, so the clip can't cha At first sight the link between asset and clip-MO is a simple logical relation between entities, but it is not strictly 1:1 because typical media are [[multichannel|MultichannelMedia]]. Even if the media is compound, there is //only one asset::Clip//, because in the logical view we have only one "clip-thing". On the other hand, in the Session/EDL, we have a compound clip ~MObject comprised of several elementary clip objects, each of which will refer to its own sub-media (channel) within the compound media (and don't forget, this structure can be tree-like) {{red{open question:}}} do the clip-MO's of the individual channels refer directly to asset::Media? does this mean the relation is different from the top level, where we have a relation to a asset::Clip??
-
+
The Render Engine is the part of the application doing the actual video calculations. Its operations are guided by the Objects and Parameters edited by the user in [[the EDL|EDL]] and it retrieves the raw audio and video data from the [[Data backend|backend.html]]. Because the inner workings of the Render Engine are closely related to the structures used in the EDL, this design covers [[the aspect of objects placed into the EDL|MObjects]] as well.
 <<<
 ''Status'': started out as design draft in summer '07, Ichthyo is now in the middle of a //first, draft, prototypical// implementation in C++
@@ -2617,7 +2645,7 @@ The system is ''open'' inasmuch every part mirrors the structure of correspondin
 &rarr; BuildProcess and RenderProcess
 &rarr; [[Two Examples|Examples]] (Object diagrams) 
 &rarr; how [[Automation]] works  {{red{to be defined in more detail}}}
-&rarr; [[Problems|ProblemsTodo]] {{red{to be solved}}}
+&rarr; [[Problems|ProblemsTodo]] to be solved and notable [[design decisions|DesignDecisions]]
 &rarr; [[Implementation Details|ImplementationDetails]] {{red{WIP}}}
 
@@ -2643,14 +2671,14 @@ The Session object is a singleton &mdash; actually it is a »~PImpl«-Facade * a collection of ''global Ports'' * the ''Fixture'' with a possibility to [[(re)build it|PlanningBuildFixture]]
-
-
The [[Session]] (sometimes also called //Project//) contains all informations and objects to be edited by the User. It can be saved and loaded. The individual Objects within the Session, i.e. Clips, Media, Effects, are contained in one (or several) collections within the Session, which we call [[EDL (Edit Decision List)|EDL]]. Moreover, the sesion contains references to all the Media files used, and it contains various default or user defined configuration. At any given time, there is //only one current session// opened within the application.
+
+
The [[Session]] (sometimes also called //Project//) contains all informations and objects to be edited by the User. It can be saved and loaded. The individual Objects within the Session, i.e. Clips, Media, Effects, are contained in one (or several) collections within the Session, which we call [[EDL (Edit Decision List)|EDL]]. Moreover, the sesion contains references to all the Media files used, and it contains various default or user defined configuration, all being represented as [[Asset]]. At any given time, there is //only one current session// opened within the application.
 
 !!!larger projects
 For larger editing projects the simple structure of a session containing "the" timeline is not sufficient. Rather, we have several timelines, e.g. one for each scene. Or we could have several layered or nested timelines (compositional work, multimedia productions). To support these cases without making the default case more complicated, Cinelerra-3 introduces a //focus// for selecting the //current EDL,// which will receive all editing operations.
 
 !!!the definitive state
-With all the structural complexities possible within such a session, we need an isolation layer to provide __one__ definitive state where all configuration has been made explicit. Thus the session manages one special object list, the [[Fixture]], which can be seen as all currently active object placed onto a single timeline.
+With all the structural complexities possible within such a session, we need an isolation layer to provide __one__ definitive state where all configuration has been made explicit. Thus the session manages one special object list, the [[Fixture]], which can be seen as all currently active objects placed onto a single timeline.
 
 !!!organisational devices
 The possibility of having multiple ~EDLs helps organizing larger projects. Each [[EDL]] is just a logical grouping; because all effective properties of any MObject within this EDL are defined by the ~MObject itself and the [[Placement]], by which the object is anchored to some time point, some track, can be connected to some port, or linked to another object. In a similar manner, Tracks are just another organisational aid for grouping objects, disabling them and defining common output ports.
@@ -3931,7 +3959,18 @@ function addKeyDownHandlers(e)
 
 
-
+
+
Tracks are just a structure used to organize the Media Objects within the EDL. They form a grid, and besides that, they have no special meaning. They are grouping devices, not first-class entities. A track doesn't "have" a port or "is" a video track and the like; it can be configured to behave in such manner by using placements.
+
+Tracks are assets on their own, but they can be found within a given EDL. So, several ~EDLs can share a single track or each EDL can have its own, separate tracks. 
+* Like most ~MObjects, tracks have a asset view: you can find a track asset in the asset manager.
+* and they have an object view: there is an track MObject which can be [[placed|Placement]], thus defining properties of this track within one EDL
+Of course, we can place other ~MObjects relative to some track (that's the main reason why we want to have tracks). In this sense, the [[handling of Tracks|TrackHandling]] is somewhat special: the placement of some track can be found directly within the EDL (and not within the general collection of placed objects which form the contents of any EDL). This placement defines properties of the track, which will be inherited if necessary by all ~MObjects placed to this track. For example, if placing a track to some global [[Port]], and if placing a clip to this track, without placing the clip directly to another port, the port information of the track will be fetched by the builder when needed to make the output connection of the clip.
+&rarr; [[Handling of Tracks|TrackHandling]]
+&rarr; [[Handling of Ports|PortHandling]]
+
+
+
''towards a definition of »Track«''. We don't want to tie ourself to some naive and overly simplistic definition, just because it is convenient. For classical (analogue) media, tracks are physical entities dictated by the nature of the process by which the media works. Especially, Tape machines have read/writing heads, which creates fixed tracks to which to route the signals. This is a practical geometric necessity. For digital media, there is no such necessity. We are bound primarily by the editor's habits of working.
 
 !!!Assessment of Properties
@@ -3946,17 +3985,20 @@ Starting with the assumption "everything is just connected processing nodes
 
 !!!the constant part
 there seems to be some non time-varying part in each EDL, that doesn't fit well with the simple model "objects on a timeline". Tracks seen as an organisational grid fall into this category: they are a global property of the given EDL. They could be associated to the Session as a whole, but effectively this would subvert the concept of having [[several EDLs|SessionOverview]]. On the other hand, 
-[[ports|Port]] for Video and Sound output are obviously a global property of the Session. There can be several global ports forming a matrix of subgroup busses. We could add ports to tracks as well, but we don't do this, because, again, this would run counter to our attempt of treating tracks as merely organisational entities. We have special [[source ports|ClipSourcePort]] on individual clips though, and we will have ports on meta-clips too.
+[[ports|Port]] for Video and Sound output are obviously a global property of the Session. There can be several global ports forming a matrix of subgroup busses. We could add ports to tracks by default as well, but we don't do this, because, again, this would run counter to our attempt of treating tracks as merely organisational entities. We have special [[source ports|ClipSourcePort]] on individual clips though, and we will have ports on meta-clips too.
 
 !Design
-__Tracks__ are just a structure used to organize the Media Objects within the EDL. They form a grid, and besides that, they have no special meaning. It seems convenient to make the tracks not just a list, but allow grouping (tree structure) right from start. __~MObjects__ are placed rather than wired. The wiring is derived from the __Placement__. Placing can happen in several dimensions:
+[[Tracks|Track]] are just a structure used to organize the Media Objects within the EDL. They form a grid, and besides that, they have no special meaning. It seems convenient to make the tracks not just a list, but allow grouping (tree structure) right from start. __~MObjects__ are ''placed'' rather than wired. The wiring is derived from the __Placement__. Placing can happen in several dimensions:
 * placing in time will define when to activate and show the object.
 * placing onto a track associates the ~MObject with this track; the GUI will show it on this track and the track may be used to resolve other properties of the object.
-* placing to a __Port__ brings the object in conjunction with this Port for the build process. It will be considered when building the render network for this port. Source-like objects (clips and exit nodes of effect chains) will be connected to the port, while transforming objects (effects) are inserted at the port.
+* placing to a __Port__ brings the object in conjunction with this Port for the build process. It will be considered when building the render network for this port. Source-like objects (clips and exit nodes of effect chains) will be connected to the port, while transforming objects (effects) are inserted at the port. (you may read "placed to port X" as "plug into port X")
 * depending on the nature of the port and the source, placing to some port may create additional degrees of freedom, demanding the object to be placed in this new, additional dimensions: Connecting to video out e.g. creates an overlay mode and a layer position which need to be specified, while connecting to a spatial sound system creates the necessity of a pan position. On the other hand, placing a mono clip onto a mono Port creates no additional degrees of freedom.
-Placements are __resolved__ resulting in an ExplicitPlacement. In most cases this is just a gathering of properties, but as Placements can be incomplete and relative, there is room for real solving. The resolving mechanism tries to __derive missing properties__ from the __context__: When a clip isn't placed to some port but to a Track, than the Track and its parents will be inspected. If some of them has been placed to a port, the object will be connected to this port. Similar for layers and pan position. This is done by [[Placement]] and LocatingPin; as the [[Builder]] uses ~ExplicitPlacements, he isn't concerned with this resolving and uses just the data they deliver to drive the [[basic building operations|BasicBuildingOperations]]
+Placements are __resolved__ resulting in an ExplicitPlacement. In most cases this is just a gathering of properties, but as Placements can be incomplete and relative, there is room for real solving. The resolving mechanism tries to __derive missing properties__ from the __context__: When a clip isn't placed to some port but to a Track, than the Track and its parents will be inspected. If some of them has been placed to a port, the object will be connected to this port. Similar for layers and pan position. This is done by [[Placement]] and LocatingPin; as the [[Builder]] uses ~ExplicitPlacements, he isn't concerned with this resolving and uses just the data they deliver to drive the [[basic building operations|BasicBuildingOperations]] +&rarr; [[Definition|Track]] and [[handling of Tracks|TrackHandling]] +&rarr; [[Definition|Port]] and [[handling of Ports|PortHandling]] +
-
+
Transitions combine the data from at least two processing chains and do this combining in a time varying fashion. So, any transition has
 * N input connections
 * either one or N output connections
@@ -3964,7 +4006,7 @@ Placements are __resolved__ resulting in an ExplicitPlacement. In most cases thi
 * some control data connection to a ParamProvider, because in the most general case the controling curves are treated like automation
 
 !!!how much output ports?
-The standard case of a transition is sort of mixing together two input streams, like e.g. a simple dissolve. For this to be of any use, this input streams need to be connected to the same ouput port before and after the transition, i.e. the inputs and the transition share placement to the same output destination. In this case, when the transition starts, the direct connections can be suspended and the transition will switch in seamlessly.
+The standard case of a transition is sort of mixing together two input streams, like e.g. a simple dissolve. For this to be of any use, this input streams need to be connected to the same ouput port before and after the transition (with regards to the timeline), i.e. the inputs and the transition share placement to the same output destination. In this case, when the transition starts, the direct connections can be suspended and the transition will switch in seamlessly.
 
 Using transitions is a very basic task and thus needs viable support by the GUI. Handling of transitions need to be very convienient, because it is so important. Because of this, it is compelling to subsume a more complicated situation and treat this more complicated case similar. This is the case, when two (or N) elements have to be combined in the way of a transition, but their further processing in the processing chain //after// the transition needs to be different, maybe they belong to differnent subgroups, have to appear on different layers or with different pan positions. Of courese, the workaround is simple, at least "simple" from the programmers point of view. It is //not// simple from the editor's point of view the moment the editor has to do this simple thing (changing the wiring and add manualy synced fade curves to the individual parts) a dozend or even a hundred times in some larger project.
 

From d255d68d350a300fd5eb633ebbcf5b6b66a391f9 Mon Sep 17 00:00:00 2001
From: Ichthyostega 
Date: Mon, 7 Jan 2008 18:16:03 +0100
Subject: [PATCH 2/8] reflect design decisions in UML, new track-MO class,
 start replacing tracknumber by Port

---
 doc/devel/uml/class128005.html                |   3 +-
 doc/devel/uml/class128133.html                |   6 +-
 doc/devel/uml/class128261.html                |   8 +-
 doc/devel/uml/class128389.html                |   6 +-
 doc/devel/uml/class129157.html                |   2 +-
 doc/devel/uml/class130053.html                |   3 +-
 doc/devel/uml/class136965.html                |   2 +-
 doc/devel/uml/class137989.html                |   3 +-
 doc/devel/uml/class138117.html                |   9 +-
 doc/devel/uml/class140421.html                |  24 ++++
 doc/devel/uml/classes.html                    |   3 +-
 doc/devel/uml/classes_list.html               |   3 +-
 doc/devel/uml/fig128133.png                   | Bin 64119 -> 67486 bytes
 doc/devel/uml/fig130309.png                   | Bin 40327 -> 40186 bytes
 doc/devel/uml/fig131205.png                   | Bin 15040 -> 15936 bytes
 doc/devel/uml/index.html                      |   5 +-
 doc/devel/uml/index_67.html                   |  34 ++---
 doc/devel/uml/index_68.html                   |   2 +-
 doc/devel/uml/index_69.html                   |   2 +-
 doc/devel/uml/index_70.html                   |   1 -
 doc/devel/uml/index_72.html                   |   2 +-
 doc/devel/uml/index_73.html                   |   2 +-
 doc/devel/uml/index_77.html                   |   2 +-
 doc/devel/uml/index_79.html                   |   4 +-
 doc/devel/uml/index_80.html                   |   3 +
 doc/devel/uml/index_82.html                   |   2 +-
 doc/devel/uml/index_83.html                   |   3 +-
 doc/devel/uml/index_84.html                   |  13 +-
 doc/devel/uml/index_86.html                   |  10 +-
 doc/devel/uml/index_87.html                   |   2 +-
 doc/devel/uml/public_properties.html          |   1 +
 src/proc/asset.hpp                            |   4 +-
 src/proc/asset/{outport.cpp => port.cpp}      |   4 +-
 src/proc/asset/{outport.hpp => port.hpp}      |  13 +-
 src/proc/asset/struct.cpp                     |  30 ++--
 src/proc/asset/struct.hpp                     |  17 ++-
 src/proc/asset/track.cpp                      |   8 +-
 src/proc/asset/track.hpp                      |   7 +-
 src/proc/assetmanager.cpp                     |   2 +
 src/proc/mobject/explicitplacement.hpp        |   6 +-
 src/proc/mobject/placement.hpp                |   5 +-
 src/proc/mobject/session/abstractmo.hpp       |   1 -
 src/proc/mobject/session/constraint.cpp       |  37 +++++
 src/proc/mobject/session/constraint.hpp       |  47 +++++++
 src/proc/mobject/session/edl.cpp              |  29 +++-
 src/proc/mobject/session/edl.hpp              |   8 +-
 src/proc/mobject/session/fixture.hpp          |   1 -
 src/proc/mobject/session/locatingpin.cpp      |   9 +-
 src/proc/mobject/session/locatingpin.hpp      |  13 +-
 src/proc/mobject/session/mobjectfactory.cpp   |  12 +-
 src/proc/mobject/session/mobjectfactory.hpp   |   7 +-
 src/proc/mobject/session/plug.cpp             |  38 +++++
 src/proc/mobject/session/plug.hpp             |  52 +++++++
 src/proc/mobject/session/track.cpp            |  16 ++-
 src/proc/mobject/session/track.hpp            |  45 ++++--
 src/proc/mobject/session/wish.cpp             |  37 +++++
 src/proc/mobject/session/wish.hpp             |  52 +++++++
 .../mobject/session/sessionstructuretest.cpp  |   9 +-
 uml/cinelerra3/128133                         |  33 +++--
 uml/cinelerra3/128133.diagram                 |  88 ++++++++----
 uml/cinelerra3/128261                         | 115 +++++++++++----
 uml/cinelerra3/129285                         |   2 +-
 uml/cinelerra3/130309.diagram                 |   9 +-
 uml/cinelerra3/130437                         | 131 +++++++++++++++++-
 uml/cinelerra3/131205.diagram                 |  29 ++--
 uml/cinelerra3/5.session                      |  23 ++-
 uml/cinelerra3/cinelerra3.prj                 |   2 +-
 67 files changed, 885 insertions(+), 216 deletions(-)
 create mode 100644 doc/devel/uml/class140421.html
 rename src/proc/asset/{outport.cpp => port.cpp} (88%)
 rename src/proc/asset/{outport.hpp => port.hpp} (75%)
 create mode 100644 src/proc/mobject/session/constraint.cpp
 create mode 100644 src/proc/mobject/session/constraint.hpp
 create mode 100644 src/proc/mobject/session/plug.cpp
 create mode 100644 src/proc/mobject/session/plug.hpp
 create mode 100644 src/proc/mobject/session/wish.cpp
 create mode 100644 src/proc/mobject/session/wish.hpp

diff --git a/doc/devel/uml/class128005.html b/doc/devel/uml/class128005.html
index fabe77cf9..524fbb0ac 100644
--- a/doc/devel/uml/class128005.html
+++ b/doc/devel/uml/class128005.html
@@ -19,7 +19,8 @@
 

Declaration :

  • C++ : class SessionImpl : public Session

Implementation class for the Session interface

Artifact : sessionimpl, Component(s) : Session

Relation edls (<directional aggregation by value>)

Declaration :

  • Uml : # edls : EDL, multiplicity : 1..*
  • C++ : protected: <EDL> edls
-
Relation fixture (<unidirectional association>)

Declaration :

  • Uml : # fixture : Fixture, multiplicity : 1
  • C++ : protected: Fixture * fixture
+
Relation theFixture (<unidirectional association>)

Declaration :

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

Declaration :

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

the global ports (busses) of the session

All public operations : currEDL , getFixture

diff --git a/doc/devel/uml/class128133.html b/doc/devel/uml/class128133.html index cbf83e3ea..caa5c3e37 100644 --- a/doc/devel/uml/class128133.html +++ b/doc/devel/uml/class128133.html @@ -18,8 +18,8 @@

Declaration :

  • C++ : class EDL

Directly inherited by : Fixture

Artifact : edl, Component(s) : Session

- -
Relation tracks (<directional aggregation by value>)

Declaration :

  • Uml : # tracks : Track, multiplicity : *
  • C++ : protected: list<Track> tracks
-
Relation clips (<directional aggregation>)

Declaration :

  • Uml : # clips : MObject, multiplicity : *
  • C++ : protected: list<MObject *> clips
+ +
Relation clips (<directional aggregation>)

Declaration :

  • Uml : # clips : MObject, multiplicity : *
  • C++ : protected: list<MObject *> clips
+
Relation track (<unidirectional association>)

Declaration :

  • Uml : # track : Track
  • C++ : protected: Track* track
diff --git a/doc/devel/uml/class128261.html b/doc/devel/uml/class128261.html index 9cb960678..0d8043e71 100644 --- a/doc/devel/uml/class128261.html +++ b/doc/devel/uml/class128261.html @@ -17,11 +17,11 @@

Declaration :

  • C++ : class Fixture : public EDL

Artifact : fixture, Component(s) : Session

- -
Relation tracks (<directional aggregation by value>)

Declaration :

  • Uml : # tracks : Track, multiplicity : 1..*
  • C++ : protected: Track tracks
-
Relation timeline (<directional aggregation by value>)

Declaration :

+ +
Relation theTimeline (<directional aggregation by value>)

Declaration :

Operation getPlaylistForRender

Declaration :

  • Uml : + getPlaylistForRender() : list<ExplicitPlacement [ProcessingLayer::MObject]>
  • C++ : public: list<ExplicitPlacement [ProcessingLayer::MObject]> getPlaylistForRender ()
-
Operation getAutomation

Declaration :

  • Uml : + getAutomation() : Auto [ProcessingLayer::MObject]*
  • C++ : public: Auto [ProcessingLayer::MObject]* getAutomation ()
+
Operation getAutomation

Declaration :

  • Uml : + getAutomation() : Auto [ProcessingLayer::MObject]*
  • C++ : public: Auto [ProcessingLayer::MObject]* getAutomation ()
+
Relation track (<unidirectional association>)

Declaration :

  • Uml : # track : Track
  • C++ : protected: Track* track

All public operations : getAutomation , getPlaylistForRender

diff --git a/doc/devel/uml/class128389.html b/doc/devel/uml/class128389.html index aeb25e07f..222aa9902 100644 --- a/doc/devel/uml/class128389.html +++ b/doc/devel/uml/class128389.html @@ -16,5 +16,9 @@ -

Declaration :

Artifact : track

+

Declaration :

Artifact : track, Diagram : Session structure

+ +
Relation subTracks (<directional aggregation by value>)

Declaration :

  • Uml : + subTracks : Track, multiplicity : *
  • C++ : public: Track subTracks

Child tracks in a tree structure

+

All public operations : apply , apply , dispatchOp

+ diff --git a/doc/devel/uml/class129157.html b/doc/devel/uml/class129157.html index fb8effd05..f4d84f14f 100644 --- a/doc/devel/uml/class129157.html +++ b/doc/devel/uml/class129157.html @@ -16,7 +16,7 @@ -

Declaration :

Directly inherited by : Auto Label

+

Declaration :

Directly inherited by : Auto Label Track

Artifact : meta

All public operations : apply , apply , dispatchOp

diff --git a/doc/devel/uml/class130053.html b/doc/devel/uml/class130053.html index 7df85e17a..a7a18ffb9 100644 --- a/doc/devel/uml/class130053.html +++ b/doc/devel/uml/class130053.html @@ -16,7 +16,8 @@ -

Declaration :

+

Declaration :

Directly inherited by : Plug

+

All public operations : get_repr

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

Declaration :

  • C++ : class Struct : public Asset

Directly inherited by : OutPort ProcPatt Track

+

Declaration :

  • C++ : class Struct : public Asset

Directly inherited by : Port ProcPatt Track

key abstraction: structural asset

Artifact : struct

All public operations : enable , getDependant , getParents , isActive

diff --git a/doc/devel/uml/class137989.html b/doc/devel/uml/class137989.html index 6c5bf6158..5ee601cc6 100644 --- a/doc/devel/uml/class137989.html +++ b/doc/devel/uml/class137989.html @@ -17,8 +17,7 @@

Declaration :

  • C++ : class Track : public Struct

structural asset holding the configuration of a track in the EDL

Artifact : track

- -
Relation wiringTemplate (<unidirectional association>)

Declaration :

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

All public operations : enable , getDependant , getParents , isActive

diff --git a/doc/devel/uml/class138117.html b/doc/devel/uml/class138117.html index 6b36b4366..a635bbfb4 100644 --- a/doc/devel/uml/class138117.html +++ b/doc/devel/uml/class138117.html @@ -4,20 +4,21 @@ -Class OutPort +Class Port -
Class OutPort
+
Class Port

-

Declaration :

structural asset corresponding to some port generating media output

Artifact : outport

-
+

Declaration :

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

Artifact : outport

+ +
Relation wiringTemplate (<unidirectional association>)

Declaration :

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

All public operations : enable , getDependant , getParents , isActive

diff --git a/doc/devel/uml/class140421.html b/doc/devel/uml/class140421.html new file mode 100644 index 000000000..9fefd2ebb --- /dev/null +++ b/doc/devel/uml/class140421.html @@ -0,0 +1,24 @@ + + + + + + +Class Plug + + + + + +
Class Plug
+

+ + + + +

Declaration :

+ +
Relation outPort (<unidirectional association>)

Declaration :

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

the Port this MObject wants to be conected to

+

All public operations : get_repr

+ + diff --git a/doc/devel/uml/classes.html b/doc/devel/uml/classes.html index a411e8c2e..861c332cc 100644 --- a/doc/devel/uml/classes.html +++ b/doc/devel/uml/classes.html @@ -88,12 +88,13 @@ MObjectinterface MutexI provided a reworked Mutex class in my cinelerra2 repository NodeCreatorToolThis 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. -OutPortstructural asset corresponding to some port generating media output ParameterDescriptor and access object for a plugin parameter. Parameters may be provided with values from the session, and this values may be automated. ParamProviderinterfaceA facility to get the actual value of a plugin/effect parameter PathManagerWhile building a render engine, this Strategy class decides on the actual render strategy in accordance to the current controller settings (system state) Placementinterfaceused to specify the position of a MObject in the EDL. This can be done in various ways (absolute, relative).
Placement at the same time acts as (refcounting) smart pointer for accessing the MObject. +Plug PluginAdapterAdapter used to integrage an effects processor in the render pipeline +Portstructural asset corresponding to some port for building a processing chain and generating media output Prefetch Previewalternative version of the media data, probably with lower resolution Prockey abstraction: data processing asset diff --git a/doc/devel/uml/classes_list.html b/doc/devel/uml/classes_list.html index b91453124..9b03604d3 100644 --- a/doc/devel/uml/classes_list.html +++ b/doc/devel/uml/classes_list.html @@ -89,12 +89,13 @@ MObject
Mutex
NodeCreatorTool
-OutPort
Parameter
ParamProvider
PathManager
Placement
+Plug
PluginAdapter
+Port
Prefetch
Preview
Proc
diff --git a/doc/devel/uml/fig128133.png b/doc/devel/uml/fig128133.png index ccbcf7d90466ac251af2c09560d08825f2e9fd7a..8b525effdda2c19eb4a2b9e92f808937b8b1b57e 100644 GIT binary patch delta 58435 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 H-~E38RE4js delta 54974 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 diff --git a/doc/devel/uml/fig130309.png b/doc/devel/uml/fig130309.png index 8e7461c94430f1cb85b888d6e71093af24157686..b485d3dcc7a54e603a93e20e35d493b381bb4fe9 100644 GIT binary patch delta 21064 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 Y+_WMuM(sMtDn%d;;Sb~32TsQR396RzmjD0& delta 21298 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 diff --git a/doc/devel/uml/fig131205.png b/doc/devel/uml/fig131205.png index 04fc181b776b859a86cd6c5f15a36733529f4d6e..b35cdf424ab816236e230cbb8f52df442906785c 100644 GIT binary patch literal 15936 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

lH2?c5=V(bS~2Bi6N&6)#;K3mv#i8S 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 diff --git a/doc/devel/uml/index.html b/doc/devel/uml/index.html index 888b6b49c..e623f8fd7 100644 --- a/doc/devel/uml/index.html +++ b/doc/devel/uml/index.html @@ -263,7 +263,7 @@ Documentation
Artifact outport

structural asset corresponding to some port generating media output

-

Artifact source associated with : OutPort

+

Artifact source associated with : Port

Artifact track

structural asset holding the configuration of a track in the EDL

@@ -612,7 +612,7 @@ Documentation
Class Effect
Class Codec
Class Track
-
Class OutPort
+
Class Port
Class ProcPatt
Class Dataset
Class DB
@@ -657,6 +657,7 @@ Documentation
+
Class Plug

2.2.2 Package Builder

diff --git a/doc/devel/uml/index_67.html b/doc/devel/uml/index_67.html index 269befa2c..c41be7ee3 100644 --- a/doc/devel/uml/index_67.html +++ b/doc/devel/uml/index_67.html @@ -29,33 +29,33 @@ checked_outrelationthis list keeps all mappings which are in use, and thus prevents them from Cache aging Cinelerra3artifactthe main executable to be built cinelerra3package +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance class instanceclass instance class instanceclass instance class instanceclass instance class instanceclass instance -class instanceclass instance -class instanceclass instance class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance class instanceclass instance -class instanceclass instance -class instanceclass instance -class instanceclass instance class instanceclass instance class instanceclass instance +class instanceclass instance +class instanceclass instance class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +class instanceclass instance +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. diff --git a/doc/devel/uml/index_68.html b/doc/devel/uml/index_68.html index 68da1dfbd..8f898d37f 100644 --- a/doc/devel/uml/index_68.html +++ b/doc/devel/uml/index_68.html @@ -28,8 +28,8 @@ designpackage designpackageAll things concering the big picture.
Not a real code package, rather a container for design drafts, specifications, decisions. detect Channelsuse case -determine Render 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 20380e20a..caf706b98 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 -effectartifactEDL representation of a pluggable and automatable effect. effectartifactEffect or media processing component +effectartifactEDL representation of a pluggable and automatable effect. 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 10124ce04..b36d60aff 100644 --- a/doc/devel/uml/index_70.html +++ b/doc/devel/uml/index_70.html @@ -35,7 +35,6 @@ fixtureartifactthe (low level) representation of the EDL with concrete placement data Fixtureclass Fixturecomponent -fixturerelation 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 58b669cd2..a26e1439f 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_77.html b/doc/devel/uml/index_77.html index 775e82c1e..68bbd5cfb 100644 --- a/doc/devel/uml/index_77.html +++ b/doc/devel/uml/index_77.html @@ -32,8 +32,8 @@ MediaFactoryclassspecialized Asset Factory for configuring (new) media asset instances based on existing media files on disk; can create placeholder assets as well merge activity nodemerge activity node Metaclasskey abstraction: metadata and organisational asset -metaartifactabstract base class of all MObjects representing meta data or processing instructions metaartifactkey abstraction: metadata and organisational asset +metaartifactabstract base class of all MObjects representing meta data or processing instructions Metaclass mobjectartifactKey Abstraction: A Media Object in the Session mobjectpackagesourcecode package

MObject Subsystem
including the Session (EDL), Builder and Processing Controller diff --git a/doc/devel/uml/index_79.html b/doc/devel/uml/index_79.html index 9ba074764..13aab1740 100644 --- a/doc/devel/uml/index_79.html +++ b/doc/devel/uml/index_79.html @@ -19,11 +19,11 @@ 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 cinelerra-3 codebase is "cin3". -ouputclass instance ouputclass instance ouputclass instance -OutPortclassstructural asset corresponding to some port generating media output +ouputclass instance outportartifactstructural asset corresponding to some port generating media output +outPortrelationthe Port this MObject wants to be conected to outputrelation Overviewcomponent diagramThis drawing shows the top level compoents and relations Overview Render Enginedeployment diagram diff --git a/doc/devel/uml/index_80.html b/doc/devel/uml/index_80.html index 2e0da44b5..9258e1132 100644 --- a/doc/devel/uml/index_80.html +++ b/doc/devel/uml/index_80.html @@ -29,11 +29,14 @@ Placementclassused to specify the position of a MObject in the EDL. This can be done in various ways (absolute, relative).
Placement at the same time acts as (refcounting) smart pointer for accessing the MObject. playoperationTODO: will probably be handled differently (see Cehteh) playlistnode +Plugclass plugIDattributeIdentifier of the Plugin to be used PluginAdapterclassAdapter used to integrage an effects processor in the render pipeline pluginadapterartifactAdapter for integrating various Effect processors in the render pipeline pnodenode pointattributeidentifying the point where the nodes should be attached +Portclassstructural asset corresponding to some port for building a processing chain and generating media output +portsrelationthe global ports (busses) of the session Posix Threads Abstractionclass viewC++ wrapers for pthreads Prefetchclass Previewclassalternative version of the media data, probably with lower resolution diff --git a/doc/devel/uml/index_82.html b/doc/devel/uml/index_82.html index a76e8f590..3a3a83808 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 diff --git a/doc/devel/uml/index_83.html b/doc/devel/uml/index_83.html index eb3719cf0..847236104 100644 --- a/doc/devel/uml/index_83.html +++ b/doc/devel/uml/index_83.html @@ -46,8 +46,8 @@ SimpleClipclassElementary clip consisting of only one media stream SmartPointerclass SmartPointersclass view -sourcerelationmedia source of this clip sourcerelationthe media source this clip referes to +sourcerelationmedia source of this clip SourceclassSource Node: represents a media source to pull data from. sourceartifactRepresentation of a Media source Source Overviewdeployment diagram @@ -64,6 +64,7 @@ Struct-Asset Relationsclass diagram subjectrelationPlacement acts as smart pointer subPatternrelation +subTracksrelationChild tracks in a tree structure diff --git a/doc/devel/uml/index_84.html b/doc/devel/uml/index_84.html index 00c40c769..b2f672c79 100644 --- a/doc/devel/uml/index_84.html +++ b/doc/devel/uml/index_84.html @@ -19,35 +19,36 @@ NameKindDescription the render configuration flowactivity diagram theApp_attributeholds the single instance and triggers initialization +theFixturerelation +theTimelinerelation ThreadclassWe can basically reuse the Thread class design from cinelerra2, Thread becomes a baseclass for all Threads timeattribute timeartifactunified representation of a time point, including conversion functions Timeclassdenotes a temporal position (time point), based on timeline start.

investigate posix.4 realtime timers, wrap these here timelinenode -timelinerelation toolpackagesourcecode package

Tools and Utilities
(separate from the main cinelrra binary) Toolclass ToolFactoryclass toolfactoryartifactsupply of Tool implementations for the Builder Trackclassstructural asset holding the configuration of a track in the EDL +trackrelation trackattribute -trackartifactdescriptor for one track in the Session +trackrelation trackartifactstructural asset holding the configuration of a track in the EDL +trackartifactdescriptor for one track in the Session Trackclass tracksrelationelementary media assets comprising this compound -tracksrelation -tracksrelation 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 diff --git a/doc/devel/uml/index_86.html b/doc/devel/uml/index_86.html index 8695a80a4..74937c93e 100644 --- a/doc/devel/uml/index_86.html +++ b/doc/devel/uml/index_86.html @@ -22,21 +22,21 @@ vframeartifacta buffer and render process holding a Video frame vid1class instance vid1class instance -vid_aclass instance -vid_Aclass instance vid_aclass instance vid_Aclass instance vid_Aclass instance -videoclass instance +vid_aclass instance +vid_Aclass instance videoclass instance videoclass instance videoclass instance -video1class instance +videoclass 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 cdf4db578..54f6d4f8c 100644 --- a/doc/devel/uml/index_87.html +++ b/doc/devel/uml/index_87.html @@ -19,7 +19,7 @@ NameKindDescription whatoperation whatoperationthe base class of all exceptions thrown by the standard library -wiringTemplaterelation +wiringTemplaterelation Wishclass write_bufferrelation WriteBufferclass diff --git a/doc/devel/uml/public_properties.html b/doc/devel/uml/public_properties.html index 6790afee8..2cf2100de 100644 --- a/doc/devel/uml/public_properties.html +++ b/doc/devel/uml/public_properties.html @@ -24,6 +24,7 @@ nodesDoAttach orgAssetorigin 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 cinelerra-3 codebase is "cin3". pointDoAttachidentifying the point where the nodes should be attached +subTracksTrackChild tracks in a tree structure versionAssetversion 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. diff --git a/src/proc/asset.hpp b/src/proc/asset.hpp index dabb73039..0df25a3fd 100644 --- a/src/proc/asset.hpp +++ b/src/proc/asset.hpp @@ -168,8 +168,8 @@ namespace asset Ident (const string& n, const Category& cat, - const string& o, - const uint ver); + const string& o = "cin3", + const uint ver=1); /** @note equality ignores version differences */ bool operator== (const Ident& other) const diff --git a/src/proc/asset/outport.cpp b/src/proc/asset/port.cpp similarity index 88% rename from src/proc/asset/outport.cpp rename to src/proc/asset/port.cpp index c0a228319..116f7ee63 100644 --- a/src/proc/asset/outport.cpp +++ b/src/proc/asset/port.cpp @@ -1,5 +1,5 @@ /* - OutPort - structural asset corresponding to some port generating media output + Port - structural asset corresponding to some port generating media output Copyright (C) CinelerraCV 2007, Hermann Vosseler @@ -21,7 +21,7 @@ * *****************************************************/ -#include "proc/asset/outport.hpp" +#include "proc/asset/port.hpp" namespace asset { diff --git a/src/proc/asset/outport.hpp b/src/proc/asset/port.hpp similarity index 75% rename from src/proc/asset/outport.hpp rename to src/proc/asset/port.hpp index c0afd059d..e854cfe86 100644 --- a/src/proc/asset/outport.hpp +++ b/src/proc/asset/port.hpp @@ -1,5 +1,5 @@ /* - OUTPORT.hpp - structural asset corresponding to some port generating media output + PORT.hpp - structural asset corresponding to some port generating media output Copyright (C) CinelerraCV 2007, Hermann Vosseler @@ -25,6 +25,7 @@ #define ASSET_OUTPORT_H #include "proc/asset/struct.hpp" +#include "proc/asset/procpatt.hpp" @@ -33,11 +34,15 @@ namespace asset /** - * structural asset corresponding to some port generating media output + * structural asset corresponding to some port + * for building a processing chain and + * generating media output */ - class OutPort : public Struct + class Port : public Struct { - + protected: + ProcPatt* wiringTemplate; + }; diff --git a/src/proc/asset/struct.cpp b/src/proc/asset/struct.cpp index 069830c27..de4160bce 100644 --- a/src/proc/asset/struct.cpp +++ b/src/proc/asset/struct.cpp @@ -23,6 +23,8 @@ #include "proc/assetmanager.hpp" #include "proc/asset/struct.hpp" +#include "proc/asset/track.hpp" + #include "common/util.hpp" #include "nobugcfg.h" @@ -31,7 +33,18 @@ namespace asset namespace // Implementation details { - /** helper: .....*/ + /** @internal derive a sensible asset ident tuple when creating + * a track asset based on a query + * @todo define the actual naming scheme of struct assets + */ + const Asset::Ident + createTrackIdent (Query& query) + { + string name ("track-" + query); // TODO something sensible here; append number, sanitize etc. + TODO ("track naming scheme??"); + Category category (STRUCT,"tracks"); + return Asset::Ident (name, category ); + } } @@ -41,19 +54,18 @@ namespace asset /** Factory method for Structural Asset instances. .... - * @todo actually define + * @todo work out the struct asset naming scheme! * @return an Struct smart ptr linked to the internally registered smart ptr * created as a side effect of calling the concrete Struct subclass ctor. */ - StructFactory::PType - StructFactory::operator() (Asset::Ident& key) ////TODO + template<> + shared_ptr + StructFactory::operator() (Query query) { - UNIMPLEMENTED ("Struct-Factory"); + TODO ("actually evaluate the query..."); + Track* pT = new Track (createTrackIdent (query)); + return AssetManager::instance().getPtr (*pT); } - - - - } // namespace asset diff --git a/src/proc/asset/struct.hpp b/src/proc/asset/struct.hpp index 33d329979..9b2c56e3f 100644 --- a/src/proc/asset/struct.hpp +++ b/src/proc/asset/struct.hpp @@ -40,6 +40,9 @@ #include "proc/asset.hpp" #include "common/factory.hpp" +#include + +using std::string; namespace asset @@ -86,6 +89,15 @@ namespace asset inline ID::ID(const Struct& stru) : ID (stru.getID()) {}; + /** + * Query for a special kind of structural Asset + */ + template + class Query : public std::string + { + public: + Query (string predicate) : string(predicate) {} + }; /** @@ -95,8 +107,9 @@ namespace asset { public: typedef shared_ptr PType; - - PType operator() (Asset::Ident& key); ////////////TODO define actual operation + + template + shared_ptr operator() (Query query); ////////////TODO define actual operation }; diff --git a/src/proc/asset/track.cpp b/src/proc/asset/track.cpp index d7b9b8feb..efbb3aaf9 100644 --- a/src/proc/asset/track.cpp +++ b/src/proc/asset/track.cpp @@ -26,8 +26,12 @@ namespace asset { - /** */ - + /** @todo work out the details of track assets */ + Track::Track (const Asset::Ident& idi) + : Struct (idi) + { + + } } // namespace asset diff --git a/src/proc/asset/track.hpp b/src/proc/asset/track.hpp index 6a7aa04e3..c4b6886c1 100644 --- a/src/proc/asset/track.hpp +++ b/src/proc/asset/track.hpp @@ -37,9 +37,14 @@ namespace asset */ class Track : public Struct { - + protected: + Track (const Asset::Ident& idi); + friend class StructFactory; }; + + typedef shared_ptr PTrack; + } // namespace asset diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index 46717c166..c8df77c65 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -234,6 +234,7 @@ namespace asset #include "proc/asset/clip.hpp" #include "proc/asset/proc.hpp" #include "proc/asset/struct.hpp" +#include "proc/asset/track.hpp" #include "proc/asset/meta.hpp" @@ -252,6 +253,7 @@ namespace asset template shared_ptr AssetManager::getPtr (const Asset& asset); template shared_ptr AssetManager::getPtr (const Media& asset); template shared_ptr AssetManager::getPtr (const Clip& asset); + template shared_ptr AssetManager::getPtr (const Track& asset); } // namespace asset diff --git a/src/proc/mobject/explicitplacement.hpp b/src/proc/mobject/explicitplacement.hpp index 416b1d4f1..9cc8bd1b7 100644 --- a/src/proc/mobject/explicitplacement.hpp +++ b/src/proc/mobject/explicitplacement.hpp @@ -48,9 +48,9 @@ namespace mobject { public: const Time time; - const Track track; + const Port port; - typedef std::pair SolutionData; //TODO (ichthyo consideres better passing of solution by subclass) + typedef std::pair SolutionData; //TODO (ichthyo consideres better passing of solution by subclass) /** no need to resolve any further, as this ExplicitPlacement * already \i is the result of a resolve()-call. @@ -70,7 +70,7 @@ namespace mobject */ ExplicitPlacement (const Placement& base, const SolutionData found) : Placement(base), - time(found.first), track(found.second) + time(found.first), port(found.second) { }; friend ExplicitPlacement Placement::resolve () const; diff --git a/src/proc/mobject/placement.hpp b/src/proc/mobject/placement.hpp index cd2ee06ac..21c4aada8 100644 --- a/src/proc/mobject/placement.hpp +++ b/src/proc/mobject/placement.hpp @@ -60,7 +60,7 @@ #include "cinelerra.h" #include "proc/mobject/mobject.hpp" #include "proc/mobject/session/locatingpin.hpp" -#include "proc/mobject/session/track.hpp" +#include "proc/asset/port.hpp" #include using std::tr1::shared_ptr; @@ -86,7 +86,8 @@ namespace mobject { protected: typedef cinelerra::Time Time; - typedef session::Track* Track; + typedef asset::shared_ptr Port; + public: diff --git a/src/proc/mobject/session/abstractmo.hpp b/src/proc/mobject/session/abstractmo.hpp index bd4fd5785..47aaff34f 100644 --- a/src/proc/mobject/session/abstractmo.hpp +++ b/src/proc/mobject/session/abstractmo.hpp @@ -27,7 +27,6 @@ #include "proc/mobject/mobject.hpp" - namespace mobject { namespace session diff --git a/src/proc/mobject/session/constraint.cpp b/src/proc/mobject/session/constraint.cpp new file mode 100644 index 000000000..ecf074ae6 --- /dev/null +++ b/src/proc/mobject/session/constraint.cpp @@ -0,0 +1,37 @@ +/* + Constraint - LocatingPin representing an mandatory directive + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "proc/mobject/session/constraint.hpp" + +namespace mobject + { + namespace session + { + + /** */ + + + + } // namespace mobject::session + +} // namespace mobject diff --git a/src/proc/mobject/session/constraint.hpp b/src/proc/mobject/session/constraint.hpp new file mode 100644 index 000000000..bfaf45775 --- /dev/null +++ b/src/proc/mobject/session/constraint.hpp @@ -0,0 +1,47 @@ +/* + CONSTRAINT.hpp - LocatingPin representing an mandatory directive + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#ifndef MOBJECT_SESSION_CONSTRAINT_H +#define MOBJECT_SESSION_CONSTRAINT_H + +#include "proc/mobject/session/allocation.hpp" + + + +namespace mobject + { + namespace session + { + + + /** + * LocatingPin representing an directive by the user + * that must not be violated + */ + class Constraint : public Allocation + {}; + + } // namespace mobject::session + +} // namespace mobject +#endif diff --git a/src/proc/mobject/session/edl.cpp b/src/proc/mobject/session/edl.cpp index 84a3f6e4c..e95b62424 100644 --- a/src/proc/mobject/session/edl.cpp +++ b/src/proc/mobject/session/edl.cpp @@ -24,12 +24,39 @@ #include "proc/mobject/session/edl.hpp" #include "proc/mobject/session/track.hpp" #include "proc/mobject/placement.hpp" -#include "proc/mobject/mobject.hpp" +#include "proc/mobject/session/mobjectfactory.hpp" +#include "proc/asset/track.hpp" namespace mobject { namespace session { + + namespace // Implementation details + { + using asset::Query; + + /** helper: create a default configured track asset */ + const Placement + makeDefaultTrack () + { + PTrackAsset tA = asset::Struct::create (Query ("dummy()")); + return MObject::create (tA); + } + + } + + + + + /** create an empty default configured EDL */ + EDL::EDL () + : track (makeDefaultTrack ()), + clips (0) + { + + } + /** @deprecated not sure if it is a good idea * to have this on the interface diff --git a/src/proc/mobject/session/edl.hpp b/src/proc/mobject/session/edl.hpp index db3ad4971..fc48f0a1a 100644 --- a/src/proc/mobject/session/edl.hpp +++ b/src/proc/mobject/session/edl.hpp @@ -29,7 +29,7 @@ #include "proc/mobject/mobject.hpp" #include "proc/mobject/placement.hpp" -#include "proc/asset/track.hpp" +#include "proc/mobject/session/track.hpp" using proc_interface::PAsset; // TODO better way to refer to a track? @@ -44,14 +44,16 @@ namespace mobject class EDL { protected: - vector tracks; + Placement track; vector clips; public: + EDL(); + bool contains (const PMO& placement); PMO& find (const string& id); ///< @todo how to refer to clips? using asset IDs?? - vector& getTracks () { return tracks; } ///< @todo use track assets correct, make const! + Placement& getTracks () { return track; } ///< @todo work out the correct use of tracks! make const correct! size_t size () { UNIMPLEMENTED ("what ist the 'size' of an EDL?"); diff --git a/src/proc/mobject/session/fixture.hpp b/src/proc/mobject/session/fixture.hpp index 78c0cdac5..f6549c185 100644 --- a/src/proc/mobject/session/fixture.hpp +++ b/src/proc/mobject/session/fixture.hpp @@ -48,7 +48,6 @@ namespace mobject class Fixture : public EDL { protected: - Track tracks; list timeline; diff --git a/src/proc/mobject/session/locatingpin.cpp b/src/proc/mobject/session/locatingpin.cpp index fc290c4be..88456d9a5 100644 --- a/src/proc/mobject/session/locatingpin.cpp +++ b/src/proc/mobject/session/locatingpin.cpp @@ -98,7 +98,7 @@ namespace mobject { LocatingSolution solution; resolve (solution); - return SolutionData (solution.getTime(), solution.getTrack()); + return SolutionData (solution.getTime(), solution.getPort()); } bool @@ -142,10 +142,11 @@ namespace mobject return minTime; } - LocatingPin::Track - LocatingPin::LocatingSolution::getTrack() + LocatingPin::Port + LocatingPin::LocatingSolution::getPort() { - UNIMPLEMENTED ("get effective Track number of Solution"); + UNIMPLEMENTED ("get effective Port of Solution"); + return Port (); } diff --git a/src/proc/mobject/session/locatingpin.hpp b/src/proc/mobject/session/locatingpin.hpp index cfa8416ba..c4e64844a 100644 --- a/src/proc/mobject/session/locatingpin.hpp +++ b/src/proc/mobject/session/locatingpin.hpp @@ -45,11 +45,14 @@ #include "cinelerra.h" #include +#include #include using boost::scoped_ptr; +namespace asset { class Port; } + namespace mobject { class MObject; @@ -61,7 +64,6 @@ namespace mobject class FixedLocation; class RelativeLocation; - class Track; //TODO /** @@ -80,8 +82,9 @@ namespace mobject { protected: typedef cinelerra::Time Time; - typedef session::Track* Track; - typedef std::pair SolutionData; //TODO (ichthyo consideres better passing of solution by subclass) + typedef Time* Track; //TODO dummy declaration; we don't use Tracks as first-class entity any longer + typedef std::tr1::shared_ptr Port; + typedef std::pair SolutionData; //TODO (ichthyo consideres better passing of solution by subclass) struct LocatingSolution; /** next additional Pin, if any */ @@ -125,7 +128,7 @@ namespace mobject { Time minTime; Time maxTime; - Track minTrack; + Track minTrack; // TODO don't use Tracks Track maxTrack; bool impo; @@ -138,7 +141,7 @@ namespace mobject { } Time getTime (); - Track getTrack (); + Port getPort (); bool is_definite (); bool is_impossible (); diff --git a/src/proc/mobject/session/mobjectfactory.cpp b/src/proc/mobject/session/mobjectfactory.cpp index c86da719b..f15d11d71 100644 --- a/src/proc/mobject/session/mobjectfactory.cpp +++ b/src/proc/mobject/session/mobjectfactory.cpp @@ -23,8 +23,10 @@ #include "proc/mobject/session/mobjectfactory.hpp" #include "proc/mobject/session/clip.hpp" +#include "proc/mobject/session/track.hpp" #include "proc/mobject/session/effect.hpp" #include "proc/asset/clip.hpp" +#include "proc/asset/track.hpp" #include "proc/asset/effect.hpp" namespace mobject @@ -61,9 +63,17 @@ namespace mobject UNIMPLEMENTED ("build multichannel compound clip-MO"); } + /** */ + Placement + MObjectFactory::operator() (PTrackAsset& trackDef) + { + TODO ("what needs to be registered when creating an Track-MO?"); + return Placement (*new Track (trackDef), &deleterFunc); + } + /** */ Placement - MObjectFactory::operator() (asset::Effect processorDef) + MObjectFactory::operator() (const asset::Effect& processorDef) { UNIMPLEMENTED ("fabricate effect-MO"); } diff --git a/src/proc/mobject/session/mobjectfactory.hpp b/src/proc/mobject/session/mobjectfactory.hpp index 3bc27a2a2..96ffbed75 100644 --- a/src/proc/mobject/session/mobjectfactory.hpp +++ b/src/proc/mobject/session/mobjectfactory.hpp @@ -32,6 +32,7 @@ namespace asset { class Clip; class Media; + class Track; class Effect; } @@ -41,7 +42,10 @@ namespace mobject namespace session { class Clip; + class Track; class Effect; + + typedef shared_ptr PTrackAsset; class MObjectFactory @@ -55,7 +59,8 @@ namespace mobject Placement operator() (const asset::Clip&, const asset::Media&); Placement operator() (const asset::Clip&, vector); - Placement operator() (const asset::Effect); + Placement operator() (PTrackAsset&); + Placement operator() (const asset::Effect&); }; diff --git a/src/proc/mobject/session/plug.cpp b/src/proc/mobject/session/plug.cpp new file mode 100644 index 000000000..91c4b9fb9 --- /dev/null +++ b/src/proc/mobject/session/plug.cpp @@ -0,0 +1,38 @@ +/* + Plug - LocatingPin for requesting connection to some Port + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "proc/mobject/session/plug.hpp" +#include "proc/asset/port.hpp" + +namespace mobject + { + namespace session + { + + /** */ + + + + } // namespace mobject::session + +} // namespace mobject diff --git a/src/proc/mobject/session/plug.hpp b/src/proc/mobject/session/plug.hpp new file mode 100644 index 000000000..53599ea52 --- /dev/null +++ b/src/proc/mobject/session/plug.hpp @@ -0,0 +1,52 @@ +/* + PLUG.hpp - LocatingPin for requesting connection to some Port + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#ifndef MOBJECT_SESSION_PLUG_H +#define MOBJECT_SESSION_PLUG_H + +#include "proc/mobject/session/wish.hpp" + + + +namespace asset { class Port; } + +namespace mobject + { + namespace session + { + + /** + * LocatingPin for requesting connection to some Port + */ + class Plug : public Wish + { + protected: + /** the Port this MObject wants to be conected to */ + asset::Port* outPort; ////////////////////////////////TODO: shared_ptr + + }; + + } // namespace mobject::session + +} // namespace mobject +#endif diff --git a/src/proc/mobject/session/track.cpp b/src/proc/mobject/session/track.cpp index 05b0dd31f..87f6dad2e 100644 --- a/src/proc/mobject/session/track.cpp +++ b/src/proc/mobject/session/track.cpp @@ -22,15 +22,29 @@ #include "proc/mobject/session/track.hpp" +#include "proc/asset/track.hpp" namespace mobject { namespace session { - /** */ + /** new track-MO linked with the given asset::Track. + * Initially, the reference (zero-point) time of this track + * will be set to 0 + */ + Track::Track (PTrackAsset& trackDef) + : start_(0), + trackDef_(trackDef) + { } + bool + Track::isValid() const + { + TODO ("sensible Track-MO self-check"); + return true; + } } // namespace mobject::session diff --git a/src/proc/mobject/session/track.hpp b/src/proc/mobject/session/track.hpp index 42d5fe783..99c7ae9cb 100644 --- a/src/proc/mobject/session/track.hpp +++ b/src/proc/mobject/session/track.hpp @@ -1,5 +1,5 @@ /* - TRACK.hpp - descriptor for one track in the Session + TRACK.hpp - A grouping device within the EDL. Copyright (C) CinelerraCV 2007, Hermann Vosseler @@ -24,31 +24,50 @@ #ifndef MOBJECT_SESSION_TRACK_H #define MOBJECT_SESSION_TRACK_H +#include "proc/mobject/session/meta.hpp" + +namespace asset { class Track; } + namespace mobject { namespace session { + typedef shared_ptr PTrackAsset; /** - * A Track in the EDL or Session. - * But, honestly, I don't quite know what a Track stands for! - * Usually, this stems from the metaphor of a multitrack tape machine, - * but I doubt this metaphor is really helpful for editing video; mostly - * people stick to such metaphors out of mental laziyness... - * - * So, let's see if the concept "Track" will get any practical functionallity - * or if we end up with "Track" beeing just a disguise for an int ID.... + * A Track is 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. */ - class Track + class Track : public Meta { + Time start_; + PTrackAsset trackDef_; + + protected: + Track (PTrackAsset&); + friend class MObjectFactory; + + public: + /** Child tracks in a tree structure */ + vector > subTracks; // TODO: Placement!!!!!!! + + virtual bool isValid() const; }; - - - + + + } // namespace mobject::session + + /** Placement defined to be subclass of Placement */ + DEFINE_SPECIALIZED_PLACEMENT (session::Track); } // namespace mobject #endif diff --git a/src/proc/mobject/session/wish.cpp b/src/proc/mobject/session/wish.cpp new file mode 100644 index 000000000..f58e0261a --- /dev/null +++ b/src/proc/mobject/session/wish.cpp @@ -0,0 +1,37 @@ +/* + Wish - LocatingPin representing a low-priority directive + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "proc/mobject/session/wish.hpp" + +namespace mobject + { + namespace session + { + + /** */ + + + + } // namespace mobject::session + +} // namespace mobject diff --git a/src/proc/mobject/session/wish.hpp b/src/proc/mobject/session/wish.hpp new file mode 100644 index 000000000..d50e8865f --- /dev/null +++ b/src/proc/mobject/session/wish.hpp @@ -0,0 +1,52 @@ +/* + WISH.hpp - LocatingPin representing a low-priority directive + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#ifndef MOBJECT_SESSION_WISH_H +#define MOBJECT_SESSION_WISH_H + +#include "proc/mobject/session/allocation.hpp" + + + +namespace mobject + { + namespace session + { + + + /** + * LocatingPin representing a low-priority directive by the user, + * to be fulfilled only if possible (and after satisfying the + * more important LocatingPins) + */ + class Wish : public Allocation + { + + }; + + + + } // namespace mobject::session + +} // namespace mobject +#endif diff --git a/tests/components/proc/mobject/session/sessionstructuretest.cpp b/tests/components/proc/mobject/session/sessionstructuretest.cpp index 46fe59aee..fc91d886b 100644 --- a/tests/components/proc/mobject/session/sessionstructuretest.cpp +++ b/tests/components/proc/mobject/session/sessionstructuretest.cpp @@ -61,11 +61,12 @@ namespace mobject PSess sess = Session::current; ASSERT (0 <= sess->currEDL().size()); // TODO implement ASSERT (0 <= sess->getFixture()->size()); // TODO implement - ASSERT (0 < sess->currEDL().getTracks().size()); // TODO implement + ASSERT (sess->currEDL().getTracks()->isValid()); - PAsset track = sess->currEDL().getTracks()[0]; - AssetManager& aMang = AssetManager::instance(); - ASSERT (track == aMang.getAsset (track->getID())); +// PAsset track = sess->currEDL().getTracks()[0]; +// AssetManager& aMang = AssetManager::instance(); +// ASSERT (track == aMang.getAsset (track->getID())); + UNIMPLEMENTED ("how to refer to tracks..."); } }; diff --git a/uml/cinelerra3/128133 b/uml/cinelerra3/128133 index aefe38ecb..591fc4844 100644 --- a/uml/cinelerra3/128133 +++ b/uml/cinelerra3/128133 @@ -1,6 +1,6 @@ format 40 "Asset" // ProcessingLayer::Asset - revision 15 + revision 16 modified_by 5 "hiv" // class settings //class diagram settings @@ -59,7 +59,7 @@ format 40 end classdiagram 131205 "Struct-Asset Relations" - draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + draw_all_relations no hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default size A4 end @@ -685,17 +685,9 @@ ${inlines} b multiplicity "" parent class_ref 136965 // Struct end - classrelation 144389 // wiringTemplate () - relation 142469 ---> - a role_name "wiringTemplate" multiplicity "1" protected - cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; -" - classrelation_ref 144389 // wiringTemplate () - b multiplicity "" parent class_ref 138757 // ProcPatt - end end - class 138117 "OutPort" + class 138117 "Port" visibility package cpp_decl "${comment}${template}class ${name}${inherit} { @@ -706,7 +698,7 @@ ${inlines} idl_decl "" explicit_switch_type "" - comment "structural asset corresponding to some port generating media output" + comment "structural asset corresponding to some port for building a processing chain and generating media output" classrelation 141445 // relation 139653 ---|> a public @@ -714,6 +706,23 @@ ${inlines} classrelation_ref 141445 // b multiplicity "" parent class_ref 136965 // Struct end + + classrelation 148101 // + relation 145925 -_-> + a default + cpp default "Generated" + classrelation_ref 148101 // + b multiplicity "" parent class_ref 138757 // ProcPatt + end + + classrelation 148229 // wiringTemplate () + relation 146053 ---> + a role_name "wiringTemplate" multiplicity "0..1" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 148229 // wiringTemplate () + b multiplicity "" parent class_ref 138757 // ProcPatt + end end class 138757 "ProcPatt" diff --git a/uml/cinelerra3/128133.diagram b/uml/cinelerra3/128133.diagram index 2df4f1453..0aa4daeb2 100644 --- a/uml/cinelerra3/128133.diagram +++ b/uml/cinelerra3/128133.diagram @@ -2,11 +2,11 @@ format 40 classcanvas 128005 class_ref 128005 // SessionImpl draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 19 606 2000 + xyz 18 679 2000 end classcanvas 128133 class_ref 128133 // EDL draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 232 606 2000 + xyz 231 679 2000 end classcanvas 128261 class_ref 128261 // Fixture draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default @@ -14,7 +14,7 @@ classcanvas 128261 class_ref 128261 // Fixture end classcanvas 129029 class_ref 128389 // Track draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 306 712 2000 + xyz 425 679 2000 end classcanvas 129413 class_ref 128517 // MObject draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default @@ -26,7 +26,7 @@ classcanvas 129669 class_ref 128645 // Placement end classcanvas 129925 class_ref 128389 // Track draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 319 1005 2000 + xyz 357 991 2000 end classcanvas 130949 class_ref 128773 // AbstractMO draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default @@ -75,12 +75,12 @@ classcanvas 136581 class_ref 129925 // Auto note 136837 "Placement \"locates\" a Media Object" xyzwh 370 73 3005 207 36 textcanvas 136965 "the Timeline is a list of placements reduced to absolute coordinates (time, track)" - xyzwh 464 925 2000 121 90 + xyzwh 468 919 2000 121 90 textcanvas 137093 "Fixture is the actual assembly of various Media Objects ready to be performed" - xyzwh 39 909 2000 147 108 + xyzwh -27 863 2000 147 108 classcanvas 137221 class_ref 130053 // Wish draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 561 532 2000 + xyz 560 532 2000 end classcanvas 137349 class_ref 130181 // Constraint draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default @@ -88,7 +88,7 @@ classcanvas 137349 class_ref 130181 // Constraint end classcanvas 138629 class_ref 135173 // Segment draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 417 678 2000 + xyz 666 731 2000 end classcanvas 139013 class_ref 138629 // CompoundClip draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default @@ -106,35 +106,33 @@ classcanvas 141317 class_ref 139909 // LocatingPin draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 518 239 2000 end +classcanvas 146053 class_ref 138117 // Port + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 344 597 2004 + end +classcanvas 146437 class_ref 140421 // Plug + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 560 597 2000 + end +textcanvas 146821 "global Port Asset" + xyzwh 299 569 2000 90 23 relationcanvas 128389 relation_ref 128005 // from ref 128005 z 1999 to ref 128133 - role_a_pos 201 603 3000 no_role_b - multiplicity_a_pos 205 636 3000 no_multiplicity_b + role_a_pos 200 676 3000 no_role_b + multiplicity_a_pos 204 709 3000 no_multiplicity_b relationcanvas 128517 relation_ref 128133 // from ref 128005 z 1999 to ref 128261 - role_a_pos 240 870 3000 no_role_b - multiplicity_a_pos 214 870 3000 no_multiplicity_b + role_a_pos 230 870 3000 no_role_b + multiplicity_a_pos 204 870 3000 no_multiplicity_b relationcanvas 128645 relation_ref 128261 // geometry VHr - from ref 128261 z 1999 to point 252 931 + from ref 128261 z 1999 to point 251 931 line 128901 z 1999 to ref 128133 no_role_a no_role_b no_multiplicity_a no_multiplicity_b -relationcanvas 129157 relation_ref 128389 // - geometry HV - from ref 128133 z 1999 stereotype "<>" xyz 286 628 3000 to point 326 625 - line 129285 z 1999 to ref 129029 - role_a_pos 338 687 3000 no_role_b - multiplicity_a_pos 314 687 3000 no_multiplicity_b -relationcanvas 130181 relation_ref 129029 // - geometry HV - from ref 128261 z 1999 stereotype "<>" xyz 334 914 3000 to point 339 931 - line 130565 z 1999 to ref 129925 - role_a_pos 351 980 3000 no_role_b - multiplicity_a_pos 315 980 3000 no_multiplicity_b relationcanvas 130821 relation_ref 128517 // geometry VH - from ref 128133 z 1999 stereotype "<>" xyz 258 547 3000 to point 252 167 + from ref 128133 z 1999 stereotype "<>" xyz 255 653 3000 to point 251 167 line 132357 z 1999 to ref 129413 role_a_pos 280 145 3000 no_role_b multiplicity_a_pos 298 178 3000 no_multiplicity_b @@ -175,7 +173,7 @@ relationcanvas 135685 relation_ref 130949 // no_multiplicity_a no_multiplicity_b relationcanvas 135941 relation_ref 131077 // from ref 128261 z 1999 stereotype "<>" xyz 371 893 3000 to ref 135813 - role_a_pos 419 844 3000 no_role_b + role_a_pos 389 857 3000 no_role_b multiplicity_a_pos 451 877 3000 no_multiplicity_b relationcanvas 136069 relation_ref 131205 // from ref 135813 z 1999 to point 433 897 @@ -198,7 +196,7 @@ relationcanvas 138245 relation_ref 131717 // no_multiplicity_a no_multiplicity_b relationcanvas 138757 relation_ref 137093 // geometry VHr - from ref 138629 z 1999 stereotype "<>" xyz 479 716 3000 to point 517 714 + from ref 138629 z 1999 stereotype "<>" xyz 611 767 3000 to point 517 767 line 138885 z 1999 to ref 135813 role_a_pos 529 783 3000 no_role_b multiplicity_a_pos 505 783 3000 no_multiplicity_b @@ -207,7 +205,7 @@ relationcanvas 139141 relation_ref 140805 // no_role_a no_role_b no_multiplicity_a no_multiplicity_b relationcanvas 139525 relation_ref 142725 // - from ref 128005 z 1999 stereotype "<>" xyz 57 558 3000 to ref 139269 + from ref 128005 z 1999 stereotype "<>" xyz 56 594 3000 to ref 139269 no_role_a no_role_b no_multiplicity_a no_multiplicity_b relationcanvas 139781 relation_ref 142853 // @@ -251,4 +249,36 @@ relationcanvas 144517 relation_ref 143877 // line 144773 z 1999 to ref 141317 role_a_pos 492 244 3000 no_role_b no_multiplicity_a no_multiplicity_b +relationcanvas 144901 relation_ref 144901 // + from ref 129029 z 1999 to point 445 489 + line 145029 z 1999 to ref 131973 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 145285 relation_ref 145029 // + from ref 129029 z 1999 stereotype "<>" xyz 389 732 3000 to point 445 749 + line 145413 z 1999 to point 369 749 + line 145541 z 1999 to ref 129029 + role_a_pos 382 748 3000 no_role_b + multiplicity_a_pos 403 704 3000 no_multiplicity_b +relationcanvas 145669 relation_ref 145157 // + from ref 128133 z 1999 to ref 129029 + role_a_pos 376 681 3000 no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 145925 relation_ref 145413 // + from ref 128261 z 1999 to ref 129925 + role_a_pos 321 978 3000 no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 146181 relation_ref 145541 // + from ref 128005 z 1999 to point 311 616 + line 146309 z 1999 stereotype "<>" xyz 103 649 3000 to ref 146053 + role_a_pos 308 594 3000 no_role_b + multiplicity_a_pos 329 627 3000 no_multiplicity_b +relationcanvas 146565 relation_ref 145669 // + from ref 146437 z 1999 to ref 137221 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 146693 relation_ref 145797 // + from ref 146437 z 1999 to ref 146053 + role_a_pos 398 594 3000 no_role_b + no_multiplicity_a no_multiplicity_b end diff --git a/uml/cinelerra3/128261 b/uml/cinelerra3/128261 index 10080e773..aea54b2f1 100644 --- a/uml/cinelerra3/128261 +++ b/uml/cinelerra3/128261 @@ -1,6 +1,6 @@ format 40 "MObject" // ProcessingLayer::MObject - revision 27 + revision 28 modified_by 5 "hiv" // class settings //class diagram settings @@ -127,12 +127,12 @@ ${inlines} b multiplicity "" parent class_ref 128133 // EDL end - classrelation 128261 // fixture () + classrelation 128261 // theFixture () relation 128133 ---> - a role_name "fixture" multiplicity "1" protected + a role_name "theFixture" multiplicity "1" protected cpp default " ${comment}${static}${mutable}${volatile}${const}${type} * ${name}${value}; " - classrelation_ref 128261 // fixture () + classrelation_ref 128261 // theFixture () b multiplicity "" parent class_ref 128261 // Fixture end @@ -144,6 +144,17 @@ ${inlines} classrelation_ref 144645 // b multiplicity "" parent class_ref 139653 // Session end + + classrelation 147717 // ports () + relation 145541 o--> + stereotype "vector" + a role_name "ports" multiplicity "*" protected + comment "the global ports (busses) of the session" + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 147717 // ports () + b multiplicity "" parent class_ref 138117 // Port + end end class 139781 "SessManager" @@ -241,16 +252,6 @@ ${inlines} idl_decl "" explicit_switch_type "" - classrelation 128645 // tracks () - relation 128389 *--> - stereotype "list" - a role_name "tracks" multiplicity "*" protected - cpp default " ${comment}${static}${mutable}${volatile}${const}${stereotype}<${type}> ${name}${value}; -" - classrelation_ref 128645 // tracks () - b multiplicity "" parent class_ref 128389 // Track - end - classrelation 128901 // clips () relation 128517 o--> stereotype "list" @@ -260,6 +261,16 @@ ${inlines} classrelation_ref 128901 // clips () b multiplicity "" parent class_ref 128517 // MObject end + + classrelation 147333 // track () + relation 145157 ---> + a role_name "track" multiplicity "" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 147333 // track () + b multiplicity "" parent class_ref 128389 // Track + association_type class_ref 128645 // Placement + end end class 128261 "Fixture" @@ -281,23 +292,13 @@ ${inlines} b multiplicity "" parent class_ref 128133 // EDL end - classrelation 129541 // tracks () - relation 129029 *--> - stereotype "list" - a role_name "tracks" multiplicity "1..*" protected - cpp default " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; -" - classrelation_ref 129541 // tracks () - b multiplicity "" parent class_ref 128389 // Track - end - - classrelation 131717 // timeline () + classrelation 131717 // theTimeline () relation 131077 *--> stereotype "list" - a role_name "timeline" multiplicity "*" protected + a role_name "theTimeline" multiplicity "*" protected cpp default " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; " - classrelation_ref 131717 // timeline () + classrelation_ref 131717 // theTimeline () b multiplicity "" parent class_ref 129797 // ExplicitPlacement end @@ -330,6 +331,16 @@ ${class}::${name} ${(}${)}${const}${volatile} ${throw}${staticnl} end + + classrelation 147589 // track () + relation 145413 ---> + a role_name "track" multiplicity "" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 147589 // track () + b multiplicity "" parent class_ref 128389 // Track + association_type class_ref 128645 // Placement + end end class 135173 "Segment" @@ -383,6 +394,26 @@ ${inlines} idl_decl "" explicit_switch_type "" + associated_diagram classdiagram_ref 128133 // Session structure + classrelation 147077 // + relation 144901 ---|> + a public + cpp default "${type}" + classrelation_ref 147077 // + b multiplicity "" parent class_ref 129157 // Meta + end + + classrelation 147205 // subTracks () + relation 145029 *--> + stereotype "vector" + a role_name "subTracks" multiplicity "*" public + comment "Child tracks in a tree structure" + cpp default " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; +" + classrelation_ref 147205 // subTracks () + b multiplicity "" parent class_ref 128389 // Track + association_type class_ref 128645 // Placement + end end class 128517 "MObject" @@ -963,6 +994,36 @@ ${inlines} end end + class 140421 "Plug" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 147845 // + relation 145669 ---|> + a public + cpp default "${type}" + classrelation_ref 147845 // + b multiplicity "" parent class_ref 130053 // Wish + end + + classrelation 147973 // outPort () + relation 145797 ---> + a role_name "outPort" multiplicity "" protected + comment "the Port this MObject wants to be conected to" + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 147973 // outPort () + b multiplicity "" parent class_ref 138117 // Port + end + end + class 134533 "Parameter" visibility public nformals 1 diff --git a/uml/cinelerra3/129285 b/uml/cinelerra3/129285 index 7b8ccd808..11729b3cf 100644 --- a/uml/cinelerra3/129285 +++ b/uml/cinelerra3/129285 @@ -1,6 +1,6 @@ format 40 "ProcessingLayer" // ProcessingLayer - revision 9 + revision 10 modified_by 5 "hiv" // class settings //class diagram settings diff --git a/uml/cinelerra3/130309.diagram b/uml/cinelerra3/130309.diagram index 81e77861e..7de6c806f 100644 --- a/uml/cinelerra3/130309.diagram +++ b/uml/cinelerra3/130309.diagram @@ -55,9 +55,9 @@ classcanvas 132485 class_ref 137989 // Track draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 614 445 2000 end -classcanvas 132613 class_ref 138117 // OutPort +classcanvas 132613 class_ref 138117 // Port draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 677 445 2000 + xyz 682 445 2000 end classcanvas 132997 class_ref 138245 // Dataset draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default @@ -207,6 +207,11 @@ relationcanvas 138501 relation_ref 144133 // from ref 131461 z 1999 to ref 131333 no_role_a no_role_b no_multiplicity_a no_multiplicity_b +relationcanvas 138629 relation_ref 145925 // + from ref 132613 z 1999 to point 714 509 + line 138757 z 1999 to ref 135813 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b line 128261 -_-_ geometry HV from ref 128005 z 1999 to point 331 150 line 128389 z 1999 to ref 128133 diff --git a/uml/cinelerra3/130437 b/uml/cinelerra3/130437 index b1c2021e8..2bad861ba 100644 --- a/uml/cinelerra3/130437 +++ b/uml/cinelerra3/130437 @@ -1,6 +1,6 @@ format 40 "session" // design::codegen::proc::mobject::session - revision 11 + revision 12 modified_by 5 "hiv" // class settings //class diagram settings @@ -274,7 +274,14 @@ ${namespace_end}" associated_classes class_ref 128389 // Track end - comment "descriptor for one track in the Session" + comment "A grouping device within the EDL. The corresponding Placement +by which this Track object is refered defines fallback placing +properties to be used by all objects placed on this track in +case they don't specify more concrete placements. +Typically, tracks are used do make default Port connections, +define a layer or pan for sound and for for disabling groups +of clips. Note tracks are grouped in a tree like fashion. +" end artifact 129285 "abstractmo" @@ -666,6 +673,126 @@ ${namespace_end}" end end + artifact 139397 "constraint" + stereotype "source" + cpp_h "/* + ${NAME}.hpp - ${description} +@{CopyrightClaim}@{GPLHeader} +*/ + + +#ifndef ${NAMESPACE}_${NAME}_H +#define ${NAMESPACE}_${NAME}_H + +${includes} +${declarations} + + +${namespace_start} + +${definition} +${namespace_end} +#endif +" + cpp_src "/* + ${Name} - ${description} +@{CopyrightClaim}@{GPLHeader} +* *****************************************************/ + + +${includes} +${namespace_start} + + +${members} +${namespace_end}" + associated_classes + class_ref 130181 // Constraint + end + comment "LocatingPin representing an directive by the user that +must not be violated" + end + + artifact 139269 "wish" + stereotype "source" + cpp_h "/* + ${NAME}.hpp - ${description} +@{CopyrightClaim}@{GPLHeader} +*/ + + +#ifndef ${NAMESPACE}_${NAME}_H +#define ${NAMESPACE}_${NAME}_H + +${includes} +${declarations} + + +${namespace_start} + +${definition} +${namespace_end} +#endif +" + cpp_src "/* + ${Name} - ${description} +@{CopyrightClaim}@{GPLHeader} +* *****************************************************/ + + +${includes} +${namespace_start} + + +${members} +${namespace_end}" + associated_classes + class_ref 130053 // Wish + end + comment "LocatingPin representing a low-priority directive by the user, +to be fulfilled only if possible (and after satisfying the +more important LocatingPins)" + end + + artifact 139525 "plug" + stereotype "source" + cpp_h "/* + ${NAME}.hpp - ${description} +@{CopyrightClaim}@{GPLHeader} +*/ + + +#ifndef ${NAMESPACE}_${NAME}_H +#define ${NAMESPACE}_${NAME}_H + +${includes} +${declarations} + + +${namespace_start} + +${definition} +${namespace_end} +#endif +" + cpp_src "/* + ${Name} - ${description} +@{CopyrightClaim}@{GPLHeader} +* *****************************************************/ + + +${includes} +${namespace_start} + + +${members} +${namespace_end}" + associated_classes + class_ref 140421 // Plug + end + comment "LocatingPin for requesting connection to some Port" + end + artifact 130181 "label" stereotype "source" cpp_h "/* diff --git a/uml/cinelerra3/131205.diagram b/uml/cinelerra3/131205.diagram index 02ad56b41..c3c077ba7 100644 --- a/uml/cinelerra3/131205.diagram +++ b/uml/cinelerra3/131205.diagram @@ -15,9 +15,9 @@ classcanvas 128389 class_ref 138757 // ProcPatt draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 684 277 2000 end -classcanvas 128517 class_ref 138117 // OutPort +classcanvas 128517 class_ref 138117 // Port draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 510 196 2000 + xyz 516 196 2000 end classcanvas 128645 class_ref 139141 // DoAttach draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default @@ -37,7 +37,7 @@ classcanvas 129029 class_ref 136965 // Struct end relationcanvas 129157 relation_ref 139653 // geometry VHV - from ref 128517 z 1999 to point 535 167 + from ref 128517 z 1999 to point 536 167 line 130437 z 1999 to point 721 167 line 130565 z 1999 to ref 129029 no_role_a no_role_b @@ -55,9 +55,9 @@ relationcanvas 129413 relation_ref 139525 // no_role_a no_role_b no_multiplicity_a no_multiplicity_b relationcanvas 129541 relation_ref 141701 // - from ref 128389 z 1999 stereotype "<>" xyz 678 340 3000 to ref 128133 - role_a_pos 704 366 3000 no_role_b - multiplicity_a_pos 668 366 3000 multiplicity_b_pos 689 328 3000 + from ref 128389 z 1999 stereotype "<>" xyz 637 314 3000 to ref 128133 + role_a_pos 640 329 3000 no_role_b + multiplicity_a_pos 668 366 3000 multiplicity_b_pos 743 320 3000 relationcanvas 129669 relation_ref 141829 // from ref 128645 z 1999 to ref 128133 no_role_a no_role_b @@ -70,10 +70,15 @@ relationcanvas 130053 relation_ref 141957 // from ref 128901 z 1999 to ref 128133 no_role_a no_role_b no_multiplicity_a no_multiplicity_b -relationcanvas 130821 relation_ref 142469 // - geometry VH - from ref 128773 z 1999 to point 624 296 - line 131205 z 1999 to ref 128389 - role_a_pos 587 295 3000 no_role_b - multiplicity_a_pos 667 307 3000 no_multiplicity_b +relationcanvas 131461 relation_ref 142085 // + from ref 128901 z 1999 to point 747 424 + line 131845 z 1999 to point 747 348 + line 131973 z 1999 to ref 128389 + role_a_pos 719 362 3000 no_role_b + multiplicity_a_pos 707 329 3000 multiplicity_b_pos 727 436 3000 +relationcanvas 131589 relation_ref 146053 // + from ref 128517 z 1999 to point 536 295 + line 131717 z 1999 to ref 128389 + role_a_pos 569 280 3000 no_role_b + multiplicity_a_pos 576 296 3000 no_multiplicity_b end diff --git a/uml/cinelerra3/5.session b/uml/cinelerra3/5.session index f89f4f060..76cf1249d 100644 --- a/uml/cinelerra3/5.session +++ b/uml/cinelerra3/5.session @@ -1,23 +1,32 @@ window_sizes 1140 830 270 860 680 71 diagrams classdiagram_ref 130309 // Asset Kinds - 860 633 100 4 0 0 - active classdiagram_ref 128133 // Session structure - 860 633 100 4 401 0 + 860 633 100 4 158 0 + classdiagram_ref 128133 // Session structure + 860 633 100 4 462 0 classdiagram_ref 128389 // Render Entities - 688 506 100 4 120 0 + 743 538 100 4 0 0 + active classdiagram_ref 131205 // Struct-Asset Relations + 741 555 100 4 0 114 end show_stereotypes selected -package_ref 129 // cinelerra3 + package_ref 129 // cinelerra3 open - deploymentview_ref 128261 // gen - deploymentview_ref 129029 // gen + + package_ref 128005 // design class_ref 137477 // Unknown class_ref 137605 // Preview + class_ref 137989 // Track + class_ref 138117 // Port + class_ref 128005 // SessionImpl + class_ref 128133 // EDL + class_ref 128261 // Fixture + class_ref 128389 // Track class_ref 128645 // Placement class_ref 129413 // RelativeLocation class_ref 129541 // Allocation + class_ref 140421 // Plug class_ref 139909 // LocatingPin class_ref 134021 // Buildable class_ref 134149 // BuilderTool diff --git a/uml/cinelerra3/cinelerra3.prj b/uml/cinelerra3/cinelerra3.prj index 47e92b6e0..2870223f2 100644 --- a/uml/cinelerra3/cinelerra3.prj +++ b/uml/cinelerra3/cinelerra3.prj @@ -1,6 +1,6 @@ format 40 "cinelerra3" - revision 39 + revision 40 modified_by 5 "hiv" cpp_root_dir "../../src/" From b7bce2a2f7074aa68403ed3320a27a2b5e5a55be Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 12 Jan 2008 18:19:37 +0100 Subject: [PATCH 3/8] WIP defined lots of details regarding the handling of Ports --- doc/devel/uml/fig131205.png | Bin 15936 -> 14369 bytes src/common/util.hpp | 8 + src/proc/asset/port.cpp | 27 +++ src/proc/asset/port.hpp | 31 ++- src/proc/asset/procpatt.hpp | 2 + src/proc/asset/struct.cpp | 30 +-- src/proc/asset/struct.hpp | 3 +- src/proc/assetmanager.cpp | 2 + src/proc/mobject/session/clip.hpp | 6 + tests/51asset.tests | 8 + tests/components/proc/asset/basicporttest.cpp | 194 ++++++++++++++++++ .../proc/asset/dependantassetstest.cpp | 2 +- uml/cinelerra3/128133 | 5 +- uml/cinelerra3/129285 | 2 +- uml/cinelerra3/131205.diagram | 54 ++--- uml/cinelerra3/5.session | 2 +- uml/cinelerra3/cinelerra3.prj | 2 +- wiki/renderengine.html | 56 +++-- 18 files changed, 368 insertions(+), 66 deletions(-) create mode 100644 tests/components/proc/asset/basicporttest.cpp diff --git a/doc/devel/uml/fig131205.png b/doc/devel/uml/fig131205.png index b35cdf424ab816236e230cbb8f52df442906785c..91a2d89e2f0e139862dc72882dfe6d35f7cf1c85 100644 GIT binary patch literal 14369 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 Y{P>EK&$a-(`UiO|sqm;!+~E2D0VsyCt^fc4 literal 15936 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

lH2?c5=V(bS~2Bi6N&6)#;K3mv#i8S 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 + 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 diff --git a/src/proc/asset/port.cpp b/src/proc/asset/port.cpp index 116f7ee63..98e758b89 100644 --- a/src/proc/asset/port.cpp +++ b/src/proc/asset/port.cpp @@ -25,6 +25,33 @@ namespace asset { + + namespace // Port Asset implementation details + { + /** @internal derive a sensible asset ident tuple when creating + * a track asset based on a query + * @todo define the actual naming scheme of struct assets + */ + const Asset::Ident + createPortIdent (PProcPatt& wiring, string& id, wstring& shortD, wstring& longD) + { + string name ("port-" + id); // TODO something sensible here; append number, sanitize etc. + TODO ("Implement port name scheme!!"); + Category category (STRUCT,"ports"); + return Asset::Ident (name, category ); + } + } + + /** */ + Port::Port (PProcPatt& wiring, string portID="", wstring shortDesc="", wstring longDesc="") + : Struct (createPortIdent (wiring,portID,shortDesc,longDesc)), + portID_ (portID), + shortDesc_ (shortDesc), + longDesc_ (longDesc) + { + + } + diff --git a/src/proc/asset/port.hpp b/src/proc/asset/port.hpp index e854cfe86..995b0c0b3 100644 --- a/src/proc/asset/port.hpp +++ b/src/proc/asset/port.hpp @@ -31,8 +31,20 @@ namespace asset { + + class Port; + + + template<> + class ID : public ID + { + public: + ID (size_t id); + ID (const Port&); + }; - + + /** * structural asset corresponding to some port * for building a processing chain and @@ -40,12 +52,27 @@ namespace asset */ class Port : public Struct { + PProcPatt wiringTemplate; + string portID_; + wstring shortDesc_; + wstring longDesc_; + protected: - ProcPatt* wiringTemplate; + Port (PProcPatt& wiring, string portID="", wstring shortDesc="", wstring longDesc="") ; + friend class StructFactory; }; + // catch up with postponed definition of ID ctors... + // + inline ID::ID(size_t id) : ID (id) {}; + inline ID::ID(const Port& port) : ID (port.getID()) {}; + + + typedef shared_ptr PPort; + + } // namespace asset #endif diff --git a/src/proc/asset/procpatt.hpp b/src/proc/asset/procpatt.hpp index 77ea5cd26..28de7b404 100644 --- a/src/proc/asset/procpatt.hpp +++ b/src/proc/asset/procpatt.hpp @@ -50,6 +50,8 @@ namespace asset }; + typedef shared_ptr PProcPatt; + } // namespace asset diff --git a/src/proc/asset/struct.cpp b/src/proc/asset/struct.cpp index de4160bce..6e50400cc 100644 --- a/src/proc/asset/struct.cpp +++ b/src/proc/asset/struct.cpp @@ -31,21 +31,21 @@ namespace asset { - namespace // Implementation details - { - /** @internal derive a sensible asset ident tuple when creating - * a track asset based on a query - * @todo define the actual naming scheme of struct assets - */ - const Asset::Ident - createTrackIdent (Query& query) - { - string name ("track-" + query); // TODO something sensible here; append number, sanitize etc. - TODO ("track naming scheme??"); - Category category (STRUCT,"tracks"); - return Asset::Ident (name, category ); - } - } + namespace // common Struct Asset implementation details + { + /** @internal derive a sensible asset ident tuple when creating + * a track asset based on a query + * @todo define the actual naming scheme of struct assets + */ + const Asset::Ident + createTrackIdent (Query& query) + { + string name ("track-" + query); // TODO something sensible here; append number, sanitize etc. + TODO ("track naming scheme??"); + Category category (STRUCT,"tracks"); + return Asset::Ident (name, category ); + } + } diff --git a/src/proc/asset/struct.hpp b/src/proc/asset/struct.hpp index 9b2c56e3f..ec52169d5 100644 --- a/src/proc/asset/struct.hpp +++ b/src/proc/asset/struct.hpp @@ -43,6 +43,7 @@ #include using std::string; +using std::wstring; namespace asset @@ -77,7 +78,7 @@ namespace asset } protected: - Struct (const Asset::Ident& idi) : Asset(idi) {} //////////////TODO + Struct (const Asset::Ident& idi) : Asset(idi) {} friend class StructFactory; }; diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index c8df77c65..4108d69b2 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -235,6 +235,7 @@ namespace asset #include "proc/asset/proc.hpp" #include "proc/asset/struct.hpp" #include "proc/asset/track.hpp" +#include "proc/asset/port.hpp" #include "proc/asset/meta.hpp" @@ -254,6 +255,7 @@ namespace asset template shared_ptr AssetManager::getPtr (const Media& asset); template shared_ptr AssetManager::getPtr (const Clip& asset); template shared_ptr AssetManager::getPtr (const Track& asset); + template shared_ptr AssetManager::getPtr (const Port& asset); } // namespace asset diff --git a/src/proc/mobject/session/clip.hpp b/src/proc/mobject/session/clip.hpp index fd87b1c39..2f7eccb06 100644 --- a/src/proc/mobject/session/clip.hpp +++ b/src/proc/mobject/session/clip.hpp @@ -60,6 +60,12 @@ namespace mobject /** startpos in source */ Time start_; + /** @todo using a mere ref here is against the scheme and only + done as temporal solution, until we work out how to handle + multichannel clips. It should be a smart pointer of some kind + and the unlink() function of the asset should take it into + account when breaking circular references. + */ const Media & mediaDef_; const asset::Clip & clipDef_; diff --git a/tests/51asset.tests b/tests/51asset.tests index 6f8afceee..6d8195ceb 100644 --- a/tests/51asset.tests +++ b/tests/51asset.tests @@ -34,6 +34,14 @@ return: 0 END +PLANNED "BasicPort_test" BasicPort_test < + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "common/test/run.hpp" +#include "common/util.hpp" + +#include "proc/asset/category.hpp" +#include "proc/asset/port.hpp" +#include "proc/assetmanager.hpp" +#include "proc/mobject/session.hpp" +#include "proc/asset/assetdiagnostics.hpp" + +#include +#include + +using boost::format; +using util::contains; +using util::isnil; +using std::string; +using std::cout; + + +namespace asset + { + namespace test + { + + + + + /*********************************************************************** + * @test basic properties of Port (structural) Assets. + *

  • created by referral
  • + *
  • access existing port by referral
  • + *
  • create with full properties
  • + *
  • access ProcPatt
  • + *
  • check dependency
  • + *
+ */ + class BasicPort_test : public Test + { + virtual void run(Arg arg) + { + string portID = isnil(arg)? "blackHole" : arg[1]; + string streamID = 2>arg.size()? "teststream" : arg[2] ; + + createExplicit (portID,streamID); + create_or_ref (portID); + dependProcPatt (portID); + } + + + + + void createExplicit (string pID, string sID) + { + PPort thePort = asset::Struct::create (pID,sID); + + ASSERT (thePort); + ASSERT (thePort->getProcPatt()); + ASSERT (thePort->getPortID() == util::sanitize(pID)); + ASSERT (thePort->getProcPatt()->getStreamID() == sID); + ASSERT (thePort->getShortDesc() == thePort->getPortID()); + + ID assetID = thePort->getID(); + ASSERT (assetID.org = "cin3"); + ASSERT (contains (assetID.name, thePort->getPortID())); + ASSERT (contains (assetID.name, thePort->getProcPatt()->getStreamID())); + + Category cat (assetID.category); + Category refcat (STRUCT,"ports"); + ASSERT ( cat.hasKind(STRUCT) ); + ASSERT ( cat.isWithin(refcat) ); + } + + + void create_or_ref(string pID) + { + pID = util::sanitize (pID); + PPort port1 = asset::Struct::query ("port("+pID+")"); + ASSERT (port1); + ASSERT (port1->getPortID() == pID); + + string pID2 = "another-" + pID; + PPort port2 = asset::Struct::query ("port("+pID2+")"); + ASSERT (port2); + ASSERT (port2 != port1); + Category c1 = port1->getID().category; + Category c2 = port2->getID().category; + ASSERT (c1 == c2); + + PPort port3 = asset::Struct::query ("port("+pID2+")"); + ASSERT (port3 == port2); + } + + + void create_using_default() + { + PPort port1 = asset::Struct::query (""); + ASSERT (port1); + ASSERT (port1 == mobject::Session::current->getDefault()); + ASSERT (port1->getID().category.hasKind(VIDEO)); + ASSERT (port1->getProcPatt()); + PProcPatt popa = mobject::Session::current->getDefault("port()"); + ASSERT (popa == port1->getProcPatt()); + + PPort port2 = asset::Struct::query ("port()"); + ASSERT (port2 == port1); + + string sID = popa->getStreamID(); // sort of a "default stream type" + PPort port3 = asset::Struct::query ("stream("+sID+")"); + ASSERT (port3); + ASSERT (port3->getProcPatt()->getStreamID() == sID); + ASSERT (port3->getProcPatt() == mobject::Session::current->getDefault("stream("+sID+")"); + } + + + void dependProcPatt(string pID) + { + PPort thePort = asset::Struct::query ("port("+pID+")"); + ASSERT (thePort); + PProcPatt thePatt = thePort->getProcPatt(); + ASSERT (thePatt); + ASSERT (dependencyCheck (thePort, thePatt)); + + PProcPatt pattern2 = thePatt->newCopy("another"); + ASSERT (thePatt != pattern2); + ASSERT (!dependencyCheck (thePort, pattern2)); + TODO ("add something to the new pattern, e.g. an effect"); + + // now querying for a port using this pattern (created on-the-fly) + // note: because the pattern is new, this new port will be used as + // default port for this pattern automatically + PPort port2x = asset::Struct::query ("pattern(another)"); + ASSERT (pattern2 == port2x->getProcPatt()); + ASSERT (port2x == mobject::Session::current->getDefault("pattern(another)")); + + thePort->switchProcPatt(pattern2); + ASSERT ( dependencyCheck (thePort, pattern2)); + ASSERT (!dependencyCheck (thePort, thePatt)); + + AssetManager& aMang = AssetManager::instance(); + ASSERT ( aMang.known (thePort->getID())); + ASSERT ( aMang.known (thePatt->getID())); + ASSERT ( aMang.known (pattern2->getID())); + aMang.remove (pattern2->getID()); + ASSERT ( aMang.known (thePatt->getID())); + ASSERT (!aMang.known (pattern2->getID())); + ASSERT (!aMang.known (thePort->getID())); // has been unlinked too, because dependant on pattern2 + + ASSERT (thePort); + ASSERT (thePort->getProcPatt()); + ASSERT (thePort->getProcPatt() == pattern2); // but is still valid, as long as the ref is alive.... + + PPort port3x = asset::Struct::query ("pattern(another)"); + ASSERT (port3x->getProcPatt() != pattern2); // because pattern2 is already unlinked... + ASSERT (port3x == mobject::Session::current->getDefault("pattern(another)")); + ASSERT (port3x != port2x); // ..we got a new default port for "pattern(another)" too! + + + TRACE (assetmem, "leaving BasicPort_test::dependProcPatt()"); + // expect now port2x and pattern2 to be destroyed... + } + }; + + + /** Register this test class... */ + LAUNCHER (BasicPort_test, "unit asset"); + + + + } // namespace test + +} // namespace asset diff --git a/tests/components/proc/asset/dependantassetstest.cpp b/tests/components/proc/asset/dependantassetstest.cpp index 3842ad933..f9cc1d412 100644 --- a/tests/components/proc/asset/dependantassetstest.cpp +++ b/tests/components/proc/asset/dependantassetstest.cpp @@ -1,5 +1,5 @@ /* - DependantAssets(Test) - unittest for the object creating factory + DependantAssets(Test) - check the asset dependency handling Copyright (C) CinelerraCV 2007, Hermann Vosseler diff --git a/uml/cinelerra3/128133 b/uml/cinelerra3/128133 index 591fc4844..cb48c458d 100644 --- a/uml/cinelerra3/128133 +++ b/uml/cinelerra3/128133 @@ -1,6 +1,6 @@ format 40 "Asset" // ProcessingLayer::Asset - revision 16 + revision 17 modified_by 5 "hiv" // class settings //class diagram settings @@ -684,7 +684,6 @@ ${inlines} classrelation_ref 141317 // b multiplicity "" parent class_ref 136965 // Struct end - end class 138117 "Port" @@ -710,7 +709,7 @@ ${inlines} classrelation 148101 // relation 145925 -_-> a default - cpp default "Generated" + cpp default "#include in header" classrelation_ref 148101 // b multiplicity "" parent class_ref 138757 // ProcPatt end diff --git a/uml/cinelerra3/129285 b/uml/cinelerra3/129285 index 11729b3cf..55db3685a 100644 --- a/uml/cinelerra3/129285 +++ b/uml/cinelerra3/129285 @@ -1,6 +1,6 @@ format 40 "ProcessingLayer" // ProcessingLayer - revision 10 + revision 11 modified_by 5 "hiv" // class settings //class diagram settings diff --git a/uml/cinelerra3/131205.diagram b/uml/cinelerra3/131205.diagram index c3c077ba7..6b22db552 100644 --- a/uml/cinelerra3/131205.diagram +++ b/uml/cinelerra3/131205.diagram @@ -2,83 +2,83 @@ format 40 packagecanvas 128005 package_ref 128133 // Asset - xyzwh 328 34 1994 448 544 + xyzwh 52 6 1994 448 544 classcanvas 128133 class_ref 139013 // BuildInstruct draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 651 391 2000 + xyz 375 363 2000 end classcanvas 128261 class_ref 136837 // Proc draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 481 508 2005 + xyz 205 480 2005 end classcanvas 128389 class_ref 138757 // ProcPatt draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 684 277 2000 + xyz 408 249 2000 end classcanvas 128517 class_ref 138117 // Port draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 516 196 2000 + xyz 240 168 2000 end classcanvas 128645 class_ref 139141 // DoAttach draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 613 459 2000 + xyz 337 431 2000 end classcanvas 128773 class_ref 137989 // Track draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 604 196 2000 + xyz 328 168 2000 end classcanvas 128901 class_ref 139269 // DoRecurse draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 685 459 2000 + xyz 409 431 2000 end classcanvas 129029 class_ref 136965 // Struct draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 701 101 2005 + xyz 425 73 2005 end relationcanvas 129157 relation_ref 139653 // geometry VHV - from ref 128517 z 1999 to point 536 167 - line 130437 z 1999 to point 721 167 + from ref 128517 z 1999 to point 260 139 + line 130437 z 1999 to point 445 139 line 130565 z 1999 to ref 129029 no_role_a no_role_b no_multiplicity_a no_multiplicity_b relationcanvas 129285 relation_ref 141189 // - from ref 128389 z 1999 to point 721 228 + from ref 128389 z 1999 to point 445 200 line 130693 z 1999 to ref 129029 no_role_a no_role_b no_multiplicity_a no_multiplicity_b relationcanvas 129413 relation_ref 139525 // geometry VHV - from ref 128773 z 1999 to point 624 167 - line 130181 z 1999 to point 721 167 + from ref 128773 z 1999 to point 348 139 + line 130181 z 1999 to point 445 139 line 130309 z 1999 to ref 129029 no_role_a no_role_b no_multiplicity_a no_multiplicity_b relationcanvas 129541 relation_ref 141701 // - from ref 128389 z 1999 stereotype "<>" xyz 637 314 3000 to ref 128133 - role_a_pos 640 329 3000 no_role_b - multiplicity_a_pos 668 366 3000 multiplicity_b_pos 743 320 3000 + from ref 128389 z 1999 stereotype "<>" xyz 361 286 3000 to ref 128133 + role_a_pos 364 301 3000 no_role_b + multiplicity_a_pos 392 338 3000 multiplicity_b_pos 467 292 3000 relationcanvas 129669 relation_ref 141829 // from ref 128645 z 1999 to ref 128133 no_role_a no_role_b no_multiplicity_a no_multiplicity_b relationcanvas 129797 relation_ref 142213 // - from ref 128645 z 1999 stereotype "<>" xyz 510 628 3000 to ref 128261 - role_a_pos 535 494 3000 no_role_b - multiplicity_a_pos 535 527 3000 no_multiplicity_b + from ref 128645 z 1999 stereotype "<>" xyz 278 485 3000 to ref 128261 + role_a_pos 259 466 3000 no_role_b + multiplicity_a_pos 259 499 3000 no_multiplicity_b relationcanvas 130053 relation_ref 141957 // from ref 128901 z 1999 to ref 128133 no_role_a no_role_b no_multiplicity_a no_multiplicity_b relationcanvas 131461 relation_ref 142085 // - from ref 128901 z 1999 to point 747 424 - line 131845 z 1999 to point 747 348 + from ref 128901 z 1999 to point 471 396 + line 131845 z 1999 to point 471 320 line 131973 z 1999 to ref 128389 - role_a_pos 719 362 3000 no_role_b - multiplicity_a_pos 707 329 3000 multiplicity_b_pos 727 436 3000 + role_a_pos 443 334 3000 no_role_b + multiplicity_a_pos 431 301 3000 multiplicity_b_pos 451 408 3000 relationcanvas 131589 relation_ref 146053 // - from ref 128517 z 1999 to point 536 295 + from ref 128517 z 1999 to point 260 267 line 131717 z 1999 to ref 128389 - role_a_pos 569 280 3000 no_role_b - multiplicity_a_pos 576 296 3000 no_multiplicity_b + role_a_pos 293 252 3000 no_role_b + multiplicity_a_pos 300 268 3000 no_multiplicity_b end diff --git a/uml/cinelerra3/5.session b/uml/cinelerra3/5.session index 76cf1249d..d8ab0b626 100644 --- a/uml/cinelerra3/5.session +++ b/uml/cinelerra3/5.session @@ -7,7 +7,7 @@ diagrams classdiagram_ref 128389 // Render Entities 743 538 100 4 0 0 active classdiagram_ref 131205 // Struct-Asset Relations - 741 555 100 4 0 114 + 555 620 100 4 0 0 end show_stereotypes selected diff --git a/uml/cinelerra3/cinelerra3.prj b/uml/cinelerra3/cinelerra3.prj index 2870223f2..f342468f2 100644 --- a/uml/cinelerra3/cinelerra3.prj +++ b/uml/cinelerra3/cinelerra3.prj @@ -1,6 +1,6 @@ format 40 "cinelerra3" - revision 40 + revision 41 modified_by 5 "hiv" cpp_root_dir "../../src/" diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 1335e6365..bf5e44e84 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -564,13 +564,21 @@ For every Asset we generate a __Ident tuple__ and a long ID (hash) derived from
The Asset Manager provides an Interface to some internal Database holding all Assets in the current Session and System state. It may be a real Database at some point (and for the moment it's a Hashtable). Each [[Asset]] is registered automatically with the Asset Manager; it can be queried either by it's //identification tuple// or by it's unique ID.
+
+
Placing an MObject relatively to another object such that it should be handled as //attached // to the latter results in several implementation problems. The typical use case is that of an effect attached to a clip or port.
+* this attachment is not a globally fixed relation, rather, it typically exists only for some limited time span (e.g. the duration of the basic clip the effect is attached to)
+* the order of attachment is important and the attached placement may create a fork in the signal flow, so we need a way for specifying reproducibly how the resulting wiring should be
+* when building, we access the information in reversed direction: we have the target object and need to query for all attachements
+
+The first step towards an solution is to isolate the problem; obviously we //need the information about attached objects // only for two isolated tasks, namely when building and for creating a GUI representation. So using a query (function call) interface, the rest of the problem is turned into an implementation detail.
+
Automation is treated as a function over time. It is always tied to a specific Parameter (which can thus be variable over the course of the timeline). All details //how// this function is defined are completely abstracted away. The Parameter uses a ParamProvider to get the value for a given Time (point). Typically, this will use linear or bezier interpolation over a set of keyframes internally. Parameters can be configured to have different value ranges and distribution types (on-off, stepped, continuous, bounded)
 
 [img[how to implement Automation|uml/fig129669.png]]
 
-
+
Starting out from the concepts of Objects, Placement to Tracks, Ports and connection properties (&rarr; see [[here|TrackPortEDL]]) within the EDL, we can identify the elementary operations occuring within the Builder. Overall, the Builder is organized as application of //visiting tools// to a collection of objects, so finally we have to consider some object kind appearing in the working function of the given builder tool, which holds at this moment some //context//. The job now is to organize this context such as to create a predictable build process from this //event driven// approach.
 
 !Builder working Situations
@@ -803,6 +811,9 @@ This is an very important external Interface, because it links together all thre
 
RenderEngine
 
+
+
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->getDefault<TYPE>("query string")}}}, where the //query string // defines a capability query similar to what is employed for ports, stream types, codecs etc.
+
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...
 
@@ -1071,7 +1082,7 @@ For this Cinelerra3 design, we could consider making GOP just another raw media
 &rarr;see in [[Wikipedia|http://en.wikipedia.org/wiki/Group_of_pictures]]
 
-
+
This wiki page is the entry point to detail notes covering some technical decisions, details and problems encountered in the course of the implementation of the Cinelerra Renderengine, the Builder and the related parts.
 
 * [[Packages, Interfaces and Namespaces|InterfaceNamespaces]]
@@ -1085,6 +1096,7 @@ For this Cinelerra3 design, we could consider making GOP just another raw media
 * [[using the Visitor pattern?|VisitorUse]] &mdash; resulting in [[»Visiting-Tool« library implementation|VisitingToolImpl]]
 * [[Handling of Tracks and Ports in the EDL|TrackPortEDL]]. [[Handling of Tracks|TrackHandling]] and [[Ports|PortHandling]]
 * [[identifying the basic Builder operations|BasicBuildingOperations]] and [[planning the Implementation|PlanningNodeCreaterTool]]
+* [[how to handle »attached placement«|AttachedPlacementProblem]]
 
@@ -1518,8 +1530,8 @@ This Design strives to achieve a StrongSeparation between the low-level Structur <style type="text/css">#contentWrapper {display:none;}</style><div id="SplashScreen" style="border: 3px solid #ccc; display: block; text-align: center; width: 320px; margin: 100px auto; padding: 50px; color:#000; font-size: 28px; font-family:Tahoma; background-color:#eee;">loading <b>Cinelerra Renderengine</b> devel doku<blink> ...</blink><br><br><span style="font-size: 14px; color:red;">Requires Javascript.</span></div>
-
-
The Interface asset::Media is a //key abstraction// It ties together several concepts and enables to deal with them on the interfaces in a uniform manner. Besides, as every Asset kind it belongs rather to the bookkeeping view: it holds the specific properties and parametrisation of the media source it stands for. Regarding the __inward interface__ &mdash; as used from within the [[EDL]] or the [[Render Nodes|ProcNode]], it is irrelevant if a given asset::Media object stands for a complete media source, just a clip taken from this source or if a placeholder version of the real media source is used instead.
+
+
The Interface asset::Media is a //key abstraction// It ties together several concepts and enables to deal with them on the interfaces in a uniform manner. Besides, as every Asset kind it belongs rather to the bookkeeping view: an asset::Media holds the specific properties and parametrisation of the media source it stands for. Regarding the __inward interface__ &mdash; as used from within the [[EDL]] or the [[Render Nodes|ProcNode]], it is irrelevant if any given asset::Media object stands for a complete media source, just a clip taken from this source or if a placeholder version of the real media source is used instead.
 [img[Asset Classess|uml/fig130437.png]]
 
@@ -2258,7 +2270,7 @@ afterwards. <<tasksum end>>
-
+
//This page is a scrapbook for working out the implementation of the builder//
 
 * NodeCreaterTool is a [[visiting tool|VisitorUse]]
@@ -2284,7 +2296,7 @@ We need a way of addressing existing [[ports|Port]]. Besides, as the Ports and T
 !!treating a {{{Placement<Clip>}}}
 <<task>>get the ProcPatt of the underlying media (asset)
 <<task>>process the ProcPatt recursively
-<<task>>create or access? {{red{TODO: decide this}}} the ClipSourcePort
+<<task>>access the ClipSourcePort (which may be created on-the-fly)
 <<task>>enqueue an WiringRequest for connecting the source pipeline to the source port
 <<task>>process the source port recursively (thus adding the camera etc.)
 <<task>>enqueue an WiringRequest for any placement to some port for this clip.
@@ -2319,6 +2331,21 @@ The GUI can connect the viewer(s) to some port (and moreover can use [[probe poi
 &rarr; [[Handling of Tracks|TrackHandling]]
 &rarr; [[Handling of Ports|PortHandling]]
 
+
+
+
+
!Identification
+Ports are distinct objects and can be identified by their asset ~IDs. Besides, as for all [[structural assets|StructAsset]] there are extended query capabilities, including a symbolic port-id and a media (stream) type id. Any port can accept and deliver exactly one media stream kind (which may be inherently structured though, e.g. spatial sound systems or stereoscopic video)
+
+!creating ports
+Port assets are created automatically by being used and referred. The [[Session]] holds a collection of global ports, and further ports can be created by using an new port reference in some placement. Moreover, every clip has an (implicit) [[source port|ClipSourcePort]], which will appear as port asset when first used (referred) while [[building|BuildProcess]].
+
+!removal
+Deleting a Port is an advanced operation, because it includes finding and "detaching" all references, otherwise the port will leap back into existence immediately. Thus, global port entries in the Session and port references in [[locating pins|LocatingPin]] within any placement have to be removed, while clips using a given source port will be disabled. {{red{todo: implementation deferred}}}
+
+!using Ports
+there is not much you can do directly with a port asset. It is an point of reference, after all. Any connection to some port is only temporarily done by a placement in some part of the timeline, so it isn't stored with the port. You can edit the (user visible) description an you can globally disable a port asset. The port's ID and media stream type of course are fixed, because any connection and referral (via the asset ID) is based on them. Later on, we should provide a {{{rewire(oldPort, newPort)}}} to search any ref to the {{{oldPort}}} and try to rewrite it to use the {{{newPort}}}, possibly with a new media stream type.
+Ports are integrated with the [[management of defaults|DefaultsManagement]]. For example, any port uses implicitly some [[processing pattern|ProcPatt]] &mdash; it may default to the empty pattern. This feature enables to apply some standard wiring to the ports (e.g a fader for audio, similar to the classic mixing consoles). This //is // a global property of the port, but &mdash; contrary to the stream type &mdash; this pattern may be switched
 
@@ -2780,16 +2807,17 @@ Instead, we should try to just connect the various subsystems via Interfaces and * to shield the rendering code of all complexities of thread communication and synchronization, we use the StateProxy
-
-
Structural Assets are intended mainly for internal use, but the user should be able to see and query them. By changing the parametrisation of some structural Asset, we can customize the default behaviour of Cinelerra to some extent.
-* [[Processing Patterns|ProcPatt]] encode the information, how to get at the actual media data when rendering a clip.
-* Tracks are one of the dimensions used for organizing the EDL. Besides, they carry parametrisation of output port, overlay mode etc.
-* Output Ports {{red{still need to be defined...}}}
-
+
+
Structural Assets are intended mainly for internal use, but the user should be able to see and query them. They are not "loaded" or "created" direcly, rather they //leap into existance // by creating or extending some other structures in the EDL/Session, hence the name. Some of the structural Asset parametrisation can be modified to control of some aspects of the Proc Layer's (default) behaviour.
+* [[Processing Patterns|ProcPatt]] encode information how to set up some parts of the render network to be created automatically: for example, when building a clip, we use the processing pattern how to decode and preprocess the actual media data.
+* [[Tracks|Track]] are one of the dimensions used for organizing the EDL. They serve as an Anchor to attach parametrisation of output port, overlay mode etc. By [[placing|Placement]] to a track, some media object inherits placement properties from this track.
+* [[Ports|Port]] form &mdash; at least as visible to the user &mdash; the basic building block of the render network, because the latter appears to be a collection of processing pipelines rooted on Ports and interconnected. (this is the //outward view; // in fact the render network consists of [[nodes|ProcNode]] and is [[built|Builder]] from the Ports, clips, effects...)
+[>img[Asset Classess|uml/fig131205.png]]
+!naming scheme
 The Asset name field of structural Assets utilizes a special naming scheme, which allows to derive the name based on the capabilities of the structural asset. For example, by default all media clips with a given media stream type (e.g. H264) will use the same [[processing Pattern|ProcPatt]] for rendering. {{red{todo: work out the details of this naming scheme??}}}
 
-[img[Asset Classess|uml/fig131205.png]]
-
+!querying +Structural assets can be queried by specifying the specific type (Port, Track, ProcPatt) and a query goal, which means in the current implementation just querying for some predicate defined with the structural asset. For example, you can {{{Query<Port> ("stream(mpeg)")}}}, yieliding the first port found which declares to have stream type "mpeg"
/*{{{*/

From 061a84f2bebff5a7f1914203cd086ced3bf2ac56 Mon Sep 17 00:00:00 2001
From: Ichthyostega 
Date: Mon, 14 Jan 2008 01:01:11 +0100
Subject: [PATCH 4/8] WIP implementing Ports, add DefaultsManager...

---
 src/proc/asset.cpp                            |  4 +-
 src/proc/asset/clip.cpp                       | 18 +----
 src/proc/asset/media.cpp                      |  2 +-
 src/proc/asset/port.cpp                       | 17 ++++-
 src/proc/asset/port.hpp                       | 25 ++++++-
 src/proc/asset/procpatt.cpp                   | 49 +++++++++++++
 src/proc/asset/procpatt.hpp                   |  9 ++-
 src/proc/asset/query.cpp                      | 58 +++++++++++++++
 src/proc/asset/query.hpp                      | 62 ++++++++++++++++
 src/proc/asset/struct.cpp                     | 33 ++++++++-
 src/proc/asset/struct.hpp                     | 17 ++---
 src/proc/assetmanager.cpp                     | 12 +--
 src/proc/assetmanager.hpp                     |  2 +-
 src/proc/mobject/session.hpp                  |  4 +-
 src/proc/mobject/session/clip.cpp             |  4 +-
 src/proc/mobject/session/defsmanager.cpp      | 55 ++++++++++++++
 src/proc/mobject/session/defsmanager.hpp      | 73 +++++++++++++++++++
 src/proc/mobject/session/session.cpp          |  9 ++-
 src/proc/mobject/session/sessionimpl.cpp      |  4 +-
 src/proc/mobject/session/sessionimpl.hpp      |  3 +-
 src/proc/mobject/session/sessmanagerimpl.cpp  | 11 ++-
 tests/components/proc/asset/basicporttest.cpp | 70 ++++++++++--------
 22 files changed, 451 insertions(+), 90 deletions(-)
 create mode 100644 src/proc/asset/query.cpp
 create mode 100644 src/proc/asset/query.hpp
 create mode 100644 src/proc/mobject/session/defsmanager.cpp
 create mode 100644 src/proc/mobject/session/defsmanager.hpp

diff --git a/src/proc/asset.cpp b/src/proc/asset.cpp
index 5878936f0..7547b9597 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/clip.cpp b/src/proc/asset/clip.cpp
index 38e78e59a..e643d96d7 100644
--- a/src/proc/asset/clip.cpp
+++ b/src/proc/asset/clip.cpp
@@ -85,29 +85,13 @@ namespace asset
   
 
 
-  /** in spite of asset::Clip being a concrete subclass (and not an asset subinterface),
-   *  we need to create the following explicit specialisation for asset::Clip#getClipAsset.
-   *  Basically, it's a "shared-ptr-from-this"-function.
-   */
-  template<>
-  shared_ptr
-  AssetManager::getPtr (const Clip& asset)
-  {
-    ENSURE (instance().known(asset.id), 
-            "unregistered asset instance encountered.");
-    return static_pointer_cast
-            (instance().getAsset (asset.id));
-    
-  }
-
-  
   /** return this wrapped into a shared ptr,
    *   because it's already the desired asset::Clip
    */
   Media::PClip
   Clip::getClipAsset ()
   {
-    return AssetManager::getPtr(*this);
+    return AssetManager::wrap (*this);
   }
   
 
diff --git a/src/proc/asset/media.cpp b/src/proc/asset/media.cpp
index 7f5206836..82ba763be 100644
--- a/src/proc/asset/media.cpp
+++ b/src/proc/asset/media.cpp
@@ -230,7 +230,7 @@ namespace asset
                                       ,CINELERRA_ERROR_PART_OF_COMPOUND
                                       );
     asset::Clip* pC = new asset::Clip (mediaref);
-    return AssetManager::instance().getPtr (*pC);
+    return AssetManager::instance().wrap (*pC);
   }
   
   CINELERRA_ERROR_DEFINE (PART_OF_COMPOUND, "part of compound used as toplevel element");
diff --git a/src/proc/asset/port.cpp b/src/proc/asset/port.cpp
index 98e758b89..f574dbd39 100644
--- a/src/proc/asset/port.cpp
+++ b/src/proc/asset/port.cpp
@@ -29,7 +29,7 @@ namespace asset
   namespace // Port Asset implementation details
     {
       /** @internal derive a sensible asset ident tuple when creating 
-       *  a track asset based on a query
+       *  a port asset based on a query
        *  @todo define the actual naming scheme of struct assets
        */
       const Asset::Ident
@@ -43,15 +43,24 @@ namespace asset
     } 
   
   /** */
-  Port::Port (PProcPatt& wiring, string portID="", wstring shortDesc="", wstring longDesc="") 
+  Port::Port (PProcPatt& wiring, string portID, wstring shortDesc, wstring longDesc) 
     : Struct (createPortIdent (wiring,portID,shortDesc,longDesc)),
       portID_ (portID),
-      shortDesc_ (shortDesc),
-      longDesc_ (longDesc)
+      shortDesc (shortDesc),
+      longDesc (longDesc)
   {
     
   }
 
+  
+  
+  void 
+  Port::switchProcPatt (PProcPatt& another)
+  {
+    wiringTemplate = another;
+    TODO ("trigger rebuild fixture");
+  }
+
 
 
 
diff --git a/src/proc/asset/port.hpp b/src/proc/asset/port.hpp
index 995b0c0b3..8784b629b 100644
--- a/src/proc/asset/port.hpp
+++ b/src/proc/asset/port.hpp
@@ -33,6 +33,7 @@ namespace asset
   {
   
   class Port;
+  typedef shared_ptr PPort;
   
   
   template<>
@@ -54,13 +55,30 @@ namespace asset
     {
       PProcPatt wiringTemplate;
       string portID_;
-      wstring shortDesc_;
-      wstring longDesc_;
+      
+    public:
+      wstring shortDesc;
+      wstring longDesc;
+      
+      virtual const ID& getID()  const    ///< @return ID typed to asset::Port 
+        { 
+          return static_cast& > (Asset::getID()); 
+        }
+
       
     protected:
-      Port (PProcPatt& wiring, string portID="", wstring shortDesc="", wstring longDesc="") ;
+      Port (PProcPatt& wiring, string portID="", wstring shortDesc =wstring(), wstring longDesc =wstring()) ;
       friend class StructFactory;
 
+    public:
+      const string& getPortID()       const { return portID_; }
+      const PProcPatt& getProcPatt()  const { return wiringTemplate; }
+      
+      /** use another wiring template. Triggers complete rebuild of the render engine. */
+      void switchProcPatt (PProcPatt& another);
+      
+      /** convienience shortcut for retrieving default configured ports */
+      static PPort query (string properties)  { return Struct::create (Query (properties)); }
     };
     
     
@@ -70,7 +88,6 @@ namespace asset
   inline ID::ID(const Port& port) : ID (port.getID()) {};
 
       
-  typedef shared_ptr PPort;
 
     
     
diff --git a/src/proc/asset/procpatt.cpp b/src/proc/asset/procpatt.cpp
index eebed7fad..3b267f1e4 100644
--- a/src/proc/asset/procpatt.cpp
+++ b/src/proc/asset/procpatt.cpp
@@ -23,11 +23,60 @@
 
 #include "proc/asset/procpatt.hpp"
 #include "proc/asset/buildinstruct.hpp"
+#include "proc/assetmanager.hpp"
 
 namespace asset
   {
   
+  namespace // ProcPattern implementation details
+    {
+      /** @internal derive a sensible asset ident tuple when creating 
+       *  a processing pattern asset based on a query
+       *  @todo define the actual naming scheme of struct assets
+       */
+      const Asset::Ident
+      createPatternIdent (const string& properties)
+        {
+          string name ("pattern-" + properties);  // TODO something sensible here; append number, sanitize etc.
+          TODO ("Implement ProcPatt name scheme!!");
+          Category category (STRUCT,"patterns");
+          return Asset::Ident (name, category );
+        }
+    } 
+  
   /** */
+  ProcPatt::ProcPatt (const string& properties, const vector& instr)
+    : Struct (createPatternIdent (properties)),
+      propDescriptor_ (properties),
+      instructions (instr)
+  {
+    TODO ("verify building instructions, maybe preprocess...");
+  }
+
+  
+  /** query the currently defined properties of this
+      processing pattern for a stream-ID predicate */
+  const string& 
+  ProcPatt::queryStreamID()  const
+  {
+    TODO ("really implement querying the properties");
+    return propDescriptor_; /////////////////////////////TODO grober Unfug
+  }
+  
+  
+  /** create a new ProcPatt asset as a literal copy
+   *  of this one. The new ProcPatt can then be customized
+   *  independently of the original one. This allows using
+   *  some ProcPatt as a template for creatind more
+   *  spezialized patterns. 
+   */
+  shared_ptr 
+  ProcPatt::newCopy (string newID)  const
+  {
+    TODO ("implement the Pattern-ID within the propDescriptor!");
+    ProcPatt* pP = new ProcPatt (this->propDescriptor_, this->instructions);
+    return AssetManager::instance().wrap (*pP);
+  }
 
 
 
diff --git a/src/proc/asset/procpatt.hpp b/src/proc/asset/procpatt.hpp
index 28de7b404..2a786027b 100644
--- a/src/proc/asset/procpatt.hpp
+++ b/src/proc/asset/procpatt.hpp
@@ -45,8 +45,15 @@ namespace asset
    */
   class ProcPatt : public Struct
     {
+      string propDescriptor_;
+      vector instructions;
+      
     protected:
-      const vector instructions;
+      ProcPatt (const string& properties, const vector& instr);
+      
+    public:
+      const string& queryStreamID()  const;
+      shared_ptr newCopy (string newID) const;
 
     };
     
diff --git a/src/proc/asset/query.cpp b/src/proc/asset/query.cpp
new file mode 100644
index 000000000..e729195c6
--- /dev/null
+++ b/src/proc/asset/query.cpp
@@ -0,0 +1,58 @@
+/*
+  Query  -  interface for capability queries
+ 
+  Copyright (C)         CinelerraCV
+    2007,               Hermann Vosseler 
+ 
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+ 
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+ 
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ 
+* *****************************************************/
+
+
+#include "proc/asset/query.hpp"
+#include "common/util.hpp"
+#include "nobugcfg.h"
+
+#include 
+
+using boost::algorithm::is_upper;
+using boost::algorithm::is_alpha;
+
+
+namespace asset
+  {
+  
+  namespace query
+    {
+    
+    void
+    normalizeID (string& id)
+    {
+      id = util::sanitize(id);
+      REQUIRE (!util::isnil(id));
+      REQUIRE (is_alpha() (id[0]));
+      
+      char first = id[0];
+      if (is_upper() (first))
+        id[0] = std::tolower (first);
+    }
+  
+  } // namespace query
+    
+  
+  /** */
+
+
+} // namespace asset
diff --git a/src/proc/asset/query.hpp b/src/proc/asset/query.hpp
new file mode 100644
index 000000000..0d91bd3de
--- /dev/null
+++ b/src/proc/asset/query.hpp
@@ -0,0 +1,62 @@
+/*
+  QUERY.hpp  -  interface for capability queries
+ 
+  Copyright (C)         CinelerraCV
+    2007,               Hermann Vosseler 
+ 
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+ 
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+ 
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ 
+*/
+
+
+#ifndef ASSET_QUERY_H
+#define ASSET_QUERY_H
+
+#include "common/util.hpp"
+
+#include 
+
+
+
+namespace asset
+  {
+  using std::string;
+  
+  /** 
+   * Generic query interface for retrieving objects matching
+   * some capability query
+   */
+  template
+  class Query : public std::string
+    {
+    public:
+      Query (string predicate="") : string(predicate) {}
+    };
+
+    
+  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);
+    
+  
+  } // namespace query
+    
+} // namespace asset
+#endif
diff --git a/src/proc/asset/struct.cpp b/src/proc/asset/struct.cpp
index 6e50400cc..e0436de9e 100644
--- a/src/proc/asset/struct.cpp
+++ b/src/proc/asset/struct.cpp
@@ -23,11 +23,15 @@
 
 #include "proc/assetmanager.hpp"
 #include "proc/asset/struct.hpp"
-#include "proc/asset/track.hpp"  
+#include "proc/asset/procpatt.hpp"
+#include "proc/asset/track.hpp"
+#include "proc/mobject/session.hpp"
 
 #include "common/util.hpp"
 #include "nobugcfg.h"
 
+using mobject::Session;
+
 namespace asset
   {
   
@@ -38,7 +42,7 @@ namespace asset
        *  @todo define the actual naming scheme of struct assets
        */
       const Asset::Ident
-      createTrackIdent (Query& query)
+      createTrackIdent (const Query& query)
         {
           string name ("track-" + query);  // TODO something sensible here; append number, sanitize etc.
           TODO ("track naming scheme??");
@@ -60,12 +64,33 @@ namespace asset
    */
   template<>
   shared_ptr 
-  StructFactory::operator() (Query query)
+  StructFactory::operator() (const Query& query)
   {
     TODO ("actually evaluate the query...");
     Track* pT = new Track (createTrackIdent (query));
-    return AssetManager::instance().getPtr (*pT);
+    return AssetManager::instance().wrap (*pT);
+  }
+  
+  
+  /** Factory method for creating Ports explicitly.
+   *  Normalizes port- and streamID, then retrieves the
+   *  default processing pattern (ProcPatt) for this streamID.
+   *  The Port ctor will fill out the shortDesc and longDesc
+   *  automatically, based on portID and streamID (and they
+   *  are editable anyways)
+   * @see ProcPatt
+   * @see DefaultsManager 
+   */ 
+  shared_ptr 
+  StructFactory::operator() (string portID, string streamID)
+  {
+    query::normalizeID (portID);
+    query::normalizeID (streamID);
+    PProcPatt processingPattern = Session::current->defaults (Query("stream("+streamID+")"));
+    Port* pP = new Port (processingPattern, portID);
+    return AssetManager::instance().wrap (*pP);
   }
 
 
+
 } // namespace asset
diff --git a/src/proc/asset/struct.hpp b/src/proc/asset/struct.hpp
index ec52169d5..723c332a3 100644
--- a/src/proc/asset/struct.hpp
+++ b/src/proc/asset/struct.hpp
@@ -38,6 +38,7 @@
 #define ASSET_STRUCT_H
 
 #include "proc/asset.hpp"
+#include "proc/asset/query.hpp"
 #include "common/factory.hpp"
 
 #include
@@ -51,6 +52,7 @@ namespace asset
   
   class Struct;
   class StructFactory;
+  class Port;
   
   
   template<>
@@ -90,15 +92,8 @@ namespace asset
   inline ID::ID(const Struct& stru) : ID (stru.getID()) {};
   
   
-  /** 
-   * Query for a special kind of structural Asset
-   */
-  template
-  class Query : public std::string
-    {
-    public:
-      Query (string predicate) : string(predicate) {}
-    };
+  
+  
   
   
   /** 
@@ -110,7 +105,9 @@ namespace asset
       typedef shared_ptr PType;
       
       template
-      shared_ptr operator() (Query query);      ////////////TODO define actual operation 
+      shared_ptr operator() (const Query& query);      ////////////TODO define actual operation 
+      
+      shared_ptr operator() (string portID, string streamID);
 
     };
     
diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp
index 4108d69b2..246411d60 100644
--- a/src/proc/assetmanager.cpp
+++ b/src/proc/assetmanager.cpp
@@ -152,7 +152,7 @@ namespace asset
    */
   template
   shared_ptr
-  AssetManager::getPtr (const KIND& asset)
+  AssetManager::wrap (const KIND& asset)
   {
     ENSURE (instance().known(asset.id), 
             "unregistered asset instance encountered.");
@@ -251,11 +251,11 @@ namespace asset
   template shared_ptr AssetManager::getAsset (const ID& id)  throw(cinelerra::error::Invalid);
   template shared_ptr   AssetManager::getAsset (const ID&   id)  throw(cinelerra::error::Invalid);
   
-  template shared_ptr  AssetManager::getPtr (const Asset& asset);
-  template shared_ptr  AssetManager::getPtr (const Media& asset);
-  template shared_ptr   AssetManager::getPtr (const Clip&  asset);
-  template shared_ptr  AssetManager::getPtr (const Track& asset);
-  template shared_ptr   AssetManager::getPtr (const Port&  asset);
+  template shared_ptr  AssetManager::wrap (const Asset& asset);
+  template shared_ptr  AssetManager::wrap (const Media& asset);
+  template shared_ptr   AssetManager::wrap (const Clip&  asset);
+  template shared_ptr  AssetManager::wrap (const Track& asset);
+  template shared_ptr   AssetManager::wrap (const Port&  asset);
 
   
 } // namespace asset
diff --git a/src/proc/assetmanager.hpp b/src/proc/assetmanager.hpp
index aaf5910dd..c035b38fa 100644
--- a/src/proc/assetmanager.hpp
+++ b/src/proc/assetmanager.hpp
@@ -73,7 +73,7 @@ namespace asset
       
       /** retrieve the registerd shared_ptr for any asset */
       template
-      static shared_ptr getPtr (const KIND& asset);
+      static shared_ptr wrap (const KIND& asset);
       
       /** find and return corresponging object */
       template
diff --git a/src/proc/mobject/session.hpp b/src/proc/mobject/session.hpp
index c61bc938a..149dc6c82 100644
--- a/src/proc/mobject/session.hpp
+++ b/src/proc/mobject/session.hpp
@@ -34,6 +34,7 @@
 #define MOBJECT_SESSION_H
 
 #include "proc/mobject/placement.hpp"
+#include "proc/mobject/session/defsmanager.hpp"
 #include "common/singleton.hpp"
 
 #include 
@@ -78,11 +79,12 @@ namespace mobject
   class Session : private boost::noncopyable
     {
     protected:
-      Session ()  throw();
+      Session (session::DefsManager&)  throw();
       virtual ~Session () = 0;
 
     public:
       static session::SessManager& current;
+      session::DefsManager& defaults;
       
       virtual bool isValid ()              = 0;
       virtual void add (PMO& placement)    = 0;
diff --git a/src/proc/mobject/session/clip.cpp b/src/proc/mobject/session/clip.cpp
index 7ea375173..38610e00f 100644
--- a/src/proc/mobject/session/clip.cpp
+++ b/src/proc/mobject/session/clip.cpp
@@ -66,14 +66,14 @@ namespace mobject
     PMedia 
     Clip::getMedia ()  const                        
     { 
-      return asset::AssetManager::getPtr (mediaDef_);
+      return asset::AssetManager::wrap (mediaDef_);
     }
     
     
     PClipAsset
     Clip::findClipAsset ()  const
     {
-      return asset::AssetManager::getPtr (clipDef_);
+      return asset::AssetManager::wrap (clipDef_);
     }
 
 
diff --git a/src/proc/mobject/session/defsmanager.cpp b/src/proc/mobject/session/defsmanager.cpp
new file mode 100644
index 000000000..53c5f1862
--- /dev/null
+++ b/src/proc/mobject/session/defsmanager.cpp
@@ -0,0 +1,55 @@
+/*
+  DefsManager  -  access to preconfigured default objects and definitions
+ 
+  Copyright (C)         CinelerraCV
+    2007,               Hermann Vosseler 
+ 
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+ 
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+ 
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ 
+* *****************************************************/
+
+
+#include "proc/mobject/session/defsmanager.hpp"
+#include "proc/asset/port.hpp"
+
+using asset::Query;
+using asset::Port;
+
+namespace mobject
+  {
+  namespace session
+    {
+    
+    /** initialize the most basic internal defaults. */
+    DefsManager::DefsManager ()  throw()
+    {
+      
+    }
+
+
+    /** create or retrieve a default-configured port asset.
+     *  @param 
+     */
+    template<>
+    shared_ptr 
+    DefsManager::operator() (const Query& properties)
+    {
+      
+    }
+
+
+  } // namespace mobject::session
+
+} // namespace mobject
diff --git a/src/proc/mobject/session/defsmanager.hpp b/src/proc/mobject/session/defsmanager.hpp
new file mode 100644
index 000000000..bc7323322
--- /dev/null
+++ b/src/proc/mobject/session/defsmanager.hpp
@@ -0,0 +1,73 @@
+/*
+  DEFSMANAGER.hpp  -  access to preconfigured default objects and definitions
+ 
+  Copyright (C)         CinelerraCV
+    2007,               Hermann Vosseler 
+ 
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+ 
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+ 
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ 
+*/
+
+
+#ifndef MOBJECT_SESSION_DEFSMANAGER_H
+#define MOBJECT_SESSION_DEFSMANAGER_H
+
+
+#include "proc/asset/query.hpp"
+
+//#include 
+//#include 
+
+//using std::vector;
+#include 
+
+
+
+namespace mobject
+  {
+  namespace session
+    {
+    using std::tr1::shared_ptr;
+
+
+    /**
+     * Organize a collection of preconfigured default objects.
+     * For various kinds of objects we can tweek the default parametrisation
+     * as part of the general session configuration. A ref to an instance of
+     * this class is accessible through the current session and can be used
+     * to fill in parts of the configuration of new objects, if the user 
+     * code didn't give more specific parameters. Necessary sub-objects 
+     * will be created on demand, and any default configuration, once
+     * found, will be remembered and stored with the current session.
+     */
+    class DefsManager
+      {
+      protected:
+        
+        DefsManager ()  throw();
+        friend class SessManagerImpl;
+        
+      public:
+        template
+        shared_ptr operator() (const asset::Query&);
+        
+      };
+
+      
+
+  } // namespace mobject::session
+
+} // namespace mobject
+#endif
diff --git a/src/proc/mobject/session/session.cpp b/src/proc/mobject/session/session.cpp
index 6e9b8f3fe..619cecf5b 100644
--- a/src/proc/mobject/session/session.cpp
+++ b/src/proc/mobject/session/session.cpp
@@ -33,6 +33,7 @@
 
 #include "proc/mobject/session.hpp"
 #include "proc/mobject/session/sessionimpl.hpp"
+#include "proc/mobject/session/defsmanager.hpp"
 
 #include "common/singleton.hpp"
 
@@ -58,8 +59,12 @@ namespace mobject
     
     
     
-  Session::Session ()  throw() { }
-  Session::~Session ()         { }
+  Session::~Session () 
+  { }
+
+  Session::Session (session::DefsManager& def)  throw()
+    : defaults(def)
+  { }
 
 
 
diff --git a/src/proc/mobject/session/sessionimpl.cpp b/src/proc/mobject/session/sessionimpl.cpp
index d89edac15..f2a0bcfa3 100644
--- a/src/proc/mobject/session/sessionimpl.cpp
+++ b/src/proc/mobject/session/sessionimpl.cpp
@@ -35,8 +35,8 @@ namespace mobject
      *        default session will inevitably halt the
      *        system (and this is desirable)
      */
-    SessionImpl::SessionImpl ()  throw()
-      : Session(),
+    SessionImpl::SessionImpl (DefsManager& defs)  throw()
+      : Session(defs),
         focusEDL_(0),
         edls(1), 
         fixture(new Fixture) 
diff --git a/src/proc/mobject/session/sessionimpl.hpp b/src/proc/mobject/session/sessionimpl.hpp
index 734a74a01..d9dc1f078 100644
--- a/src/proc/mobject/session/sessionimpl.hpp
+++ b/src/proc/mobject/session/sessionimpl.hpp
@@ -63,7 +63,7 @@ namespace mobject
         vector edls;
         PFix fixture;
         
-        SessionImpl ()  throw();
+        SessionImpl (DefsManager&)  throw();
         friend class SessManagerImpl;
         
         void clear ();
@@ -87,6 +87,7 @@ namespace mobject
      */
     class SessManagerImpl : public SessManager
       {
+        boost::scoped_ptr pDefs_;
         boost::scoped_ptr pImpl_;
         
         SessManagerImpl()  throw();
diff --git a/src/proc/mobject/session/sessmanagerimpl.cpp b/src/proc/mobject/session/sessmanagerimpl.cpp
index 9031bb712..ca2797151 100644
--- a/src/proc/mobject/session/sessmanagerimpl.cpp
+++ b/src/proc/mobject/session/sessmanagerimpl.cpp
@@ -38,6 +38,7 @@
 
 #include "proc/mobject/session.hpp"
 #include "proc/mobject/session/sessionimpl.hpp"
+#include "proc/mobject/session/defsmanager.hpp"
 
 using boost::scoped_ptr;
 
@@ -54,7 +55,8 @@ namespace mobject
      *        the system (and this behaviour is desirable).
      */
     SessManagerImpl::SessManagerImpl ()  throw()
-      : pImpl_ (new SessionImpl)
+      : pDefs_ (new DefsManager),
+        pImpl_ (new SessionImpl (*pDefs_))
     {
     }
 
@@ -77,12 +79,15 @@ namespace mobject
     void
     SessManagerImpl::reset ()
     {
-      scoped_ptr tmp (new SessionImpl);
+      scoped_ptr tmpD (new DefsManager);
+      scoped_ptr tmpS (new SessionImpl (*tmpD));
       
       TODO ("reset the assets registered with AssetManager");
       // Ichthyo-intern: ticket #95
       
-      pImpl_.swap (tmp);
+      TODO ("thread lock");
+      pDefs_.swap (tmpD);
+      pImpl_.swap (tmpS);
     }
 
 
diff --git a/tests/components/proc/asset/basicporttest.cpp b/tests/components/proc/asset/basicporttest.cpp
index 35329a169..7e68f4950 100644
--- a/tests/components/proc/asset/basicporttest.cpp
+++ b/tests/components/proc/asset/basicporttest.cpp
@@ -26,6 +26,7 @@
 
 #include "proc/asset/category.hpp"
 #include "proc/asset/port.hpp"
+#include "proc/asset/query.hpp"
 #include "proc/assetmanager.hpp"
 #include "proc/mobject/session.hpp"
 #include "proc/asset/assetdiagnostics.hpp"
@@ -37,6 +38,7 @@ using boost::format;
 using util::contains;
 using util::isnil;
 using std::string;
+using std::wstring;
 using std::cout;
 
 
@@ -44,7 +46,7 @@ namespace asset
   {
   namespace test
     {
-    
+    using mobject::Session;
     
     
     
@@ -74,20 +76,23 @@ namespace asset
         
         void createExplicit (string pID, string sID)
           { 
+            string pID_sane (pID);
+            query::normalizeID (pID_sane);
+            
             PPort thePort = asset::Struct::create (pID,sID);
             
             ASSERT (thePort);
             ASSERT (thePort->getProcPatt());
-            ASSERT (thePort->getPortID() == util::sanitize(pID));
-            ASSERT (thePort->getProcPatt()->getStreamID() == sID);
-            ASSERT (thePort->getShortDesc() == thePort->getPortID());
+            ASSERT (thePort->getPortID() == pID_sane);
+            ASSERT (thePort->getProcPatt()->queryStreamID() == sID);
+            ASSERT (thePort->shortDesc == wstring (pID_sane.begin(), pID_sane.end()));
             
-            ID assetID = thePort->getID();
-            ASSERT (assetID.org = "cin3");
-            ASSERT (contains (assetID.name, thePort->getPortID()));
-            ASSERT (contains (assetID.name, thePort->getProcPatt()->getStreamID()));
+            Asset::Ident idi = thePort->ident;
+            ASSERT (idi.org == "cin3");
+            ASSERT (contains (idi.name, thePort->getPortID()));
+            ASSERT (contains (idi.name, thePort->getProcPatt()->queryStreamID()));
 
-            Category cat (assetID.category);
+            Category cat (idi.category);
             Category refcat (STRUCT,"ports");
             ASSERT ( cat.hasKind(STRUCT) );
             ASSERT ( cat.isWithin(refcat) );
@@ -96,48 +101,55 @@ namespace asset
         
         void create_or_ref(string pID)
           { 
-            pID = util::sanitize (pID);
-            PPort port1 = asset::Struct::query ("port("+pID+")");
+            query::normalizeID (pID);
+            
+            PPort port1 = Port::query ("port("+pID+")");
             ASSERT (port1);
             ASSERT (port1->getPortID() == pID);
             
             string pID2 = "another-" + pID;
-            PPort port2 = asset::Struct::query ("port("+pID2+")");
+            PPort port2 = Port::query ("port("+pID2+")");
             ASSERT (port2);
             ASSERT (port2 != port1);
-            Category c1 = port1->getID().category;
-            Category c2 = port2->getID().category;
+            Category c1 = port1->ident.category;
+            Category c2 = port2->ident.category;
             ASSERT (c1 == c2);
             
-            PPort port3 = asset::Struct::query ("port("+pID2+")");
+            PPort port3 = Port::query ("port("+pID2+")");
             ASSERT (port3 == port2);
           }
         
         
         void create_using_default()
           { 
-            PPort port1 = asset::Struct::query ("");
+            PPort port1 = Port::query (""); // "the default port"
+            PPort port2;
             ASSERT (port1);
-            ASSERT (port1 == mobject::Session::current->getDefault());
-            ASSERT (port1->getID().category.hasKind(VIDEO));
+            ASSERT (port1 == Session::current->defaults (Query()));
+            ASSERT (port1->ident.category.hasKind(VIDEO));
             ASSERT (port1->getProcPatt());
-            PProcPatt popa = mobject::Session::current->getDefault("port()");
+            PProcPatt popa = Session::current->defaults (Query("port()"));
             ASSERT (popa == port1->getProcPatt());
             
-            PPort port2 = asset::Struct::query ("port()");
+            // several variants to query for "the default port"
+            port2 = Session::current->defaults(Query ());
+            ASSERT (port2 == port1);
+            port2 = asset::Struct::create (Query ());
+            ASSERT (port2 == port1);
+            port2 = asset::Struct::create (Query ("port()"));
             ASSERT (port2 == port1);
             
-            string sID = popa->getStreamID(); // sort of a "default stream type"
-            PPort port3 = asset::Struct::query ("stream("+sID+")");
+            string sID = popa->queryStreamID(); // sort of a "default stream type"
+            PPort port3 = Port::query ("stream("+sID+")");
             ASSERT (port3);
-            ASSERT (port3->getProcPatt()->getStreamID() == sID);
-            ASSERT (port3->getProcPatt() == mobject::Session::current->getDefault("stream("+sID+")");
+            ASSERT (port3->getProcPatt()->queryStreamID() == sID);
+            ASSERT (port3->getProcPatt() == Session::current->defaults (Query("stream("+sID+")")));
           }
         
         
         void dependProcPatt(string pID)
           {
-            PPort thePort = asset::Struct::query ("port("+pID+")");
+            PPort thePort = Port::query ("port("+pID+")");
             ASSERT (thePort);
             PProcPatt thePatt = thePort->getProcPatt();
             ASSERT (thePatt);
@@ -151,9 +163,9 @@ namespace asset
               // now querying for a port using this pattern (created on-the-fly)
              //  note: because the pattern is new, this new port will be used as
             //         default port for this pattern automatically
-            PPort port2x = asset::Struct::query ("pattern(another)");
+            PPort port2x = Port::query ("pattern(another)");
             ASSERT (pattern2 == port2x->getProcPatt());
-            ASSERT (port2x == mobject::Session::current->getDefault("pattern(another)"));
+            ASSERT (port2x == Session::current->defaults (Query("pattern(another)")));
             
             thePort->switchProcPatt(pattern2);
             ASSERT ( dependencyCheck (thePort, pattern2));
@@ -172,9 +184,9 @@ namespace asset
             ASSERT (thePort->getProcPatt());
             ASSERT (thePort->getProcPatt() == pattern2); // but is still valid, as long as the ref is alive....
             
-            PPort port3x = asset::Struct::query ("pattern(another)");
+            PPort port3x = Port::query ("pattern(another)");
             ASSERT (port3x->getProcPatt() != pattern2);  // because pattern2 is already unlinked...
-            ASSERT (port3x == mobject::Session::current->getDefault("pattern(another)"));
+            ASSERT (port3x == Session::current->defaults (Query("pattern(another)")));
             ASSERT (port3x != port2x);                 // ..we got a new default port for "pattern(another)" too!
             
             

From 7e345ffabc5e6860a40ac18411c9ea5d23c5edab Mon Sep 17 00:00:00 2001
From: Ichthyostega 
Date: Thu, 17 Jan 2008 15:42:19 +0100
Subject: [PATCH 5/8] draft: how to get default configured objects and query
 for capabilities. My plan is to embed a YAP Prolog system at some point in
 the furure for this purpose.

---
 wiki/renderengine.html | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/wiki/renderengine.html b/wiki/renderengine.html
index bf5e44e84..55c7c0c61 100644
--- a/wiki/renderengine.html
+++ b/wiki/renderengine.html
@@ -792,6 +792,26 @@ TertiaryMid: #99a
 TertiaryDark: #667
 Error: #f88
+
+
Many features can be implemented by specifically configuring and wiring some unspecific components. Rather than tie the client code in need of some given feature to these configuration internals, in Cinelerra-3 the client can //query // for some kind of object providing the //needed capabilities. // Right from start (summer 2007), Ichthyo had the intention to implement such a feature using sort of a ''declarative database'', e.g. by embedding a Prolog system. By adding rules to the basic session configuration, users should be able to customize the semi-automatic part of Cinelerra's behaviour to great extent.
+
+[[Configuration Queries|ConfigQuery]] are used at various places, when creating and adding new objects, as well when building or optimizing the render engine node network.
+* Creating a [[port|PortHandling]] queries for a default port or a port with a certain stream type
+* Adding a new [[track|TrackHandling]] queries for some default placement configuration, e.g. the port.
+* when processing a [[wiring request|WiringRequest]], connection possibilities have to be evaluated.
+* actually building such a connection may create additional degrees of freedom, like panning for sound or layering for video.
+
+!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 constant 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)}}}"
+
+!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.
+
+!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.
+
+
Here, in the context of the Render Engine, the Controller component is responsible for triggering and coordinating the build process and for activating the backend and the Render Engine configuration created by the Builder to carry out the actual rendering. There is another Controller in the backend, the ~PlaybackController, which is in charge of the playback/rendering/display state of the application, and consequently will call this (Proc-Layer) Controller to get the necessary Render Engine.
 
@@ -811,8 +831,9 @@ This is an very important external Interface, because it links together all thre
 
RenderEngine
 
-
-
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->getDefault<TYPE>("query string")}}}, where the //query string // defines a capability query similar to what is employed for ports, stream types, codecs etc.
+
+
For several components and properties there is an implicit default value or configuration; it is stored alongside with the session. The intention is that defaults never create an error, instead, they are to be extended silently on demand. Objects configured according to this defaults can be retrieved at the [[Session]] interface by a set of overloaded functions {{{Session::current->default(Query<TYPE> ("query string"))}}}, where the //query string // defines a capability query similar to what is employed for ports, stream types, codecs etc. The Queries are implemented by [[configuration rules|ConfigRules]]
+
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...
@@ -1082,7 +1103,7 @@ For this Cinelerra3 design, we could consider making GOP just another raw media
 &rarr;see in [[Wikipedia|http://en.wikipedia.org/wiki/Group_of_pictures]]
 
-
+
This wiki page is the entry point to detail notes covering some technical decisions, details and problems encountered in the course of the implementation of the Cinelerra Renderengine, the Builder and the related parts.
 
 * [[Packages, Interfaces and Namespaces|InterfaceNamespaces]]
@@ -1095,6 +1116,7 @@ For this Cinelerra3 design, we could consider making GOP just another raw media
 * [[collecting Ideas for Implementation Guidelines|ImplementationGuidelines]]
 * [[using the Visitor pattern?|VisitorUse]] &mdash; resulting in [[»Visiting-Tool« library implementation|VisitingToolImpl]]
 * [[Handling of Tracks and Ports in the EDL|TrackPortEDL]]. [[Handling of Tracks|TrackHandling]] and [[Ports|PortHandling]]
+* [[getting default configured|DefaultsManagement]] Objects relying on [[rule-based Configuration Queries|ConfigRules]]
 * [[identifying the basic Builder operations|BasicBuildingOperations]] and [[planning the Implementation|PlanningNodeCreaterTool]]
 * [[how to handle »attached placement«|AttachedPlacementProblem]]
 
From 430f38ab2fce053f4b196710eb3291bb5f772fad Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 18 Jan 2008 16:43:53 +0100 Subject: [PATCH 6/8] started a mock implementation for the capability queries. Later on, I want to embedd Prolog, but for now it is more important to get ahead with the builder... --- src/common/configrules.cpp | 44 ++++++++++ src/common/configrules.hpp | 81 +++++++++++++++++++ src/{proc/asset => common}/query.cpp | 6 +- src/{proc/asset => common}/query.hpp | 9 +-- src/common/query/mockconfigrules.cpp | 43 ++++++++++ src/common/query/mockconfigrules.hpp | 73 +++++++++++++++++ src/proc/asset.hpp | 24 ++++-- src/proc/asset/struct.cpp | 6 +- src/proc/asset/struct.hpp | 3 +- src/proc/assetmanager.cpp | 12 +-- src/proc/mobject/session/defsmanager.cpp | 2 +- src/proc/mobject/session/defsmanager.hpp | 4 +- .../proc/asset/assetdiagnostics.hpp | 2 +- tests/components/proc/asset/basicporttest.cpp | 8 +- wiki/renderengine.html | 9 ++- 15 files changed, 294 insertions(+), 32 deletions(-) create mode 100644 src/common/configrules.cpp create mode 100644 src/common/configrules.hpp rename src/{proc/asset => common}/query.cpp (95%) rename src/{proc/asset => common}/query.hpp (92%) create mode 100644 src/common/query/mockconfigrules.cpp create mode 100644 src/common/query/mockconfigrules.hpp diff --git a/src/common/configrules.cpp b/src/common/configrules.cpp new file mode 100644 index 000000000..3213df15a --- /dev/null +++ b/src/common/configrules.cpp @@ -0,0 +1,44 @@ +/* + ConfigRules - interface for rule based configuration + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "common/configrules.hpp" +//#include "common/util.hpp" +#include "nobugcfg.h" + + + +namespace cinelerra + { + + namespace query + { + + + } // namespace query + + + /** storage for the Singleton instance factory */ + Singleton ConfigRules::instance; + + +} // namespace cinelerra diff --git a/src/common/configrules.hpp b/src/common/configrules.hpp new file mode 100644 index 000000000..265cae29e --- /dev/null +++ b/src/common/configrules.hpp @@ -0,0 +1,81 @@ +/* + CONFIGRULES.hpp - interface for rule based configuration + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file 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 \i 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... + ** + ** @see cinelerra::Query + ** @see mobject::session::DefsManager + ** @see asset::StructFactory + ** + */ + + +#ifndef CINELERRA_CONFIGRULES_H +#define CINELERRA_CONFIGRULES_H + +#include "common/query.hpp" +#include "common/singleton.hpp" + +#include + + + +namespace cinelerra + { + using std::string; + + /** + * Generic query interface for retrieving objects matching + * some capability query + */ + class ConfigRules + { + protected: + ConfigRules (); + friend class cinelerra::singleton::StaticCreate; + + public: + static Singleton instance; + }; + + + namespace query + { + + + + } // namespace query + +} // namespace cinelerra +#endif diff --git a/src/proc/asset/query.cpp b/src/common/query.cpp similarity index 95% rename from src/proc/asset/query.cpp rename to src/common/query.cpp index e729195c6..bb3e6ae86 100644 --- a/src/proc/asset/query.cpp +++ b/src/common/query.cpp @@ -21,7 +21,7 @@ * *****************************************************/ -#include "proc/asset/query.hpp" +#include "common/query.hpp" #include "common/util.hpp" #include "nobugcfg.h" @@ -31,7 +31,7 @@ using boost::algorithm::is_upper; using boost::algorithm::is_alpha; -namespace asset +namespace cinelerra { namespace query @@ -55,4 +55,4 @@ namespace asset /** */ -} // namespace asset +} // namespace cinelerra diff --git a/src/proc/asset/query.hpp b/src/common/query.hpp similarity index 92% rename from src/proc/asset/query.hpp rename to src/common/query.hpp index 0d91bd3de..85172d965 100644 --- a/src/proc/asset/query.hpp +++ b/src/common/query.hpp @@ -21,16 +21,15 @@ */ -#ifndef ASSET_QUERY_H -#define ASSET_QUERY_H +#ifndef CINELERRA_QUERY_H +#define CINELERRA_QUERY_H -#include "common/util.hpp" #include -namespace asset +namespace cinelerra { using std::string; @@ -58,5 +57,5 @@ namespace asset } // namespace query -} // namespace asset +} // namespace cinelerra #endif diff --git a/src/common/query/mockconfigrules.cpp b/src/common/query/mockconfigrules.cpp new file mode 100644 index 000000000..7a938728e --- /dev/null +++ b/src/common/query/mockconfigrules.cpp @@ -0,0 +1,43 @@ +/* + MockConfigRules - mock implementation of the config rules system + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "common/query/mockconfigrules.hpp" +//#include "common/util.hpp" +#include "nobugcfg.h" + + + +namespace cinelerra + { + + namespace query + { + + + } // namespace query + + + /** */ + + +} // namespace cinelerra diff --git a/src/common/query/mockconfigrules.hpp b/src/common/query/mockconfigrules.hpp new file mode 100644 index 000000000..4d942dd29 --- /dev/null +++ b/src/common/query/mockconfigrules.hpp @@ -0,0 +1,73 @@ +/* + MOCKCONFIGRULES.hpp - mock implementation of the config rules system + + Copyright (C) CinelerraCV + 2007, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file 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 cinelerra::Query + ** @see cinelerra::ConfigRules + ** + */ + + +#ifndef CINELERRA_MOCKCONFIGRULES_H +#define CINELERRA_MOCKCONFIGRULES_H + +#include "common/configrules.hpp" + +#include + + + +namespace cinelerra + { + using std::string; + + /** + * Generic query interface for retrieving objects matching + * some capability query + */ + class MockConfigRules + { + protected: + MockConfigRules (); + friend class cinelerra::singleton::StaticCreate; + + public: + }; + + + namespace query + { + + + + } // namespace query + +} // namespace cinelerra +#endif diff --git a/src/proc/asset.hpp b/src/proc/asset.hpp index 0df25a3fd..d9e2e5833 100644 --- a/src/proc/asset.hpp +++ b/src/proc/asset.hpp @@ -77,6 +77,7 @@ namespace asset using std::size_t; using std::tr1::shared_ptr; + using std::tr1::static_pointer_cast; /** @@ -290,22 +291,31 @@ namespace asset /** ordering of Asset smart ptrs based on Ident tuple. * @todo currently supporting only smart_ptr. */ - inline bool operator== (const PAsset& a1, const PAsset& a2) { return a1 && a2 && ( 0==a1->ident.compare(a2->ident));} - inline bool operator< (const PAsset& a1, const PAsset& a2) { return a1 && a2 && (-1==a1->ident.compare(a2->ident));} - inline bool operator> (const PAsset& a1, const PAsset& a2) { return a2 < a1; } - inline bool operator>= (const PAsset& a1, const PAsset& a2) { return !(a1 < a2); } - inline bool operator<= (const PAsset& a1, const PAsset& a2) { return !(a1 > a2); } - inline bool operator!= (const PAsset& a1, const PAsset& a2) { return !(a1== a2); } + inline bool operator== (const PcAsset& a1, const PcAsset& a2) { return a1 && a2 && ( 0==a1->ident.compare(a2->ident));} + inline bool operator< (const PcAsset& a1, const PcAsset& a2) { return a1 && a2 && (-1==a1->ident.compare(a2->ident));} + inline bool operator> (const PcAsset& a1, const PcAsset& a2) { return a2 < a1; } + inline bool operator>= (const PcAsset& a1, const PcAsset& a2) { return !(a1 < a2); } + inline bool operator<= (const PcAsset& a1, const PcAsset& a2) { return !(a1 > a2); } + inline bool operator!= (const PcAsset& a1, const PcAsset& a2) { return !(a1== a2); } /** ordering of Asset Ident tuples. * @note version is irrelevant */ - inline int Asset::Ident::compare (const Asset::Ident& oi) const + inline int + Asset::Ident::compare (const Asset::Ident& oi) const { int res; if (0 != (res=category.compare (oi.category))) return res; if (0 != (res=org.compare (oi.org))) return res; return name.compare (oi.name); } + + /** promote to PAsset, e.g. for comparing */ + template + inline PcAsset + pAsset (shared_ptr& subPtr) + { + return static_pointer_cast (subPtr); + } /** convienient for debugging */ diff --git a/src/proc/asset/struct.cpp b/src/proc/asset/struct.cpp index e0436de9e..3f9a911f5 100644 --- a/src/proc/asset/struct.cpp +++ b/src/proc/asset/struct.cpp @@ -27,10 +27,12 @@ #include "proc/asset/track.hpp" #include "proc/mobject/session.hpp" +#include "common/query.hpp" #include "common/util.hpp" #include "nobugcfg.h" using mobject::Session; +using cinelerra::query::normalizeID; namespace asset { @@ -84,8 +86,8 @@ namespace asset shared_ptr StructFactory::operator() (string portID, string streamID) { - query::normalizeID (portID); - query::normalizeID (streamID); + normalizeID (portID); + normalizeID (streamID); PProcPatt processingPattern = Session::current->defaults (Query("stream("+streamID+")")); Port* pP = new Port (processingPattern, portID); return AssetManager::instance().wrap (*pP); diff --git a/src/proc/asset/struct.hpp b/src/proc/asset/struct.hpp index 723c332a3..18554f770 100644 --- a/src/proc/asset/struct.hpp +++ b/src/proc/asset/struct.hpp @@ -38,7 +38,7 @@ #define ASSET_STRUCT_H #include "proc/asset.hpp" -#include "proc/asset/query.hpp" +#include "common/query.hpp" #include "common/factory.hpp" #include @@ -49,6 +49,7 @@ using std::wstring; namespace asset { + using cinelerra::Query; class Struct; class StructFactory; diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index 246411d60..4d988aa61 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -237,6 +237,7 @@ namespace asset #include "proc/asset/track.hpp" #include "proc/asset/port.hpp" #include "proc/asset/meta.hpp" +#include "proc/asset/procpatt.hpp" namespace asset @@ -251,11 +252,12 @@ namespace asset template shared_ptr AssetManager::getAsset (const ID& id) throw(cinelerra::error::Invalid); template shared_ptr AssetManager::getAsset (const ID& id) throw(cinelerra::error::Invalid); - template shared_ptr AssetManager::wrap (const Asset& asset); - template shared_ptr AssetManager::wrap (const Media& asset); - template shared_ptr AssetManager::wrap (const Clip& asset); - template shared_ptr AssetManager::wrap (const Track& asset); - template shared_ptr AssetManager::wrap (const Port& asset); + template shared_ptr AssetManager::wrap (const Asset& asset); + template shared_ptr AssetManager::wrap (const Media& asset); + template shared_ptr AssetManager::wrap (const Clip& asset); + template shared_ptr AssetManager::wrap (const Track& asset); + template shared_ptr AssetManager::wrap (const Port& asset); + template shared_ptr AssetManager::wrap (const ProcPatt& asset); } // namespace asset diff --git a/src/proc/mobject/session/defsmanager.cpp b/src/proc/mobject/session/defsmanager.cpp index 53c5f1862..305db5cab 100644 --- a/src/proc/mobject/session/defsmanager.cpp +++ b/src/proc/mobject/session/defsmanager.cpp @@ -43,7 +43,7 @@ namespace mobject * @param */ template<> - shared_ptr + shared_ptr DefsManager::operator() (const Query& properties) { diff --git a/src/proc/mobject/session/defsmanager.hpp b/src/proc/mobject/session/defsmanager.hpp index bc7323322..ccc75d6ac 100644 --- a/src/proc/mobject/session/defsmanager.hpp +++ b/src/proc/mobject/session/defsmanager.hpp @@ -25,7 +25,7 @@ #define MOBJECT_SESSION_DEFSMANAGER_H -#include "proc/asset/query.hpp" +#include "common/query.hpp" //#include //#include @@ -61,7 +61,7 @@ namespace mobject public: template - shared_ptr operator() (const asset::Query&); + shared_ptr operator() (const cinelerra::Query&); }; diff --git a/tests/components/proc/asset/assetdiagnostics.hpp b/tests/components/proc/asset/assetdiagnostics.hpp index c8df758f8..4788b687f 100644 --- a/tests/components/proc/asset/assetdiagnostics.hpp +++ b/tests/components/proc/asset/assetdiagnostics.hpp @@ -75,7 +75,7 @@ namespace asset inline bool dependencyCheck (C child, P parent) { - return (child == parent) + return (pAsset(child) == pAsset(parent)) || (0 < child->getParents().size() && (parent == child->getParents()[0]) && (contains (parent->getDependant(), child))); diff --git a/tests/components/proc/asset/basicporttest.cpp b/tests/components/proc/asset/basicporttest.cpp index 7e68f4950..e68a20738 100644 --- a/tests/components/proc/asset/basicporttest.cpp +++ b/tests/components/proc/asset/basicporttest.cpp @@ -26,7 +26,7 @@ #include "proc/asset/category.hpp" #include "proc/asset/port.hpp" -#include "proc/asset/query.hpp" +#include "common/query.hpp" #include "proc/assetmanager.hpp" #include "proc/mobject/session.hpp" #include "proc/asset/assetdiagnostics.hpp" @@ -47,6 +47,8 @@ namespace asset namespace test { using mobject::Session; + using cinelerra::Query; + using cinelerra::query::normalizeID; @@ -77,7 +79,7 @@ namespace asset void createExplicit (string pID, string sID) { string pID_sane (pID); - query::normalizeID (pID_sane); + normalizeID (pID_sane); PPort thePort = asset::Struct::create (pID,sID); @@ -101,7 +103,7 @@ namespace asset void create_or_ref(string pID) { - query::normalizeID (pID); + normalizeID (pID); PPort port1 = Port::query ("port("+pID+")"); ASSERT (port1); diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 55c7c0c61..468a41b16 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -792,7 +792,12 @@ TertiaryMid: #99a TertiaryDark: #667 Error: #f88
-
+
+
Configuration Queries are requests to the system to "create or retrieve an object with //this and that // capabilities". They are resolved by a rule based system ({{red{planned feature}}}) and the user can extend the used rules for each Session. Syntactically, they are stated in ''prolog'' syntax as a conjunction (=logical and) of ''predicates'', for example {{{stream(mpeg), port(myPort)}}}. Queries are typed to the kind of expected result object: {{{Query<Port> ("stream(mpeg)")}}} requests a port excepting/delivering mpeg stream data &mdash; and it depends on the current configuration what "mpeg" means. If there is any stream data producing component in the system, which advertises to deliver {{{stream(mpeg)}}}, and a port can be configured or connected with this component, then the [[defaults manager|DefaultsManagement]] will create/deliver a [[Port|PortHandling]] object configured accordingly.
+&rarr; [[Configuration Rules system|ConfigRules]]
+
+
+
Many features can be implemented by specifically configuring and wiring some unspecific components. Rather than tie the client code in need of some given feature to these configuration internals, in Cinelerra-3 the client can //query // for some kind of object providing the //needed capabilities. // Right from start (summer 2007), Ichthyo had the intention to implement such a feature using sort of a ''declarative database'', e.g. by embedding a Prolog system. By adding rules to the basic session configuration, users should be able to customize the semi-automatic part of Cinelerra's behaviour to great extent.
 
 [[Configuration Queries|ConfigQuery]] are used at various places, when creating and adding new objects, as well when building or optimizing the render engine node network.
@@ -802,7 +807,7 @@ Error: #f88
* actually building such a connection may create additional degrees of freedom, like panning for sound or layering for video. !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 constant 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. +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)}}}" !executing a Configuration Query From b0be36c8fb54b62afb40ead30052b411bd69feb2 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 19 Jan 2008 14:24:24 +0100 Subject: [PATCH 7/8] early draft how the Prolog interface /could/ be... (need to draft it in order to provide a mock implementation) --- src/common/configrules.cpp | 3 +- src/common/configrules.hpp | 54 ++++++++++++++++++++++++++-- src/common/query/mockconfigrules.hpp | 28 +++++++-------- 3 files changed, 67 insertions(+), 18 deletions(-) diff --git a/src/common/configrules.cpp b/src/common/configrules.cpp index 3213df15a..794f402d9 100644 --- a/src/common/configrules.cpp +++ b/src/common/configrules.cpp @@ -22,6 +22,7 @@ #include "common/configrules.hpp" +#include "common/query/mockconfigrules.hpp" //#include "common/util.hpp" #include "nobugcfg.h" @@ -38,7 +39,7 @@ namespace cinelerra /** storage for the Singleton instance factory */ - Singleton ConfigRules::instance; + Singleton ConfigRules::instance; } // namespace cinelerra diff --git a/src/common/configrules.hpp b/src/common/configrules.hpp index 265cae29e..fe716a423 100644 --- a/src/common/configrules.hpp +++ b/src/common/configrules.hpp @@ -54,6 +54,8 @@ namespace cinelerra { using std::string; + namespace query { class MockConfigRules; } + /** * Generic query interface for retrieving objects matching @@ -62,16 +64,62 @@ namespace cinelerra class ConfigRules { protected: - ConfigRules (); - friend class cinelerra::singleton::StaticCreate; + ConfigRules () {} + virtual ~ConfigRules() {} public: - static Singleton instance; + static Singleton instance; + + // TODO: find out what operations we need to support here for the »real solution« (using Prolog) }; namespace query { + // The intention is to support the following style of Prolog code + // + // retrieve(T) :- type(T, track), find(T), capabilities(T). + // retrieve(T) :- type(T, track), make(T), capabilities(T). + // + // capabilities(T) :- stream(T,mpeg). + // stream(T, mpeg) :- type(T, track), type(P, port), retrieve(P), 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. + + class Resolver + { + + }; + + typedef const char * const Symbol; + + template + < const Symbol SYM, // Predicate symbol + typename SIG = bool(string) // Signature + > + class Pred + { + + }; + + template + class TypeHandler + { + static const TY NIL; + + template + TY find (Pred capability); + + template + TY make (Pred capability, TY& refObj =NIL); + }; + + template + class QueryHandler + { + TY resolve (Query q); + }; diff --git a/src/common/query/mockconfigrules.hpp b/src/common/query/mockconfigrules.hpp index 4d942dd29..3bcf98969 100644 --- a/src/common/query/mockconfigrules.hpp +++ b/src/common/query/mockconfigrules.hpp @@ -48,23 +48,23 @@ namespace cinelerra { using std::string; - /** - * Generic query interface for retrieving objects matching - * some capability query - */ - class MockConfigRules - { - protected: - MockConfigRules (); - friend class cinelerra::singleton::StaticCreate; - - public: - }; - - + namespace query { + /** + * Generic query interface for retrieving objects matching + * some capability query + */ + class MockConfigRules : public ConfigRules + { + protected: + MockConfigRules (); + friend class cinelerra::singleton::StaticCreate; + + public: + }; + } // namespace query From 398bed8d7201f8ed369b76e7777552e6f591b362 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 21 Jan 2008 02:57:09 +0100 Subject: [PATCH 8/8] WIP some more details on the (planned) Prolog interface -- basically I know enough to provide a mock implementation now. Compiles OK but fails to link because of missing StructFactory implementation --- src/common/configrules.cpp | 3 +- src/common/configrules.hpp | 122 ++++++++++++++++++++++----- src/common/query/mockconfigrules.hpp | 12 ++- wiki/renderengine.html | 25 +++++- 4 files changed, 134 insertions(+), 28 deletions(-) diff --git a/src/common/configrules.cpp b/src/common/configrules.cpp index 794f402d9..09b46d51e 100644 --- a/src/common/configrules.cpp +++ b/src/common/configrules.cpp @@ -34,12 +34,11 @@ namespace cinelerra namespace query { + } // namespace query - /** storage for the Singleton instance factory */ - Singleton ConfigRules::instance; } // namespace cinelerra diff --git a/src/common/configrules.hpp b/src/common/configrules.hpp index fe716a423..2c2c52d7c 100644 --- a/src/common/configrules.hpp +++ b/src/common/configrules.hpp @@ -46,6 +46,11 @@ #include "common/query.hpp" #include "common/singleton.hpp" +#include "common/typelist.hpp" + +#include "proc/mobject/session/track.hpp" +#include "proc/asset/port.hpp" + #include @@ -57,35 +62,23 @@ namespace cinelerra namespace query { class MockConfigRules; } - /** - * Generic query interface for retrieving objects matching - * some capability query - */ - class ConfigRules - { - protected: - ConfigRules () {} - virtual ~ConfigRules() {} - - public: - static Singleton instance; - - // TODO: find out what operations we need to support here for the »real solution« (using Prolog) - }; - namespace query { // The intention is to support the following style of Prolog code // - // retrieve(T) :- type(T, track), find(T), capabilities(T). - // retrieve(T) :- type(T, track), make(T), capabilities(T). + // retrieve(O, Cap) :- find(T), capabilities(Cap). + // retrieve(O, Cap) :- make(T), capabilities(Cap). + // capabilities(Q) :- call(Q). // - // capabilities(T) :- stream(T,mpeg). - // stream(T, mpeg) :- type(T, track), type(P, port), retrieve(P), place_to(P, T). + // stream(T, mpeg) :- type(T, track), type(P, port), retrieve(P, stream(P,mpeg)), place_to(P, T). // // The type guard is inserted auomatically, while the predicate implementations for // find/1, make/1, stream/2, and place_to/2 are to be provided by the target types. + // + // As a example, the goal ":-retrieve(T, stream(T,mpeg))." would search a Track object, try to + // retrieve a port object with stream-type=mpeg and associate the track with this Port. The + // predicate "stream(P,mpeg)" needs to be implemented (natively) for the port object. class Resolver { @@ -118,12 +111,97 @@ namespace cinelerra template class QueryHandler { - TY resolve (Query q); + protected: + virtual ~QueryHandler(); + public: + virtual TY resolve (Query q); }; + + // 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. + + + + + using cinelerra::typelist::Node; + using cinelerra::typelist::NullType; + + /** + * 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 ConfigRulesInterface; + + template<> + class ConfigRulesInterface + { + protected: + virtual ~ConfigRulesInterface(); + }; + + template + class ConfigRulesInterface > + : public QueryHandler, + public ConfigRulesInterface + { }; + + template + < typename TYPES, + class IMPL + > + class ConfigRules + : public ConfigRulesInterface + { + protected: + ConfigRules () {} + virtual ~ConfigRules() {} + + public: + static cinelerra::Singleton instance; + + // TODO: find out what operations we need to support here for the »real solution« (using Prolog) + }; + + /** storage for the Singleton instance factory */ + template + cinelerra::Singleton ConfigRules::instance; + } // namespace query - + + + + + + /* ============= global configuration ==================== */ + + /** + * the list of all concrete types participating in the + * rule based config query system + */ + typedef cinelerra::typelist::Types < mobject::session::Track + , asset::Port + > + InterfaceTypes; + + typedef query::ConfigRules< InterfaceTypes, // List of Types to generate interface functions + query::MockConfigRules // actual Implementation to use + > + ConfigRules; // user-visible Interface to the ConfigRules subsystem. + + } // namespace cinelerra #endif diff --git a/src/common/query/mockconfigrules.hpp b/src/common/query/mockconfigrules.hpp index 3bcf98969..856d283c3 100644 --- a/src/common/query/mockconfigrules.hpp +++ b/src/common/query/mockconfigrules.hpp @@ -51,18 +51,24 @@ namespace cinelerra namespace query { + using mobject::session::Track; + using asset::Port; /** - * Generic query interface for retrieving objects matching - * some capability query + * 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 ConfigRules + class MockConfigRules : public cinelerra::ConfigRules { protected: MockConfigRules (); friend class cinelerra::singleton::StaticCreate; public: + + virtual Track resolve (Query q); + virtual Port resolve (Query q); }; diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 468a41b16..8d57363ad 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -797,7 +797,7 @@ Error: #f88 &rarr; [[Configuration Rules system|ConfigRules]]
-
+
Many features can be implemented by specifically configuring and wiring some unspecific components. Rather than tie the client code in need of some given feature to these configuration internals, in Cinelerra-3 the client can //query // for some kind of object providing the //needed capabilities. // Right from start (summer 2007), Ichthyo had the intention to implement such a feature using sort of a ''declarative database'', e.g. by embedding a Prolog system. By adding rules to the basic session configuration, users should be able to customize the semi-automatic part of Cinelerra's behaviour to great extent.
 
 [[Configuration Queries|ConfigQuery]] are used at various places, when creating and adding new objects, as well when building or optimizing the render engine node network.
@@ -815,6 +815,7 @@ 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]]
 
@@ -2449,6 +2450,28 @@ Like all [[structural assets|StructAsset]], ~ProcPatt employs a special naming s
a given Render Engine configuration is a list of Processors. Each Processor in turn contains a Graph of ProcNode.s to do the acutal data processing. In order to cary out any calculations, the Processor needs to be called with a StateProxy containing the state information for this RenderProcess
 
+
+
//obviously, getting this one to work requires quite a lot of technical details to be planned and implemented.// This said...
+The intention is to get much more readable ("declarative") and changeable configuration as by programming it directly within the implementation of some object.
+
+!Draft
+As an example, specifying how a Track can be configured for connecting automatically to some "mpeg" bus (=port)
+{{{
+retrieve(O, Cap) :- find(T), capabilities(Cap).
+retrieve(O, Cap) :- make(T), capabilities(Cap).
+capabilities(Q) :- call(Q).
+
+stream(T, mpeg) :- type(T, track), type(P, port), retrieve(P, stream(P,mpeg)), place_to(P, T).
+}}}
+
+Then, running the goal {{{:-retrieve(T, stream(T,mpeg)).}}} would search a Track object, try to retrieve a port object with stream-type=mpeg and associate the track with this Port. This relies on a predicate "stream(P,mpeg)" implemented (natively) for the port object. So, "Cap" is the query issued from calling code &mdash; here {{{stream(T,mpeg)}}}, the type guard {{{type(T, track)}}} will probably be handled or inserted inserted automatically, while the predicate implementations for find/1, make/1, stream/2, and place_to/2 are to be provided by the target types.
+* __The supporting system__ had to combine several code snippets into one rule system to be used for running queries, with some global base rules, rules injected by each individual participating object kind and finally user provided rules added by the current session. The actual query is bound to "Cap" (and consequently run as a goal by {{{call(Q)}}}). The implementation needs to provide a symbol table associating variable terms (like "T" or "P") to C/C++ object types, enabling the participating object kinds to register their specific predicate implementations. This is crucial, because there can be no general scheme of object-provided predicates (for each object kind different predicates make sense, e.g. [[ports|PortHandling]] have other possibilities than [[wiring requests|WiringRequest]]). Basically, a query issues a Prolog goal, which in turn evaluates domain specific predicates provided by the participating objects and thus calls back into C/C++ code. The supporting system maintains the internal connection (via the "type" predicate) such that from Prolog viewpoint it looks as if we were binding Variables directly to object instances. (there are some nasty technical details because of the backtracking nature of Prolog evaluations which need to be hidden away)
+* Any __participating object kind__ needs a way to declare domain specific predicates, thus triggering the registration of the necessary hooks within the supporting system. Moreover, it should be able to inject further prolog code (as shown in the example above with the {{{strem(T, mpeg)}}} predicate. For each of these new domain specific predicates, there needs to be a functor which can be invoked when the C implementation of the predicate is called from Prolog (in some cases even later, when the final solution is "executed", e.g. a new instance has been created and now some properties need to be set).
+
+!!a note on Plugins
+In the design of the Cinelerra-3 Proc Layer done thus far, we provide //no possibility to introduce a new object kind// into the system via plugin interface. The system uses a fixed collection of classes intended to cover all needs (Clip, Effect, Track, Port, Label, Automation, ~Macro-Clips). Thus, plugins will only be able to provide new parametrisations of existing classes. This should not be any real limitation, because the whole system is designed to achieve most of its functionality by freely combining rather basic object kinds. As a plus, it plays nicely with any plain-C based plugin interface. For example, we will have C++ adapter classes for the most common sorts of effect plugin (pull system and synchronous frame-by-frame push with buffering) with a thin C adaptation layer for the specific external plugin systems used.
+
+
/***
 |''Name:''|RSSReaderPlugin|