diff --git a/src/lib/meta/no-instance.hpp b/src/lib/meta/no-instance.hpp new file mode 100644 index 000000000..73f7b71b0 --- /dev/null +++ b/src/lib/meta/no-instance.hpp @@ -0,0 +1,47 @@ +/* + NO-INSTANCE.hpp - marker for pure metaprogramming types + + Copyright (C) Lumiera.org + 2011, Hermann Vosseler + + 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 + + +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 + struct NoInstance + { + NoInstance() { BOOST_STATIC_ASSERT(!sizeof(X)); } + NoInstance (NoInstance const&) { BOOST_STATIC_ASSERT(!sizeof(X)); } + }; + +}} // namespace lib::meta +#endif diff --git a/src/lib/time/formats.hpp b/src/lib/time/formats.hpp index 0bd6f7788..7ded43c77 100644 --- a/src/lib/time/formats.hpp +++ b/src/lib/time/formats.hpp @@ -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 #include @@ -48,27 +51,11 @@ namespace time { typedef std::tr1::shared_ptr 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 { 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 { 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 { 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 { 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 + static Supported + formats(); + + template + bool + check(); + }; + + struct SupportStandardTimecode + : Supported + { + SupportStandardTimecode() + : Supported(formats >()) + { } + }; + + }}} // lib::time::format #endif diff --git a/src/lib/time/grid.hpp b/src/lib/time/grid.hpp index 57a06eec0..4053fa5b0 100644 --- a/src/lib/time/grid.hpp +++ b/src/lib/time/grid.hpp @@ -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; }; diff --git a/src/lib/time/quantiser.hpp b/src/lib/time/quantiser.hpp index ebb02e0a7..20764bf33 100644 --- a/src/lib/time/quantiser.hpp +++ b/src/lib/time/quantiser.hpp @@ -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 _FormatTable; - typedef _FormatTable::const_iterator _SrcIter; - typedef lib::PtrDerefIter<_SrcIter> _Iter; public: template 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; }; diff --git a/src/lib/time/timecode.cpp b/src/lib/time/timecode.cpp index c4831785d..4af2fec19 100644 --- a/src/lib/time/timecode.cpp +++ b/src/lib/time/timecode.cpp @@ -36,8 +36,7 @@ namespace lib { namespace time { - Format::~Format() { } // emit VTable here.... - TCode::~TCode() { } + TCode::~TCode() { } // emit VTable here.... namespace format { diff --git a/src/lib/typed-counter.hpp b/src/lib/typed-counter.hpp index 252faaab5..f208f8cdc 100644 --- a/src/lib/typed-counter.hpp +++ b/src/lib/typed-counter.hpp @@ -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 diff --git a/src/proc/asset/meta/time-grid.cpp b/src/proc/asset/meta/time-grid.cpp index b0b41f2c1..65f1978c8 100644 --- a/src/proc/asset/meta/time-grid.cpp +++ b/src/proc/asset/meta/time-grid.cpp @@ -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); } diff --git a/src/proc/asset/meta/time-grid.hpp b/src/proc/asset/meta/time-grid.hpp index 2de580655..01b96f480 100644 --- a/src/proc/asset/meta/time-grid.hpp +++ b/src/proc/asset/meta/time-grid.hpp @@ -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; diff --git a/tests/lib/time/format-support-test.cpp b/tests/lib/time/format-support-test.cpp new file mode 100644 index 000000000..066c44375 --- /dev/null +++ b/tests/lib/time/format-support-test.cpp @@ -0,0 +1,94 @@ +/* + FormatSupport(Test) - verify the configuration to support a specific format + + Copyright (C) Lumiera.org + 2011, Hermann Vosseler + + 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 +//#include + +//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 >(); + Supported just_simple = Supported::formats >(); + + Supported& support1 (just_fine); + Supported& support2 (just_smpte); + Supported& support3 (just_simple); + + CHECK ( support1.check()); + CHECK ( support1.check()); + CHECK ( support1.check()); + CHECK ( support1.check()); + + CHECK (!support2.check()); + CHECK ( support2.check()); + CHECK (!support2.check()); + CHECK (!support2.check()); + + CHECK (!support3.check()); + CHECK (!support3.check()); + CHECK ( support3.check()); + CHECK ( support3.check()); + + // format support descriptors are assignable + just_smpte = just_simple; + CHECK (support2.check() == support3.check()); + CHECK (support2.check() == support3.check()); + CHECK (support2.check() == support3.check()); + CHECK (support2.check() == support3.check()); + } + }; + + + /** Register this test class... */ + LAUNCHER (FormatSupport_test, "unit common"); + + + +}}}} // namespace lib::time::format::test