lumiera_/src/proc/asset.hpp

347 lines
12 KiB
C++

/*
ASSET.hpp - Superinterface: bookeeping view of "things" present in the session
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 asset.hpp
** Proc-Layer Interface: Assets.
** Declares the Asset top level Interface, the Asset::Ident identification tuple
** and the asset::ID primary key wrapper. Normally, Assets should be handled
** using asset::PAsset, a ref counting smart pointer.
**
** These classes are placed into namespace asset and proc_interface.
**
** Assets are handled by a hierarchy of interfaces. Below the top level Asset interface
** there are interfaces for various different <i>Kinds</i> of Assets, like asset::Media,
** asset::Proc, etc. Code utilizing the specific properties of e.g. Media assets, will
** be implemented directly against the asset::Media interface. To make this feasible
** while at the same time being able to handle all asset Kinds in a uniform manner,
** we use a hierarchy of ID classes. These IDs are actually just thin wrappers around
** a hash value, but they carry a template parameter specifying the Asset Kind and the
** Asset Kind subinterfaces provide a overloaded getID method with a covariant return
** value. For example the asset::Media#getID returns an ID<Media>. By using the
** templated query function AssetManager#getAsset, we can get at references to the more
** specific subinterface asset::media just by using the ID value in a typesafe manner.
** This helps avoiding dynamic typing and switch-on-type, leading to much more robust,
** extensible and clear code.
**
** (Implementation detail: as g++ is not able to handle member function template
** instantiations completely automatic, we need to trigger some template instantiations
** at the end of assetmanager.cpp )
**
** @see assetmanager.hpp
** @see media.hpp
*/
#ifndef PROC_INTERFACE_ASSET_H
#define PROC_INTERFACE_ASSET_H
#include "pre.hpp"
#include "proc/asset/category.hpp"
#include "common/error.hpp"
#include <cstddef>
#include <string>
#include <vector>
#include <set>
#include <tr1/memory>
#include <boost/utility.hpp>
using std::string;
using std::vector;
using std::set;
namespace asset
{
using std::size_t;
using std::tr1::shared_ptr;
using std::tr1::static_pointer_cast;
/**
* thin wrapper around a size_t hash ID
* used as primary key for all Asset objects.
* The Templace parameter is intended for tagging
* the ID with type information, causing the
* compiler to select specialized behaviour
* for the different kinds of Assets.
* @see Asset
* @see AssetManager#getID generating ID values
* @see asset::Media
* @see ID<asset::Media>
*/
template<class KIND>
class ID
{
public:
const size_t hash;
ID (size_t id) : hash(id) {}
ID (const KIND& asset) : hash(asset.getID()) {}
operator size_t() const { return hash; }
};
class DB;
class Asset;
class AssetManager;
typedef const ID<Asset>& IDA;
typedef shared_ptr<Asset> PAsset;
typedef shared_ptr<const Asset> PcAsset;
/**
* Superinterface describing especially bookeeping properties.
* As of 09/2007, there are four <b>Kinds</b> of Assets, each
* comprising a sub-Interface of the Asset Interface:
* <ul><li>asset::Media representing mediafiles</li>
* <li>asset::Proc representing media data processing components (e.g. Effects)</li>
* <li>asset::Struct representing structural components used in the sesion (e.g. Tracks)</li>
* <li>asset::Meta representing meta objects created while editing (e.g. Automation)</li>
* </ul>
* And of course there are various concret Asset subclasses, like asset::Clip,
* asset::Effect, asset::Codec, asset::Track, asset::Dataset.
* @note Assets objects have a strict unique identity and because of this are non-copyable.
* You can not create an Asset derived object without registering it with the AssetManager
* automatically. I is possible to copy the PAsset (smart pointer) though.
*
* @since 09/2007
* @author Ichthyo
*/
class Asset : private boost::noncopyable
{
public:
/**
* a POD comprised of all the information
* sufficiently identifying any given Asset.
*/
struct Ident
{
/** element ID, comprehensible but sanitized.
* The tuple (category, name, org) is unique.
*/
string name;
/** primary tree like classification of the asset.
* Includes the distinction of different kinds of Assets,
* like Media, Audio, Video, Effects... */
asset::Category category;
/** origin or authorship id.
* Can be a project abbreviation, a package id or just the authors nickname or UID.
* This allows for the compnent name to be more generic (e.g. "blur").
* Default for all assets provided by the core cinelerra-3 codebase is "cin3".
*/
const string org;
/** version number of the thing or concept represented by this asset.
* Of each unique tuple (name, category, org) there will be only one version
* in the whole system. Version 0 is reserved for internal purposes.
* Versions are considered to be ordered, and any higher version is
* supposed to be fully backwards compatible to all previous versions.
*/
const uint version;
Ident (const string& n,
const Category& cat,
const string& o = "cin3",
const uint ver=1);
/** @note equality ignores version differences */
bool operator== (const Ident& other) const
{
return org == other.org
&& name == other.name
&& category == other.category;
}
bool operator!= (const Ident& other) const
{
return !operator==(other);
}
int compare (const Ident& other) const;
operator string () const;
};
/* ===== Asset ID and Datafields ===== */
public:
const Ident ident; ///< Asset identification tuple
virtual const ID<Asset>& getID() const { return id; }
virtual operator string () const;
protected:
const ID<Asset> id; ///< Asset primary key.
/** additional classification, selections or departments this asset belongs to.
* Groups are optional, non-exclusive and may be overlapping.
*/
set<string> groups;
/** user visible Name-ID. To be localized. */
const string shortDesc;
/** user visible qualification of the thing, unit or concept represented by this asset.
* perferably "in one line". To be localized. */
const string longDesc;
vector<PAsset> parents;
vector<PAsset> dependants;
bool enabled;
protected:
/** Asset is a Interface class; usually, objects of
* concrete subclasses are created via specialized Factories.
* Calling this base ctor causes registration with AssetManager.
*/
Asset (const Ident& idi);
virtual ~Asset() = 0; ///< @note Asset is abstract
/** release all links to other Asset objects held internally.
* The lifecycle of Asset objects is managed by smart pointers
* and the Asset manager. Calling \c release() breaks interconnectons
* to other Assets in the central Object network comprising the session.
* It is up to the AssetManager to asure the notification of any other
* components that may need to release references to the Asset object
* beeing removed. The rationale is, after releasing all interlinkings,
* when the AssetManager removes its DB entry for this asset, the
* smart pointer goes out of scope and triggers cleanup.
*/
virtual void unlink ();
/** variant of #unlink() dropping only the links to the given specific
* Asset, leaving all other links intact. Usable for propagating */
virtual void unlink (IDA target);
/** establish a connection between this and the given parent asset,
* denoting we are in some way dependant on the parent. */
void defineDependency (PAsset parent);
void defineDependency (Asset& parent);
friend class AssetManager;
friend class DB;
private:
void unregister (PAsset& other);
public:
/** List of entities this asset depends on or requires to be functional.
* May be empty. The head of this list can be considered the primary prerequisite
*/
const vector<PAsset>& getParents () const { return parents; }
/** All the other assets requiring this asset to be functional.
* For example, all the clips depending on a given media file.
* May be empty. The dependency relation is transitive.
*/
const vector<PAsset>& getDependant () const { return dependants; }
/** weather this asset is swithced on and consequently
* included in the fixture and participates in rendering
*/
bool isActive () const;
/** change the enabled status of this asset.
* Note the corresponding #isActive predicate may
* depend on the enablement status of parent assets as well
* @return \c false if the state could not be changed
* due to parent objects being disabled
*/
bool enable (bool on=true) throw(cinelerra::error::State);
};
/** ordering of Asset smart ptrs based on Ident tuple.
* @todo currently supporting only smart_ptr<Asset>. */
inline bool operator== (const PcAsset& a1, const PcAsset& a2) { return a1 && a2 && ( 0==a1->ident.compare(a2->ident));}
inline bool operator< (const PcAsset& a1, const PcAsset& a2) { return a1 && a2 && (-1==a1->ident.compare(a2->ident));}
inline bool operator> (const PcAsset& a1, const PcAsset& a2) { return a2 < a1; }
inline bool operator>= (const PcAsset& a1, const PcAsset& a2) { return !(a1 < a2); }
inline bool operator<= (const PcAsset& a1, const PcAsset& a2) { return !(a1 > a2); }
inline bool operator!= (const PcAsset& a1, const PcAsset& a2) { return !(a1== a2); }
/** ordering of Asset Ident tuples.
* @note version is irrelevant */
inline int
Asset::Ident::compare (const Asset::Ident& oi) const
{
int res;
if (0 != (res=category.compare (oi.category))) return res;
if (0 != (res=org.compare (oi.org))) return res;
return name.compare (oi.name);
}
/** promote to PAsset, e.g. for comparing */
template<class A>
inline PcAsset
pAsset (shared_ptr<A>& subPtr)
{
return static_pointer_cast<const Asset,A> (subPtr);
}
/** convienient for debugging */
inline string str (const PcAsset& a)
{
if (a)
return string (*a.get());
else
return "Asset(NULL)";
}
} // namespace asset
namespace proc_interface
{
using asset::Asset;
using asset::Category;
using asset::ID;
using asset::IDA;
using asset::PAsset;
}
#endif