From 814f6fc734b36c328f55391ba1717c19a80f8383 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 12 Sep 2007 06:53:12 +0200 Subject: [PATCH] CreateAsset_test now passes the compiler, after quite some tinkering.... --- src/proc/asset.hpp | 39 ++++++++++----- src/proc/asset/db.hpp | 3 +- src/proc/asset/media.cpp | 37 ++++++++++++--- src/proc/asset/media.hpp | 47 ++++++++++++++----- src/proc/assetmanager.cpp | 41 ++++++++++++---- src/proc/assetmanager.hpp | 7 ++- .../components/proc/asset/createassettest.cpp | 15 +++--- 7 files changed, 136 insertions(+), 53 deletions(-) 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!!! */ } };