WIP getting the placement part through the compiler,

still having to solve problems with the asset-to-MObject relation
This commit is contained in:
Fischlurch 2007-11-12 02:05:39 +01:00
parent 5c2fa504e7
commit 89e4fa9db7
31 changed files with 261 additions and 165 deletions

View file

@ -22,10 +22,16 @@
#include "common/time.hpp"
#include <limits>
namespace cinelerra
{
// TODO: dummy values; should be adjusted when switching to the real time implementation provided by the backend
const Time Time::MAX = std::numeric_limits<long>::max();
const Time Time::MIN = -MAX;
} // namespace cinelerra

View file

@ -24,6 +24,7 @@
#ifndef CINELERRA_TIME_H
#define CINELERRA_TIME_H
#include <boost/operators.hpp>
namespace cinelerra
@ -38,13 +39,22 @@ namespace cinelerra
* elaborate timehandling functions in the backend and the goal
* is for class Time to be just a thin wrapper!
*/
class Time
class Time : boost::totally_ordered<Time>
{
long dummy;
public:
Time(long dum=0) : dummy(dum) {}
operator long () { return dummy; }
bool operator< (const Time& ot) const { return dummy < ot.dummy; }
bool operator== (const Time& ot) const { return dummy == ot.dummy; }
static const Time MAX ;
static const Time MIN ;
};
} // namespace cinelerra
#endif

View file

@ -165,6 +165,6 @@ namespace util
/** shortcut for subclass test, intended for assertions only.
* @note it is considered bad style to use such in non-assertion code,
* and we probably will enforce this design rule in future. */
#define INSTANCEOF(CLASS, EXPR) (dynamic_cast<CLASS*> (EXPR))
#define INSTANCEOF(CLASS, EXPR) (dynamic_cast<const CLASS*> (EXPR))
#endif /*UTIL_HPP_*/

View file

@ -78,6 +78,7 @@ namespace asset
bool hasKind (Kind refKind) const { return kind_ == refKind; }
bool isWithin (const Category&) const;
void setPath (const string & newpath) { this->path_ = newpath; }
operator string () const;

View file

@ -26,6 +26,47 @@
namespace asset
{
namespace
{
/** @internal derive a sensible asset ident tuple
* when creating a asset::Clip based on some asset::Media
* @todo getting this one is important for handling creation
* of multiple clip instances from one media. Means we
* have still to figure out a sensible concept...
*/
const Asset::Ident
createClipIdent (const Media& mediaref)
{
string name (mediaref.ident.name + "-clip"); // TODO something sensible here; append number, sanitize etc.
Category category (mediaref.ident.category);
category.setPath(CLIP_SUBFOLDER);
return Asset::Ident (name, category,
mediaref.ident.org,
mediaref.ident.version );
}
Media::PClipMO
createClipMO (const ID<Media>& mediaID)
{
return mobject::MObject::create(
AssetManager::instance()
.getAsset (mediaID));
}
}
Clip::Clip (const Media& mediaref)
: Media (createClipIdent (mediaref),
mediaref.getFilename())
, source_ (mediaref)
, clipMO_ (createClipMO (this->getID()))
{
}
/** Directly object creating specialisation of the
* asset::Media interface method: immediately starting
* out from this asset::Clip and doing the actual
@ -35,12 +76,12 @@ namespace asset
Media::PClipMO
Clip::createClip ()
{
if (!this.clipMO_)
this.clipMO_ = MObject::create(
AssetManager::instance()
.getAsset (this.getID()));
if (!clipMO_)
clipMO_ = mobject::MObject::create(
AssetManager::instance()
.getAsset (this->getID()));
return this.clipMO_;
return clipMO_;
}
@ -51,7 +92,7 @@ namespace asset
Clip::getClipAsset ()
{
return PClip (AssetManager::instance()
.getAsset (this.getID()));
.getAsset (this->getID()));
}
@ -61,7 +102,7 @@ namespace asset
Media::PMedia
Clip::checkCompound ()
{
return this.source_.checkCompound();
return source_.checkCompound();
}

View file

@ -38,21 +38,26 @@ namespace asset
/** media source of this clip */
const Media& source_;
/** the corresponding (dependant) clip-MO */
/** the corresponding (dependant) clip-MO
* @todo seems to be obsolete by the reworked design of multichannel media 11/07 */
PClipMO clipMO_;
public:
virtual PClipMO createClip ();
virtual PMedia checkCompound ();
private:
Clip (const Media& mediaref) : source_(mediaref) {};
protected:
Clip (const Media& mediaref);
friend class MediaFactory;
virtual PClip getClipAsset ();
};
typedef shared_ptr<const asset::Clip> PClipAsset;
const string CLIP_SUBFOLDER = "clips"; // TODO: handling of hard-wired constants....
} // namespace asset

View file

@ -90,7 +90,7 @@ namespace asset
Media::PMedia
Media::checkCompound()
Media::checkCompound() const
{
PAsset parents = this.getParents();
PMedia parent(0);

View file

@ -38,7 +38,7 @@
#include "proc/asset.hpp"
#include "common/factory.hpp"
#include "proc/mobject/mobject.hpp"
#include "proc/mobject/session/clip.hpp"
@ -72,7 +72,7 @@ namespace asset
typedef shared_ptr<Media> PMedia;
typedef shared_ptr<const asset::Clip> PClip;
typedef shared_ptr<asset::ProcPatt> PProcPatt;
typedef mobject::Placement<mobject::session::Clip> PClipMO;
typedef mobject::session::PClipMO PClipMO;
static MediaFactory create;
@ -111,7 +111,7 @@ namespace asset
* is part of a compound (multichannel) media.
* @return pointer to parent, or \code null
*/
virtual PMedia checkCompound ();
virtual PMedia checkCompound () const;
};

View file

@ -49,6 +49,8 @@ namespace mobject
public:
const Time time;
const Track track;
typedef std::pair<Time,Track> 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.
@ -66,12 +68,12 @@ namespace mobject
* be initialized directly here in the ExplicitPlacement ctor.
* (ichthyo: siehe Trac #100)
*/
ExplicitPlacement (Placement<MObject>& base, const session::FixedLocation found)
: Placement(base),
time(found.time_), track(found.track_)
ExplicitPlacement (const Placement<MObject>& base, const SolutionData found)
: Placement<MObject>(base),
time(found.first), track(found.second)
{ };
friend ExplicitPlacement::resolve () const;
friend ExplicitPlacement Placement<MObject>::resolve () const;
};

View file

@ -22,7 +22,7 @@
#include "proc/mobject/mobject.hpp"
#include "proc/mobject/placement.hpp"
#include "proc/mobject/session/mobjectfactory.hpp"
namespace mobject
{

View file

@ -64,8 +64,11 @@ namespace mobject
// TODO: how to represent time intervals best?
Time length;
MObject() {}
virtual ~MObject() {};
friend class session::MObjectFactory;
public:
static session::MObjectFactory create;
@ -77,7 +80,6 @@ namespace mobject
};
typedef Placement<MObject> PMO;

View file

@ -58,7 +58,7 @@
#define MOBJECT_PLACEMENT_H
#include "cinelerra.h"
#include "proc/mobject/session/abstractmo.hpp"
#include "proc/mobject/mobject.hpp"
#include "proc/mobject/session/locatingpin.hpp"
#include "proc/mobject/session/track.hpp"
@ -68,11 +68,13 @@ using std::tr1::shared_ptr;
namespace mobject
{
namespace session{ class MObjectFactory; }
class MObject;
class ExplicitPlacement;
/**
* A refcounting Handle to an MObject of type MO,
* used to constrain or explicitly specify the
@ -95,8 +97,8 @@ namespace mobject
virtual MO *
operator-> () const
{
ENSURE (this.get());
return shared_ptr::operator-> ();
ENSURE (*this);
return shared_ptr<MO>::operator-> ();
}
@ -110,80 +112,30 @@ namespace mobject
* by the various LocatingPin (\see #chain) and
* provide the resulting (explicit) placement.
*/
virtual ExplicitPlacement
resolve () const
{
return ExplicitPlacement (*this, chain.resolve());
}
virtual ExplicitPlacement resolve () const;
protected:
virtual ~Placement() {};
Placement (MO & subject)
: shared_ptr (&subject, &session::AbstractMO::destroy) {};
Placement (MO & subject, void (*moKiller)(MO*))
: shared_ptr<MO> (&subject, moKiller) {};
friend class session::MObjectFactory;
};
/* === defining specialisations to be subclasses === */
typedef Placement<MObject> PMO;
/* === defining specialisations to be subclasses === */
namespace session
{
class Clip;
class Effect;
class Meta;
}
template<>
class Placement<session::Clip> : public Placement<MObject>
{
Placement (session::Clip & c)
: Placement<MObject>::Placement (c)
{ };
public:
virtual session::Clip*
operator-> () const
{
ENSURE (INSTANCEOF(session::Clip, this.get()));
return static_cast<session::Clip*> (shared_ptr::operator-> ());
}
};
/////TODO: define Macro for specialisations here
template<>
class Placement<session::Effect> : public Placement<MObject>
{
Placement (session::Effect & e)
: Placement<MObject>::Placement (e)
{ };
public:
virtual session::Effect*
operator-> () const
{
ENSURE (INSTANCEOF(session::Effect, this.get()));
return static_cast<session::Effect*> (shared_ptr::operator-> ());
}
};
template<>
class Placement<session::Meta> : public Placement<MObject>
{
Placement (session::Meta & m)
: Placement<MObject>::Placement (m)
{ };
public:
virtual session::Meta*
operator-> () const
{
ENSURE (INSTANCEOF(session::Meta, this.get()));
return static_cast<session::Meta*> (shared_ptr::operator-> ());
}
};
/* a note to the maintainer: please don't add any fields or methods to
* these subclasses which aren't also present in Placement<MObject>!
* Placements are frequently treated like values and thus slicing

View file

@ -84,9 +84,9 @@ namespace mobject
public:
static session::SessManager& current;
virtual bool isValid () = 0;
virtual void add (PPla& placement) = 0;
virtual bool remove (PPla& placement) = 0;
virtual bool isValid () = 0;
virtual void add (PMO& placement) = 0;
virtual bool remove (PMO& placement) = 0;
/// @deprecated Ichthyo doubts it is good design to hand out the EDL??
virtual session::EDL& currEDL () = 0;

View file

@ -34,10 +34,12 @@ namespace mobject
{
/**
* abstract base class of all MObjects for providing common services.
* @todo seems that we don't need this intermediate class...
*/
class AbstractMO : public MObject
{
////////////// TODO: work out common services to provide!!!!
shared_ptr<Placement> placement_;
public:
@ -45,13 +47,6 @@ namespace mobject
virtual Time& getLength() { return length; }
protected:
/** custom deleter func allowing class Placement
* to take ownership of MObjct instances
*/
static void destroy (MObject* o) { delete o; }
friend class Placement;
};

View file

@ -55,7 +55,7 @@ namespace mobject
public:
const string& getRepr () const { return repr; }
virtual LocatingPin* clone () const = 0;
virtual Allocation* clone () const = 0;
};

View file

@ -35,7 +35,7 @@ namespace mobject
: start_(0),
mediaDef_(mediaDef)
{
this.setupLength();
setupLength();
}

View file

@ -25,15 +25,22 @@
#define MOBJECT_SESSION_CLIP_H
#include "proc/mobject/session/abstractmo.hpp"
#include "proc/mobject/placement.hpp"
namespace asset
{
class Media;
class Clip;
typedef shared_ptr<const asset::Clip> PClipAsset;
}
namespace mobject
{
namespace session
{
using asset::Media;
using asset::PClipAsset;
typedef shared_ptr<Media> PMedia;
/**
@ -52,7 +59,7 @@ namespace mobject
{
protected:
/** startpos in source */
Time start;
Time start_;
//TODO: where to put the duration ???
@ -68,19 +75,40 @@ namespace mobject
virtual bool isValid() const;
/** access the underlying media asset */
virtual Media::PMedia getMedia ()
virtual PMedia getMedia ()
{
UNIMPLEMENTED ("how to relate MObjects and media assets...");
return AssetManager::instance().getAsset(IDA(0)); // KABOOM! (just to make it compile)
//return AssetManager::instance().getAsset(IDA(0)); // KABOOM! (just to make it compile)
}
};
typedef Placement<Clip> PClipMO;
} // namespace mobject::session
///////////////////////////TODO use macro for specialsation...
template<>
class Placement<session::Clip> : public Placement<MObject>
{
protected:
Placement (session::Clip & m, void (*moKiller)(MObject*))
: Placement<MObject>::Placement (m, moKiller)
{ };
friend class session::MObjectFactory;
public:
virtual session::Clip*
operator-> () const
{
ENSURE (INSTANCEOF(session::Clip, &(*this)));
return static_cast<session::Clip*> (shared_ptr<MObject>::operator-> ());
}
};
} // namespace mobject
#endif

View file

@ -35,13 +35,13 @@ namespace mobject
* to have this on the interface
*/
bool
EDL::contains (const PPla& placement)
EDL::contains (const PMO& placement)
{
UNIMPLEMENTED ("test if a given placement is contained within this EDL");
}
PPla&
PMO&
EDL::find (const string& id)
{
UNIMPLEMENTED ("serch for a given 'thing' within the EDL");

View file

@ -48,8 +48,8 @@ namespace mobject
vector<MObject *> clips;
public:
bool contains (const PPla& placement);
PPla& find (const string& id); ///< @todo how to refer to clips? using asset IDs??
bool contains (const PMO& placement);
PMO& find (const string& id); ///< @todo how to refer to clips? using asset IDs??
vector<PAsset>& getTracks () { return tracks; } ///< @todo use track assets correct, make const!
size_t size ()

View file

@ -50,5 +50,22 @@ namespace mobject
} // namespace mobject::session
///////////////////////////TODO use macro for specialsation...
template<>
class Placement<session::Effect> : public Placement<MObject>
{
Placement (session::Effect & m, void (*moKiller)(MObject*))
: Placement<MObject>::Placement (m, moKiller)
{ };
public:
virtual session::Effect*
operator-> () const
{
ENSURE (INSTANCEOF(session::Effect, &(*this)));
return static_cast<session::Effect*> (shared_ptr<MObject>::operator-> ());
}
};
} // namespace mobject
#endif

View file

@ -28,8 +28,8 @@ namespace mobject
namespace session
{
LocatingPin*
LocatingPin::clone ()
FixedLocation*
FixedLocation::clone () const
{
return new FixedLocation (*this);
}
@ -42,12 +42,12 @@ namespace mobject
LocatingPin::intersect (solution);
TODO ("either set position or make overconstrained");
if (solution.minTime <= this.time_)
solution.minTime = this.time_;
if (solution.minTime <= this->time_)
solution.minTime = this->time_;
else
solution.impo = true;
if (solution.maxTime >= this.time_)
solution.maxTime = this.time_;
if (solution.maxTime >= this->time_)
solution.maxTime = this->time_;
else
solution.impo = true;
}

View file

@ -51,11 +51,12 @@ namespace mobject
protected:
FixedLocation (Time ti, Track tra) : time_(ti), track_(tra) {};
friend class LocatingPin;
virtual void intersect (LocatingSolution&) const;
public:
virtual LocatingPin* clone () const;
virtual FixedLocation* clone () const;
};

View file

@ -31,7 +31,7 @@ namespace mobject
namespace session
{
inline LocatingPin*
cloneChain (scoped_ptr<LocatingPin>& chain)
cloneChain (const scoped_ptr<LocatingPin>& chain)
{
if (!chain)
return 0;
@ -51,14 +51,14 @@ namespace mobject
LocatingPin&
LocatingPin::operator= (const LocatingPin& other)
{
if (this!=other)
this.next_.reset (cloneChain (other.next_));
if (this != &other)
this->next_.reset (cloneChain (other.next_));
return *this;
}
LocatingPin*
LocatingPin::clone ()
LocatingPin::clone () const
{
return new LocatingPin(*this);
}
@ -76,8 +76,8 @@ namespace mobject
else
{
scoped_ptr<LocatingPin> tmp_next (newLp);
tmp_next->next_.swap(this.next_);
this.next_.swap(tmp_next);
tmp_next->next_.swap(next_);
next_.swap(tmp_next);
return *newLp;
}
}
@ -93,12 +93,12 @@ namespace mobject
* @todo we are packing and unpacking the information (time,track)
* several times. Ichthyo considers a more elegant solution.
*/
const FixedLocation
const LocatingPin::SolutionData
LocatingPin::resolve () const
{
LocatingSolution solution;
resolve (solution);
return FixedLocation (solution.getTime(), solution.getTrack());
return SolutionData (solution.getTime(), solution.getTrack());
}
bool
@ -109,22 +109,15 @@ namespace mobject
return solution.is_impossible();
}
inline bool
still_to_solve (LocatingPin::LocatingSolution& solution)
{
return !(solution.is_definite() || solution.is_impossible());
}
void
LocatingPin::resolve (LocatingSolution& solution) const
{
if (!still_to_solve(solution))
if (!solution.still_to_solve())
return;
this.intersect (solution);
if (this.next_ &&
still_to_solve (solution))
this->intersect (solution);
if (next_ && solution.still_to_solve())
next_->resolve(solution);
}
@ -132,7 +125,7 @@ namespace mobject
void
LocatingPin::intersect (LocatingSolution& solution) const
{
REQUIRE (still_to_solve (solution));
REQUIRE (solution.still_to_solve());
// base class Implementation is NOP...
}
@ -170,6 +163,14 @@ namespace mobject
return impo;
}
bool
LocatingPin::LocatingSolution::still_to_solve ()
{
return !(is_definite() || is_impossible());
}
@ -178,18 +179,18 @@ namespace mobject
/* === Factory functions for adding LocatingPins === */
FixedLocation&
LocatingPin::operator() (Time, Track)
LocatingPin::operator() (Time start, Track track)
{
return static_cast<FixedLocation&>
(this.addChain (new FixedLocation (Time, Track)));
(addChain (new FixedLocation (start, track)));
}
RelativeLocation&
LocatingPin::operator() (PMO refObj, Time offset=0)
LocatingPin::operator() (PMO refObj, Time offset)
{
return static_cast<RelativeLocation&>
(this.addChain (new RelativeLocation (Time, Track)));
(addChain (new RelativeLocation (refObj, offset)));
}

View file

@ -44,6 +44,7 @@
#include "cinelerra.h"
#include <utility>
#include <boost/scoped_ptr.hpp>
using boost::scoped_ptr;
@ -51,13 +52,17 @@ using boost::scoped_ptr;
namespace mobject
{
class MObject;
template<class MO> class Placement;
typedef Placement<MObject> PMO;
namespace session
{
class FixedLocation;
class RelativeLocation;
class Track; //TODO
/**
* Positioning specification, possibliy chained
@ -76,6 +81,8 @@ namespace mobject
protected:
typedef cinelerra::Time Time;
typedef session::Track* Track;
typedef std::pair<Time,Track> SolutionData; //TODO (ichthyo consideres better passing of solution by subclass)
struct LocatingSolution;
/** next additional Pin, if any */
scoped_ptr<LocatingPin> next_;
@ -88,12 +95,12 @@ namespace mobject
virtual void intersect (LocatingSolution&) const;
public:
const FixedLocation resolve () const;
const SolutionData resolve () const;
bool isOverdetermined () const;
/* Factory functions for adding LocatingPins */
FixedLocation& operator() (Time, Track=0);
FixedLocation& operator() (Time start, Track track=0);
RelativeLocation& operator() (PMO refObj, Time offset=0);
LocatingPin (const LocatingPin&);
@ -104,6 +111,8 @@ namespace mobject
protected:
LocatingPin () {};
friend class Placement<MObject>;
/**
* @internal helper for the (preliminary)
* position resolve() implementation.
@ -121,18 +130,20 @@ namespace mobject
bool impo;
LocatingSolution ()
: minTime(-1e15), // TODO: better implementation of "unspecified..."
maxTime(+1e15),
: minTime(Time::MAX), // TODO: better implementation of "unspecified..."
maxTime(Time::MIN),
minTrack(0), // TODO
maxTrack(0),
impo(false)
{ }
Time getTime();
Track getTrack();
Time getTime ();
Track getTrack ();
bool is_definite ();
bool is_impossible ();
bool still_to_solve ();
bool is_definite();
bool is_impossible();
};
};

View file

@ -48,6 +48,23 @@ namespace mobject
} // namespace mobject::session
//////////////////////////////////TODO
template<>
class Placement<session::Meta> : public Placement<MObject>
{
Placement (session::Meta & m, void (*moKiller)(MObject*))
: Placement<MObject>::Placement (m, moKiller)
{ };
public:
virtual session::Meta*
operator-> () const
{
ENSURE (INSTANCEOF(session::Meta, &(*this)));
return static_cast<session::Meta*> (shared_ptr<MObject>::operator-> ());
}
};
} // namespace mobject
#endif

View file

@ -48,7 +48,7 @@ namespace mobject
Placement<Clip>
MObjectFactory::operator() (PClipAsset& mediaDef)
{
return Placement<Clip> (new Clip (mediaDef));
return Placement<Clip> (*new Clip (mediaDef), &deleterFunc);
}

View file

@ -46,11 +46,15 @@ namespace mobject
class MObjectFactory
{
public:
typedef Placement PType;
/** custom deleter func allowing class Placement
* to take ownership of MObjct instances
*/
static void deleterFunc (MObject* o) { delete o; }
PType<Clip> operator() (PClipAsset&);
PType<Effect> operator() (const asset::Effect);
public:
Placement<Clip> operator() (PClipAsset&);
Placement<Effect> operator() (const asset::Effect);
};

View file

@ -29,8 +29,8 @@ namespace mobject
namespace session
{
LocatingPin*
LocatingPin::clone ()
RelativeLocation*
RelativeLocation::clone () const
{
return new RelativeLocation (*this);
}

View file

@ -38,6 +38,8 @@ namespace mobject
class RelativeLocation : public LocatingPin
{
const PMO & anchor_; ////////////TODO: ooooops, this is a nasty design problem!!!
public:
/**
@ -49,13 +51,14 @@ namespace mobject
};
protected:
Placement anchor; ////////////TODO: ooooops, this is a nasty design problem!!!
RelativeLocation (const PMO& a, Time ofs) : anchor_(a), offset_(ofs) { }
friend class LocatingPin;
/** the kind of relation denoted by this Placement */
RelType relType;
/** Offset the actual position by this (time) value relative to the anchor point. */
Time offset;
Time offset_;
//TODO: suitable representation?
@ -63,7 +66,7 @@ namespace mobject
public:
virtual LocatingPin* clone () const;
virtual RelativeLocation* clone () const;
};

View file

@ -74,14 +74,14 @@ namespace mobject
void
SessionImpl::add (PPla& placement)
SessionImpl::add (PMO& placement)
{
UNIMPLEMENTED ("add Placement to the current EDL");
}
bool
SessionImpl::remove (PPla& placement)
SessionImpl::remove (PMO& placement)
{
UNIMPLEMENTED ("search and remove a given Placement from current EDL");
return false; // TODO

View file

@ -65,8 +65,8 @@ namespace mobject
public:
virtual bool isValid ();
virtual void add (PPla& placement);
virtual bool remove (PPla& placement);
virtual void add (PMO& placement);
virtual bool remove (PMO& placement);
virtual EDL& currEDL ();