diff --git a/src/proc/asset.hpp b/src/proc/asset.hpp
index d9bb4f41b..fb7fab2e5 100644
--- a/src/proc/asset.hpp
+++ b/src/proc/asset.hpp
@@ -26,9 +26,28 @@
** 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.
+ ** 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,
+ ** 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. 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
*/
@@ -70,6 +89,7 @@ namespace asset
* @see Asset
* @see AssetManager#getID generating ID values
* @see asset::Media
+ * @see ID
*/
template
class ID
@@ -85,16 +105,9 @@ namespace asset
class AssetManager;
typedef const ID& IDA;
- class Media;
- template<>
- class ID : public ID
- {
- public:
- ID (size_t id);
- ID (const Media&);
- };
+
/**
* Superinterface describing especially bookeeping properties.
@@ -105,7 +118,7 @@ namespace asset
* asset::Struct representing structural components used in the sesion (e.g. Tracks)
* asset::Meta representing meta objects created while editing (e.g. Automation)
*
- * And of course, there are various concret Asset subclasses, like asset::Clip,
+ * 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
@@ -168,7 +181,7 @@ namespace asset
const Ident ident; ///< Asset identification tuple
virtual const ID& getID() const { return id; }
- private:
+ protected:
const ID id; ///< Asset primary key.
@@ -256,8 +269,8 @@ namespace proc_interface
{
using asset::Asset;
using asset::Category;
-// using asset::ID;
-// using asset::IDA;
+ using asset::ID;
+ using asset::IDA;
using asset::PAsset;
}
diff --git a/src/proc/asset/db.hpp b/src/proc/asset/db.hpp
index 1f97ebff5..ea3c41a67 100644
--- a/src/proc/asset/db.hpp
+++ b/src/proc/asset/db.hpp
@@ -81,11 +81,10 @@ namespace asset
{
IdHashtable table;
- friend class AssetManager;
-
DB () : table() {}
~DB () {}
+ friend class cinelerra::singleton::Static;
};
diff --git a/src/proc/asset/media.cpp b/src/proc/asset/media.cpp
index be6cdc070..180b5b89b 100644
--- a/src/proc/asset/media.cpp
+++ b/src/proc/asset/media.cpp
@@ -57,20 +57,28 @@ namespace asset
return "";
}
}
+
+
+
+ MediaFactory Media::create; ///< storage for the static MediaFactory instance
- MediaFactory Media::create;
/** Factory method for Media Asset instances. Depending on the filename given,
* either a asset::Media object or an "Unknown" placeholder will be provided. If
* the given Category already contains an "Unkown", we just get the
- * corresponding smart-ptr. Otherwise a new asset::Unknown is created. */
+ * corresponding smart-ptr. Otherwise a new asset::Unknown is created.
+ * @return an Media smart ptr linked to the internally registered smart ptr
+ * created as a side effect of calling the concrete Media subclass ctor.
+ */
MediaFactory::PType
MediaFactory::operator() (Asset::Ident& key, const string& file)
{
asset::Media* pM (0);
AssetManager& aMang = AssetManager::instance();
+
TODO ("check and fix Category if necessary");
+
if (isnil (file))
{
if (isnil (key.name)) key.name="nil";
@@ -86,11 +94,13 @@ namespace asset
TODO ("file exists?");
pM = new Media (key,file);
}
+ ASSERT (pM);
ENSURE (key.category.hasKind (VIDEO) || key.category.hasKind(AUDIO));
ENSURE (isnil (key.name));
ENSURE (dynamic_cast(pM) || (isnil (file) && dynamic_cast(pM)));
- return PType (pM, &destroy);
+ return aMang.getAsset (pM->getID()); // note: because we query with an ID,
+ // we get a Media smart ptr.
}
@@ -101,7 +111,14 @@ namespace asset
MediaFactory::operator() (const string& file, Category& cat)
{
Asset::Ident key(extractName(file), cat, "cin3", 1);
- return MediaFactory::operator() (key, file);
+ return operator() (key, file);
+ }
+
+ MediaFactory::PType
+ MediaFactory::operator() (const string& file, asset::Kind kind)
+ {
+ Category cat(kind);
+ return operator() (file, cat);
}
@@ -109,16 +126,22 @@ namespace asset
MediaFactory::operator() (const char* file, Category& cat)
{
if (!file) file = "";
- return operator() (file,cat);
+ return operator() (string(file),cat);
+ }
+
+ MediaFactory::PType
+ MediaFactory::operator() (const char* file, asset::Kind kind)
+ {
+ if (!file) file = "";
+ return operator() (string(file),kind);
}
MediaFactory::PType
MediaFactory::operator() (Asset::Ident& key, const char* file)
{
if (!file) file = "";
- return operator() (key,file);
+ return operator() (key, string(file));
}
-
} // namespace asset
diff --git a/src/proc/asset/media.hpp b/src/proc/asset/media.hpp
index 38d6be307..4e6507a2a 100644
--- a/src/proc/asset/media.hpp
+++ b/src/proc/asset/media.hpp
@@ -21,6 +21,17 @@
*/
+/** @file media.hpp
+ ** Media data is a specific Kind of Asset.
+ ** For the different Kinds of Assets, we use sub-intefaces inheriting
+ ** from the general Asset interface. To be able to get asset::Media instances
+ ** directly from the AssetManager, we define a specialization of the Asset ID.
+ **
+ ** @see asset.hpp for explanation
+ ** @see MediaFactory creating concrete asset::Media instances
+ **
+ */
+
#ifndef ASSET_MEDIA_H
#define ASSET_MEDIA_H
@@ -36,8 +47,16 @@ namespace asset
class MediaFactory;
+ template<>
+ class ID : public ID
+ {
+ public:
+ ID (size_t id);
+ ID (const Media&);
+ };
+
/**
* key abstraction: media-like assets
*/
@@ -46,27 +65,29 @@ namespace asset
string filename_;
public:
- virtual const ID& getID() const { return getID(); }
static MediaFactory create;
- const string& getFilename () { return filename_; }
+ const string& getFilename () const { return filename_; }
+
+ virtual const ID& getID() const ///< @return ID of kind Media
+ {
+ return static_cast& > (Asset::getID());
+ }
protected:
Media (const Asset::Ident& idi, const string& file) : Asset(idi), filename_(file) {}
friend class MediaFactory;
};
-
+
// definition of ID ctors is possible now,
// after providing full definition of class Media
-/*
- ID::ID(size_t id)
- : ID (id) {};
-
- ID::ID(const Media& media)
- : ID (media.getID()) {};
-*/
-
+ inline ID::ID(size_t id) : ID (id) {};
+ inline ID::ID(const Media& media) : ID (media.getID()) {};
+
+
+
+
/**
* Factory specialized for createing Media Asset objects.
*/
@@ -77,9 +98,11 @@ namespace asset
PType operator() (Asset::Ident& key, const string& file="");
PType operator() (const string& file, Category& cat);
+ PType operator() (const string& file, asset::Kind);
- PType operator() (Asset::Ident& key, const char* file); ///< convienience overload using cString
+ PType operator() (Asset::Ident& key, const char* file); ///< convienience overload using C-String
PType operator() (const char* file, Category& cat);
+ PType operator() (const char* file, asset::Kind);
protected:
static void destroy (Media* m) { delete m; }
diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp
index c9ddae933..3a8111fb8 100644
--- a/src/proc/assetmanager.cpp
+++ b/src/proc/assetmanager.cpp
@@ -23,7 +23,6 @@
#include "proc/assetmanager.hpp"
#include "proc/asset/db.hpp"
-#include "common/singleton.hpp"
//#include
@@ -35,14 +34,10 @@ namespace asset
/** get at the system-wide asset manager instance.
* Implemented as singleton.
*/
- AssetManager&
- AssetManager::instance ()
- {
- return *(new AssetManager); //////////////////////////////TODO Singleton::instance();
- }
+ Singleton AssetManager::instance;
AssetManager::AssetManager ()
- : registry (*(new DB)) //(Singleton::instance())
+ : registry (Singleton() ())
{ }
@@ -61,7 +56,7 @@ namespace asset
*/
template
ID
- AssetManager::reg (KIND& obj, const Asset::Ident& idi)
+ AssetManager::reg (KIND* obj, const Asset::Ident& idi)
throw(cinelerra::error::Invalid)
{
UNIMPLEMENTED ("AssetManager::reg");
@@ -110,6 +105,32 @@ namespace asset
{
}
-
-
+
+} // namespace asset
+
+
+
+
+ /************************************************************/
+ /* explicit template instantiations for various Asset Kinds */
+ /************************************************************/
+
+#include "proc/asset/media.hpp"
+#include "proc/asset/proc.hpp"
+#include "proc/asset/struct.hpp"
+#include "proc/asset/meta.hpp"
+
+
+namespace asset
+ {
+
+ template ID AssetManager::reg (Asset* obj, const Asset::Ident& idi);
+
+
+ template shared_ptr AssetManager::getAsset (const ID& id) throw(cinelerra::error::Invalid);
+ template shared_ptr AssetManager::getAsset (const ID& id) throw(cinelerra::error::Invalid);
+ template shared_ptr AssetManager::getAsset (const ID& id) throw(cinelerra::error::Invalid);
+ template shared_ptr AssetManager::getAsset (const ID& id) throw(cinelerra::error::Invalid);
+ template shared_ptr AssetManager::getAsset (const ID& id) throw(cinelerra::error::Invalid);
+
} // namespace asset
diff --git a/src/proc/assetmanager.hpp b/src/proc/assetmanager.hpp
index 2143fcff5..d7effe221 100644
--- a/src/proc/assetmanager.hpp
+++ b/src/proc/assetmanager.hpp
@@ -38,6 +38,7 @@
#include "proc/asset.hpp"
#include "common/error.hpp"
+#include "common/singleton.hpp"
#include
#include
@@ -62,7 +63,7 @@ namespace asset
public:
- static AssetManager& instance();
+ static cinelerra::Singleton instance;
/** provide the unique ID for given Asset::Ident tuple */
static ID getID (const Asset::Ident&);
@@ -90,12 +91,14 @@ namespace asset
* @internal used by the Asset base class ctor to create Asset::id.
*/
template
- static ID reg (KIND& obj, const Asset::Ident& idi)
+ static ID reg (KIND* obj, const Asset::Ident& idi)
throw(cinelerra::error::Invalid);
friend Asset::Asset (const Asset::Ident& idi);
AssetManager ();
+
+ friend class cinelerra::singleton::Static;
};
diff --git a/tests/components/proc/asset/createassettest.cpp b/tests/components/proc/asset/createassettest.cpp
index e31dc2ecc..771c7a568 100644
--- a/tests/components/proc/asset/createassettest.cpp
+++ b/tests/components/proc/asset/createassettest.cpp
@@ -60,13 +60,12 @@ namespace asset
void createMedia()
{
-/* typedef shared_ptr PM;
+ typedef shared_ptr PM;
Category cat(VIDEO,"bin1");
Asset::Ident key("Name-1", cat, "ichthyo", 5);
PM mm1 = asset::Media::create(key,"testfile.mov");
PM mm2 = asset::Media::create(key);
- Category vid(VIDEO);////////////////////////////////////////////////FIXME
- PM mm3 = asset::Media::create("testfile2.mov", vid);
+ PM mm3 = asset::Media::create("testfile2.mov", VIDEO);
// Assets have been registered and can be retrieved by ID
AssetManager& aMang = AssetManager::instance();
@@ -76,11 +75,11 @@ namespace asset
ASSERT (aMang.getAsset (mm1->getID()) != mm2);
-// PAsset aa1 = aMang.getAsset (ID(mm1->getID())); // note we get an Asset ref
-// ASSERT (aa1 == mm1);
+ PAsset aa1 = aMang.getAsset (ID(mm1->getID())); // note we get an Asset ref
+ ASSERT (aa1 == mm1);
PM mX1 = aMang.getAsset (mm1->getID()); // ..and now we get a Media ref
ASSERT (mX1 == mm1);
-// ASSERT (mX1 == aa1);
+ ASSERT (mX1 == aa1);
ASSERT (aMang.known (mm1->getID()));
ASSERT (aMang.known (mm2->getID()));
@@ -89,7 +88,7 @@ namespace asset
ASSERT ( !aMang.known (mm3->getID(), Category(AUDIO))); // not found within AUDIO-Category
try
{ // can't be found if specifying wrong Asset kind....
-// aMang.getAsset (ID(mm1->getID()));
+ aMang.getAsset (ID(mm1->getID()));
NOTREACHED;
}
catch (cinelerra::error::Invalid) { }
@@ -116,6 +115,8 @@ namespace asset
ASSERT (mm1->getFilename() == "testfile.mov");
ASSERT (isnil (mm2->getFilename()));
ASSERT (mm3->getFilename() == "testfile2.mov");
+/*
+////////////////////////////////////////////////////////////////////////////////TODO fuck the compiler!!!
*/
}
};