lumiera_/src/proc/mobject/placement.hpp

168 lines
6 KiB
C++

/*
PLACEMENT.hpp - Key Abstraction: a way to place and locate a Media Object
Copyright (C) CinelerraCV
2007, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file placement.hpp
** 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.
**
** 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),
** while by dereferencing the Placement object, we access the "real" media object.
** Usually, any MObject is created by a factory and immediately wrapped into a Placement,
** which takes ownership of the MObject.
**
** Besides being a handle, Placements define the logical position where some MObject is
** supposed to be located within the EDL or Fixture. The way in which this placing happens
** is controlled and parametrized by a collection (chain) of LocatingPin objects. By adding
** to this chain, the position of the MObject is increasingly constrained. The simplest
** case of such constraining is to add a FixedLocation, thus placing the MObject at one
** absolute position (time, track).
**
** 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
** labeling and downcasting is the <i>only</i> difference between these subclasses,
** besides that, they can be replaced literally by one another (slicing is accepted).
**
** @see ExplicitPlacement
** @see LocatingPin interface for controlling the positioning parameters
**
*/
#ifndef MOBJECT_PLACEMENT_H
#define MOBJECT_PLACEMENT_H
#include "pre.hpp"
#include "proc/mobject/mobject.hpp"
#include "proc/mobject/session/locatingpin.hpp"
#include "proc/asset/port.hpp"
#include <tr1/memory>
using std::tr1::shared_ptr;
namespace mobject
{
namespace session{ class MObjectFactory; }
class ExplicitPlacement;
/**
* 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
*/
template<class MO>
class Placement : protected shared_ptr<MO>
{
protected:
typedef cinelerra::Time Time;
typedef asset::shared_ptr<asset::Port> Port;
public:
/** smart pointer: accessing the MObject,
* which is subject to placement.
* @note we don't provide operator*
*/
virtual MO *
operator-> () const
{
ENSURE (*this);
return shared_ptr<MO>::operator-> ();
}
virtual ~Placement() {};
/** */ /////////////////////////////////////////////////////////////TODO: totmachen?
// DEFINE_PROCESSABLE_BY (builder::BuilderTool);
/** interface for defining the kind of placement
* to employ, and for controling any additional
* constraints and properties.
*/
session::LocatingPin chain;
/** combine and resolve all constraints defined
* by the various LocatingPin (\see #chain) and
* provide the resulting (explicit) placement.
*/
virtual ExplicitPlacement resolve () const;
protected:
Placement (MO & subject, void (*moKiller)(MO*))
: shared_ptr<MO> (&subject, moKiller) {};
friend class session::MObjectFactory;
};
typedef Placement<MObject> PMO;
/* === defining specialisations to be subclasses === */
#define DEFINE_SPECIALIZED_PLACEMENT(SUBCLASS) \
template<> \
class Placement<SUBCLASS> : public Placement<MObject> \
{ \
protected: \
Placement (SUBCLASS & m, void (*moKiller)(MObject*)) \
: Placement<MObject>::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-> ()); \
} \
};
// DEFINE_PROCESSABLE_BY (builder::BuilderTool);
/* 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.
*/
} // namespace mobject
#endif