From efa7b4717cf53d9f1be22c05a15a340a198ca181 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 29 May 2009 07:10:54 +0200 Subject: [PATCH] rework placement to contain a LUID, and to deal with inheritance according to the concept draft --- src/lib/hash-indexed.hpp | 4 +- src/proc/mobject/builder/buildertool.hpp | 7 +- src/proc/mobject/placement.cpp | 45 +++--- src/proc/mobject/placement.hpp | 134 ++++++++++++------ src/proc/mobject/session/clip.hpp | 21 +-- src/proc/mobject/session/effect.hpp | 35 ++--- src/proc/mobject/session/locatingpin.cpp | 2 +- src/proc/mobject/session/locatingpin.hpp | 34 +++-- src/proc/mobject/session/meta.hpp | 39 +++-- src/proc/mobject/session/relativelocation.hpp | 13 +- src/proc/mobject/session/track.hpp | 29 ++-- 11 files changed, 212 insertions(+), 151 deletions(-) diff --git a/src/lib/hash-indexed.hpp b/src/lib/hash-indexed.hpp index ab759ff90..6645a9850 100644 --- a/src/lib/hash-indexed.hpp +++ b/src/lib/hash-indexed.hpp @@ -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" diff --git a/src/proc/mobject/builder/buildertool.hpp b/src/proc/mobject/builder/buildertool.hpp index fefa22172..1ad28d0d8 100644 --- a/src/proc/mobject/builder/buildertool.hpp +++ b/src/proc/mobject/builder/buildertool.hpp @@ -116,6 +116,11 @@ namespace mobject { { currentWrapper_ = ptr_toWrappedTarget; } + template + void rememberWrapper (Placement* 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 diff --git a/src/proc/mobject/placement.cpp b/src/proc/mobject/placement.cpp index 58e145e72..e148694a9 100644 --- a/src/proc/mobject/placement.cpp +++ b/src/proc/mobject/placement.cpp @@ -26,34 +26,45 @@ #include "proc/mobject/mobject.hpp" #include + +using boost::format; using boost::str; -namespace mobject - { +namespace mobject { - template - ExplicitPlacement - Placement::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, * so they will inherit this function. */ - template ExplicitPlacement Placement::resolve() const; - - + ExplicitPlacement + Placement::resolve () const + { + return ExplicitPlacement (*this, chain.resolve()); + } + + - template<> Placement::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 const& pla) + { + static format fmt ("pID(%x)"); + + size_t hashVal = pla.getID(); + return str(fmt % hashVal); + } diff --git a/src/proc/mobject/placement.hpp b/src/proc/mobject/placement.hpp index 6ac85a866..49c7005aa 100644 --- a/src/proc/mobject/placement.hpp +++ b/src/proc/mobject/placement.hpp @@ -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 refcounting smart pointers: 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 to be able to use the more specific methods of the ** session::Clip interface. But please note the following detail: 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 @@ -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 is required. + * + * @param MO the (compile time) type of the referent + * @param B immediate base class of this placement */ - template - class Placement : protected shared_ptr + template + class Placement ; + + + /** + * this specialisation forms the root of all placements + * and defines all of Placement's actual functionality. + */ + template<> + class Placement + : protected shared_ptr, + public HashIndexed, lib::hash::LuidH> //////TODO: really need to be inherited publicly? { protected: - typedef shared_ptr Base; + typedef shared_ptr _SmartPtr; + typedef void (*Deleter)(MObject*); typedef lumiera::Time Time; - typedef asset::shared_ptr Pipe; + typedef asset::shared_ptr 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 (&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 : public Placement \ - { \ - protected: \ - Placement (SUBCLASS & m, void (*moKiller)(MObject*)) \ - : Placement::Placement (m, moKiller) \ - { }; \ - friend class session::MObjectFactory; \ - \ - public: \ - virtual SUBCLASS* \ - operator-> () const \ - { \ - ENSURE (INSTANCEOF (SUBCLASS, this->get())); \ - return static_cast \ - (shared_ptr::operator-> ()); \ - } \ + /** + * any specific placements are supposed to be derived + * from Placement, 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 Placement + : public Placement + { + protected: + typedef Placement _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 + (_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! - * Placements are frequently treated like values and thus slicing - * will happen, which in this special case is acceptable. - */ + string + format_PlacementID (Placement const&) ; + + + /** @todo cleanup uses of ref-to-placement. See Trac #115 */ + typedef Placement PMO; } // namespace mobject diff --git a/src/proc/mobject/session/clip.hpp b/src/proc/mobject/session/clip.hpp index 362b6fe11..f0652c2e6 100644 --- a/src/proc/mobject/session/clip.hpp +++ b/src/proc/mobject/session/clip.hpp @@ -33,10 +33,9 @@ namespace asset class Clip; } -namespace mobject - { - namespace session - { +namespace mobject { +namespace session { + using asset::Media; typedef P PMedia; typedef P 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 PClipMO; - - - - } // namespace mobject::session - - /** Placement defined to be subclass of Placement */ - DEFINE_SPECIALIZED_PLACEMENT (session::Clip, MObject); - -} // namespace mobject + + +}} // namespace mobject::session #endif diff --git a/src/proc/mobject/session/effect.hpp b/src/proc/mobject/session/effect.hpp index e4cdbee16..587cec927 100644 --- a/src/proc/mobject/session/effect.hpp +++ b/src/proc/mobject/session/effect.hpp @@ -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 defined to be subclass of Placement */ - DEFINE_SPECIALIZED_PLACEMENT (session::Effect, MObject); - -} // namespace mobject + protected: + /** Identifier of the Plugin to be used */ + string plugID; + + }; + + + +}} // namespace mobject::session #endif diff --git a/src/proc/mobject/session/locatingpin.cpp b/src/proc/mobject/session/locatingpin.cpp index 17bb34bbe..d1f4ba6dd 100644 --- a/src/proc/mobject/session/locatingpin.cpp +++ b/src/proc/mobject/session/locatingpin.cpp @@ -188,7 +188,7 @@ namespace mobject RelativeLocation& - LocatingPin::operator() (PMO refObj, Time offset) + LocatingPin::operator() (PlacementRef& refObj, Time offset) { return static_cast (addChain (new RelativeLocation (refObj, offset))); diff --git a/src/proc/mobject/session/locatingpin.hpp b/src/proc/mobject/session/locatingpin.hpp index 799255589..c9e478f10 100644 --- a/src/proc/mobject/session/locatingpin.hpp +++ b/src/proc/mobject/session/locatingpin.hpp @@ -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 Placement; - typedef Placement PMO; - namespace session - { +///////////////////////////////////////////TODO: all those dependencies are just a plain mess right now. +// +//template +//class Placement ; +//typedef Placement 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 Pipe; - typedef std::pair SolutionData; //TODO (ichthyo consideres better passing of solution by subclass) + typedef std::pair 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; +// friend class Placement; /** * @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 { diff --git a/src/proc/mobject/session/meta.hpp b/src/proc/mobject/session/meta.hpp index db679a904..f1a69b98d 100644 --- a/src/proc/mobject/session/meta.hpp +++ b/src/proc/mobject/session/meta.hpp @@ -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 defined to be subclass of Placement */ - DEFINE_SPECIALIZED_PLACEMENT (session::Meta, MObject); - -} // namespace mobject + + +}} // namespace mobject::session #endif diff --git a/src/proc/mobject/session/relativelocation.hpp b/src/proc/mobject/session/relativelocation.hpp index 33b857053..d5967b606 100644 --- a/src/proc/mobject/session/relativelocation.hpp +++ b/src/proc/mobject/session/relativelocation.hpp @@ -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 */ diff --git a/src/proc/mobject/session/track.hpp b/src/proc/mobject/session/track.hpp index f8b2c0017..d58284dc6 100644 --- a/src/proc/mobject/session/track.hpp +++ b/src/proc/mobject/session/track.hpp @@ -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 PTrack; typedef P 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 > subTracks; ////TODO: it should really work with Placements! this here is just a decoy!!!!!!! @@ -82,8 +81,8 @@ namespace mobject } // namespace mobject::session - /** Placement defined to be subclass of Placement */ - DEFINE_SPECIALIZED_PLACEMENT (session::Track, session::Meta); - + /** Placement defined to be subclass of Placement */ + template class Placement; + } // namespace mobject #endif