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)"));
|
answer_->insert (entry_Struct<Pipe> ("pipe(master), stream(video)"));
|
||||||
item<Pipe> (answer_, "") = item<Pipe>(answer_,"pipe(master), stream(video)");// use as default
|
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 *
|
/* under some circumstances we need to emulate the behaviour *
|
||||||
* of a real resolution engine in a more detailed manner. *
|
* 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... */
|
/** special case: create a new pipe with matching pipe and stream IDs on the fly when referred... */
|
||||||
bool
|
bool
|
||||||
|
|
@ -130,14 +132,14 @@ namespace lumiera {
|
||||||
answer_->insert (entry<Pipe> (q, newPipe));
|
answer_->insert (entry<Pipe> (q, newPipe));
|
||||||
return true;
|
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
|
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 const ProcPatt cPP;
|
||||||
typedef WrapReturn<cPP>::Wrapper Ptr;
|
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));
|
answer_->insert (entry<cPP> (q, newPP));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,12 +49,9 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace lumiera
|
namespace lumiera {
|
||||||
{
|
namespace query {
|
||||||
|
|
||||||
|
|
||||||
namespace query
|
|
||||||
{
|
|
||||||
using asset::Pipe;
|
using asset::Pipe;
|
||||||
using asset::ProcPatt;
|
using asset::ProcPatt;
|
||||||
using asset::PProcPatt;
|
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 */
|
/** a traits-class to define the smart-ptr to wrap the result */
|
||||||
template<class TY>
|
template<class TY>
|
||||||
|
|
@ -81,16 +77,18 @@ namespace lumiera
|
||||||
|
|
||||||
|
|
||||||
/** helper detecting if a query actually intended to retrieve a "default" object.
|
/** 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" ... */
|
* parse and evaluate the query. @note query is modified if "default" ... */
|
||||||
inline bool
|
inline bool
|
||||||
is_defaults_query (string& query)
|
is_defaults_query (string& query)
|
||||||
{
|
{
|
||||||
return !isnil (removeTerm ("default", query));
|
return !isnil (removeTerm ("default", query));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // details (end)
|
} // details (end)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the actual table holding preconfigured answers
|
* the actual table holding preconfigured answers
|
||||||
* packaged as boost::any objects.
|
* packaged as boost::any objects.
|
||||||
|
|
@ -112,7 +110,7 @@ namespace lumiera
|
||||||
bool detect_case (typename WrapReturn<TY>::Wrapper&, Query<TY>& q);
|
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_matching_new_Pipe (Query<Pipe>& q, string const& pipeID, string const& streamID);
|
||||||
bool fabricate_just_new_Pipe (Query<Pipe>& q);
|
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>
|
template<class TY>
|
||||||
bool set_new_mock_solution (Query<TY>& q, typename WrapReturn<TY>::Wrapper& candidate);
|
bool set_new_mock_solution (Query<TY>& q, typename WrapReturn<TY>::Wrapper& candidate);
|
||||||
|
|
@ -184,7 +182,7 @@ namespace lumiera
|
||||||
if (!isnil (extractID("make", q)))
|
if (!isnil (extractID("make", q)))
|
||||||
return false; // let the query fail here,
|
return false; // let the query fail here,
|
||||||
// so the invoking factory will go ahead
|
// 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 pipeID = extractID("pipe", q);
|
||||||
const string streamID = extractID("stream", q);
|
const string streamID = extractID("stream", q);
|
||||||
|
|
@ -210,7 +208,7 @@ namespace lumiera
|
||||||
|
|
||||||
const string streamID = extractID("stream", q);
|
const string streamID = extractID("stream", q);
|
||||||
if (!candidate && !isnil(streamID))
|
if (!candidate && !isnil(streamID))
|
||||||
return fabricate_ProcPatt_on_demand (q, streamID);
|
return fabricate_ProcPatt_on_demand (q);
|
||||||
|
|
||||||
q.clear();
|
q.clear();
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -240,13 +238,11 @@ namespace lumiera
|
||||||
|
|
||||||
public:
|
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::query
|
||||||
|
|
||||||
} // namespace lumiera
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace asset
|
namespace asset {
|
||||||
{
|
|
||||||
using lumiera::P;
|
using lumiera::P;
|
||||||
|
|
||||||
class Pipe;
|
class Pipe;
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ namespace asset {
|
||||||
|
|
||||||
/** create an empty default configured Sequence */
|
/** create an empty default configured Sequence */
|
||||||
Sequence::Sequence (const Asset::Ident& idi)
|
Sequence::Sequence (const Asset::Ident& idi)
|
||||||
|
: Struct (idi)
|
||||||
// : track (makeDefaultTrack ())
|
// : track (makeDefaultTrack ())
|
||||||
// , clips (0)
|
// , clips (0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ namespace asset {
|
||||||
|
|
||||||
/** TODO??? */
|
/** TODO??? */
|
||||||
Timeline::Timeline (const Asset::Ident& idi)
|
Timeline::Timeline (const Asset::Ident& idi)
|
||||||
|
: Struct (idi)
|
||||||
// : track (makeDefaultTrack ())
|
// : track (makeDefaultTrack ())
|
||||||
// , clips (0)
|
// , clips (0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@
|
||||||
#include "lib/test/run.hpp"
|
#include "lib/test/run.hpp"
|
||||||
#include "proc/mobject/session.hpp"
|
#include "proc/mobject/session.hpp"
|
||||||
#include "proc/mobject/session/fixture.hpp" // TODO only temporarily needed
|
#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/lumitime.hpp"
|
||||||
#include "lib/util.hpp"
|
#include "lib/util.hpp"
|
||||||
|
|
||||||
|
|
@ -42,6 +44,9 @@ namespace test {
|
||||||
using proc_interface::AssetManager;
|
using proc_interface::AssetManager;
|
||||||
using proc_interface::PAsset;
|
using proc_interface::PAsset;
|
||||||
|
|
||||||
|
using asset::PTimeline;
|
||||||
|
using asset::PSequence;
|
||||||
|
|
||||||
using lumiera::Time;
|
using lumiera::Time;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -88,23 +93,23 @@ namespace test {
|
||||||
UNIMPLEMENTED ("how to refer to tracks...");
|
UNIMPLEMENTED ("how to refer to tracks...");
|
||||||
|
|
||||||
ASSERT (0 < sess->timelines.size());
|
ASSERT (0 < sess->timelines.size());
|
||||||
Timeline& til = sess->timelines[0];
|
PTimeline til = sess->timelines[0];
|
||||||
|
|
||||||
ASSERT (0 < sess->sequences.size());
|
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
|
//verify default timeline
|
||||||
Axis& axis = til.getAxis();
|
Axis& axis = til->getAxis();
|
||||||
ASSERT (Time(0) == axis.origin());
|
ASSERT (Time(0) == axis.origin());
|
||||||
ASSERT (Time(0) == til.length()); ////////////////////////TICKET #177
|
ASSERT (Time(0) == til->length()); ////////////////////////TICKET #177
|
||||||
|
|
||||||
//verify global pipes
|
//verify global pipes
|
||||||
//TODO
|
//TODO
|
||||||
|
|
||||||
//verify default sequence
|
//verify default sequence
|
||||||
Track rootTrack = seq.rootTrack();
|
Track rootTrack = seq->rootTrack();
|
||||||
ASSERT (rootTrack->isValid());
|
ASSERT (rootTrack->isValid());
|
||||||
ASSERT (Time(0) == rootTrack->length());
|
ASSERT (Time(0) == rootTrack->length());
|
||||||
ASSERT (0 == rootTrack->subTracks.size());
|
ASSERT (0 == rootTrack->subTracks.size());
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,12 @@
|
||||||
#include "lib/test/run.hpp"
|
#include "lib/test/run.hpp"
|
||||||
#include "proc/mobject/session.hpp"
|
#include "proc/mobject/session.hpp"
|
||||||
//#include "proc/mobject/session/fixture.hpp" // TODO only temporarily needed
|
//#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/lumitime.hpp"
|
||||||
|
#include "lib/query.hpp"
|
||||||
#include "lib/util.hpp"
|
#include "lib/util.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
@ -42,12 +46,24 @@ namespace test {
|
||||||
using proc_interface::AssetManager;
|
using proc_interface::AssetManager;
|
||||||
using proc_interface::PAsset;
|
using proc_interface::PAsset;
|
||||||
|
|
||||||
|
using asset::PTimeline;
|
||||||
|
using asset::PSequence;
|
||||||
|
using asset::Pipe;
|
||||||
|
|
||||||
|
using lumiera::Query;
|
||||||
using lumiera::Time;
|
using lumiera::Time;
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* @test verify retrieval and instance management of the top level facade objects
|
* @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 session-structure-test.cpp
|
||||||
* @see Timeline
|
* @see Timeline
|
||||||
|
|
@ -63,52 +79,57 @@ namespace test {
|
||||||
ASSERT (Session::current.isUp());
|
ASSERT (Session::current.isUp());
|
||||||
|
|
||||||
verify_retrieval();
|
verify_retrieval();
|
||||||
|
verify_creation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
verify_retrieval()
|
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;
|
PSess sess = Session::current;
|
||||||
ASSERT (sess->isValid());
|
ASSERT (sess->isValid());
|
||||||
|
|
||||||
|
uint num_timelines = sess->timelines.size();
|
||||||
|
ASSERT (0 < num_timelines);
|
||||||
|
|
||||||
ASSERT (0 < sess->timelines.size());
|
Query<Timeline> special = "id(aSillyName), sequence("
|
||||||
Timeline& til = sess->timelines[0];
|
+ sess->sequences[0]->getNameID()
|
||||||
|
+ "), pipe(ambiance).";
|
||||||
|
|
||||||
ASSERT (0 < sess->sequences.size());
|
PTimeline specialTimeline (asset::Struct::create (special));
|
||||||
Sequence& seq = sess->sequences[0];
|
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
|
ASSERT (specialTimeline.use_count() == 3); // we, the AssetManager and the session
|
||||||
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()));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5794,7 +5794,7 @@ function addKeyDownHandlers(e)
|
||||||
<div title="TiddlyWiki" modifier="Ichthyostega" created="200706220430" changecount="1">
|
<div title="TiddlyWiki" modifier="Ichthyostega" created="200706220430" changecount="1">
|
||||||
<pre>http://tiddlywiki.com/</pre>
|
<pre>http://tiddlywiki.com/</pre>
|
||||||
</div>
|
</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:
|
<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 time axis in abolute time ({{red{WIP 1/10}}}: not clear if this is an entity or just a conceptual definition)
|
||||||
* a PlayControler
|
* a PlayControler
|
||||||
|
|
@ -5808,6 +5808,8 @@ Within the Project, there may be ''multiple timelines'', to be viewed and render
|
||||||
|
|
||||||
!Façade and implementation
|
!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.
|
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>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
<div title="TimelineSequences" modifier="Ichthyostega" modified="200811022211" created="200811011836" tags="design draft discuss img" changecount="14">
|
<div title="TimelineSequences" modifier="Ichthyostega" modified="200811022211" created="200811011836" tags="design draft discuss img" changecount="14">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue