WIP idea how to represent support for some timecode formats

concrete quantiser instances need a way to state
support for just some timecode formats -- yet I dont
want to push vectors aroud all over the place
This commit is contained in:
Fischlurch 2011-01-16 15:41:34 +01:00
parent aa5c78a30f
commit 2c90335b1d
9 changed files with 217 additions and 41 deletions

View file

@ -0,0 +1,47 @@
/*
NO-INSTANCE.hpp - marker for pure metaprogramming types
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
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 LIB_META_NO_INSTANCE_H
#define LIB_META_NO_INSTANCE_H
#include <boost/static_assert.hpp>
namespace lib {
namespace meta{
/**
* An Entity never to be instantiated.
* Marker baseclass for elements used for metaprogramming only.
* Every attempt to instantiate such an element will cause an
* compilation failure
*/
template<class X>
struct NoInstance
{
NoInstance() { BOOST_STATIC_ASSERT(!sizeof(X)); }
NoInstance (NoInstance const&) { BOOST_STATIC_ASSERT(!sizeof(X)); }
};
}} // namespace lib::meta
#endif

View file

@ -25,6 +25,9 @@
#define LIB_TIME_FORMATS_H
#include "lib/time/timevalue.hpp"
#include "lib/meta/no-instance.hpp"
#include "lib/meta/typelist.hpp"
#include "lib/meta/generator.hpp"
//#include <boost/operators.hpp>
#include <tr1/memory>
@ -48,27 +51,11 @@ namespace time {
typedef std::tr1::shared_ptr<const Quantiser> PQuant;
/**
* descriptor for a time representation format (ABC).
* A time format describes how to specify time; it allows
* to format a time value and to parse a textual representation.
* @note while Format is an generic descriptor, the actual
* TCode (timecode) values are time values, which \em
* use a specific format, given as template parameter
*
* @todo WIP-WIP-WIP
*/
class Format
{
public:
virtual ~Format();
};
namespace format {
using lib::meta::NoInstance; // the following types are for metaprogramming only...
/**
* Frame count as timecode format.
* An integral number used to count frames
@ -78,7 +65,7 @@ namespace time {
* underlying framerate/quantisation remains implicit.
*/
struct Frames
: Format
: NoInstance<Frames>
{
static void rebuild (FrameNr&, QuantR, TimeValue const&);
static TimeValue evaluate (FrameNr const&, QuantR);
@ -92,7 +79,7 @@ namespace time {
* frame number within the actual second.
*/
struct Smpte
: Format
: NoInstance<Smpte>
{
static void rebuild (SmpteTC&, QuantR);
static TimeValue evaluate (SmpteTC const&, QuantR);
@ -107,7 +94,7 @@ namespace time {
* floating point milliseconds value instead of the frame count
*/
struct Hms
: Format
: NoInstance<Hms>
{
static void rebuild (HmsTC&, QuantR);
static TimeValue evaluate (HmsTC const&, QuantR);
@ -124,7 +111,7 @@ namespace time {
* decimal format, not the usual sexagesimal time format
*/
struct Seconds
: Format
: NoInstance<Seconds>
{
static void rebuild (Secs&, QuantR);
static TimeValue evaluate (Secs const&, QuantR);
@ -163,5 +150,39 @@ namespace time {
using lumiera::typelist::Types;
/**
* Denote support for a specific (timecode) format.
* This helper can be used to configure a selection of specific
* timecode formats to be or not to be supported by some facility.
* Formats are described by the format descriptor types defined in
* this header (or elsewhere for additional formats). This helper
* establishes an numeric ID at runtime and uses a bitset to keep
* track of the support for a given format.
*
* @todo WIP-WIP-WIP
*/
class Supported
{
public:
template<typename TY>
static Supported
formats();
template<class F>
bool
check();
};
struct SupportStandardTimecode
: Supported
{
SupportStandardTimecode()
: Supported(formats<Types<Hms,Smpte,Frames,Seconds> >())
{ }
};
}}} // lib::time::format
#endif

View file

@ -62,8 +62,8 @@ namespace time {
virtual ~Grid(); ///< this is an Interface
virtual TimeValue gridAlign (TimeValue const& raw) const =0;
virtual long gridPoint (TimeValue const& raw) const =0;
virtual TimeValue gridAlign (TimeValue const& raw) const =0;
virtual TimeValue timeOf (long gridPoint) const =0;
virtual TimeValue timeOf (FSecs, int =0) const =0;
};

View file

@ -66,28 +66,29 @@ namespace time {
/**
* Facility to create grid-aligned time values.
* Effectively, a quantiser exposes the value Grid API, but
* additionally also manages a set of supported (display) formats or
* "time code" formats. Plus there is an static API to fetch a suitable
* quantiser instance by-name; actually this utilises a hidden link to
* the Lumiera session. Time quantisation and timecode handling explicitly
* relies on this Quantiser interface.
*
* @todo WIP-WIP-WIP
*/
class Quantiser
: public Grid
{
typedef std::vector<Format*> _FormatTable;
typedef _FormatTable::const_iterator _SrcIter;
typedef lib::PtrDerefIter<_SrcIter> _Iter;
public:
template<class FMT>
bool supports() const;
typedef _Iter iterator;
iterator getSupportedFormats() const;
//------Grid-API----------------------------------------------
virtual TimeValue gridAlign (TimeValue const& raw) const =0;
virtual long gridPoint (TimeValue const& raw) const =0;
virtual TimeValue gridAlign (TimeValue const& raw) const =0;
virtual TimeValue timeOf (long gridPoint) const =0;
virtual TimeValue timeOf (FSecs, int =0) const =0;
};
@ -116,8 +117,8 @@ namespace time {
FixedFrameQuantiser (Duration const& frame_duration, TimeValue referencePoint =TimeValue(0));
TimeValue gridAlign (TimeValue const&) const;
long gridPoint (TimeValue const&) const;
TimeValue gridAlign (TimeValue const&) const;
TimeValue timeOf (long gridPoint) const;
TimeValue timeOf (FSecs, int =0) const;
};

View file

@ -36,8 +36,7 @@ namespace lib {
namespace time {
Format::~Format() { } // emit VTable here....
TCode::~TCode() { }
TCode::~TCode() { } // emit VTable here....
namespace format {

View file

@ -22,13 +22,27 @@
/** @file typed-counter.hpp
** Creating sets of type-based contexts.
** Creating series of type-based contexts.
** The idea is to get a "slot" for any given type, so we can build
** tables or families of implementations based on these types. Currently,
** the slot allocation is based on static variables and thus is global.
** This leads to a waste of slots, as the various clients of this service
** typically will utilise different sets of types.
** @todo WIP WIP... this is the first, preliminary version of a facility,
** tables or families of implementations based on these types. Each of
** those "slots" can be addressed by a distinct (compile time) type, but
** at the same time holds a numeric ID (runtime assigned on demand). This
** setup allows to bridge between metaprogramming and (runtime) dispatcher tables.
**
** Each such series of type-id-slots is associated to a distinct usage context.
** Those usage contexts are discerned by the template parameter \c XY. Each of
** these usage contexts uses a separate numbering scheme on his own, i.e. every
** new type encountered at runtime gets the next higher ID number (slot).
** @warning the actual ID numbers depend on the sequence of first encountering
** a given type. If this sequence isn't reproducible between runs, then
** also the generated type-IDs aren't reproducible. Thus its advisable
** \em not to rely on any specific numeric value here, but always just
** access the service through the type slots.
** @note Locking is based on a class lock per usage context, but a lock needs
** only be acquired to allocate a new ID number (double checked locking).
** Thus lock contention is considered not to be a problem, yet we need
** actually to verify this by real measurements (as of 2011)
** @todo 2010 ... this is the first, preliminary version of a facility,
** which is expected to get quite important for custom allocation management.
**
** @see typed-counter-test.cpp

View file

@ -74,8 +74,8 @@ namespace meta {
lib::time::FixedFrameQuantiser frameGrid_;
/* == grid API forwarded to embedded quantiser == */
TimeValue gridAlign (TimeValue const& rawTime) const { return frameGrid_.gridAlign (rawTime); }
long gridPoint (TimeValue const& rawTime) const { return frameGrid_.gridPoint (rawTime); }
TimeValue gridAlign (TimeValue const& rawTime) const { return frameGrid_.gridAlign (rawTime); }
TimeValue timeOf (long gridPoint) const { return frameGrid_.timeOf (gridPoint); }
TimeValue timeOf (FSecs gridTime, int gridOffset =0) const { return frameGrid_.timeOf (gridTime,gridOffset); }

View file

@ -80,8 +80,8 @@ namespace meta {
public:
//--------Grid-API------------------------------------
TimeValue gridAlign (TimeValue const& raw) const =0;
long gridPoint (TimeValue const& raw) const =0;
TimeValue gridAlign (TimeValue const& raw) const =0;
TimeValue timeOf (long gridPoint) const =0;
TimeValue timeOf (FSecs, int =0) const =0;

View file

@ -0,0 +1,94 @@
/*
FormatSupport(Test) - verify the configuration to support a specific format
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
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 "lib/test/run.hpp"
#include "lib/time/formats.hpp"
//#include <iostream>
//#include <cstdlib>
//using std::rand;
//using std::cout;
//using std::endl;
namespace lib {
namespace time {
namespace format{
namespace test {
namespace {
}
/********************************************************
* @test check how support for a specific timecode format
* can be enabled and detected. Actually this test
* verifies a simple metaprogramming facility,
* which allows to check type support at runtime.
*/
class FormatSupport_test : public Test
{
virtual void
run (Arg)
{
SupportStandardTimecode just_fine;
Supported just_smpte = Supported::formats<Types<Smpte> >();
Supported just_simple = Supported::formats<Types<Frames,Seconds> >();
Supported& support1 (just_fine);
Supported& support2 (just_smpte);
Supported& support3 (just_simple);
CHECK ( support1.check<Hms>());
CHECK ( support1.check<Smpte>());
CHECK ( support1.check<Frames>());
CHECK ( support1.check<Seconds>());
CHECK (!support2.check<Hms>());
CHECK ( support2.check<Smpte>());
CHECK (!support2.check<Frames>());
CHECK (!support2.check<Seconds>());
CHECK (!support3.check<Hms>());
CHECK (!support3.check<Smpte>());
CHECK ( support3.check<Frames>());
CHECK ( support3.check<Seconds>());
// format support descriptors are assignable
just_smpte = just_simple;
CHECK (support2.check<Hms>() == support3.check<Hms>());
CHECK (support2.check<Smpte>() == support3.check<Smpte>());
CHECK (support2.check<Frames>() == support3.check<Frames>());
CHECK (support2.check<Seconds>() == support3.check<Seconds>());
}
};
/** Register this test class... */
LAUNCHER (FormatSupport_test, "unit common");
}}}} // namespace lib::time::format::test