WIP: fleshed out a good deal of the AssetManager foundation.

compiles ok, singleton test pass (most of asset creation just commented out...)
This commit is contained in:
Fischlurch 2007-09-10 06:45:36 +02:00
parent 79c88c2c87
commit 26374ce409
18 changed files with 420 additions and 199 deletions

View file

@ -33,6 +33,13 @@ using boost::algorithm::split;
using boost::algorithm::join;
using boost::algorithm::is_any_of;
using boost::algorithm::token_compress_on;
using boost::regex;
using boost::smatch;
using boost::regex_search;
using boost::regex;
using boost::smatch;
using boost::regex_search;
@ -59,12 +66,12 @@ namespace util
*/
Cmdline::Cmdline (const string cmdline)
{
boost::regex tokendef("[^ \r\n\t]+");
boost::smatch match;
regex tokendef("[^ \r\n\t]+");
smatch match;
string::const_iterator it = cmdline.begin();
string::const_iterator end = cmdline.end();
while (boost::regex_search(it, end, match, tokendef))
while (regex_search(it, end, match, tokendef))
{
string ss(match[0]);
this->push_back(ss);

View file

@ -1,102 +0,0 @@
/*
Singleton - template for implementing the singleton pattern
Copyright (C) CinelerraCV
2007, Christian Thaeter <ct@pipapo.org>
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.
====================================================================
This code is heavily inspired by
The Loki Library (loki-lib/trunk/include/loki/Singleton.h)
Copyright (c) 2001 by Andrei Alexandrescu
This Loki code accompanies the book:
Alexandrescu, Andrei. "Modern C++ Design:
Generic Programming and Design Patterns Applied".
Copyright (c) 2001. Addison-Wesley. ISBN 0201704315
* *****************************************************/
#include "common/singleton.hpp"
#include "common/util.hpp"
#include "nobugcfg.h"
namespace cinelerra
{
/** Interface to be used by Singleton's clients.
* Manages internally the instance creation, lifecycle
* and access handling in a multithreaded context.
* @return "the" single instance of class S
*/
template
< class SI, // the class to make Singleton
template <class> class Create, // how to create/destroy the instance
template <class> class Life, // how to manage Singleton Lifecycle
template <class> class Threading
>
SI&
Singleton<SI,Create,Life,Threading>::instance()
{
if (!pInstance_)
{
ThreadLock guard;
if (!pInstance_)
{
if (isDead_)
{
Life<SI>::onDeadReference();
isDead_ = false;
}
pInstance_ = Create<SI>::create();
Life<SI>::scheduleDelete (&destroy);
} }
ENSURE (pInstance_);
ENSURE (!isDead_);
return *pInstance_;
}
/** @internal helper used to delegate destroying the single instance
* to the Create policy, at the same time allowing the Life policy
* to control the point in the Application lifecycle when the
* destruction of this instance occures.
*/
template
< class SI,
template <class> class Create,
template <class> class Life,
template <class> class Threading
>
void
Singleton<SI,Create,Life,Threading>::destroy()
{
REQUIRE (!isDead_);
Create<SI>::destroy (pInstance_);
pInstance_ = 0;
isDead_ = true;
}
namespace singleton
{
} // namespace singleton
} // namespace cinelerra

View file

@ -37,40 +37,120 @@ This code is heavily inspired by
#include "common/singletonpolicies.hpp" ///< several Policies usable together with singleton
#include "common/util.hpp"
#include "nobugcfg.h"
#include <boost/bind.hpp>
namespace cinelerra
{
/**
* A configurable Template for implementing Singletons
* A configurable Template for implementing Singletons.
* Actually this is a Functor object, which could be placed into a static field
* of the Singleton (target) class or used directly.
* @note internally uses static fields, so all functor instances share pInstance_
*/
template
< class S, // the class to make Singleton
< class SI, // the class to make Singleton
template <class> class Create = singleton::Static, // how to create/destroy the instance
template <class> class Life = singleton::Automatic, // how to manage Singleton Lifecycle
template <class> class Threading = singleton::IgnoreThreadsafety //TODO use Multithreaded!!!
>
class Singleton
{
public:
static S& instance();
private:
typedef typename Threading<S>::VolatileType SType;
typedef typename Threading<S>::Lock ThreadLock;
typedef typename Threading<SI>::VolatileType SType;
typedef typename Threading<SI>::Lock ThreadLock;
static SType* pInstance_;
static bool isDead_;
protected:
Singleton () { }
Singleton (const Singleton&) { }
Singleton& operator= (const Singleton&) { return *this; }
public:
/** Interface to be used by Singleton's clients.
* Manages internally the instance creation, lifecycle
* and access handling in a multithreaded context.
* @return "the" single instance of class S
*/
SI& operator() ()
{
if (!pInstance_)
{
ThreadLock guard;
if (!pInstance_)
{
if (isDead_)
{
Life<SI>::onDeadReference();
isDead_ = false;
}
pInstance_ = Create<SI>::create();
Life<SI>::scheduleDelete (&destroy);
} }
ENSURE (pInstance_);
ENSURE (!isDead_);
return *pInstance_;
}
private:
static void destroy();
/** @internal helper used to delegate destroying the single instance
* to the Create policy, at the same time allowing the Life policy
* to control the point in the Application lifecycle when the
* destruction of this instance occures.
*/
static void destroy()
{
REQUIRE (!isDead_);
Create<SI>::destroy (pInstance_);
pInstance_ = 0;
isDead_ = true;
}
};
// Storage for Singleton's static fields...
template
< class SI,
template <class> class C,
template <class> class L,
template <class> class T
>
typename Singleton<SI,C,L,T>::SType*
Singleton<SI,C,L,T>::pInstance_;
template
< class SI,
template <class> class C,
template <class> class L,
template <class> class T
>
bool Singleton<SI,C,L,T>::isDead_;
///// TODO: get rid of the static fields?
///// is tricky because of invoking the destructors. If we rely on instance vars,
///// the object may already have been released when the runtime system calls the
///// destructors of static objects at shutdown.
/** @internal used to link together the Create policy and Life policy.
* @return a functor object for invoking this->destroy() */
/* singleton::DelFunc getDeleter()
{
return boost::bind (&Singleton<SI,Create,Life,Threading>::destroy,
this);
}
*/
/* template<class T>
class DelFunc
{
typedef void (T::*Fp)(void);
T* t_;
Fp fun_;
public:
DelFunc (T* t, Fp f) : t_(t), fun_(f) {}
void operator() () { (t_->*fun_)(); }
};
*/
} // namespace cinelerra
#endif

View file

@ -36,6 +36,7 @@ This code is heavily inspired by
#include "common/error.hpp"
#include <vector>
namespace cinelerra
@ -56,8 +57,8 @@ namespace cinelerra
static uint callCount (0);
ASSERT ( 0 == callCount++ );
#endif
static S _theSingle_;
return &_theSingle_;
static char buff[sizeof(S)];
return new(buff) S();
}
static void destroy (S* pSi)
{
@ -76,30 +77,46 @@ namespace cinelerra
static void destroy (S* pS) { delete pS; }
};
typedef void (*DelFunc)(void);
using std::vector;
/**
* Policy relying on the compiler/runtime system for Singleton Lifecycle
*/
template<class S>
struct Automatic
{
typedef void (*DeleterFunc) (void);
/** implements the Singleton removal by calling
* the provided deleter function at application shutdown,
* relying on the runtime system calling destructors of
* static objects
* the provided deleter function(s) at application shutdown,
* relying on the runtime system calling destructors of static
* objects. Because this Policy class can be shared between
* several Singletons, we need to memoize all registered
* deleter functions for calling them at shutdown.
*/
static void scheduleDelete (DeleterFunc kill_the_singleton)
static void scheduleDelete (DelFunc kill_the_singleton)
{
struct DeleteTrigger
class DeleteTrigger
{
~DeleteTrigger() { *del_ (); }
DeleteTrigger(DeleterFunc d) : del_(d) {}
DeleterFunc del_;
vector<DelFunc> dels_;
public:
void schedule (DelFunc del)
{
dels_.push_back(del);
}
~DeleteTrigger()
{
vector<DelFunc>::iterator i = dels_.begin();
for ( ; i != dels_.end(); ++i )
(*i)(); // invoke deleter func
}
};
static DeleteTrigger finally(kill_the_singleton);
REQUIRE (kill_the_singleton);
static DeleteTrigger finally;
finally.schedule (kill_the_singleton);
}
static void onDeadReference ()

View file

@ -44,11 +44,11 @@ namespace asset
/** Asset is a Interface class; usually, objects of
* concrete subclasses are created via specialized Factories
*/
Asset::Asset (Ident& idi)
Asset::Asset (const Ident& idi)
: ident(idi), id(AssetManager::reg (this, idi))
{ }
Asset::~Asset () throw()
Asset::~Asset ()
{
TRACE (assetmem, "dtor Asset(id=%d) : %s", size_t(id), cStr(this->ident) );
}

View file

@ -76,16 +76,26 @@ namespace asset
{
public:
const size_t hash;
ID (size_t id) : hash(id) {}
ID (const KIND& asset) : hash(asset.id) {}
ID (size_t id) : hash(id) {}
ID (const KIND& asset) : hash(asset.getID()) {}
operator size_t() const { return hash; }
};
class Asset;
class AssetManager;
typedef const ID<Asset>& IDA;
class Media;
template<>
class ID<Media> : public ID<Asset>
{
public:
ID (size_t id);
ID (const Media&);
};
/**
* Superinterface describing especially bookeeping properties.
* As of 09/2007, there are four <b>Kinds</b> of Assets, each
@ -156,7 +166,9 @@ namespace asset
operator string () const;
};
const Ident ident; ///< Asset identification tuple
const Ident ident; ///< Asset identification tuple
virtual const ID<Asset>& getID() const { return id; }
private:
const ID<Asset> id; ///< Asset primary key.
@ -180,8 +192,8 @@ namespace asset
* concrete subclasses are created via specialized Factories.
* Calling this base ctor causes registration with AssetManager.
*/
Asset (Ident& idi);
virtual ~Asset() throw() = 0;
Asset (const Ident& idi);
virtual ~Asset() = 0;
/** release all links to other Asset objects held internally.
* The lifecycle of Asset objects is managed by smart pointers
@ -244,8 +256,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;
}

View file

@ -75,6 +75,9 @@ namespace asset
bool operator== (const Category& other) const { return kind_== other.kind_ && path_== other.path_; }
bool operator!= (const Category& other) const { return kind_!= other.kind_ || path_!= other.path_; }
bool hasKind (Kind refKind) const { return kind_ == refKind; }
operator string () const;

View file

@ -50,7 +50,7 @@ namespace asset
size_t
hash_value (const Asset& asset)
{
return asset.id;
return asset.getID();
}

View file

@ -21,13 +21,104 @@
* *****************************************************/
#include "proc/assetmanager.hpp"
#include "proc/asset/media.hpp"
#include "proc/asset/clip.hpp"
#include "proc/asset/unknown.hpp"
#include "common/util.hpp"
#include "nobugcfg.h"
#include <boost/regex.hpp>
using util::isnil;
using boost::regex;
using boost::smatch;
using boost::regex_search;
namespace asset
{
/** */
namespace // Implementation details
{
/** helper: extract a name token out of a given path/filename
* @return sanitized token based on the name (minus extension),
* empty string if not the common filename pattern.
*/
string extractName (const string& path)
{
regex pathname_pattern("([^/\\.]+)(\\.\\w+)?$");
smatch match;
if (regex_search (path, match, pathname_pattern))
return util::sanitize (string (match[1]));
else
return "";
}
}
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. */
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";
ID<Asset> id = aMang.getID (key);
if (aMang.known (id))
return aMang.getAsset(ID<Media>(id));
else
pM = new Unknown(key);
}
else
{
if (isnil (key.name)) key.name=extractName(file);
TODO ("file exists?");
pM = new Media (key,file);
}
ENSURE (key.category.hasKind (VIDEO) || key.category.hasKind(AUDIO));
ENSURE (isnil (key.name));
ENSURE (dynamic_cast<Media*>(pM) || (isnil (file) && dynamic_cast<Unknown*>(pM)));
return PType (pM, &destroy);
}
/** Variant of the Factory method for Media Assets, automatically
* providing most of the Asset key fields based on the filename given
*/
MediaFactory::PType
MediaFactory::operator() (const string& file, Category& cat)
{
Asset::Ident key(extractName(file), cat, "cin3", 1);
return MediaFactory::operator() (key, file);
}
MediaFactory::PType
MediaFactory::operator() (const char* file, Category& cat)
{
if (!file) file = "";
return operator() (file,cat);
}
MediaFactory::PType
MediaFactory::operator() (Asset::Ident& key, const char* file)
{
if (!file) file = "";
return operator() (key,file);
}
} // namespace asset

View file

@ -25,21 +25,68 @@
#define ASSET_MEDIA_H
#include "proc/asset.hpp"
#include "common/factory.hpp"
namespace asset
{
class Media;
class MediaFactory;
/**
* key abstraction: media-like assets
*/
class Media : public proc_interface::Asset
class Media : public Asset
{
string filename_;
public:
virtual const ID<Media>& getID() const { return getID(); }
static MediaFactory create;
const string& getFilename () { return filename_; }
protected:
Media (const Asset::Ident& idi, const string& file) : Asset(idi), filename_(file) {}
friend class MediaFactory;
};
// definition of ID<Media> ctors is possible now,
// after providing full definition of class Media
/*
ID<Media>::ID(size_t id)
: ID<Asset> (id) {};
ID<Media>::ID(const Media& media)
: ID<Asset> (media.getID()) {};
*/
/**
* Factory specialized for createing Media Asset objects.
*/
class MediaFactory : public cinelerra::Factory<asset::Media>
{
public:
typedef shared_ptr<asset::Media> PType;
PType operator() (Asset::Ident& key, const string& file="");
PType operator() (const string& file, Category& cat);
PType operator() (Asset::Ident& key, const char* file); ///< convienience overload using cString
PType operator() (const char* file, Category& cat);
protected:
static void destroy (Media* m) { delete m; }
};
} // namespace asset

View file

@ -36,7 +36,9 @@ namespace asset
*/
class Preview : public Media
{
protected:
Preview (const Asset::Ident& idi) : Media(idi,"") {}
friend class MediaFactory;
};

View file

@ -37,7 +37,9 @@ namespace asset
*/
class Unknown : public Preview
{
protected:
Unknown (const Asset::Ident& idi) : Preview(idi) {}
friend class MediaFactory;
};

View file

@ -38,11 +38,11 @@ namespace asset
AssetManager&
AssetManager::instance ()
{
return Singleton<AssetManager>::instance();
return *(new AssetManager); //////////////////////////////TODO Singleton<AssetManager>::instance();
}
AssetManager::AssetManager ()
: registry (Singleton<asset::DB>::instance())
: registry (*(new DB)) //(Singleton<asset::DB>::instance())
{ }
@ -62,8 +62,9 @@ namespace asset
template<class KIND>
ID<KIND>
AssetManager::reg (KIND& obj, const Asset::Ident& idi)
//throw(cinelerra::error::Invalid)
throw(cinelerra::error::Invalid)
{
UNIMPLEMENTED ("AssetManager::reg");
}
@ -72,8 +73,10 @@ namespace asset
*/
template<class KIND>
shared_ptr<KIND>
AssetManager::getAsset (const ID<KIND>& id) ////throw(cinelerra::Invalid)
AssetManager::getAsset (const ID<KIND>& id)
throw(cinelerra::error::Invalid)
{
UNIMPLEMENTED ("AssetManager::getAsset");
}
@ -83,6 +86,17 @@ namespace asset
bool
AssetManager::known (IDA id)
{
UNIMPLEMENTED ("asset search");
}
/**
* @return true if the given id is registered with the given Category
*/
bool
AssetManager::known (IDA id, const Category& cat)
{
UNIMPLEMENTED ("asset search");
}
@ -90,7 +104,9 @@ namespace asset
* remove the given asset <i>together with all its dependants</i> from the internal DB
*/
void
AssetManager::remove (IDA id) /////throw(cinelerra::Invalid, cinelerra::State)
AssetManager::remove (IDA id)
throw(cinelerra::error::Invalid,
cinelerra::error::State)
{
}

View file

@ -70,15 +70,19 @@ namespace asset
/** find and return corresponging object */
template<class KIND>
shared_ptr<KIND> getAsset (const ID<KIND>& id) ;///throw(cinelerra::error::Invalid);
shared_ptr<KIND> getAsset (const ID<KIND>& id) throw(cinelerra::error::Invalid);
/** @return true if the given id is registered in the internal asset DB */
bool known (IDA id) ;
/** @return true if the given id is registered with the given Category */
bool known (IDA id, const Category& cat) ;
/**remove the given asset from the internal DB.
* <i>together with all its dependants</i> */
void remove (IDA id) ;///throw(cinelerra::error::Invalid, cinelerra::error::State);
void remove (IDA id) throw(cinelerra::error::Invalid,
cinelerra::error::State);
protected:
@ -87,9 +91,9 @@ namespace asset
*/
template<class KIND>
static ID<KIND> reg (KIND& obj, const Asset::Ident& idi)
;
// throw(cinelerra::error::Invalid);
friend Asset::Asset (Asset::Ident& idi);
throw(cinelerra::error::Invalid);
friend Asset::Asset (const Asset::Ident& idi);
AssetManager ();

View file

@ -133,3 +133,21 @@ out: --> Testgroup=TestGroupID
out: --> Test-ID =SingleTestID
out: --> remaining=SingleTestID spam --eggs
END
PLANNED "SanitizedIdentifier_test" SanitizedIdentifier_test <<END
END
TEST "Singleton_test" Singleton_test 23 <<END
out: testing TargetObj(23) as Singleton(statically allocated)
out: ctor TargetObj(23) successfull
out: calling a non-static method on the Singleton instance
out: .....TargetObj(23): data="***********************", array[23]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,}
out: testing TargetObj(24) as Singleton(heap allocated)
out: ctor TargetObj(24) successfull
out: calling a non-static method on the Singleton instance
out: .....TargetObj(24): data="************************", array[24]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,}
out: dtor ~TargetObj(23) successfull
out: dtor ~TargetObj(24) successfull
END

View file

@ -29,9 +29,11 @@
#include "nobugcfg.h"
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include <iostream>
using boost::lexical_cast;
using boost::format;
using util::isnil;
using std::string;
using std::cout;
@ -42,8 +44,6 @@ namespace cinelerra
namespace test
{
class ObjFactory;
/**
* Target object to be instantiated as Singleton
@ -57,6 +57,9 @@ namespace cinelerra
static void setCountParam (uint c) { TargetObj::cnt = c; }
protected:
TargetObj () : TestTargetObj(cnt) {}
friend class singleton::Static<TargetObj>;
friend class singleton::Heap<TargetObj>;
};
int TargetObj::cnt = 0;
@ -76,42 +79,45 @@ namespace cinelerra
*/
class Singleton_test : public Test
{
typedef TargetObj& (*InstanceAccessFunc) (void);
typedef boost::function<TargetObj& ()> InstanceAccessFunc;
InstanceAccessFunc instance;
virtual void run(Arg arg)
{
uint num= isnil(arg)? 1 : lexical_cast<uint>(arg[1]);
TargetObj::setCountParam(num);
testStaticallyAllocatedSingleton ();
testHeapAllocatedSingleton ();
testStaticallyAllocatedSingleton (num++);
testHeapAllocatedSingleton (num++);
}
/** @test parametrize the Singleton creation such as to create
* the single TargetObj instance as a static variable.
*/
void testStaticallyAllocatedSingleton ()
void testStaticallyAllocatedSingleton (uint num)
{
instance = &Singleton<TargetObj>::instance;
useInstance ();
Singleton<TargetObj> single;
instance = single;
useInstance (num, "statically allocated");
}
/** @test parametrize the Singleton creation such as to create
* the single TargetObj instance allocated on the Heap
* and deleted automatically at application shutdown.
*/
void testHeapAllocatedSingleton ()
void testHeapAllocatedSingleton (uint num)
{
instance = &Singleton<TargetObj,singleton::Heap>::instance;
useInstance ();
Singleton<TargetObj,singleton::Heap> single;
instance = single;
useInstance (num, "heap allocated");
}
void useInstance ()
void useInstance (uint num, string kind)
{
cout << format("testing TargetObj(%d) as Singleton(%s)\n") % num % kind;
TargetObj::setCountParam(num);
TargetObj& t1 = instance();
TargetObj& t2 = instance();

View file

@ -23,14 +23,16 @@
#include "common/test/run.hpp"
//#include "common/factory.hpp"
//#include "common/util.hpp"
#include "common/util.hpp"
#include "proc/assetmanager.hpp"
#include "proc/asset/media.hpp"
#include "proc/asset/proc.hpp"
//#include <boost/format.hpp>
#include <iostream>
using util::isnil;
//using boost::format;
using std::string;
using std::cout;
@ -58,28 +60,36 @@ namespace asset
void createMedia()
{
typedef shared_ptr<asset::Media> PM;
/* typedef shared_ptr<asset::Media> 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);
PM mm3 = asset::Media::create("testfile2.mov",Category::VIDEO);
Category vid(VIDEO);////////////////////////////////////////////////FIXME
PM mm3 = asset::Media::create("testfile2.mov", vid);
// Assets have been registered and can be retrieved by ID
ASSERT (AssetManager::getAsset (mm1.id) == mm1);
ASSERT (AssetManager::getAsset (mm2.id) == mm2);
ASSERT (AssetManager::getAsset (mm3.id) == mm3);
AssetManager& aMang = AssetManager::instance();
ASSERT (aMang.getAsset (mm1->getID()) == mm1);
ASSERT (aMang.getAsset (mm2->getID()) == mm2);
ASSERT (aMang.getAsset (mm3->getID()) == mm3);
ASSERT (AssetManager::getAsset (mm1.id) != mm2);
ASSERT (aMang.getAsset (mm1->getID()) != mm2);
PAsset aa1 = AssetManager::getAsset (mm1.id);
ASSERT (aa1 == mm1);
PM mX1 = AssetManager::getAsset (mm1.id, Category::VIDEO);
// PAsset aa1 = aMang.getAsset (ID<Asset>(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()));
ASSERT (aMang.known (mm3->getID()));
ASSERT ( !aMang.known (mm3->getID(), Category(AUDIO))); // not found within AUDIO-Category
try
{ // can't be found if the Category is wrong....
AssetManager::getAsset (mm1.id, Category::AUDIO);
{ // can't be found if specifying wrong Asset kind....
// aMang.getAsset (ID<asset::Proc>(mm1->getID()));
NOTREACHED;
}
catch (cinelerra::error::Invalid) { }
@ -93,7 +103,7 @@ namespace asset
ASSERT (cat == Category (VIDEO,"bin1"));
ASSERT (mm1->ident.category == Category (VIDEO,"bin1"));
ASSERT (mm2->ident.category == Category (VIDEO,"bin1"));
ASSERT (mm3->ident.category == Category (VIDEO,""));
ASSERT (mm3->ident.category == Category (VIDEO ));
ASSERT (mm1->ident.org == "ichthyo");
ASSERT (mm2->ident.org == "ichthyo");
@ -104,9 +114,9 @@ namespace asset
ASSERT (mm3->ident.version == 1);
ASSERT (mm1->getFilename() == "testfile.mov");
ASSERT (isnil (mm2.getFilename()));
ASSERT (isnil (mm2->getFilename()));
ASSERT (mm3->getFilename() == "testfile2.mov");
*/
}
};

View file

@ -1,26 +1,34 @@
window_sizes 1140 783 270 860 584 120
window_sizes 1140 783 270 860 633 71
diagrams
active classdiagram_ref 130309 // Asset Kinds
860 584 100 4 0 0
classdiagram_ref 130309 // Asset Kinds
860 607 100 4 0 0
classdiagram_ref 130437 // Media-Asset Relations
688 506 100 4 0 0
classdiagram_ref 128133 // Session structure
688 506 100 4 60 0
classdiagram_ref 128389 // Render Entities
688 506 100 4 120 0
objectdiagram_ref 128901 // EDL Example2
688 506 100 4 132 0
objectdiagram_ref 128773 // EDL Example1
688 506 100 4 0 0
active objectdiagram_ref 129029 // Engine Example1
860 633 100 4 28 0
end
show_stereotypes
selected
package_ref 129 // cinelerra3
selected objectdiagram_ref 129029 // Engine Example1
open
deploymentview_ref 128517 // gen
deploymentview_ref 128645 // gen
deploymentview_ref 128773 // gen
deploymentview_ref 128901 // gen
deploymentview_ref 129029 // gen
package_ref 130309 // engine
package_ref 128005 // design
class_ref 136453 // Asset
operation_ref 133125 // getID
operation_ref 132357 // reg
class_ref 136709 // Media
class_ref 137349 // Clip
classview_ref 128005 // Session
classview_ref 128133 // Engine Workings
class_ref 138501 // SpecialWish
package_ref 128389 // RenderEngine
usecaseview_ref 128005 // Renderengine Use
class_ref 135685 // Logic
class_ref 135813 // Config
class_ref 135941 // State