LUMIERA.clone/src/steam/asset.hpp

338 lines
11 KiB
C++
Raw Normal View History

/*
2008-11-30 03:08:48 +01:00
ASSET.hpp - Superinterface: bookkeeping view of "things" present in the session
2010-12-17 23:28:49 +01:00
Copyright: clarify and simplify the file headers * Lumiera source code always was copyrighted by individual contributors * there is no entity "Lumiera.org" which holds any copyrights * Lumiera source code is provided under the GPL Version 2+ == Explanations == Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above. For this to become legally effective, the ''File COPYING in the root directory is sufficient.'' The licensing header in each file is not strictly necessary, yet considered good practice; attaching a licence notice increases the likeliness that this information is retained in case someone extracts individual code files. However, it is not by the presence of some text, that legally binding licensing terms become effective; rather the fact matters that a given piece of code was provably copyrighted and published under a license. Even reformatting the code, renaming some variables or deleting parts of the code will not alter this legal situation, but rather creates a derivative work, which is likewise covered by the GPL! The most relevant information in the file header is the notice regarding the time of the first individual copyright claim. By virtue of this initial copyright, the first author is entitled to choose the terms of licensing. All further modifications are permitted and covered by the License. The specific wording or format of the copyright header is not legally relevant, as long as the intention to publish under the GPL remains clear. The extended wording was based on a recommendation by the FSF. It can be shortened, because the full terms of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
Copyright (C)
2008, Hermann Vosseler <Ichthyostega@web.de>
2010-12-17 23:28:49 +01:00
Copyright: clarify and simplify the file headers * Lumiera source code always was copyrighted by individual contributors * there is no entity "Lumiera.org" which holds any copyrights * Lumiera source code is provided under the GPL Version 2+ == Explanations == Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above. For this to become legally effective, the ''File COPYING in the root directory is sufficient.'' The licensing header in each file is not strictly necessary, yet considered good practice; attaching a licence notice increases the likeliness that this information is retained in case someone extracts individual code files. However, it is not by the presence of some text, that legally binding licensing terms become effective; rather the fact matters that a given piece of code was provably copyrighted and published under a license. Even reformatting the code, renaming some variables or deleting parts of the code will not alter this legal situation, but rather creates a derivative work, which is likewise covered by the GPL! The most relevant information in the file header is the notice regarding the time of the first individual copyright claim. By virtue of this initial copyright, the first author is entitled to choose the terms of licensing. All further modifications are permitted and covered by the License. The specific wording or format of the copyright header is not legally relevant, as long as the intention to publish under the GPL remains clear. The extended wording was based on a recommendation by the FSF. It can be shortened, because the full terms of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
  **Lumiera** 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. See the file COPYING for further details.
2010-12-17 23:28:49 +01:00
*/
/** @file asset.hpp
** @ingroup asset
** Steam-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 _Kinds of Assets_, like asset::Media,
2008-11-30 03:08:48 +01:00
** asset::Proc, etc. Code utilising the specific properties of e.g. Media assets, will
2025-06-07 23:59:57 +02:00
** 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
2025-06-07 23:59:57 +02:00
** 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 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 STEAM_INTERFACE_ASSET_H
#define STEAM_INTERFACE_ASSET_H
2008-12-27 00:53:35 +01:00
#include "lib/error.hpp"
#include "lib/nocopy.hpp"
#include "include/logging.h"
#include "steam/asset/category.hpp"
2012-12-02 23:03:37 +01:00
#include "lib/hash-value.h"
#include "lib/p.hpp"
#include <type_traits>
#include <compare>
#include <string>
#include <vector>
#include <set>
using std::string;
using std::vector;
using std::set;
namespace steam {
2008-11-30 03:08:48 +01:00
namespace asset {
namespace error = lumiera::error;
using std::size_t;
using std::shared_ptr;
using std::static_pointer_cast;
2012-12-02 23:03:37 +01:00
using lib::HashVal;
/**
2025-06-07 23:59:57 +02:00
* thin wrapper around a size_t hash ID
* used as primary key for all Asset objects.
2008-11-30 03:08:48 +01:00
* The Template parameter is intended for tagging
* the ID with type information, causing the
2025-06-07 23:59:57 +02:00
* compiler to select specialised behaviour
* for the different kinds of Assets.
* @see Asset
* @see AssetManager#getID generating ID values
* @see asset::Media
* @see ID<asset::Media>
*
2025-06-07 23:59:57 +02:00
* @todo it would be desirable to use EntryID instead ///////////////////////////////////////////TICKET #739 : make identification schemes compatible
*/
template<class KIND>
class ID
{
HashVal hash_;
public:
ID (HashVal id) : hash_(id) {}
ID (const KIND& asset) : hash_(asset.getID()) {}
operator HashVal() const { return hash_; }
static ID INVALID;
};
class DB;
class Asset;
class AssetManager;
typedef const ID<Asset>& IDA;
typedef lib::P<Asset> PAsset;
typedef lib::P<const Asset> PcAsset;
/**
2008-11-30 03:08:48 +01:00
* Superinterface describing especially bookkeeping properties.
* As of 09/2007, there are four <b>Kinds</b> of Assets, each
* comprising a sub-Interface of the Asset Interface:
2010-03-21 23:45:56 +01:00
* - asset::Media representing mediafiles
* - asset::Proc representing media data processing components (e.g. Effects)
* - asset::Struct representing structural components used in the session (e.g. Tracks)
* - asset::Meta representing metadata, parametrisation, customisation.
2010-03-21 23:45:56 +01:00
*
2008-11-30 03:08:48 +01:00
* And of course there are various concrete Asset subclasses, like asset::Clip,
* asset::Effect, asset::Codec, 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
2025-06-07 23:59:57 +02:00
* automatically. It is possible to copy the PAsset (smart pointer) though.
*
* @since 09/2007
* @author Ichthyo
*/
class Asset
: util::NonCopyable
{
public:
2025-06-07 23:59:57 +02:00
/**
* a POD comprised of all the information
2025-06-07 23:59:57 +02:00
* sufficiently identifying any given Asset.
*/
struct Ident
{
2008-11-30 03:08:48 +01:00
/** element ID, comprehensible but sanitised.
* The tuple (category, name, org) is unique.
*/
string name;
2025-06-07 23:59:57 +02:00
/** primary tree like classification of the asset.
* Includes the distinction of different kinds of Assets,
* like Media, Audio, Video, Effects... */
asset::Category category;
2025-06-07 23:59:57 +02:00
/** origin or authorship id.
* Can be a project abbreviation, a package id or just the authors nickname or UID.
2025-06-07 23:59:57 +02:00
* This allows for the component name to be more generic (e.g. "blur").
2008-03-10 06:09:44 +01:00
* Default for all assets provided by the core Lumiera codebase is "lumi".
*/
const string org;
2025-06-07 23:59:57 +02:00
/** version number of the thing or concept represented by this asset.
2025-06-07 23:59:57 +02:00
* 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;
2025-06-07 23:59:57 +02:00
Ident (string const& n
,Category const& cat
,string const& o = "lumi"
,const uint ver=1);
/** ordering of Assets is based on the ordering of Ident tuples,
* descending from Category to origin and finally to the asset element ID.
* @note version info is ignored for this comparison */
auto operator<=>(Ident const& oi) const { return std::tie ( category, org, name)
<=> std::tie (oi.category,oi.org,oi.name); }
bool operator== (Ident const& oi) const { return 0 == *this <=> oi; }
2025-06-07 23:59:57 +02:00
operator string () const;
bool isValid() const;
};
2025-06-07 23:59:57 +02:00
/* ===== Asset ID and Datafields ===== */
2025-06-07 23:59:57 +02:00
public:
const Ident ident; ///< Asset identification tuple
virtual const ID<Asset>& getID() const { return id; }
bool operator== (Asset const& oa) const { return ident == oa.ident; }
auto operator<=>(Asset const& oa) const { return ident <=> oa.ident; }
2025-06-07 23:59:57 +02:00
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 localised. */
const string shortDesc;
/** user visible qualification of the thing, unit or concept represented by this asset.
* preferably "in one line". To be localised. */
const string longDesc;
vector<PAsset> parents;
vector<PAsset> dependants;
bool enabled;
protected:
2025-06-07 23:59:57 +02:00
/** Asset is a Interface class; usually, objects of
* concrete subclasses are created via specialised 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 unlink() breaks interconnections
* to other Assets in the central Object network comprising the session.
* Especially, the \em downward links to dependent entities are released,
* while the primary (upward) smart-ptr links to our prerequisites are
* still retained. The rationale is, after releasing these redundant
* or cyclic interlinking, when the AssetManager removes its DB entry
* for this asset, the smart pointer goes out of scope and causes
* unwinding of the whole dependency chain.
*/
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 dependent on the parent. */
void defineDependency (PAsset parent);
2025-06-07 23:59:57 +02:00
void defineDependency (Asset& parent);
friend class AssetManager;
friend class DB;
private:
void unregister (PAsset& other);
2025-06-07 23:59:57 +02:00
public:
2025-06-07 23:59:57 +02:00
/** 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; }
2025-06-07 23:59:57 +02:00
/** 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; }
2025-06-07 23:59:57 +02:00
/** weather this asset is switched on and consequently
* included in the fixture and participates in rendering
*/
bool isActive () const;
/** change the enabled status of this asset.
2025-06-07 23:59:57 +02:00
* 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);
};
/** promote subtype-ptr to PAsset, e.g. for comparing */
template<class A>
inline const PcAsset
pAsset (shared_ptr<A> const& subPtr)
{
return static_pointer_cast<const Asset,A> (subPtr);
}
/** type trait for detecting a shared-ptr-to-asset */
template <class X>
struct is_pAsset : std::false_type { };
template <class A>
2016-12-23 04:23:03 +01:00
struct is_pAsset<shared_ptr<A>>
: std::is_base_of<Asset, A> { };
/** marker constant denoting a NIL asset */
template<class KIND>
ID<KIND> ID<KIND>::INVALID = ID{0};
}} // namespace steam::asset
2010-03-21 23:45:56 +01:00
namespace proc_interface {
using steam::asset::Asset;
using steam::asset::Category;
using steam::asset::ID;
using steam::asset::IDA;
using steam::asset::PAsset;
}
#endif