/* AssetManager - Facade for the Asset subsystem Copyright (C) CinelerraCV 2007, Christian Thaeter 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. * *****************************************************/ #include "proc/assetmanager.hpp" #include "proc/asset/db.hpp" #include "common/multithread.hpp" #include "common/util.hpp" //#include #include #include #include using boost::format; using boost::bind; //using boost::lambda::_1; using util::for_each; using cinelerra::Singleton; using cinelerra::Thread; namespace asset { /** * AssetManager error responses, cause by querying * invalid Asset IDs from the internal DB. */ class IDErr : public cinelerra::error::Invalid { public: IDErr (const char* eID, format fmt) : cinelerra::error::Invalid(fmt.str(),eID) {} }; // ------pre-defined-common-error-cases--------------- // CINELERRA_ERROR_DEFINE (UNKNOWN_ASSET_ID, "non-registered Asset ID"); CINELERRA_ERROR_DEFINE (WRONG_ASSET_KIND, "wrong Asset kind, unable to cast"); class UnknownID : public IDErr { public: UnknownID (ID aID) : IDErr (CINELERRA_ERROR_UNKNOWN_ASSET_ID, format("Query for Asset with ID=%d, which up to now " "hasn't been created or encountered.") % aID) {} }; class WrongKind : public IDErr { public: WrongKind (Asset::Ident idi) : IDErr (CINELERRA_ERROR_WRONG_ASSET_KIND, format("Request for Asset(%s), specifying an Asset kind, " "that doesn't match the actual type (and can't be " "casted either).") % string(idi)) {} }; /** get at the system-wide asset manager instance. * Implemented as singleton. */ Singleton AssetManager::instance; AssetManager::AssetManager () : registry (Singleton() ()) { } /** provide the unique ID for given Asset::Ident tuple */ ID AssetManager::getID (const Asset::Ident& idi) { return asset::hash_value (idi); } /** * registers an asset object in the internal DB, providing its unique key. * This includes creating the smart ptr in charge of the asset's lifecycle */ template ID AssetManager::reg (KIND* obj, const Asset::Ident& idi) throw(cinelerra::error::Invalid) { typedef shared_ptr PType; AssetManager& _aMang (AssetManager::instance()); TODO ("check validity of Ident Category"); ID asset_id (getID (idi)); Thread::Lock guard SIDEEFFECT; TODO ("handle duplicate Registrations"); PType smart_ptr (obj, &destroy); _aMang.registry.put (asset_id, smart_ptr); return asset_id; } /** * find and return the object registered with the given ID. * @throws Invalid if nothing is found or if the actual KIND * of the stored object differs and can't be casted. */ template shared_ptr AssetManager::getAsset (const ID& id) throw(cinelerra::error::Invalid) { if (shared_ptr obj = registry.get (id)) return obj; else if (known (id)) // provide Ident tuple of existing Asset throw WrongKind (registry.get(ID(id))->ident); else throw UnknownID (id); } /** * @return true if the given id is registered in the internal asset DB */ bool AssetManager::known (IDA id) { return ( registry.get (ID(id)) ); } // query most general Asset ID-kind and use implicit // conversion from shared_ptr to bool (test if empty) /** * @return true if the given id is registered with the given Category */ bool AssetManager::known (IDA id, const Category& cat) { PAsset pA = registry.get (id); return ( pA && pA->ident.category.isWithin(cat)); } void AssetManager::detach_child (PAsset& pA, IDA id) { pA->unlink(id); } /** * remove the given asset together with all its dependants from the internal DB */ void AssetManager::remove (IDA id) throw(cinelerra::error::Invalid, cinelerra::error::State) { UNIMPLEMENTED ("remove Asset with all dependecies"); PAsset pA = getAsset (id); vector par = pA->getParents(); boost::function func = bind(&detach_child, _1,id ); for_each (par, func); // ,boost::lambda::var(id))); } list AssetManager::listContent() const { list res; registry.asList (res); res.sort(); return res; } } // 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