Merge branch 'builder'

This commit is contained in:
Fischlurch 2007-09-18 05:24:22 +02:00
commit c81ef3bb3c
29 changed files with 1098 additions and 84 deletions

View file

@ -62,7 +62,7 @@ def setupBasicEnvironment():
, BINDIR=BINDIR
, CPPPATH=["#"+SRCDIR] # used to find includes, "#" means always absolute to build-root
, CPPDEFINES=['-DCINELERRA_VERSION='+VERSION ] # note: it's a list to append further defines
, CCFLAGS='-Wall'
, CCFLAGS='-Wall ' # -fdiagnostics-show-option
)
handleNoBugSwitches(env)

View file

@ -0,0 +1,54 @@
/*
MULTITHREAD.hpp - generic interface for multithreading primitives
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.
*/
#ifndef CINELERRA_MULTITHREAD_H
#define CINELERRA_MULTITHREAD_H
namespace cinelerra
{
/**
* Interface/Policy for managing parallelism issues.
* Basically everything is forwarded to the corresponding backend functions,
* because managing threads and locking belongs to the cinelerra backend layer.
*
* @todo actually implement this policy using the cinelerra databackend.
*/
struct Thread
{
template<class X>
class Lock
{
public:
Lock() { TODO ("aquire Thread Lock for Class"); }
Lock(X*) { TODO ("aquire Thread Lock for Instance"); }
~Lock() { TODO ("release Thread Lock"); }
};
};
} // namespace cinelerra
#endif

View file

@ -75,7 +75,7 @@ namespace cinelerra
{
if (!pInstance_)
{
ThreadLock guard;
ThreadLock guard SIDEEFFECT;
if (!pInstance_)
{
if (isDead_)

View file

@ -34,6 +34,7 @@ This code is heavily inspired by
#ifndef CINELERRA_SINGLETONPOLICIES_H
#define CINELERRA_SINGLETONPOLICIES_H
#include "common/multithread.hpp"
#include "common/error.hpp"
#include <vector>
@ -136,12 +137,7 @@ namespace cinelerra
struct Multithreaded
{
typedef volatile S* VolatileType;
class Lock
{
public:
Lock() { UNIMPLEMENTED ("aquire Thread Lock"); }
~Lock() { UNIMPLEMENTED ("release Thread Lock"); }
};
typedef cinelerra::Thread::Lock<S> Lock;
};

72
src/common/util.cpp Normal file
View file

@ -0,0 +1,72 @@
/*
util.cpp - helper functions implementation
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.
* *****************************************************/
#include "common/util.hpp"
#include <boost/algorithm/string.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
using boost::algorithm::trim_right_copy_if;
using boost::algorithm::is_any_of;
using boost::algorithm::is_alnum;
using boost::algorithm::is_space;
namespace util
{
typedef boost::function<bool(string::value_type)> ChPredicate;
ChPredicate operator! (ChPredicate p) { return ! boost::bind(p,_1); }
// character classes used for sanitizing a string
ChPredicate isValid (is_alnum() || is_any_of("-_.:+$'()@")); ///< characters to be retained
ChPredicate isPunct (is_space() || is_any_of(",;#*~´`?\\=/&%![]{}")); ///< punctuation to be replaced by '_'
string
sanitize (const string& org)
{
string res (trim_right_copy_if(org, !isValid ));
string::iterator j = res.begin();
string::const_iterator i = org.begin();
string::const_iterator e = i + (res.length());
while ( i != e )
{
while ( i != e && !isValid (*i) ) ++i;
while ( i != e && isValid (*i) ) *(j++) = *(i++);
if ( i != e && isPunct (*i) )
{
*j++ = '_';
do ++i;
while ( i != e && isPunct (*i));
}
}
res.erase(j,res.end());
return res;
}
} // namespace util

View file

@ -81,7 +81,7 @@ namespace util
*/
template <typename Container, typename Oper>
inline Oper
for_each (Container& c, Oper& doIt)
for_each (Container& c, Oper doIt)
{
return std::for_each (c.begin(),c.end(), doIt);
}
@ -89,14 +89,25 @@ namespace util
/** produce an identifier based on the given string.
* remove non-standard-chars, reduce punctuation to underscores
* remove non-standard-chars, reduce sequences of punctuation
* and whitespace to single underscores. The sanitized string
* will start with an alphanumeric character.
*
* @par Example Conversions
\verbatim
"Word" --> 'Word'
"a Sentence" --> 'a_Sentence'
"trailing Withespace \t \n" --> 'trailing_Withespace'
"with a lot \nof Whitespace" --> 'with_a_lot_of_Whitespace'
"with\"much (punctuation)[]!" --> 'withmuch_(punctuation)'
"§&Ω%€ leading garbarge" --> 'leading_garbarge'
"mixed Ω garbarge" --> 'mixed_garbarge'
"Bääääh!!" --> 'Bh'
\endverbatim
*/
inline string
sanitize (const string& org)
{
UNIMPLEMENTED ("sanitize String");
return org; ///////////////////////////TODO
}
string sanitize (const string& org);
/** convienience shortcut: conversion to c-String via string.
@ -113,6 +124,11 @@ namespace util
/* some common macro definitions */
/** supress "warning: unused variable" on vars, which
* are introduced into a scope because of some sideeffect, i.e. Locking
*/
#define SIDEEFFECT __attribute__ ((unused));
/** this macro wraps its parameter into a cstring literal */
#define STRINGIFY(TOKEN) __STRNGFY(TOKEN)
#define __STRNGFY(TOKEN) #TOKEN

View file

@ -27,6 +27,8 @@
#include <boost/format.hpp>
#include <iostream>
#include <string>
using boost::format;
using util::cStr;
@ -46,19 +48,27 @@ namespace asset
*/
Asset::Asset (const Ident& idi)
: ident(idi), id(AssetManager::reg (this, idi))
{ }
{ TRACE (assetmem, "ctor Asset(id=%lu) : adr=%x %s", size_t(id), this, cStr(this->ident) );
}
Asset::~Asset ()
{
TRACE (assetmem, "dtor Asset(id=%d) : %s", size_t(id), cStr(this->ident) );
TRACE (assetmem, "dtor Asset(id=%lu) : adr=%x", size_t(id), this );
}
Asset::Ident::operator string () const
{
static format id_tuple("(%2%:%3%.%1% v%4%)"); // ignoring threadsafety
format id_tuple("(%2%:%3%.%1% v%4%)");
return str (id_tuple % name % category % org % version);
}
Asset::operator string () const
{
format id_tuple("Asset(%2%:%3%.%1% v%4%)");
return str (id_tuple % ident.name % ident.category % ident.org % ident.version);
}
/** List of entities this asset depends on or requires to be functional.

View file

@ -175,17 +175,30 @@ namespace asset
&& name == other.name
&& category == other.category;
}
bool operator!= (const Ident& other) const
{
return !operator==(other);
}
int compare (const Ident& other) const;
operator string () const;
};
/* ===== Asset ID and Datafields ===== */
public:
const Ident ident; ///< Asset identification tuple
virtual const ID<Asset>& getID() const { return id; }
virtual operator string () const;
protected:
const ID<Asset> id; ///< Asset primary key.
protected:
/** additional classification, selections or departments this asset belongs to.
* Groups are optional, non-exclusive and may be overlapping.
*/
@ -206,7 +219,7 @@ namespace asset
* Calling this base ctor causes registration with AssetManager.
*/
Asset (const Ident& idi);
virtual ~Asset() = 0;
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
@ -227,6 +240,7 @@ namespace asset
friend class AssetManager;
public:
/** 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
@ -259,6 +273,32 @@ namespace asset
/** shorthand for refcounting Asset pointers */
typedef shared_ptr<Asset> PAsset;
/** ordering of Assets based on Ident tuple */
inline bool operator< (const PAsset& a1, const PAsset& a2) { return a1 && a2 && (-1==a1->ident.compare(a2->ident));}
inline bool operator> (const PAsset& a1, const PAsset& a2) { return a2 < a1; }
inline bool operator>= (const PAsset& a1, const PAsset& a2) { return !(a1 < a2); }
inline bool operator<= (const PAsset& a1, const PAsset& a2) { return !(a1 > a2); }
/** ordering of Asset Ident tuples.
* @note version is irrelevant */
inline int Asset::Ident::compare (const Asset::Ident& oi) const
{
int res;
if (1 != (res=category.compare (oi.category))) return res;
if (1 != (res=org.compare (oi.org))) return res;
return name.compare (oi.name);
}
/** convienient for debugging */
inline string str (const PAsset& a)
{
if (a)
return string (*a.get());
else
return "Asset(NULL)";
}
} // namespace asset

View file

@ -25,6 +25,9 @@
#include "common/util.hpp"
#include "nobugcfg.h"
#include <boost/algorithm/string.hpp>
using boost::algorithm::starts_with;
using util::isnil;
namespace asset
@ -48,6 +51,20 @@ namespace asset
str += "/"+path_;
return str;
}
/** hierarchical inclusion test.
* @return true if \c this can be considered
* a subcategory of the given reference
*/
bool
Category::isWithin (const Category& ref) const
{
return ( ref.hasKind (kind_)
&& starts_with (path_, ref.path_)
);
}
} // namespace asset

View file

@ -76,7 +76,8 @@ 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; }
bool hasKind (Kind refKind) const { return kind_ == refKind; }
bool isWithin (const Category&) const;
operator string () const;
@ -88,12 +89,22 @@ namespace asset
boost::hash_combine(hash, cat.kind_);
boost::hash_combine(hash, cat.path_);
return hash;
}
}
int compare (const Category& co) const
{
int res = int(kind_) - int(co.kind_);
if (1 != res)
return res;
else
return path_.compare (co.path_);
}
};
inline ostream& operator<< (ostream& os, const Category& cago) { return os << string(cago); }
} // namespace asset
#endif

View file

@ -33,7 +33,9 @@
namespace asset
{
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
/* ===== hash implementations ===== */
@ -45,14 +47,14 @@ namespace asset
boost::hash_combine(hash, idi.name);
boost::hash_combine(hash, idi.category);
return hash;
}
}
size_t
size_t
hash_value (const Asset& asset)
{
return asset.getID();
}
/**
* trivial hash functor.
@ -66,12 +68,12 @@ namespace asset
size_t
operator() (size_t val) const { return val; }
};
typedef std::tr1::unordered_map<size_t, PAsset, IdentityHash> IdHashtable;
/**
* Implementation of the registry holding all Asset
* instances known to the Asset Manager subsystem.
@ -85,6 +87,42 @@ namespace asset
~DB () {}
friend class cinelerra::singleton::Static<DB>;
public:
template<class KIND>
void put (ID<KIND> hash, shared_ptr<KIND>& ptr) { table[hash] = static_pointer_cast (ptr); }
void put (ID<Asset> hash, PAsset& ptr) { table[hash] = ptr; }
template<class KIND>
shared_ptr<KIND>
get (ID<KIND> hash) const
{
return dynamic_pointer_cast<KIND,Asset> (find (hash));
}
/** intended for diagnostics */
void
asList (list<PAsset>& output) const
{
IdHashtable::const_iterator i = table.begin();
IdHashtable::const_iterator e = table.end();
for ( ; i!=e ; ++i )
output.push_back (i->second);
}
private:
const PAsset &
find (size_t hash) const
{
static const PAsset NULLP;
IdHashtable::const_iterator i = table.find (hash);
if (i == table.end())
return NULLP; // empty ptr signaling "not found"
else
return i->second;
}
};

View file

@ -96,7 +96,7 @@ namespace asset
}
ASSERT (pM);
ENSURE (key.category.hasKind (VIDEO) || key.category.hasKind(AUDIO));
ENSURE (isnil (key.name));
ENSURE (!isnil (key.name));
ENSURE (dynamic_cast<Media*>(pM) || (isnil (file) && dynamic_cast<Unknown*>(pM)));
return aMang.getAsset (pM->getID()); // note: because we query with an ID<Media>,
@ -108,7 +108,7 @@ namespace asset
* providing most of the Asset key fields based on the filename given
*/
MediaFactory::PType
MediaFactory::operator() (const string& file, Category& cat)
MediaFactory::operator() (const string& file, const Category& cat)
{
Asset::Ident key(extractName(file), cat, "cin3", 1);
return operator() (key, file);
@ -123,7 +123,7 @@ namespace asset
MediaFactory::PType
MediaFactory::operator() (const char* file, Category& cat)
MediaFactory::operator() (const char* file, const Category& cat)
{
if (!file) file = "";
return operator() (string(file),cat);

View file

@ -97,15 +97,12 @@ namespace asset
typedef shared_ptr<asset::Media> PType;
PType operator() (Asset::Ident& key, const string& file="");
PType operator() (const string& file, Category& cat);
PType operator() (const string& file, const Category& cat);
PType operator() (const string& file, asset::Kind);
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, const Category& cat);
PType operator() (const char* file, asset::Kind);
protected:
static void destroy (Media* m) { delete m; }
};

View file

@ -21,13 +21,37 @@
* *****************************************************/
#include "proc/assetmanager.hpp"
#include "proc/asset/meta.hpp"
#include "common/util.hpp"
#include "nobugcfg.h"
namespace asset
{
/** */
namespace // Implementation details
{
/** helper: .....*/
}
MetaFactory Meta::create; ///< storage for the static MetaFactory instance
/** Factory method for Metadata Asset instances. ....
* @todo actually define
* @return an Meta smart ptr linked to the internally registered smart ptr
* created as a side effect of calling the concrete Meta subclass ctor.
*/
MetaFactory::PType
MetaFactory::operator() (Asset::Ident& key) ////TODO
{
UNIMPLEMENTED ("Meta-Factory");
}
} // namespace asset

View file

@ -21,26 +21,86 @@
*/
/** @file meta.hpp
** Some Metatdata elements (e.g. Automation Datasets) can be treated as
** specific Kind of Asset.
** For the different <i>Kinds</i> of Assets, we use sub-intefaces inheriting
** from the general Asset interface. To be able to get asset::Meta instances
** directly from the AssetManager, we define a specialization of the Asset ID.
**
** @see asset.hpp for explanation
** @see MetaFactory creating concrete asset::Meta instances
**
*/
#ifndef ASSET_META_H
#define ASSET_META_H
#include "proc/asset.hpp"
#include "common/factory.hpp"
namespace asset
{
class Meta;
class MetaFactory;
template<>
class ID<Meta> : public ID<Asset>
{
public:
ID (size_t id);
ID (const Meta&);
};
/**
* key abstraction: metadata and organisational asset
* @todo just a stub, have to figure out what a asset::Proc is
*/
class Meta : public proc_interface::Asset
class Meta : public Asset
{
public:
static MetaFactory create;
virtual const ID<Meta>& getID() const ///< @return ID of kind Meta
{
return static_cast<const ID<Meta>& > (Asset::getID());
}
protected:
Meta (const Asset::Ident& idi) : Asset(idi) {} //////////////TODO
friend class MetaFactory;
};
// definition of ID<Meta> ctors is possible now,
// after providing full definition of class Proc
inline ID<Meta>::ID(size_t id) : ID<Asset> (id) {};
inline ID<Meta>::ID(const Meta& meta) : ID<Asset> (meta.getID()) {};
/**
* Factory specialized for createing Metadata Asset objects.
*/
class MetaFactory : public cinelerra::Factory<asset::Meta>
{
public:
typedef shared_ptr<asset::Meta> PType;
PType operator() (Asset::Ident& key); ////////////TODO define actual operation
};
} // namespace asset
#endif

View file

@ -21,13 +21,37 @@
* *****************************************************/
#include "proc/assetmanager.hpp"
#include "proc/asset/proc.hpp"
#include "common/util.hpp"
#include "nobugcfg.h"
namespace asset
{
/** */
namespace // Implementation details
{
/** helper: .....*/
}
ProcFactory Proc::create; ///< storage for the static ProcFactory instance
/** Factory method for Processor Asset instances. ....
* @todo actually define
* @return an Proc smart ptr linked to the internally registered smart ptr
* created as a side effect of calling the concrete Proc subclass ctor.
*/
ProcFactory::PType
ProcFactory::operator() (Asset::Ident& key) ////TODO
{
UNIMPLEMENTED ("Proc-Factory");
}
} // namespace asset

View file

@ -21,26 +21,85 @@
*/
/** @file proc.hpp
** Data processing Plugins and Codecs can be treated as a specific Kind of Asset.
** For the different <i>Kinds</i> of Assets, we use sub-intefaces inheriting
** from the general Asset interface. To be able to get asset::Proc instances
** directly from the AssetManager, we define a specialization of the Asset ID.
**
** @see asset.hpp for explanation
** @see ProcFactory creating concrete asset::Proc instances
**
*/
#ifndef ASSET_PROC_H
#define ASSET_PROC_H
#include "proc/asset.hpp"
#include "common/factory.hpp"
namespace asset
{
class Proc;
class ProcFactory;
template<>
class ID<Proc> : public ID<Asset>
{
public:
ID (size_t id);
ID (const Proc&);
};
/**
* key abstraction: data processing asset
* @todo just a stub, have to figure out what a asset::Proc is
*/
class Proc : public Asset
{
public:
static ProcFactory create;
virtual const ID<Proc>& getID() const ///< @return ID of kind Proc
{
return static_cast<const ID<Proc>& > (Asset::getID());
}
protected:
Proc (const Asset::Ident& idi) : Asset(idi) {} //////////////TODO
friend class ProcFactory;
};
// definition of ID<Proc> ctors is possible now,
// after providing full definition of class Proc
inline ID<Proc>::ID(size_t id) : ID<Asset> (id) {};
inline ID<Proc>::ID(const Proc& proc) : ID<Asset> (proc.getID()) {};
/**
* Factory specialized for createing Processor Asset objects.
*/
class ProcFactory : public cinelerra::Factory<asset::Proc>
{
public:
typedef shared_ptr<asset::Proc> PType;
PType operator() (Asset::Ident& key); ////////////TODO define actual operation
};
} // namespace asset
#endif

View file

@ -21,10 +21,38 @@
* *****************************************************/
#include "proc/assetmanager.hpp"
#include "proc/asset/struct.hpp"
#include "common/util.hpp"
#include "nobugcfg.h"
namespace asset
{
namespace // Implementation details
{
/** helper: .....*/
}
StructFactory Struct::create; ///< storage for the static StructFactory instance
/** Factory method for Structural Asset instances. ....
* @todo actually define
* @return an Struct smart ptr linked to the internally registered smart ptr
* created as a side effect of calling the concrete Struct subclass ctor.
*/
StructFactory::PType
StructFactory::operator() (Asset::Ident& key) ////TODO
{
UNIMPLEMENTED ("Struct-Factory");
}

View file

@ -21,23 +21,83 @@
*/
/** @file struct.hpp
** Structural facilities of the EDL (e.g. Tracks) can be treated in the
** "bookkeeping view" as a specific Kind of Asset.
** For the different <i>Kinds</i> of Assets, we use sub-intefaces inheriting
** from the general Asset interface. To be able to get asset::Struct instances
** directly from the AssetManager, we define a specialization of the Asset ID.
**
** @see asset.hpp for explanation
** @see StructFactory creating concrete asset::Struct instances
**
*/
#ifndef ASSET_STRUCT_H
#define ASSET_STRUCT_H
#include "proc/asset.hpp"
#include "common/factory.hpp"
namespace asset
{
class Struct;
class StructFactory;
template<>
class ID<Struct> : public ID<Asset>
{
public:
ID (size_t id);
ID (const Struct&);
};
/**
* key abstraction: structural asset
* @todo just a stub, have to figure out what a asset::Proc is
*/
class Struct : public Asset
{
public:
static StructFactory create;
virtual const ID<Struct>& getID() const ///< @return ID of kind asset::Struct
{
return static_cast<const ID<Struct>& > (Asset::getID());
}
protected:
Struct (const Asset::Ident& idi) : Asset(idi) {} //////////////TODO
friend class StructFactory;
};
// definition of ID<Struct> ctors is possible now,
// after providing full definition of class Proc
inline ID<Struct>::ID(size_t id) : ID<Asset> (id) {};
inline ID<Struct>::ID(const Struct& stru) : ID<Asset> (stru.getID()) {};
/**
* Factory specialized for createing Structural Asset objects.
*/
class StructFactory : public cinelerra::Factory<asset::Struct>
{
public:
typedef shared_ptr<asset::Struct> PType;
PType operator() (Asset::Ident& key); ////////////TODO define actual operation
};

View file

@ -24,13 +24,65 @@
#include "proc/assetmanager.hpp"
#include "proc/asset/db.hpp"
//#include <boost/functional/hash.hpp>
#include "common/multithread.hpp"
#include "common/util.hpp"
//#include <boost/lambda/lambda.hpp>
#include <boost/function.hpp>
#include <boost/format.hpp>
#include <boost/bind.hpp>
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<Asset> 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.
*/
@ -52,26 +104,45 @@ namespace asset
/**
* registers an asset object in the internal DB, providing its unique key
* 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<class KIND>
ID<KIND>
AssetManager::reg (KIND* obj, const Asset::Ident& idi)
throw(cinelerra::error::Invalid)
{
UNIMPLEMENTED ("AssetManager::reg");
typedef shared_ptr<KIND> PType;
AssetManager& _aMang (AssetManager::instance());
TODO ("check validity of Ident Category");
ID<KIND> asset_id (getID (idi));
Thread::Lock<DB> guard SIDEEFFECT;
TODO ("handle duplicate Registrations");
PType smart_ptr (obj, &destroy);
_aMang.registry.put (asset_id, smart_ptr);
return asset_id;
}
/**
* find and return corresponging object
* 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<class KIND>
shared_ptr<KIND>
AssetManager::getAsset (const ID<KIND>& id)
throw(cinelerra::error::Invalid)
{
UNIMPLEMENTED ("AssetManager::getAsset");
if (shared_ptr<KIND> obj = registry.get (id))
return obj;
else
if (known (id)) // provide Ident tuple of existing Asset
throw WrongKind (registry.get(ID<Asset>(id))->ident);
else
throw UnknownID (id);
}
@ -81,8 +152,9 @@ namespace asset
bool
AssetManager::known (IDA id)
{
UNIMPLEMENTED ("asset search");
}
return ( registry.get (ID<Asset>(id)) );
} // query most general Asset ID-kind and use implicit
// conversion from shared_ptr to bool (test if empty)
/**
@ -91,9 +163,16 @@ namespace asset
bool
AssetManager::known (IDA id, const Category& cat)
{
UNIMPLEMENTED ("asset search");
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 <i>together with all its dependants</i> from the internal DB
@ -103,6 +182,23 @@ namespace asset
throw(cinelerra::error::Invalid,
cinelerra::error::State)
{
UNIMPLEMENTED ("remove Asset with all dependecies");
PAsset pA = getAsset (id);
vector<PAsset> par = pA->getParents();
boost::function<void(PAsset&)> func = bind(&detach_child, _1,id );
for_each (par, func); // ,boost::lambda::var(id)));
}
list<PAsset>
AssetManager::listContent() const
{
list<PAsset> res;
registry.asList (res);
res.sort();
return res;
}

View file

@ -40,11 +40,14 @@
#include "common/error.hpp"
#include "common/singleton.hpp"
#include <cstddef>
#include <string>
#include <list>
#include <boost/utility.hpp>
using std::string;
using std::list;
@ -85,6 +88,10 @@ namespace asset
void remove (IDA id) throw(cinelerra::error::Invalid,
cinelerra::error::State);
/** extract a sorted list of all registered Assets */
list<PAsset> listContent() const;
protected:
/** registers an asset object in the internal DB, providing its unique key.
@ -94,13 +101,23 @@ namespace asset
static ID<KIND> reg (KIND* obj, const Asset::Ident& idi)
throw(cinelerra::error::Invalid);
/** deleter function used by the Asset smart pointers to delet Asset objects */
static void destroy (Asset* m) { delete m; }
friend Asset::Asset (const Asset::Ident& idi);
AssetManager ();
friend class cinelerra::singleton::Static<AssetManager>;
private:
static void detach_child (PAsset&, IDA);
};
CINELERRA_ERROR_DECLARE (UNKNOWN_ASSET_ID); ///< use of a non-registered Asset ID.
CINELERRA_ERROR_DECLARE (WRONG_ASSET_KIND); ///< Asset ID of wrong Asset kind, unable to cast.
} // namespace asset

View file

@ -41,8 +41,12 @@ out: 2|ä|
out: 3|+|
out: 4|€|
out: -->oo _O()O_ ä + €
out: wrapping cmdline:...
out: -->
out: wrapping cmdline:Ω ooΩ oΩo Ωoo...
out: 0|Ω|
out: 1|ooΩ|
out: 2|oΩo|
out: 3|Ωoo|
out: -->Ω ooΩ oΩo Ωoo
out: Standard Cmdlineformat:one two
END
@ -135,7 +139,18 @@ out: --> remaining=SingleTestID spam --eggs
END
PLANNED "SanitizedIdentifier_test" SanitizedIdentifier_test <<END
TEST "SanitizedIdentifier_test" SanitizedIdentifier_test <<END
out: 'Word' --> 'Word'
out: 'a Sentence' --> 'a_Sentence'
out: 'trailing Withespace
out: ' --> 'trailing_Withespace'
out: 'with a lot
out: of Whitespace' --> 'with_a_lot_of_Whitespace'
out: 'with"much (punctuation)[]!' --> 'withmuch_(punctuation)'
out: '§&Ω%€ leading garbarge' --> 'leading_garbarge'
out: 'mixed Ω garbarge' --> 'mixed_garbarge'
out: 'Bääääh!!' --> 'Bh'
out: '§&Ω%€' --> ''
END

View file

@ -2,7 +2,8 @@ TESTING "Component Test Suite: Asset Manager" ./test-components --group=asset
PLANNED "CreateAsset_test" CreateAsset_test <<END
TEST "CreateAsset_test" CreateAsset_test <<END
return: 0
END
@ -12,3 +13,12 @@ END
PLANNED "DependantAssets_test" DependantAssets_test <<END
END
TEST "IdentityOfAssets_test" IdentityOfAssets_test <<END
return: 0
END
PLANNED "OrderingOfAssets_test" OrderingOfAssets_test <<END
END

View file

@ -44,13 +44,17 @@ namespace util
{
print_clean ("Word");
print_clean ("a Sentence");
print_clean ("with a lot \nof Whitespace");
print_clean ("with\"much (punctuation)!");
print_clean ("trailing Withespace\n \t");
print_clean ("with a \t lot\n of Whitespace");
print_clean ("with\"much (punctuation)[]!");
print_clean ("§&Ω%€ leading garbarge");
print_clean ("mixed Ω garbarge");
print_clean ("Bääääh!!");
print_clean ("§&Ω%€");
}
/** @test print the original and the sanitized string */
void print_clean (const string& org)
void print_clean (const string org)
{
cout << "'" << org << "' --> '" << sanitize(org) << "'\n";
}

View file

@ -54,7 +54,7 @@ namespace util
testLine("\nspam");
testLine("eat more spam");
testLine(" oo _O()O_ ä + €");
testLine("\0\too\0\to\0o\t\0oo");
testLine("Ω\tooΩ\toΩo\tΩoo");
testStandardCmdlineformat();
}

View file

@ -0,0 +1,73 @@
/*
ASSETDIAGNOSTICS.hpp - collection of test and debug helpers
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.
*/
/** @file assetdiagnostics.hpp
** Small helper and diagnosic functions related to Asset and AssetManager
**
** @see assetmanager.hpp
** @see CreateAsset_test
** @see IdentityOfAssets_test
*/
#ifndef ASSET_ASSETDIAGNOSTICS_H
#define ASSET_ASSETDIAGNOSTICS_H
#include "proc/assetmanager.hpp"
#include "common/util.hpp"
#include <boost/format.hpp>
#include <boost/bind.hpp>
#include <iostream>
using util::for_each;
using boost::format;
using boost::bind;
using std::string;
using std::cout;
namespace asset
{
inline void dump (const PAsset& aa)
{
if (!aa)
cout << "Asset(NULL)\n";
else
{
format fmt("%s %|50T.| id=%s adr=%x smart-ptr=%x use-count=%d");
cout << fmt % str(aa) % aa->getID() % aa.get() % &aa % (aa.use_count() - 1) << "\n";
} }
inline void dumpAssetManager ()
{
list<PAsset> assets (AssetManager::instance().listContent());
cout << "----all-registered-Assets----\n";
for_each (assets, bind (&dump, _1));
}
} // namespace asset
#endif

View file

@ -22,20 +22,16 @@
#include "common/test/run.hpp"
//#include "common/factory.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>
#include "proc/asset/assetdiagnostics.hpp"
using util::isnil;
//using boost::format;
using std::string;
using std::cout;
namespace asset
@ -43,7 +39,6 @@ namespace asset
namespace test
{
// typedef Category::Kind Kind;
@ -56,15 +51,29 @@ namespace asset
virtual void run(Arg arg)
{
createMedia();
}
factoryVariants();
if (!isnil (arg))
dumpAssetManager();
TRACE (assetmem, "leaving CreateAsset_test::run()");
}
typedef shared_ptr<asset::Media> PM;
/** @test Creating and automatically registering Asset instances.
* Re-Retrieving the newly created objects from AssetManager.
* Checking AssetManager access functions, esp. getting
* different kinds of Assets by ID, querying with the
* wrong Category and querying unknown IDs.
*/
void createMedia()
{
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 mm2 = asset::Media::create("testfile1.mov", cat);
PM mm3 = asset::Media::create("testfile2.mov", VIDEO);
// Assets have been registered and can be retrieved by ID
@ -91,12 +100,18 @@ namespace asset
aMang.getAsset (ID<asset::Proc>(mm1->getID()));
NOTREACHED;
}
catch (cinelerra::error::Invalid) { }
catch (cinelerra::error::Invalid& xxx) {ASSERT (xxx.getID()==CINELERRA_ERROR_WRONG_ASSET_KIND);}
try
{ // try accessing nonexistant ID
aMang.getAsset (ID<Asset> (1234567890));
NOTREACHED;
}
catch (cinelerra::error::Invalid& xxx) {ASSERT (xxx.getID()==CINELERRA_ERROR_UNKNOWN_ASSET_ID);}
// checking the Ident-Fields
ASSERT (mm1->ident.name == "Name-1");
ASSERT (mm2->ident.name == "Name-1");
ASSERT (mm2->ident.name == "testfile1");
ASSERT (mm3->ident.name == "testfile2");
ASSERT (cat == Category (VIDEO,"bin1"));
@ -105,19 +120,64 @@ namespace asset
ASSERT (mm3->ident.category == Category (VIDEO ));
ASSERT (mm1->ident.org == "ichthyo");
ASSERT (mm2->ident.org == "ichthyo");
ASSERT (mm2->ident.org == "cin3");
ASSERT (mm3->ident.org == "cin3");
ASSERT (mm1->ident.version == 5);
ASSERT (mm2->ident.version == 5);
ASSERT (mm2->ident.version == 1);
ASSERT (mm3->ident.version == 1);
ASSERT (mm1->getFilename() == "testfile.mov");
ASSERT (isnil (mm2->getFilename()));
ASSERT (mm2->getFilename() == "testfile1.mov");
ASSERT (mm3->getFilename() == "testfile2.mov");
/*
////////////////////////////////////////////////////////////////////////////////TODO fuck the compiler!!!
*/
TRACE (assetmem, "leaving test method scope");
}
/** @test different variants of calling the MediaFactory,
* with focus on the behaviour of the basic Asset
* creation machinery. Covers filling out Asset's
* datafields, amending missing pieces of information.
*/
void factoryVariants()
{
PM candi;
Asset::Ident key1("Au-1", Category(AUDIO), "ichthyo", 5);
candi = asset::Media::create(key1);
ASSERT ( checkProperties (candi, key1, ""));
candi = asset::Media::create(key1, string("testfile.wav"));
ASSERT ( checkProperties (candi, key1, "testfile.wav"));
Asset::Ident key2("", Category(AUDIO), "ichthyo", 5);
candi = asset::Media::create(key2, string("testfile2.wav"));
ASSERT ( checkProperties (candi, key2, "testfile2.wav"));
ASSERT (key2.name == "testfile2"); // name filled in automatically
candi = asset::Media::create(string("testfile3.wav"), Category(AUDIO));
ASSERT ( checkProperties (candi, Asset::Ident("testfile3", Category(AUDIO), "cin3", 1)
, "testfile3.wav"));
candi = asset::Media::create("some/path/testfile4.wav", Category(AUDIO));
ASSERT ( checkProperties (candi, Asset::Ident("testfile4", Category(AUDIO), "cin3", 1)
, "some/path/testfile4.wav"));
candi = asset::Media::create("", Category(AUDIO,"sub/bin"));
ASSERT ( checkProperties (candi, Asset::Ident("nil", Category(AUDIO,"sub/bin"), "cin3", 1)
, ""));
candi = asset::Media::create("", AUDIO);
ASSERT ( checkProperties (candi, Asset::Ident("nil", Category(AUDIO), "cin3", 1)
, ""));
}
bool checkProperties (PM object, Asset::Ident identity, string filename)
{
return identity == object->ident
&& filename == object->getFilename();
}
};

View file

@ -0,0 +1,108 @@
/*
IdentityOfAssets(Test) - Asset object identity and versioning
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.
* *****************************************************/
#include "common/test/run.hpp"
#include "common/util.hpp"
#include "proc/assetmanager.hpp"
#include "proc/asset/media.hpp"
#include "proc/asset/proc.hpp"
#include "proc/asset/assetdiagnostics.hpp"
using util::isnil;
using std::string;
namespace asset
{
namespace test
{
/***********************************************************************
* @test creating several Assets and checking object identity,
* detection of duplicates and version handling.
* @see proc_interface::AssetManager#reg
* @todo to be written; features are missing as of 9/07
*/
class IdentityOfAssets_test : public Test
{
virtual void run(Arg arg)
{
createDuplicate();
if (!isnil (arg))
dumpAssetManager();
TRACE (assetmem, "leaving IdentityOfAssets_test::run()");
}
typedef shared_ptr<asset::Media> PM;
/** @test produce an ID clash.
* documents the current behaviour of the code as of 9/07
* @todo this test is expected to break when the detection
* of duplicate registrations is implemented.
*/
void createDuplicate()
{
PM mm1 = asset::Media::create ("testfile1.mov", VIDEO);
Asset::Ident idi (mm1->ident); // duplicate Ident record
PM mm1X = asset::Media::create (idi); // note: we actually don't call any ctor
ASSERT (mm1 == mm1X); // instead, we got mm1 back.
PM mm2 = asset::Media::create (idi,"testfile2.mov");
ASSERT (mm1->getID() == mm2->getID()); // different object, same hash
AssetManager& aMang = AssetManager::instance();
ASSERT (aMang.getAsset (mm1->getID()) == mm2); // record of mm1 was replaced by mm2
ASSERT (aMang.getAsset (mm2->getID()) == mm2);
ASSERT (aMang.known (mm1->getID()));
ASSERT (aMang.known (mm2->getID()));
ASSERT (mm1->ident.name == "testfile1");
ASSERT (mm2->ident.name == "testfile1");
ASSERT (mm1->getFilename() == "testfile1.mov");
ASSERT (mm2->getFilename() == "testfile2.mov");
TRACE (assetmem, "leaving test method scope");
}
};
/** Register this test class... */
LAUNCHER (IdentityOfAssets_test, "unit asset");
} // namespace test
} // namespace asset

View file

@ -0,0 +1,125 @@
/*
OrderingOfAssets(Test) - equality and comparisons
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.
* *****************************************************/
#include "common/test/run.hpp"
#include "common/util.hpp"
#include "proc/assetmanager.hpp"
#include "proc/asset/media.hpp"
#include "proc/asset/proc.hpp"
#include "proc/asset/assetdiagnostics.hpp"
using util::isnil;
using std::string;
namespace asset
{
namespace test
{
/******************************************************
* @test validate the equality and order relations of
* Asset::Ident and Asset objects.
* @see Asset::Ident#compare
*/
class OrderingOfAssets_test : public Test
{
virtual void run(Arg arg)
{
typedef shared_ptr<asset::Media> PM;
Asset::Ident key1("Au-1", Category(AUDIO), "ichthyo", 5);
PM mm1 = asset::Media::create(key1, "Name-1");
Asset::Ident key2("Au-1", Category(AUDIO), "ichthyo", 7);
PM mm2 = asset::Media::create(key2, "Name-2");
Asset::Ident key3("Au-2", Category(AUDIO), "ichthyo", 5);
PM mm3 = asset::Media::create(key3, "Name-3");
Asset::Ident key4("Au-2", Category(AUDIO), "stega", 5);
PM mm4 = asset::Media::create(key4, "Name-4");
Asset::Ident key5("Au-1", Category(VIDEO), "ichthyo", 5);
PM mm5 = asset::Media::create(key5, "Name-5");
// ordering of keys
ASSERT (key1 == key2);
ASSERT (key2 != key3);
ASSERT (key3 != key4);
ASSERT (key4 != key5);
ASSERT (key1 != key5);
ASSERT (-1 == key2.compare(key3));
ASSERT (+1 == key3.compare(key2));
ASSERT (-1 == key3.compare(key4));
ASSERT (-1 == key4.compare(key5));
ASSERT (-1 == key1.compare(key5));
ASSERT (-1 == key2.compare(key5));
ASSERT (-1 == key3.compare(key5));
ASSERT (-1 == key1.compare(key3));
ASSERT (-1 == key1.compare(key4));
ASSERT (-1 == key2.compare(key4));
// ordering of Asset smart ptrs
ASSERT (mm1 == mm2);
ASSERT (mm2 != mm3);
ASSERT (mm3 != mm4);
ASSERT (mm4 != mm5);
ASSERT (mm1 != mm5);
ASSERT (mm2 < mm3);
ASSERT (mm2 <= mm3);
ASSERT (mm3 > mm2);
ASSERT (mm3 >= mm2);
ASSERT (mm3 < mm4);
ASSERT (mm4 < mm5);
ASSERT (mm1 < mm5);
ASSERT (mm2 < mm5);
ASSERT (mm3 < mm5);
ASSERT (mm1 < mm3);
ASSERT (mm1 < mm4);
ASSERT (mm2 < mm4);
}
};
/** Register this test class... */
LAUNCHER (OrderingOfAssets_test, "unit asset");
} // namespace test
} // namespace asset