rework placement to contain a LUID, and to deal with inheritance according to the concept draft

This commit is contained in:
Fischlurch 2009-05-29 07:10:54 +02:00
parent 0d41379dda
commit efa7b4717c
11 changed files with 212 additions and 151 deletions

View file

@ -113,8 +113,8 @@ namespace lib {
/* === for use within unordered_map === */
size_t hash_value (Plain const& plainHash) { return plainHash; }
size_t hash_value (LuidH const& luid_Hash) { return luid_Hash; }
inline size_t hash_value (Plain const& plainHash) { return plainHash; }
inline size_t hash_value (LuidH const& luid_Hash) { return luid_Hash; }
} // namespace "hash"

View file

@ -116,6 +116,11 @@ namespace mobject {
{
currentWrapper_ = ptr_toWrappedTarget;
}
template<class TAR>
void rememberWrapper (Placement<TAR>* ptr_toWrappedTarget)
{
currentWrapper_ = ptr_toWrappedTarget;
}
void forgetWrapper ()
{
@ -153,7 +158,7 @@ namespace mobject {
/**
* declare the concrete types a BuilderTool may recievee and treat.
* declare the concrete types a BuilderTool may receive and treat.
* @note it is recommended to use ApplicableBuilderTargetTypes
*/
template

View file

@ -26,34 +26,45 @@
#include "proc/mobject/mobject.hpp"
#include <boost/format.hpp>
using boost::format;
using boost::str;
namespace mobject
{
namespace mobject {
template<class MO>
ExplicitPlacement
Placement<MO>::resolve () const
{
return ExplicitPlacement (*this, chain.resolve());
}
/** @note we know we need only this single specialisation,
* because we define the Placements of more specific
* MObject kinds to be subclasses of Placement<MObject>,
* so they will inherit this function.
*/
template ExplicitPlacement Placement<MObject>::resolve() const;
ExplicitPlacement
Placement<MObject>::resolve () const
{
return ExplicitPlacement (*this, chain.resolve());
}
template<>
Placement<MObject>::operator string () const
{
static boost::format fmt("Placement<%s> %|50T.| use-cnt=%x adr=%x pointee=%x");
return str(fmt % typeid(*get()).name() % use_count() % this % get() );
}
{
static format fmt("Placement<%s> %|50T.| use-cnt=%x ID(%x) adr=%x pointee=%x");
return str(fmt % typeid(*get()).name() % use_count()
% (size_t)getID()
% this
% get()
);
}
string
format_PlacementID (Placement<MObject> const& pla)
{
static format fmt ("pID(%x)");
size_t hashVal = pla.getID();
return str(fmt % hashVal);
}

View file

@ -25,8 +25,8 @@
** Placements are at the very core of all editing operations,
** because they act as handles to access the media objects to be manipulated.
** Moreover, Placements are the actual content of the EDL(s) and Fixture and thus
** are small objects with value semantics. Many editing tasks include locating some
** Placement in the EDL or directly take a ref to a Placement.
** are small handle like objects. Many editing tasks include locating some Placement
** within the Session or directly take a ref to a Placement.
**
** Placements are <b>refcounting smart pointers</b>: By acting on the Placement object,
** we can change parameters of the way the media object is placed (e.g. adjust an offset),
@ -41,6 +41,17 @@
** case of such constraining is to add a FixedLocation, thus placing the MObject at one
** absolute position (time, track).
**
** Together, this yields semantics somewhere in between value semantics and reference semantics.
** As any smart-ptr, placements are copyable, any such copies being considered equivalent. \em But,
** when added to the Session, a placement acts as if it was an \em instance of the object it
** points at, with the purpose to bind this instance into the Session with specific placement
** properties. Thus, such a placement-within-session \em is an distinguishable entity, because
** the settings on the contained LocatingPin chain \em do constitute the relation properties
** of the MObject "placed" by this placement. To support this rather ref-like semantics, any
** placement has an embedded ID (identity), and the Session won't allow to add a clone copy
** of an placement with the same identity. Moreover, it is possible to create a smart-ptr
** like PlacementRef to denote a specific placement found within the current Session.
**
** Placements are templated on the type of the actual MObject they refer to, so, sometimes
** we rather use a Placement<Clip> to be able to use the more specific methods of the
** session::Clip interface. But <i>please note the following detail:</i> this type
@ -58,8 +69,10 @@
#define MOBJECT_PLACEMENT_H
#include "pre.hpp"
#include "lib/hash-indexed.hpp"
#include "proc/mobject/session/locatingpin.hpp"
#include "proc/asset/pipe.hpp"
#include "proc/asset/pipe.hpp" /////TODO: get rid of this (Trac #109)
#include <tr1/memory>
@ -68,25 +81,49 @@ namespace mobject {
namespace session{ class MObjectFactory; }
class MObject;
class ExplicitPlacement;
using std::tr1::shared_ptr;
using lib::HashIndexed;
/**
* A refcounting Handle to an MObject of type MO,
* used to constrain or explicitly specify the
* location where the MObject is supposed to
* be within the Session/EDL
* used to constrain or explicitly specify the location
* where the MObject is supposed to be within the Session/EDL.
* Placements are copyable (like values), but may be distinguished
* by their identity (reference semantics), which is based on an
* \link lib::HashIndexed hash-ID \endlink.
*
* Placements are defined to form a hierarchy, thereby mirroring
* the relations between their referents to some degree. This allows
* for building APIs targeted at specific kinds of MObjects, and
* at the same time allows a specific placement to stand-in when
* just a unspecific Placement<MObject> is required.
*
* @param MO the (compile time) type of the referent
* @param B immediate base class of this placement
*/
template<class MO>
class Placement : protected shared_ptr<MO>
template<class MO, class B =MObject>
class Placement ;
/**
* this specialisation forms the root of all placements
* and defines all of Placement's actual functionality.
*/
template<>
class Placement<MObject,MObject>
: protected shared_ptr<MObject>,
public HashIndexed<Placement<MObject>, lib::hash::LuidH> //////TODO: really need to be inherited publicly?
{
protected:
typedef shared_ptr<MO> Base;
typedef shared_ptr<MObject> _SmartPtr;
typedef void (*Deleter)(MObject*);
typedef lumiera::Time Time;
typedef asset::shared_ptr<asset::Pipe> Pipe;
typedef asset::shared_ptr<asset::Pipe> Pipe; ////TODO: get rid of this
@ -95,15 +132,15 @@ namespace mobject {
* which is subject to placement.
* @note we don't provide operator*
*/
virtual MO *
virtual MObject *
operator-> () const
{
ENSURE (*this);
return Base::operator-> ();
return _SmartPtr::operator-> ();
}
operator string() const ;
size_t use_count() const { return Base::use_count(); }
size_t use_count() const { return _SmartPtr::use_count(); }
virtual ~Placement() {};
@ -123,44 +160,55 @@ namespace mobject {
protected:
Placement (MO & subject, void (*moKiller)(MO*))
: shared_ptr<MO> (&subject, moKiller) {};
Placement (MObject & subject, Deleter killer)
: _SmartPtr (&subject, killer) {};
friend class session::MObjectFactory;
};
/* === defining specialisations to be subclasses === */
#define DEFINE_SPECIALIZED_PLACEMENT(SUBCLASS, BASE) \
template<> \
class Placement<SUBCLASS> : public Placement<BASE> \
{ \
protected: \
Placement (SUBCLASS & m, void (*moKiller)(MObject*)) \
: Placement<BASE>::Placement (m, moKiller) \
{ }; \
friend class session::MObjectFactory; \
\
public: \
virtual SUBCLASS* \
operator-> () const \
{ \
ENSURE (INSTANCEOF (SUBCLASS, this->get())); \
return static_cast<SUBCLASS*> \
(shared_ptr<MObject>::operator-> ()); \
} \
/**
* any specific placements are supposed to be derived
* from Placement<MObject>, or an intermediary interface,
* in case the second template parameter is used.
* @note please refrain from adding additional functionality
* to these subclasses. Especially, don't add any fields
* to the subclass, as Placements are treated like values
* at times, and thus slicing will happen, which in this
* special case is acceptable.
*/
template<class MO, class B>
class Placement
: public Placement<B>
{
protected:
typedef Placement<B> _Parent;
typedef typename _Parent::Deleter Deleter;
typedef typename _Parent::_SmartPtr _SmartPtr;
Placement (MO & mo, Deleter killer)
: _Parent (mo, killer)
{ };
friend class session::MObjectFactory;
public:
virtual MO*
operator-> () const
{
ENSURE (INSTANCEOF (MO, this->get()));
return static_cast<MO*>
(_SmartPtr::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
* will happen, which in this special case is acceptable.
*/
string
format_PlacementID (Placement<MObject> const&) ;
/** @todo cleanup uses of ref-to-placement. See Trac #115 */
typedef Placement<MObject> PMO;
} // namespace mobject

View file

@ -33,10 +33,9 @@ namespace asset
class Clip;
}
namespace mobject
{
namespace session
{
namespace mobject {
namespace session {
using asset::Media;
typedef P<Media> PMedia;
typedef P<asset::Clip> PClipAsset;
@ -57,7 +56,7 @@ namespace mobject
class Clip : public AbstractMO
{
protected:
/** startpos in source */
/** start position in source */
Time start_;
/** @todo using a mere ref here is against the scheme and only
@ -93,14 +92,8 @@ namespace mobject
};
typedef Placement<Clip> PClipMO;
} // namespace mobject::session
/** Placement<Clip> defined to be subclass of Placement<MObject> */
DEFINE_SPECIALIZED_PLACEMENT (session::Clip, MObject);
} // namespace mobject
}} // namespace mobject::session
#endif

View file

@ -32,26 +32,19 @@
using std::string;
namespace mobject
{
namespace session
namespace mobject {
namespace session {
class Effect : public AbstractMO
{
class Effect : public AbstractMO
{
protected:
/** Identifier of the Plugin to be used */
string plugID;
};
} // namespace mobject::session
/** Placement<Effect> defined to be subclass of Placement<MObject> */
DEFINE_SPECIALIZED_PLACEMENT (session::Effect, MObject);
} // namespace mobject
protected:
/** Identifier of the Plugin to be used */
string plugID;
};
}} // namespace mobject::session
#endif

View file

@ -188,7 +188,7 @@ namespace mobject
RelativeLocation&
LocatingPin::operator() (PMO refObj, Time offset)
LocatingPin::operator() (PlacementRef& refObj, Time offset)
{
return static_cast<RelativeLocation&>
(addChain (new RelativeLocation (refObj, offset)));

View file

@ -31,6 +31,11 @@
** RelativeLocation#resolve(LocatingSolution&) etc. If this is to be extended,
** we'll need a real spatial discrete constraint solver (and this probably will be
** some library implementation, because the problem is anything but trivial).
**
** @todo this can be considered a preliminary sketch without being backed
** by actual functionality. Just enough to be able to drive the design of
** other parts ahead. See esp. Trac #100, which contains an idea for a
** refactoring.
**
*/
@ -53,21 +58,28 @@ using boost::scoped_ptr;
namespace asset { class Pipe; }
namespace mobject
{
namespace mobject {
class MObject;
template<class MO> class Placement;
typedef Placement<MObject> PMO;
namespace session
{
///////////////////////////////////////////TODO: all those dependencies are just a plain mess right now.
//
//template<class MO, class B=MObject>
//class Placement ;
//typedef Placement<MObject> PMO;
class PlacementRef; ///TODO: as of 5/09 the idea is to phase out direct dependency on the placement class and recast those dependencies in terms of PlacementRef
namespace session {
class FixedLocation;
class RelativeLocation;
/**
* Positioning specification, possibliy chained
* Positioning specification, possibly chained
* to further specifications. The base class LocatingPin
* is a "no-op" specification which doesn't constrain the
* possible locations and thus can be embedded into pristine
@ -84,7 +96,7 @@ namespace mobject
typedef lumiera::Time Time;
typedef Time* Track; //TODO dummy declaration; we don't use Tracks as first-class entity any longer
typedef std::tr1::shared_ptr<asset::Pipe> Pipe;
typedef std::pair<Time,Pipe> SolutionData; //TODO (ichthyo consideres better passing of solution by subclass)
typedef std::pair<Time,Pipe> SolutionData; //TODO (ichthyo considers better passing of solution by subclass)
struct LocatingSolution;
/** next additional Pin, if any */
@ -104,7 +116,7 @@ namespace mobject
/* Factory functions for adding LocatingPins */
FixedLocation& operator() (Time start, Track track=0);
RelativeLocation& operator() (PMO refObj, Time offset=0);
RelativeLocation& operator() (PlacementRef& refObj, Time offset=0);
LocatingPin (const LocatingPin&);
LocatingPin& operator= (const LocatingPin&);
@ -117,7 +129,7 @@ namespace mobject
//TODO (for working out the buildable interface; ctor should be protected)
protected:
friend class Placement<MObject>;
// friend class Placement<MObject>;
/**
* @internal helper for the (preliminary)
@ -125,7 +137,7 @@ protected:
* @todo we can't sensibly reason about tracks,
* because at the moment (10/07) we lack a track implementation...
* @todo shouldn't we use a range-restriction LocatingPin (subclass)
* to represent the to-be-found solution? (ichthyo: siehe Trac #100)
* to represent the to-be-found solution? (ichthyo: see Trac #100)
*/
struct LocatingSolution
{

View file

@ -28,29 +28,22 @@
namespace mobject
{
namespace session
namespace mobject {
namespace session {
/**
* Meta-MObject doesn't represent real Media Content,
* but rather all sorts of Processing Instructions
* and other metadata, which can be placed and
* attached within the EDL/Session.
*/
class Meta : public AbstractMO
{
/**
* Meta-MObject doesn't represent real Media Content,
* but rather all sorts of Processing Instructions
* and other metadata, which can be placed and
* attached within the EDL/Session.
*/
class Meta : public AbstractMO
{
///////////
};
} // namespace mobject::session
///////////
};
/** Placement<Meta> defined to be subclass of Placement<MObject> */
DEFINE_SPECIALIZED_PLACEMENT (session::Meta, MObject);
} // namespace mobject
}} // namespace mobject::session
#endif

View file

@ -24,6 +24,7 @@
#ifndef MOBJECT_SESSION_RELATIVELOCATION_H
#define MOBJECT_SESSION_RELATIVELOCATION_H
#include "proc/mobject/placement-ref.hpp"
#include "proc/mobject/session/locatingpin.hpp"
@ -35,10 +36,16 @@ namespace mobject
{
/**
* @todo just a design sketch, nothing finished yet.
* possibly to be reworked or phased out completely.
* See Trac #100
*/
class RelativeLocation : public LocatingPin
{
const PMO & anchor_; ////////////TODO: ooooops, this is a nasty design problem!!!
// const PMO & anchor_; ////////////TODO: ooooops, this is a nasty design problem!!!
const PlacementRef anchor_;
public:
@ -51,7 +58,7 @@ namespace mobject
};
protected:
RelativeLocation (const PMO& a, Time ofs) : anchor_(a), offset_(ofs) { }
RelativeLocation (PlacementRef const& a, Time ofs) : anchor_(a), offset_(ofs) { }
friend class LocatingPin;
/** the kind of relation denoted by this Placement */

View file

@ -30,10 +30,9 @@
namespace asset { class Track; }
namespace mobject
{
namespace session
{
namespace mobject {
namespace session {
using lumiera::P;
class Track;
@ -41,26 +40,26 @@ namespace mobject
typedef P<Track> PTrack;
typedef P<TrackAsset> PTrackAsset;
/**
* A Track is grouping device within the EDL.
* The corresponding Placement by which this Track object is refered
* The corresponding Placement by which this Track object is referred
* 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 processing pipe connections,
* define a layer or pan for sound and for for disabling groups
* of clips. Note tracks are grouped in a tree like fashion.
* \par
* This Media Object (often refered to as "track-MO") is allways dealt with
* This Media Object (often referred to as "track-MO") is always dealt with
* locally within one EDL. Client code normally doesn't have to care for creating
* or retrieving track-MO. Rather, it referes to the global track-asset-ID. The same
* or retrieving track-MO. Rather, it refers to the global track-asset-ID. The same
* holds true when placing some other Media Object onto a track: the corresponding
* placement just refers the global trackID, while the builder automatically retrieves
* the matching track-MO for the EDL in question. If some EDL contains several instances
* (track-MO) refering to the same trackID (asset), then this causes all objects placed
* (track-MO) referring to the same trackID (asset), then this causes all objects placed
* onto this track to be included several times in the resulting render nodes network
* (possibliy with varying placement properties)
* (possibly with varying placement properties)
*/
class Track : public Meta
{
@ -70,7 +69,7 @@ namespace mobject
protected:
Track (PTrackAsset&);
friend class MObjectFactory;
public:
/** Child tracks in a tree structure */
vector<Placement<Track> > subTracks; ////TODO: it should really work with Placements! this here is just a decoy!!!!!!!
@ -82,8 +81,8 @@ namespace mobject
} // namespace mobject::session
/** Placement<Track> defined to be subclass of Placement<MObject> */
DEFINE_SPECIALIZED_PLACEMENT (session::Track, session::Meta);
/** Placement<Track> defined to be subclass of Placement<Meta> */
template class Placement<session::Track, session::Meta>;
} // namespace mobject
#endif