Merge branch 'master' of git://git.pipapo.org/cinelerra3/ichthyo into library

This commit is contained in:
Christian Thaeter 2007-09-19 09:39:16 +02:00
commit 9bccc7b29e
46 changed files with 3115 additions and 182 deletions

50
AUTHORS Normal file
View file

@ -0,0 +1,50 @@
Cinelerra(2) Authors
====================
hv=Jack Crossfire <broadcast@earthling.net>
j6t=Johannes Sixt <johannes.sixt@telecom.at>
minmax=Andraz Tori <Andraz.tori1@guest.arnes.si>
herman=Herman Robak <herman@skolelinux.no>
baver=Richard Baverstock <baver@thebeever.com>
pere=Petter Reinholdtsen <pere@hungry.com>
tfheen=Tollef Fog Heen <tollef@add.no>
andreask=Andreas Kielb <andreaskielb@web.de>
theraz=Tyler Geddes <tgeddes@wgeddes.com>
dyce=Gergely Erdelyi <dyce@rovidzar.hu>
dreamlx=David Arendt <admin@prnet.org>
ga=Gustavo Iniguez <ga@kutxa.homeunix.org>
memenk=Michael Eric Menk <meklev@osys.grm.hia.no>
benjif=Benjamin Flaming <cinelerra@solobanjo.com>
cobra=Kevin Brosius <cobra@compuserve.com>
taraba=Mark Taraba <m_taraba@yahoo.com>
nate=Nathan Kurz <nate@verse.com>
mammique=Camille Harang <mammique@garbure.org>
kbielefe=Karl Bielefeldt <uhauufo02@sneakemail.com>
alexf=Alex Ferrer <alex@ftconsult.com>
pmdumuid=Pierre Dumuid <pierre.dumuid@adelaide.edu.au>
giskard=Riccardo Setti <giskard@autistici.org>
jstewart=Joe Stewart <jstewart@lurhq.com>
doudou=Sylvain Joyeux <doudou@melix.net>
rafael2k=Rafael Diniz <rafael@riseup.net>
nicolasm=Nicolas Maufrais <e.conti@gmx.net>
Involved in Design Studies / Prototypes for Cinelerra-3
=======================================================
cehteh=Christian Thaeter <ct@pipapo.org>
ichthyo=Hermann Vosseler <Ichthyostega@web.de>
plouj=Michael Ploujnikov <ploujj@gmail.com>
_______________________________________________________________
Further Credits
Parts of the Proc-Layer Implementation are heavily inspired by
The Loki Library
Copyright (c) 2001 by Andrei Alexandrescu
Loki is governed by a MIT-License.
See: http://loki-lib.sourceforge.net
and the book:
Alexandrescu, Andrei.
"Modern C++ Design: Generic Programming and Design
Patterns Applied". Copyright (c) 2001. Addison-Wesley.
ISBN 0201704315

340
COPYING Normal file
View file

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

6
INSTALL Normal file
View file

@ -0,0 +1,6 @@
Running / Installing Cinelerra-3 Prototype
==========================================
** to be written **

17
LICENSE Normal file
View file

@ -0,0 +1,17 @@
The Cinelerra source code is (C) by the original authors (see AUTHORS)
=======================================================================
Cinelerra is free software -- you may use and redistribute it under the
Terms and conditions of the GNU GENERAL PUBLIC LICENSE (GPL);
either version 2 of the License, or (at your option) any later version.
=======================================================================
For a copy of the GPL Version 2 see the file "COPYING"
In addition to the GPL's warranty stipulation, Cinelerra is distributed WITHOUT
GUARANTEED SUPPORT; without even the guarantee of ADDITIONAL LABOR. Support
that is not guaranteed includes technical support, compiler troubleshooting,
debugging, version matching, updating, among other additional labor which
may or may not be required to meet a user's requirements.

37
README Normal file
View file

@ -0,0 +1,37 @@
======================================
Cinelerra -- the video NLE for Linux
======================================
Cinelerra is a nonlinear video editing and compositing tool.
It understands some of the common multimedia formats
(quicktime, avi, ogg) and audio/video compression
codecs (divx, xvid, mpeg1/2/4, ...)
.
It features non-destructive editing, compositing tools,
a selection of effects plugins, processing in RGB, YUV
and RGB-float colormodels and the ability to mix media
with differing sizes and framerates.
For more information about Cinelerra visit http://cinelerra.org/
------------------------------
"Cinelerra-3" prototype code
------------------------------
**This source tree doesn't contain a working video editing application**
Rather, it contains some design studies and prototype code for improving
some aspects of the Cinelerra Application. This work may eventually
evolve into a new major release of Cinelerra.
As of 7/2007, we start here with some backend and render engine modules
together with some unit tests. You should find a wiki with detailed
design considerations and developer documentation and a UML model
(usable with BOUML 2.29) in the sibling directories.
Build Requirements
------------------
*to be written*

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

@ -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);
@ -82,4 +89,4 @@ namespace util
} // namespace cinelerra
} // namespace util

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

156
src/common/singleton.hpp Normal file
View file

@ -0,0 +1,156 @@
/*
SINGLETON.hpp - 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
*/
#ifndef CINELERRA_SINGLETON_H
#define CINELERRA_SINGLETON_H
#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.
* 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 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
{
typedef typename Threading<SI>::VolatileType SType;
typedef typename Threading<SI>::Lock ThreadLock;
static SType* pInstance_;
static bool isDead_;
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 SIDEEFFECT;
if (!pInstance_)
{
if (isDead_)
{
Life<SI>::onDeadReference();
isDead_ = false;
}
pInstance_ = Create<SI>::create();
Life<SI>::scheduleDelete (&destroy);
} }
ENSURE (pInstance_);
ENSURE (!isDead_);
return *pInstance_;
}
private:
/** @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

@ -0,0 +1,158 @@
/*
SINGLETONPOLICIES.hpp - how to manage creation, lifecycle and multithreading
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
*/
#ifndef CINELERRA_SINGLETONPOLICIES_H
#define CINELERRA_SINGLETONPOLICIES_H
#include "common/multithread.hpp"
#include "common/error.hpp"
#include <vector>
namespace cinelerra
{
namespace singleton
{
/* == several Policies usable in conjunction with cinelerra::Singleton == */
/**
* Policy for creating the Singleton instance statically
*/
template<class S>
struct Static
{
static S* create ()
{
#ifdef DEBUG
static uint callCount (0);
ASSERT ( 0 == callCount++ );
#endif
static char buff[sizeof(S)];
return new(buff) S();
}
static void destroy (S* pSi)
{
pSi-> ~S();
}
};
/**
* Policy for creating the Singleton instance heap allocated
*/
template<class S>
struct Heap
{
static S* create () { return new S; }
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
{
/** implements the Singleton removal by calling
* 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 (DelFunc kill_the_singleton)
{
class DeleteTrigger
{
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
}
};
REQUIRE (kill_the_singleton);
static DeleteTrigger finally;
finally.schedule (kill_the_singleton);
}
static void onDeadReference ()
{
throw error::Logic ("Trying to access the a Singleton instance that has "
"already been released or finished its lifecycle.");
}
};
/**
* Policy for handling multithreaded access to the singleton instance
* @todo actually implement this policy using the cinelerra databackend.
*/
template<class S>
struct Multithreaded
{
typedef volatile S* VolatileType;
typedef cinelerra::Thread::Lock<S> Lock;
};
/**
* Policy just ignoring thread safety
*/
template<class S>
struct IgnoreThreadsafety
{
typedef S VolatileType;
struct Lock {};
};
} // namespace singleton
} // namespace cinelerra
#endif

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

@ -27,6 +27,8 @@
#include <string>
#include <cstring>
#include "nobugcfg.h" ///////////////////TODO: just temporarily!!!!
namespace util
{
@ -36,19 +38,22 @@ namespace util
/** a family of util functions providing a "no value whatsoever" test.
Works on strings and all STL containers, includes NULL test for pointers */
template <class CONT>
inline bool isnil(const CONT& container)
inline bool
isnil(const CONT& container)
{
return container.empty();
}
template <class CONT>
inline bool isnil(const CONT* pContainer)
inline bool
isnil(const CONT* pContainer)
{
return !pContainer || pContainer->empty();
}
template <>
inline bool isnil(const char* pCStr)
inline bool
isnil(const char* pCStr)
{
return !pCStr || 0 == std::strlen(pCStr);
}
@ -56,14 +61,16 @@ namespace util
/** cut a numeric value to be >=0 */
template <typename NUM>
inline NUM noneg (NUM val)
inline NUM
noneg (NUM val)
{
return (0<val? val : 0);
}
/** shortcut for containment test on a map */
template <typename MAP>
inline bool contains (MAP& map, typename MAP::key_type& key)
inline bool
contains (MAP& map, typename MAP::key_type& key)
{
return map.find(key) != map.end();
}
@ -74,16 +81,54 @@ 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);
}
/** produce an identifier based on the given string.
* 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
*/
string sanitize (const string& org);
/** convienience shortcut: conversion to c-String via string.
* usable for printf with objects providing to-string conversion.
*/
inline const char*
cStr (const string& org)
{
return org.c_str();
}
} // 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

@ -50,6 +50,8 @@
/* declare flags used throughout the code base... */
NOBUG_DECLARE_FLAG(config);
NOBUG_DECLARE_FLAG(test);
NOBUG_DECLARE_FLAG(assetmem);
NOBUG_DECLARE_FLAG(mobjectmem);
#endif /*NOBUGCFG_H ======= (End) Part 1: DECLARATIONS ======== */
@ -74,6 +76,8 @@
/* flags used throughout the code base... */
NOBUG_CPP_DEFINE_FLAG(config);
NOBUG_CPP_DEFINE_FLAG(test);
NOBUG_CPP_DEFINE_FLAG_LIMIT(assetmem, LOG_WARNING);
NOBUG_CPP_DEFINE_FLAG_LIMIT(mobjectmem, LOG_WARNING);
#include "common/error.hpp"

View file

@ -22,48 +22,112 @@
#include "proc/asset.hpp"
#include "proc/asset/category.hpp"
#include "proc/assetmanager.hpp"
#include "common/util.hpp"
namespace proc_interface
#include <boost/format.hpp>
#include <iostream>
#include <string>
using boost::format;
using util::cStr;
namespace asset
{
Asset::Ident::Ident(const string& n, const Category& cat, const string& o, const uint ver)
: name(util::sanitize (n)),
category(cat), org(o), version(ver)
{ }
/** Asset is a Interface class; usually, objects of
* concrete subclasses are created via specialized Factories
*/
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=%lu) : adr=%x", size_t(id), this );
}
/**
* 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
Asset::Ident::operator string () const
{
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.
* May be empty. The head of this list can be considered the primary prerequisite
*/
vector<PAsset>
Asset::getParents ()
Asset::getParents () const
{
UNIMPLEMENTED ("Asset dependencies.");
}
/** All the other assets requiring this asset to be functional.
* For example, all the clips depending on a given media file.
* May be empty. The dependency relation is transitive.
*/
vector<PAsset>
Asset::getDependant () const
{
UNIMPLEMENTED ("Asset dependencies.");
}
/**
* All the other assets requiring this asset to be functional. For example, all the clips depending on a given media file. May be empty. The dependency relation is transitive.
*/
vector<PAsset>
Asset::getDependant ()
{
}
/**
* weather this asset is swithced on and consequently included in the fixture and participates in rendering
* weather this asset is swithced on and consequently included
* in the fixture and participates in rendering.
*/
bool
Asset::isActive ()
Asset::isActive () const
{
UNIMPLEMENTED ("enable/disable Assets.");
}
/**
* change the enabled status of this asset. Note the corresponding #isActive predicate may depend on the enablement status of parent assets as well
* change the enablement status of this asset.
* @note the corresponding #isActive predicate may depend
* on the enablement status of parent assets as well.
*/
void
Asset::enable () throw(cinelerra::error::State)
{
UNIMPLEMENTED ("enable/disable Assets.");
}
/** release all links to other Asset objects held internally. */
void
Asset::unlink ()
{
UNIMPLEMENTED ("deleting Assets.");
}
/** variant dropping only the links to the given Asset */
void
Asset::unlink (IDA target)
{
UNIMPLEMENTED ("deleting Assets.");
}
} // namespace proc_interface
} // namespace asset

View file

@ -20,62 +20,185 @@
*/
/** @file asset.hpp
** Proc-Layer Interface: Assets.
** Declares the Asset top level Interface, the Asset::Ident identification tuple
** 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.
**
** Assets are handled by a hierarchy of interfaces. Below the top level Asset interface
** there are interfaces for various different <i>Kinds</i> 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<Media>. 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
*/
#ifndef PROC_INTERFACE_ASSET_H
#define PROC_INTERFACE_ASSET_H
#include "proc/asset/category.hpp"
#include "common/error.hpp"
#include <cstddef>
#include <string>
#include <vector>
#include <set>
#include "common/error.hpp"
#include <tr1/memory>
#include <boost/utility.hpp>
using std::string;
using std::vector;
using std::set;
namespace asset { class Category; }
namespace proc_interface
namespace asset
{
typedef void* PAsset; //////TODO
using std::size_t;
using std::tr1::shared_ptr;
/**
* Superinterface describing especially the bookeeping properties of Assets
/**
* thin wrapper around a size_t hash ID
* used as primary key for all Asset objects.
* The Templace parameter is intended for tagging
* the ID with type information, causing the
* compiler to select specialized behaviour
* for the different kinds of Assets.
* @see Asset
* @see AssetManager#getID generating ID values
* @see asset::Media
* @see ID<asset::Media>
*/
class Asset
template<class KIND>
class ID
{
public:
/** Asset primary key. */
const long id;
const size_t hash;
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;
/** element ID, comprehensible but sanitized.
* The tuple (category, name, org) is unique.
/**
* Superinterface describing especially bookeeping properties.
* As of 09/2007, there are four <b>Kinds</b> of Assets, each
* comprising a sub-Interface of the Asset Interface:
* <ul><li>asset::Media representing mediafiles</li>
* <li>asset::Proc representing media data processing components (e.g. Effects)</li>
* <li>asset::Struct representing structural components used in the sesion (e.g. Tracks)</li>
* <li>asset::Meta representing meta objects created while editing (e.g. Automation)</li>
* </ul>
* 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
* automatically. I is possible to copy the PAsset (smart pointer) though.
*
* @since 09/2007
* @author Ichthyo
*/
class Asset : private boost::noncopyable
{
public:
/**
* a POD comprised of all the information
* sufficiently identifying any given Asset.
*/
const string name;
struct Ident
{
/** element ID, comprehensible but sanitized.
* The tuple (category, name, org) is unique.
*/
string name;
/** primary tree like classification of the asset.
* Includes the distinction of different kinds of Assets,
* like Media, Audio, Video, Effects... */
asset::Category category;
/** origin or authorship id.
* Can be a project abbreviation, a package id or just the authors nickname or UID.
* This allows for the compnent name to be more generic (e.g. "blur").
* Default for all assets provided by the core cinelerra-3 codebase is "cin3".
*/
const string org;
/** version number of the thing or concept represented by this asset.
* Of each unique tuple (name, category, org) there will be only one version
* in the whole system. Version 0 is reserved for internal purposes.
* Versions are considered to be ordered, and any higher version is
* supposed to be fully backwards compatible to all previous versions.
*/
const uint version;
/**primary tree like classification of the asset */
const asset::Category* category;
/** origin or authorship id.
* Can be a project abbreviation, a package id or just the authors nickname or UID.
* This allows for the compnent name to be more generic (e.g. "blur").
* Default for all assets provided by the core cinelerra-3 codebase is "cin3".
*/
const string org;
/** version number of the thing or concept represented by this asset.
* Of each unique tuple (name, category, org) there will be only one version
* in the whole system. Version 0 is reserved for internal purposes.
* Versions are considered to be ordered, and any higher version is
* supposed to be fully backwards compatible to all previous versions.
*/
const unsigned int version;
Ident (const string& n,
const Category& cat,
const string& o,
const uint ver);
/** @note equality ignores version differences */
bool operator== (const Ident& other) const
{
return org == other.org
&& 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.
/** additional classification, selections or departments this asset belongs to.
* Groups are optional, non-exclusive and may be overlapping.
*/
@ -88,38 +211,107 @@ namespace proc_interface
* perferably "in one line". To be localized. */
const string longDesc;
protected:
/** Asset is a Interface class; usually, objects of
* concrete subclasses are created via specialized Factories.
* Calling this base ctor causes registration with AssetManager.
*/
Asset (const Ident& idi);
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
* and the Asset manager. Calling \c release() breaks interconnectons
* to other Assets in the central Object network comprising the session.
* It is up to the AssetManager to asure the notification of any other
* components that may need to release references to the Asset object
* beeing removed. The rationale is, after releasing all interlinkings,
* when the AssetManager removes its DB entry for this asset, the
* smart pointer goes out of scope and triggers cleanup.
*/
virtual void unlink ();
/** variant of #unlink() dropping only the links to the given specific
* Asset, leaving all other links intact. Usable for propagating */
virtual void unlink (IDA target);
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
*/
vector<PAsset> getParents () ;
vector<shared_ptr<Asset> >
getParents () const;
/** All the other assets requiring this asset to be functional.
* For example, all the clips depending on a given media file.
* May be empty. The dependency relation is transitive.
*/
vector<PAsset> getDependant () ;
vector<shared_ptr<Asset> >
getDependant () const;
/** weather this asset is swithced on and consequently
* included in the fixture and participates in rendering
*/
bool isActive () ;
bool isActive () const;
/** change the enabled status of this asset.
* Note the corresponding #isActive predicate may
* depend on the enablement status of parent assets as well
*/
void enable () throw(cinelerra::error::State);
};
/** 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); }
} // namespace proc_interface
/** 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
namespace asset
namespace proc_interface
{
using proc_interface::Asset;
using asset::Asset;
using asset::Category;
using asset::ID;
using asset::IDA;
using asset::PAsset;
}
#endif

View file

@ -22,10 +22,49 @@
#include "proc/asset/category.hpp"
#include "common/util.hpp"
#include "nobugcfg.h"
#include <boost/algorithm/string.hpp>
using boost::algorithm::starts_with;
using util::isnil;
namespace asset
{
/** human readable representation of the asset::Category.
* @todo to be localized.
*/
Category::operator string () const
{
char *kinds[6] = { "AUDIO"
, "VIDEO"
, "EFFECT"
, "CODEC"
, "STRUCT"
, "META"
};
REQUIRE ( 0<=kind_ && kind_< 6 );
string str (kinds[kind_]);
if (!isnil (path_))
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

@ -24,17 +24,87 @@
#ifndef ASSET_CATEGORY_H
#define ASSET_CATEGORY_H
#include <string>
#include <iostream>
#include <boost/functional/hash.hpp>
namespace asset
{
using std::string;
using std::ostream;
/** top-level distinction of different Kinds of Assets.
* For convienience, this classification is slightly denormalized,
* as AUDIO, and VIDEO are both asset::Media objects, EFFECT and CODEC
* are asset::Proc objects, while STRUCT and META refer directly to
* the corresponding Interfaces asset::Struct and asset::Meta.
*/
enum Kind
{
AUDIO,
VIDEO,
EFFECT,
CODEC,
STRUCT,
META
};
/**
* tree like classification of Assets
* Tree like classification of Assets.
* By virtue of the Category, Assets can be organized in nested bins (folders).
* This includes the distinction of different kinds of Assets, like Audio, Video, Effects...
*
* @todo could be far more elaborate. could be a singleton like centralized tree, while
* just holding references to Catetory nodes in the individual Asset. At the moment,
* we use just the most simplistic implementation and handle Category objects
* using value semantics.
*/
class Category
{};
{
public:
private:
Kind kind_;
string path_;
public:
Category (const Kind root, string subfolder ="")
: kind_(root), path_(subfolder) {};
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 isWithin (const Category&) const;
operator string () const;
friend size_t hash_value (const Category& cat)
{
size_t hash = 0;
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

130
src/proc/asset/db.hpp Normal file
View file

@ -0,0 +1,130 @@
/*
DB.hpp - registry holding known Asset instances.
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 ASSET_DB_H
#define ASSET_DB_H
#include "proc/asset.hpp"
#include <tr1/unordered_map>
#include <boost/utility.hpp>
namespace asset
{
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
/* ===== hash implementations ===== */
size_t
hash_value (const Asset::Ident& idi)
{
size_t hash = 0;
boost::hash_combine(hash, idi.org);
boost::hash_combine(hash, idi.name);
boost::hash_combine(hash, idi.category);
return hash;
}
size_t
hash_value (const Asset& asset)
{
return asset.getID();
}
/**
* trivial hash functor.
* returns any hash value unmodified.
* For building a hashtable with keys
* already containing valid hash values.
*/
struct IdentityHash
: public std::unary_function<size_t, size_t>
{
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.
* As of 8/2007 implemented by a hashtable.
*/
class DB : private boost::noncopyable
{
IdHashtable table;
DB () : table() {}
~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;
}
};
} // namespace asset
#endif

View file

@ -21,13 +21,127 @@
* *****************************************************/
#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; ///< storage for the static MediaFactory instance
/** 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.
* @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";
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);
}
ASSERT (pM);
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 aMang.getAsset (pM->getID()); // note: because we query with an ID<Media>,
// we get a Media smart ptr.
}
/** 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, const Category& cat)
{
Asset::Ident key(extractName(file), cat, "cin3", 1);
return operator() (key, file);
}
MediaFactory::PType
MediaFactory::operator() (const string& file, asset::Kind kind)
{
Category cat(kind);
return operator() (file, cat);
}
MediaFactory::PType
MediaFactory::operator() (const char* file, const Category& cat)
{
if (!file) file = "";
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, string(file));
}
} // namespace asset

View file

@ -21,26 +21,93 @@
*/
/** @file media.hpp
** Media data is 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::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
#include "proc/asset.hpp"
#include "common/factory.hpp"
namespace asset
{
class Media;
class MediaFactory;
template<>
class ID<Media> : public ID<Asset>
{
public:
ID (size_t id);
ID (const Media&);
};
/**
* key abstraction: media-like assets
*/
class Media : public proc_interface::Asset
class Media : public Asset
{
string filename_;
public:
static MediaFactory create;
const string& getFilename () const { return filename_; }
virtual const ID<Media>& getID() const ///< @return ID of kind Media
{
return static_cast<const ID<Media>& > (Asset::getID());
}
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
inline ID<Media>::ID(size_t id) : ID<Asset> (id) {};
inline 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, 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, const Category& cat);
PType operator() (const char* file, asset::Kind);
};
} // namespace asset
#endif

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

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

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

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

View file

@ -22,29 +22,127 @@
#include "proc/assetmanager.hpp"
#include "proc/asset/db.hpp"
namespace proc_interface
#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) {}
};
/**
* registers an asset object in the internal DB, providing its unique key
// ------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.
*/
long
AssetManager::reg (string& name, string& category, string& org, uint version)
//throw(cinelerra::error::Invalid)
Singleton<AssetManager> AssetManager::instance;
AssetManager::AssetManager ()
: registry (Singleton<asset::DB>() ())
{ }
/** provide the unique ID for given Asset::Ident tuple */
ID<Asset>
AssetManager::getID (const Asset::Ident& idi)
{
return asset::hash_value (idi);
}
/**
* find and return corresponging object
* 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> ////TODO: does this work????
KIND
AssetManager::getAsset (long id) ////throw(cinelerra::Invalid)
template<class KIND>
ID<KIND>
AssetManager::reg (KIND* obj, const Asset::Ident& idi)
throw(cinelerra::error::Invalid)
{
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 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)
{
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);
}
@ -52,19 +150,83 @@ namespace proc_interface
* @return true if the given id is registered in the internal asset DB
*/
bool
AssetManager::known (long id)
AssetManager::known (IDA id)
{
return ( registry.get (ID<Asset>(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 <i>together with all its dependants</i> from the internal DB
*/
void
AssetManager::remove (long id) /////throw(cinelerra::Invalid, cinelerra::State)
{
}
AssetManager::remove (IDA id)
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;
}
} // namespace asset
} // namespace proc_interface
/************************************************************/
/* 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<Asset> AssetManager::reg (Asset* obj, const Asset::Ident& idi);
template shared_ptr<Asset> AssetManager::getAsset (const ID<Asset>& id) throw(cinelerra::error::Invalid);
template shared_ptr<Media> AssetManager::getAsset (const ID<Media>& id) throw(cinelerra::error::Invalid);
template shared_ptr<Proc> AssetManager::getAsset (const ID<Proc>& id) throw(cinelerra::error::Invalid);
template shared_ptr<Struct> AssetManager::getAsset (const ID<Struct>& id) throw(cinelerra::error::Invalid);
template shared_ptr<Meta> AssetManager::getAsset (const ID<Meta>& id) throw(cinelerra::error::Invalid);
} // namespace asset

View file

@ -20,48 +20,112 @@
*/
/** @file assetmanager.hpp
** Proc-Layer Interface: Asset Lookup and Organization.
** Declares the AssetManager interface used to access individual
** Asset instances.
**
** These classes are placed into namespace asset and proc_interface.
**
** @see asset.hpp
** @see mobject.hpp
*/
#ifndef PROC_INTERFACE_ASSETMANAGER_H
#define PROC_INTERFACE_ASSETMANAGER_H
#include <string>
#include "proc/asset.hpp"
#include "common/error.hpp"
#include "common/singleton.hpp"
#include <cstddef>
#include <string>
#include <list>
#include <boost/utility.hpp>
using std::string;
using std::list;
namespace asset
{
class DB;
/**
* Facade for the Asset subsystem
*/
class AssetManager : private boost::noncopyable
{
asset::DB & registry;
public:
static cinelerra::Singleton<AssetManager> instance;
/** provide the unique ID for given Asset::Ident tuple */
static ID<Asset> getID (const Asset::Ident&);
/** find and return corresponging object */
template<class KIND>
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);
/** 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.
* @internal used by the Asset base class ctor to create Asset::id.
*/
template<class KIND>
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
namespace proc_interface
{
using asset::AssetManager;
}
/**
* Facade for the Asset subsystem
*/
class AssetManager
{
int bla;
public:
/** registers an asset object in the internal DB, providing its unique key
*/
static long reg (string& name, string& category, string& org, uint version)
;
// throw(cinelerra::error::Invalid);
/** find and return corresponging object */
template<class KIND>
// void* /////////////////TODO
KIND
getAsset (long id) ;///throw(cinelerra::error::Invalid);
/** @return true if the given id is registered in the internal asset DB */
bool known (long id) ;
/**remove the given asset from the internal DB.
* <i>together with all its dependants</i>
*/
void remove (long id) ;///throw(cinelerra::error::Invalid, cinelerra::error::State);
};
} // namespace proc_interface
#endif

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
@ -133,3 +137,32 @@ out: --> Testgroup=TestGroupID
out: --> Test-ID =SingleTestID
out: --> remaining=SingleTestID spam --eggs
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
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

@ -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

@ -48,7 +48,7 @@ moduledirs = globRootdirs('*')
#
# have to treat the plugin-example specially.
isnt_plugin = lambda dir : dir!='plugin'
isnt_plugin = lambda dir : not (dir=='plugin' or dir=='locking')
moduledirs = filter(isnt_plugin, moduledirs)
pluginExe = treatPluginTestcase(env)

View file

@ -0,0 +1,69 @@
/*
SanitizedIdentifier(Test) - remove non-standard-chars and punctuation
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 "nobugcfg.h"
#include "common/test/run.hpp"
#include "common/util.hpp"
#include <iostream>
using std::cout;
namespace util
{
namespace test
{
class SanitizedIdentifier_test : public Test
{
virtual void run (Arg arg)
{
print_clean ("Word");
print_clean ("a Sentence");
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)
{
cout << "'" << org << "' --> '" << sanitize(org) << "'\n";
}
};
LAUNCHER (SanitizedIdentifier_test, "unit common");
} // namespace test
} // namespace util

View file

@ -0,0 +1,140 @@
/*
Singleton(Test) - unittest for our Singleton template
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/testtargetobj.hpp"
#include "common/test/run.hpp"
#include "common/singleton.hpp"
#include "common/util.hpp"
#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;
namespace cinelerra
{
namespace test
{
/**
* Target object to be instantiated as Singleton
* Allocates a variable amount of additional heap memory
* and prints diagnostic messages.
*/
class TargetObj : public TestTargetObj
{
public:
static int cnt;
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;
/*******************************************************************
* @test implement a Singleton class using our Singleton Template.
* Expected results: no memory leaks.
* @see cinelerra::Singleton
* @see cinelerra::singleton::Static
* @see cinelerra::singleton::Heap
*/
class Singleton_test : public Test
{
typedef boost::function<TargetObj& ()> InstanceAccessFunc;
InstanceAccessFunc instance;
virtual void run(Arg arg)
{
uint num= isnil(arg)? 1 : lexical_cast<uint>(arg[1]);
testStaticallyAllocatedSingleton (num++);
testHeapAllocatedSingleton (num++);
}
/** @test parametrize the Singleton creation such as to create
* the single TargetObj instance as a static variable.
*/
void testStaticallyAllocatedSingleton (uint num)
{
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 (uint num)
{
Singleton<TargetObj,singleton::Heap> single;
instance = single;
useInstance (num, "heap allocated");
}
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();
ASSERT ( &t1 == &t2, "not a Singleton, got two different instances." );
cout << "calling a non-static method on the Singleton instance\n"
<< string (t1) << "\n";
}
};
/** Register this test class... */
LAUNCHER (Singleton_test, "unit common");
} // namespace test
} // namespace cinelerra

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

@ -46,7 +46,7 @@ namespace cinelerra
namespace test
{
/**
* Target object to be created by the Test-Factory.
* Target object to be created by Test-Factories or as Singleton.
* Allocates a variable amount of additional heap memory
* and prints diagnostic messages.
*/

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,15 +22,16 @@
#include "common/test/run.hpp"
//#include "common/factory.hpp"
//#include "common/util.hpp"
#include "common/util.hpp"
//#include <boost/format.hpp>
#include <iostream>
#include "proc/assetmanager.hpp"
#include "proc/asset/media.hpp"
#include "proc/asset/proc.hpp"
//using boost::format;
#include "proc/asset/assetdiagnostics.hpp"
using util::isnil;
using std::string;
using std::cout;
namespace asset
@ -49,7 +50,135 @@ 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()
{
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("testfile1.mov", cat);
PM mm3 = asset::Media::create("testfile2.mov", VIDEO);
// Assets have been registered and can be retrieved by ID
AssetManager& aMang = AssetManager::instance();
ASSERT (aMang.getAsset (mm1->getID()) == mm1);
ASSERT (aMang.getAsset (mm2->getID()) == mm2);
ASSERT (aMang.getAsset (mm3->getID()) == mm3);
ASSERT (aMang.getAsset (mm1->getID()) != mm2);
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 (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 specifying wrong Asset kind....
aMang.getAsset (ID<asset::Proc>(mm1->getID()));
NOTREACHED;
}
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 == "testfile1");
ASSERT (mm3->ident.name == "testfile2");
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 (mm1->ident.org == "ichthyo");
ASSERT (mm2->ident.org == "cin3");
ASSERT (mm3->ident.org == "cin3");
ASSERT (mm1->ident.version == 5);
ASSERT (mm2->ident.version == 1);
ASSERT (mm3->ident.version == 1);
ASSERT (mm1->getFilename() == "testfile.mov");
ASSERT (mm2->getFilename() == "testfile1.mov");
ASSERT (mm3->getFilename() == "testfile2.mov");
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

View file

@ -1,6 +1,6 @@
format 40
"AssetManager" // ProcessingLayer::AssetManager
revision 4
"Asset" // ProcessingLayer::Asset
revision 6
modified_by 5 "hiv"
// class settings
//class diagram settings
@ -228,18 +228,13 @@ ${members}};
explicit_switch_type ""
comment "Facade for the Asset subsystem"
operation 132357 "register"
class_operation public explicit_return_type "long"
nparams 4
param inout name "name" explicit_type "string"
param inout name "category" explicit_type "string"
param inout name "org" explicit_type "string"
param inout name "uint" explicit_type "version"
nexceptions 1
explicit_exception "Invalid"
cpp_decl " ${comment}${friend}${static}${inline}${virtual}${type} ${name} ${(}${t0} & ${p0}, ${t1} & ${p1}, ${t2} & ${p2}, ${t3}& ${p3}${)}${const}${volatile} ${throw}${abstract};"
operation 133125 "getID"
class_operation public explicit_return_type ""
nparams 1
param in name "idi" type class_ref 136453 // Asset
cpp_decl " ${comment}${friend}${static}${inline}${virtual}${type} ${name} ${(}${)}${const}${volatile} ${throw}${abstract};"
cpp_def "${comment}${inline}${type}
${class}::${name} ${(}${t0} & ${p0}, ${t1} & ${p1}, ${t2} & ${p2}, ${t3}& ${p3}${)}${const}${volatile} ${throw}${staticnl}
${class}::${name} ${(}${)}${const}${volatile} ${throw}${staticnl}
{
${body}
}
@ -247,7 +242,6 @@ ${class}::${name} ${(}${t0} & ${p0}, ${t1} & ${p1}, ${t2} & ${p2}, ${t3}& ${p3}$
"
comment "registers an asset object in the internal DB, providing its unique key"
end
operation 132485 "getAsset"
@ -307,6 +301,38 @@ ${class}::${name} ${(}${t0} ${p0}${)}${const}${volatile} ${throw}${staticnl}
comment "remove the given asset <i>together with all its dependants</i> from the internal DB"
end
operation 132357 "reg"
class_operation protected explicit_return_type "long"
nparams 4
param inout name "name" explicit_type "string"
param inout name "category" explicit_type "string"
param inout name "org" explicit_type "string"
param inout name "uint" explicit_type "version"
nexceptions 1
explicit_exception "Invalid"
cpp_decl " ${comment}${friend}${static}${inline}${virtual}${type} ${name} ${(}${t0} & ${p0}, ${t1} & ${p1}, ${t2} & ${p2}, ${t3}& ${p3}${)}${const}${volatile} ${throw}${abstract};"
cpp_def "${comment}${inline}${type}
${class}::${name} ${(}${t0} & ${p0}, ${t1} & ${p1}, ${t2} & ${p2}, ${t3}& ${p3}${)}${const}${volatile} ${throw}${staticnl}
{
${body}
}
"
comment "registers an asset object in the internal DB, providing its unique key"
end
classrelation 142085 // registry (<unidirectional association>)
relation 140293 --->
a role_name "registry" multiplicity "1" protected
comment "@internal Table or DB holding all registered asset instances."
cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value};
"
classrelation_ref 142085 // registry (<unidirectional association>)
b multiplicity "1" parent class_ref 138373 // DB
end
end
class 136709 "Media"
@ -585,5 +611,19 @@ ${inlines}
b multiplicity "" parent class_ref 137093 // Meta
end
end
class 138373 "DB"
visibility package
cpp_decl "${comment}${template}class ${name}${inherit}
{
${members} };
${inlines}
"
java_decl ""
idl_decl ""
explicit_switch_type ""
comment "Implementation of the registry holding all Asset instances known to the Asset Manager subsystem. As of 8/2007 implemented by a hashtable."
end
end
end

View file

@ -1,6 +1,6 @@
format 40
"asset" // design::codegen::proc::asset
revision 4
revision 5
modified_by 5 "hiv"
// class settings
//class diagram settings
@ -544,5 +544,44 @@ ${namespace_end}"
end
comment "structural asset holding the configuration of a track in the EDL"
end
artifact 137861 "db"
stereotype "source"
cpp_h "/*
${NAME}.hpp - ${description}
@{CopyrightClaim}@{GPLHeader}
*/
#ifndef ${NAMESPACE}_${NAME}_H
#define ${NAMESPACE}_${NAME}_H
${includes}
${declarations}
${namespace_start}
${definition}
${namespace_end}
#endif
"
cpp_src "/*
${Name} - ${description}
@{CopyrightClaim}@{GPLHeader}
* *****************************************************/
${includes}
${namespace_start}
${members}
${namespace_end}"
associated_classes
class_ref 138373 // DB
end
comment "registry holding known Asset instances."
end
end
end

View file

@ -6,11 +6,11 @@ classcanvas 128005 class_ref 136453 // Asset
end
classcanvas 128133 class_ref 136581 // AssetManager
draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode class drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default
xyz 289 26 2000
xyz 290 16 2005
end
packagecanvas 128517
package_ref 128133 // AssetManager
xyzwh 217 182 1994 575 534
package_ref 128133 // Asset
show_context_mode namespace xyzwh 217 182 1994 575 534
classcanvas 128645 class_ref 136709 // Media
draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default
xyz 273 347 2005
@ -63,6 +63,10 @@ classcanvas 132997 class_ref 138245 // Dataset
draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default
xyz 719 445 2000
end
classcanvas 133253 class_ref 138373 // DB
draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default
xyz 486 233 2000
end
relationcanvas 129157 relation_ref 138117 // <realization>
geometry VHV
from ref 128645 z 1999 to point 293 315
@ -127,7 +131,13 @@ relationcanvas 133125 relation_ref 139781 // <generalisation>
from ref 132997 z 1999 to ref 129029
no_role_a no_role_b
no_multiplicity_a no_multiplicity_b
relationcanvas 133381 relation_ref 140293 // <unidirectional association>
geometry HV
from ref 128133 z 1999 to point 506 93
line 133637 z 1999 to ref 133253
role_a_pos 518 208 3000 no_role_b
multiplicity_a_pos 492 208 3000 multiplicity_b_pos 386 104 3000
line 128261 -_-_ geometry HV
from ref 128005 z 1999 to point 330 150
from ref 128005 z 1999 to point 331 150
line 128389 z 1999 to ref 128133
end

View file

@ -1,20 +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
package_ref 128005 // design
class_ref 136453 // Asset
class_ref 136581 // AssetManager
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

View file

@ -514,12 +514,13 @@ ColorPalette
SiteUrl</pre>
</div>
<div title="Asset" modifier="Ichthyostega" modified="200709021530" created="200708100337" tags="def classes" changecount="9">
<div title="Asset" modifier="Ichthyostega" modified="200709040256" created="200708100337" tags="def classes" changecount="11">
<pre>Asset management is a subsystem on its own. Assets are &quot;things&quot; that can be loaded into a session, like Media, Clips, Effects, Transitions. It is the &quot;bookkeeping view&quot;, while the EDL is the &quot;manipulation and process view&quot;. Some Assets can be //loaded// and a collection of Assets is saved with eatch Session. Besides, there is a collection of basic Assets allways available by default.
The Assets are important reference points holding the information needed to access external resources. For example, an Clip asset can reference a Media asset, which in turn holds the external filename from which to get the media stream. For Effects, the situatin is similar. Assets thus serve two quite distinct purposes. One is to load, list, group serarch and browse them, and to provide an entry point to create new or get at existing MObjects in the EDL, while the other purpose is to provide attribute and property informations to the inner parts of the engine, while at the same time isolating and decoupling them from environmental details.
The Assets are important reference points holding the information needed to access external resources. For example, an Clip asset can reference a Media asset, which in turn holds the external filename from which to get the media stream. For Effects, the situation is similar. Assets thus serve two quite distinct purposes. One is to load, list, group search and browse them, and to provide an entry point to create new or get at existing MObjects in the EDL, while the other purpose is to provide attribute and property informations to the inner parts of the engine, while at the same time isolating and decoupling them from environmental details.
We can distinguish several different Kinds of Assets, each one with specific properties. While all these Kinds of Assets implement the basic Asset interface, they themselfs are the __key abstractions__ of the asset management view. Mostly, their interfaces will be used directly, because they are quite different in behaviour. Thus it is common to see asset related operations being templated on the Asset Kind.
&amp;rarr; see also [[Creating and registering Assets|AssetCreation]]
[img[Asset Classess|uml/fig130309.png]]
!Media Asset
@ -547,9 +548,16 @@ Some additional, virtual facilities created in the course of the editing process
&amp;rarr; MetaAsset {{red{to be defined}}}
!!!!still to be worked out..
is how to implement the relationship between [[MObject]]s and Assets. Do we use direct pointers, or do we prefer an ID + central registry approach? And how to handle the removal of an Asset (&amp;rarr; see also [[analysis of mem management|ManagementAssetRelation]])
is how to implement the relationship between [[MObject]]s and Assets. Do we use direct pointers, or do we prefer an ID + central registry approach? And how to handle the removal of an Asset
&amp;rarr; see also [[analysis of mem management|ManagementAssetRelation]]
&amp;rarr; see also [[Creating Objects|ObjectCreation]], especially [[Assets|AssetCreation]]
</pre>
</div>
<div title="AssetCreation" modifier="Ichthyostega" created="200709040307" changecount="1">
<pre>Assets are created by a Factories returning smart pointers; the Asset creation is bound to specific use cases and //only available// for these specific situations. There is no generic Asset Factory.
For every Asset we generate a __Ident tuple__ and a long ID (hash) derived from this Ident tuple. The constructor of the abstract base class {{{Asset}}} takes care of this step and automatically registeres the new Asset object with the AssetManager. Typically, the factory methods for concrete Asset classes provide some shortcuts providing sensible default values for some of the Ident tuple data fields. They may take additional parameters &amp;mdash; for example the factory method for creating {{{asset::Media}}} takes a filename (and may at some point in the future aply &quot;magic&quot; based on examination of the file)</pre>
</div>
<div title="Automation" modifier="Ichthyostega" modified="200708100315" created="200706250751" tags="def" changecount="5">
<pre>Automation is treated as a function over time. It is always tied to a specific Parameter (which can thus be variable over the course of the timeline). All details //how// this function is defined are completely abstracted away. The Parameter uses a ParamProvider to get the value for a given Time (point). Typically, this will use linear or bezier interpolation over a set of keyframes internally. Parameters can be configured to have different value ranges and distribution types (on-off, stepped, continuous, bounded)
@ -940,11 +948,13 @@ For this Cinelerra3 design, we could consider making GOP just another raw media
&amp;rarr;see in [[Wikipedia|http://en.wikipedia.org/wiki/Group_of_pictures]]
</pre>
</div>
<div title="ImplementationDetails" modifier="Ichthyostega" modified="200708100408" created="200708080322" tags="overview" changecount="4">
<div title="ImplementationDetails" modifier="Ichthyostega" modified="200709040256" created="200708080322" tags="overview" changecount="6">
<pre>This wiki page is the entry point to detail notes covering some technical decisions, details and problems encountered in the course of the implementation of the Cinelerra Renderengine, the Builder and the related parts.
* [[Packages, Interfaces and Namespaces|InterfaceNamespaces]]
* [[Memory Management Issues|MemoryManagement]]
* [[Creating and registering Assets|AssetCreation]]
* [[Creating new Objects|ObjectCreation]]
</pre>
</div>
@ -1298,8 +1308,8 @@ From experiences with other middle scale projects, I prefer having the test code
* {{red{and what else?}}}
</pre>
</div>
<div title="MObjects" modifier="MichaelPloujnikov" modified="200706271500" created="200706190636" tags="overview" changecount="7">
<pre>The MObjects Subsystem contains everything related to the [[EDL]] and the various Media Objects placed within it. Examples for [[MObjects|MObject]] being:
<div title="MObjects" modifier="Ichthyostega" modified="200709030128" created="200706190636" tags="overview" changecount="8">
<pre>The ~MObjects Subsystem contains everything related to the [[EDL]] and the various Media Objects placed within. It is complemented by the Asset Management (see &amp;rarr; [[Asset]]). Examples for [[MObjects|MObject]] being:
* audio/video clips
* effects and plugins
* special facilities like mask and projector
@ -1377,6 +1387,27 @@ For the case in question this seems to be the ''resource allocation is construct
And, last but not least, doing all actual allocations is the job of the backend. Exceptions being long-lived objects, like the Session or the EDL, which are created once and don't bear the danger of causing memory pressure. Besides that, the ProcLayer code shouldn't issue &quot;new&quot; and &quot;delete&quot;, rather it should use some central [[Factories]] for all allocation and freeing, so we can redirect these calls down to the backend, which may use pooling or special placement allocators or the like. The rationale is, for modern hardware/architectures, care has to be taken with heap allocations, esp. with many small objects and irregular usage patterns.
</pre>
</div>
<div title="ObjectCreation" modifier="Ichthyostega" modified="200709040257" created="200709030139" tags="impl design" changecount="10">
<pre>We have to consider carefully how to handle the Creation of new class instances. Because, when done naively, it can defeat all efforts of separating subsystems, or &amp;mdash; the other extreme &amp;mdash; lead to a //switch-on-typeID// programming style. We strive at a solution somewhere in the middle by utilizing __Abstract Factories__ on Interface or key abstraction classes, but providing specialized overloads for the different use cases. So in each use case we have to decide if we want to create a representant of some general concept (Interface), or if we have a direct colaboration and thus need the Factory to provide
a more specific sub-Interface or even a concrete type.
!Object creation use cases
!![[Assets|Asset]]
|!Action|&gt;|!creates |
|loading a media file|asset::Media, asset::Codec| |
|viewing media|asset::Clip| for the whole Media, if not already existant|
|mark selection as clip|asset::Clip| doesn't add to EDL|
|loading Plugin|asset::Effect| usually at program startup|
|create Session|asset::Track, asset::OutPort| |
&amp;rarr; [[Creating and registering Assets|AssetCreation]]
!![[MObjects|MObject]]
|add media to EDL|asset::Clip, session::Clip, FixedPlacement| creating whole-media clip on-the-fly |
|add Clip|session::Clip, FixedPlacement| |
|attach Effect|session::Effect, RelativePlacement| |
|start using Automation|session::Auto, asset::Dataset, RelativePlacement| |
</pre>
</div>
<div title="OpenGL" modifier="Ichthyostega" modified="200706220359" created="200706220345" tags="def discuss" changecount="3">
<pre>Cinelerra2 introduced OpenGL support for rendering previews. I must admit, I am very unhappy with this, because
* it just supports some hardware
@ -1392,8 +1423,9 @@ But because I know the opinions on this topc are varying (users tend to be delig
My proposed aproach is to treat OpenGL as a separate video raw data type, requiring separete and specialized [[Processing Nodes|ProcNode]] for all calculations. Thus the Builder could connect OpenGL nodes if it is possible to cover the whole render path for preview and fall back to the normal ~ProcNodes for all relevant renders
</pre>
</div>
<div title="Overview" modifier="Ichthyostega" modified="200706220216" created="200706190300" tags="overview" changecount="3">
<pre>[img[Block Diagram|uml/fig128005.png]]
<div title="Overview" modifier="Ichthyostega" modified="200709030125" created="200706190300" tags="overview" changecount="4">
<pre>The Cinelerra-3 Processing Layer is comprised of various subsystems and can be separated into a low-level and a high-level part. At the low-level end is the [[Render Engine|OverviewRenderEngine]] which basically is a network of render nodes cooperating closely with the Backend Layer in order to carry out the actual playback and media transforming calculations. Whereas on the high-level side we find several different [[Media Objects|MObjects]] that can be placed into the [[EDL]], edited and manipulated. This is complemented by the [[Asset Management|Asset]], which is the &quot;bookkeeping view&quot; of all the different &quot;things&quot; within each Session.
[img[Block Diagram|uml/fig128005.png]]
</pre>
</div>
<div title="OverviewRenderEngine" modifier="MichaelPloujnikov" modified="200706271432" created="200706190647" tags="overview" changecount="17">
@ -2344,7 +2376,7 @@ Instead, we should try to just connect the various subsystems via Interfaces and
* to shield the rendering code of all complexities of thread communication and synchronization, we use the StateProxy
</pre>
</div>
<div title="StyleSheet" modifier="Ichthyostega" modified="200706260459" created="200701131624" tags="MPTWTheme excludeMissing" server.type="file" server.host="file:///home/ct/.homepage/home.html" server.page.revision="200706090017" changecount="6">
<div title="StyleSheet" modifier="Ichthyostega" modified="200709040043" created="200701131624" tags="MPTWTheme excludeMissing" server.type="file" server.host="file:///home/ct/.homepage/home.html" server.page.revision="200706090017" changecount="14">
<pre>/*{{{*/
/* a contrasting background so I can see where one tiddler ends and the other begins */
body {
@ -2509,6 +2541,10 @@ h1,h2,h3,h4,h5,h6 {
color: #ff2210;
padding: 0px 0.8ex;
}
.viewer th {
background: #91a6af;
}
/*}}}*/
</pre>
</div>