WIP: test driven brainstorming regarding sequence/timeline handling
This commit is contained in:
parent
c2cbe4c9e8
commit
4594ddde3a
8 changed files with 103 additions and 75 deletions
|
|
@ -101,6 +101,8 @@ namespace lumiera {
|
|||
|
||||
answer_->insert (entry_Struct<Pipe> ("pipe(master), stream(video)"));
|
||||
item<Pipe> (answer_, "") = item<Pipe>(answer_,"pipe(master), stream(video)");// use as default
|
||||
|
||||
answer_->insert (entry_Struct<Pipe> ("pipe(ambiance)"));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -108,7 +110,7 @@ namespace lumiera {
|
|||
|
||||
/* under some circumstances we need to emulate the behaviour *
|
||||
* of a real resolution engine in a more detailed manner. *
|
||||
* These case are hard wired in code below */
|
||||
* The code below implements these cases hard wired. */
|
||||
|
||||
/** special case: create a new pipe with matching pipe and stream IDs on the fly when referred... */
|
||||
bool
|
||||
|
|
@ -130,14 +132,14 @@ namespace lumiera {
|
|||
answer_->insert (entry<Pipe> (q, newPipe));
|
||||
return true;
|
||||
}
|
||||
/** special case: create/retrieve new rocessing pattern for given stream ID... */
|
||||
/** special case: create/retrieve new processing pattern for given stream ID... */
|
||||
bool
|
||||
MockTable::fabricate_ProcPatt_on_demand (Query<const ProcPatt>& q, string const& streamID)
|
||||
MockTable::fabricate_ProcPatt_on_demand (Query<const ProcPatt>& q)
|
||||
{
|
||||
typedef const ProcPatt cPP;
|
||||
typedef WrapReturn<cPP>::Wrapper Ptr;
|
||||
|
||||
Ptr newPP (Struct::create (Query<cPP> ("make(PP), "+q)));
|
||||
Ptr newPP (Struct::create (Query<cPP> ("make(PP), "+q))); // magic token: bail out and invoke factory for new object
|
||||
answer_->insert (entry<cPP> (q, newPP));
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,12 +49,9 @@
|
|||
|
||||
|
||||
|
||||
namespace lumiera
|
||||
{
|
||||
|
||||
|
||||
namespace query
|
||||
{
|
||||
namespace lumiera {
|
||||
namespace query {
|
||||
|
||||
using asset::Pipe;
|
||||
using asset::ProcPatt;
|
||||
using asset::PProcPatt;
|
||||
|
|
@ -69,8 +66,7 @@ namespace lumiera
|
|||
|
||||
|
||||
|
||||
namespace // internal details
|
||||
{
|
||||
namespace { // internal details
|
||||
|
||||
/** a traits-class to define the smart-ptr to wrap the result */
|
||||
template<class TY>
|
||||
|
|
@ -81,16 +77,18 @@ namespace lumiera
|
|||
|
||||
|
||||
/** helper detecting if a query actually intended to retrieve a "default" object.
|
||||
* This implementation is quite crude, of cours it would be necessary to actually
|
||||
* This implementation is quite crude, of course it would be necessary actually to
|
||||
* parse and evaluate the query. @note query is modified if "default" ... */
|
||||
inline bool
|
||||
is_defaults_query (string& query)
|
||||
{
|
||||
return !isnil (removeTerm ("default", query));
|
||||
}
|
||||
|
||||
} // details (end)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* the actual table holding preconfigured answers
|
||||
* packaged as boost::any objects.
|
||||
|
|
@ -112,7 +110,7 @@ namespace lumiera
|
|||
bool detect_case (typename WrapReturn<TY>::Wrapper&, Query<TY>& q);
|
||||
bool fabricate_matching_new_Pipe (Query<Pipe>& q, string const& pipeID, string const& streamID);
|
||||
bool fabricate_just_new_Pipe (Query<Pipe>& q);
|
||||
bool fabricate_ProcPatt_on_demand (Query<const ProcPatt>& q, string const& streamID);
|
||||
bool fabricate_ProcPatt_on_demand (Query<const ProcPatt>& q);
|
||||
|
||||
template<class TY>
|
||||
bool set_new_mock_solution (Query<TY>& q, typename WrapReturn<TY>::Wrapper& candidate);
|
||||
|
|
@ -184,7 +182,7 @@ namespace lumiera
|
|||
if (!isnil (extractID("make", q)))
|
||||
return false; // let the query fail here,
|
||||
// so the invoking factory will go ahead
|
||||
// and create a new object.
|
||||
// and create a new object. (prevents infinite recursion)
|
||||
|
||||
const string pipeID = extractID("pipe", q);
|
||||
const string streamID = extractID("stream", q);
|
||||
|
|
@ -210,7 +208,7 @@ namespace lumiera
|
|||
|
||||
const string streamID = extractID("stream", q);
|
||||
if (!candidate && !isnil(streamID))
|
||||
return fabricate_ProcPatt_on_demand (q, streamID);
|
||||
return fabricate_ProcPatt_on_demand (q);
|
||||
|
||||
q.clear();
|
||||
return false;
|
||||
|
|
@ -240,13 +238,11 @@ namespace lumiera
|
|||
|
||||
public:
|
||||
|
||||
// TODO: implementation of any additional functions on the ConfigRules inteface goes here
|
||||
// TODO: implementation of any additional functions on the ConfigRules interface goes here
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace query
|
||||
|
||||
} // namespace lumiera
|
||||
}} // namespace lumiera::query
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@
|
|||
|
||||
|
||||
|
||||
namespace asset
|
||||
{
|
||||
namespace asset {
|
||||
|
||||
using lumiera::P;
|
||||
|
||||
class Pipe;
|
||||
|
|
@ -44,9 +44,9 @@ namespace asset
|
|||
ID (size_t id);
|
||||
ID (const Pipe&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* structural asset corresponding to some
|
||||
* processing pipe for generating media output
|
||||
|
|
@ -64,13 +64,13 @@ namespace asset
|
|||
{
|
||||
return static_cast<const ID<Pipe>& > (Asset::getID());
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
Pipe (const Asset::Ident&, PProcPatt& wiring, const string& pipeID, wstring shortName =wstring(), wstring longName =wstring()) ;
|
||||
friend class StructFactory;
|
||||
friend class StructFactoryImpl;
|
||||
|
||||
|
||||
public:
|
||||
const string& getPipeID() const { return pipeID_; }
|
||||
const PProcPatt& getProcPatt() const { return wiringTemplate; }
|
||||
|
|
@ -87,10 +87,10 @@ namespace asset
|
|||
//
|
||||
inline ID<Pipe>::ID(size_t id) : ID<Struct> (id) {};
|
||||
inline ID<Pipe>::ID(const Pipe& pipe) : ID<Struct> (pipe.getID()) {};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace asset
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ namespace asset {
|
|||
|
||||
/** create an empty default configured Sequence */
|
||||
Sequence::Sequence (const Asset::Ident& idi)
|
||||
: Struct (idi)
|
||||
// : track (makeDefaultTrack ())
|
||||
// , clips (0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ namespace asset {
|
|||
|
||||
/** TODO??? */
|
||||
Timeline::Timeline (const Asset::Ident& idi)
|
||||
: Struct (idi)
|
||||
// : track (makeDefaultTrack ())
|
||||
// , clips (0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@
|
|||
#include "lib/test/run.hpp"
|
||||
#include "proc/mobject/session.hpp"
|
||||
#include "proc/mobject/session/fixture.hpp" // TODO only temporarily needed
|
||||
#include "proc/assetmanager.hpp"
|
||||
#include "proc/assetmanager.hpp" //////??
|
||||
#include "proc/asset/timeline.hpp"
|
||||
#include "proc/asset/sequence.hpp"
|
||||
#include "lib/lumitime.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
|
|
@ -42,6 +44,9 @@ namespace test {
|
|||
using proc_interface::AssetManager;
|
||||
using proc_interface::PAsset;
|
||||
|
||||
using asset::PTimeline;
|
||||
using asset::PSequence;
|
||||
|
||||
using lumiera::Time;
|
||||
|
||||
|
||||
|
|
@ -88,23 +93,23 @@ namespace test {
|
|||
UNIMPLEMENTED ("how to refer to tracks...");
|
||||
|
||||
ASSERT (0 < sess->timelines.size());
|
||||
Timeline& til = sess->timelines[0];
|
||||
PTimeline til = sess->timelines[0];
|
||||
|
||||
ASSERT (0 < sess->sequences.size());
|
||||
Sequence& seq = sess->sequences[0];
|
||||
PSequence seq = sess->sequences[0];
|
||||
|
||||
ASSERT (isSameObject (seq, til.getSequence()));
|
||||
ASSERT (isSameObject (seq, til->getSequence()));
|
||||
|
||||
//verify default timeline
|
||||
Axis& axis = til.getAxis();
|
||||
Axis& axis = til->getAxis();
|
||||
ASSERT (Time(0) == axis.origin());
|
||||
ASSERT (Time(0) == til.length()); ////////////////////////TICKET #177
|
||||
ASSERT (Time(0) == til->length()); ////////////////////////TICKET #177
|
||||
|
||||
//verify global pipes
|
||||
//TODO
|
||||
|
||||
//verify default sequence
|
||||
Track rootTrack = seq.rootTrack();
|
||||
Track rootTrack = seq->rootTrack();
|
||||
ASSERT (rootTrack->isValid());
|
||||
ASSERT (Time(0) == rootTrack->length());
|
||||
ASSERT (0 == rootTrack->subTracks.size());
|
||||
|
|
|
|||
|
|
@ -24,8 +24,12 @@
|
|||
#include "lib/test/run.hpp"
|
||||
#include "proc/mobject/session.hpp"
|
||||
//#include "proc/mobject/session/fixture.hpp" // TODO only temporarily needed
|
||||
#include "proc/assetmanager.hpp"
|
||||
#include "proc/assetmanager.hpp" ///??
|
||||
#include "proc/asset/timeline.hpp"
|
||||
#include "proc/asset/sequence.hpp"
|
||||
#include "proc/asset/pipe.hpp"
|
||||
#include "lib/lumitime.hpp"
|
||||
#include "lib/query.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
|
@ -42,13 +46,25 @@ namespace test {
|
|||
using proc_interface::AssetManager;
|
||||
using proc_interface::PAsset;
|
||||
|
||||
using asset::PTimeline;
|
||||
using asset::PSequence;
|
||||
using asset::Pipe;
|
||||
|
||||
using lumiera::Query;
|
||||
using lumiera::Time;
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
* @test verify retrieval and instance management of the top level facade objects
|
||||
* as integrated with the session and high-level model.
|
||||
*
|
||||
* as integrated with the session and high-level model. Both sequences and
|
||||
* timelines are at the same time structural assets and act as facades
|
||||
* on the session API. Thus we can query specific instances from the
|
||||
* struct factory or alternatively access them through the session.
|
||||
* Moreover we can create new top level elements in the session
|
||||
* just by querying the respective asset.
|
||||
*
|
||||
* @todo specify how deletion is handled
|
||||
*
|
||||
* @see session-structure-test.cpp
|
||||
* @see Timeline
|
||||
* @see Sequence
|
||||
|
|
@ -63,52 +79,57 @@ namespace test {
|
|||
ASSERT (Session::current.isUp());
|
||||
|
||||
verify_retrieval();
|
||||
verify_creation();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
verify_retrieval()
|
||||
{
|
||||
PSess sess = Session::current;
|
||||
ASSERT (sess->isValid());
|
||||
ASSERT (0 < sess->timelines.size());
|
||||
|
||||
PTimeline defaultTimeline = sess->defaults (Query<Timeline> ()); //////////////////////TICKET #549
|
||||
Query<Timeline> query1 = "id("+defaultTimeline->getNameID()+").";
|
||||
|
||||
PTimeline queriedTimeline = asset::Struct::create (query1);
|
||||
ASSERT (queriedTimeline);
|
||||
ASSERT (queriedTimeline == defaultTimeline); // retrieved the existing timeline asset again
|
||||
ASSERT (queriedTimeline == sess->timelines[0]);
|
||||
|
||||
Query<Sequence> query2 = "id("+defaultTimeline->getSequence()->getNameID()+").";
|
||||
PSequence queriedSequence = asset::Struct::create (query2);
|
||||
ASSERT (queriedSequence);
|
||||
ASSERT (queriedSequence == sess->sequences[0]);
|
||||
ASSERT (queriedSequence == sess->timelines[0]->getSequence());
|
||||
ASSERT (queriedSequence == defaultTimeline->getSequence());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
verify_creation()
|
||||
{
|
||||
PSess sess = Session::current;
|
||||
ASSERT (sess->isValid());
|
||||
|
||||
uint num_timelines = sess->timelines.size();
|
||||
ASSERT (0 < num_timelines);
|
||||
|
||||
ASSERT (0 < sess->timelines.size());
|
||||
Timeline& til = sess->timelines[0];
|
||||
Query<Timeline> special = "id(aSillyName), sequence("
|
||||
+ sess->sequences[0]->getNameID()
|
||||
+ "), pipe(ambiance).";
|
||||
|
||||
ASSERT (0 < sess->sequences.size());
|
||||
Sequence& seq = sess->sequences[0];
|
||||
PTimeline specialTimeline (asset::Struct::create (special));
|
||||
ASSERT (specialTimeline);
|
||||
ASSERT (num_timelines + 1 == sess->timelines.size());
|
||||
ASSERT (specialTimeline == session->timelines[num_timelines]); // new one got appended at the end
|
||||
|
||||
ASSERT (isSameObject (seq, til.getSequence()));
|
||||
// verify the properties
|
||||
ASSERT (specialTimeline->getSequence() == sess->sequences[0]); // the already existing sequence got bound into that timeline too
|
||||
ASSERT (contains (specialTimeline->pipes, Pipe::query("pipe(ambiance)")));
|
||||
|
||||
//verify default timeline
|
||||
Axis& axis = til.getAxis();
|
||||
ASSERT (Time(0) == axis.origin());
|
||||
ASSERT (Time(0) == til.length()); ////////////////////////TICKET #177
|
||||
|
||||
//verify global pipes
|
||||
//TODO
|
||||
|
||||
//verify default sequence
|
||||
Track rootTrack = seq.rootTrack();
|
||||
ASSERT (rootTrack->isValid());
|
||||
ASSERT (Time(0) == rootTrack->length());
|
||||
ASSERT (0 == rootTrack->subTracks.size());
|
||||
ASSERT (0 == rootTrack->clips.size());
|
||||
//TODO verify the output slots of the sequence
|
||||
|
||||
//TODO now use the generic query API to discover the same structure.
|
||||
ASSERT (til == *(sess->all<Timeline>()));
|
||||
ASSERT (seq == *(sess->all<Sequence>()));
|
||||
ASSERT (rootTrack == *(sess->all<Track>()));
|
||||
ASSERT (! sess->all<Clip>());
|
||||
|
||||
QueryFocus& focus = sess->focus();
|
||||
ASSERT (rootTrack == focus.getObject());
|
||||
focus.navigate (til);
|
||||
ASSERT (til.getBinding() == focus.getObject());
|
||||
ASSERT (rootTrack == *(focus.children()));
|
||||
ASSERT (specialTimeline.use_count() == 3); // we, the AssetManager and the session
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5794,7 +5794,7 @@ function addKeyDownHandlers(e)
|
|||
<div title="TiddlyWiki" modifier="Ichthyostega" created="200706220430" changecount="1">
|
||||
<pre>http://tiddlywiki.com/</pre>
|
||||
</div>
|
||||
<div title="Timeline" modifier="Ichthyostega" modified="201002270504" created="200706250721" tags="def" changecount="11">
|
||||
<div title="Timeline" modifier="Ichthyostega" modified="201003010218" created="200706250721" tags="def" changecount="14">
|
||||
<pre>Timeline is the top level element within the [[Session (Project)|Session]]. It is visible within a //timeline view// in the GUI and represents the effective (resulting) arrangement of media objects, to be rendered for output or viewed in a Monitor (viewer window). A timeline is comprised of:
|
||||
* a time axis in abolute time ({{red{WIP 1/10}}}: not clear if this is an entity or just a conceptual definition)
|
||||
* a PlayControler
|
||||
|
|
@ -5808,6 +5808,8 @@ Within the Project, there may be ''multiple timelines'', to be viewed and render
|
|||
|
||||
!Façade and implementation
|
||||
Actually, Timeline is both an interface and acts as façade. Its an interface, because we'll need "timeline views" ({{red{really? is that a reason to create a hierarchy right here, or shouldn't that be rather conceptual?}}}. It is a façade to the raw structures in the model, in this case a {{{Placement<BindingMO>}}} attached immediately below the [[root scope|ModelRootMO]]. The implementation of the timeline(s) is maintained as StructAsset {{red{Really? or should this be a ~MetaAsset??}}} within the AssetManager, managed by shared-ptr.
|
||||
|
||||
Besides building on the asset management, implementing Timeline (and Sequence) as StructAsset yields another benefit: ~StructAssets can be retrieved by query, allowing to specify more details of the configuration immediately on creation. //But on the short term, this approach causes problems:// there is no real inference engine integrated into Lumiera yet (as of 2/2010 the plan is to get an early alpha working end to end first). For now we're bound to use the {{{fake-configrules}}} and to rely on a hard wired simulation of the intended behaviour of a real query resolution. Just some special magic queries will work for now, but that's enough to get ahead.
|
||||
</pre>
|
||||
</div>
|
||||
<div title="TimelineSequences" modifier="Ichthyostega" modified="200811022211" created="200811011836" tags="design draft discuss img" changecount="14">
|
||||
|
|
|
|||
Loading…
Reference in a new issue