2011-01-02 01:21:39 +01:00
|
|
|
/*
|
|
|
|
|
FORMATS.hpp - formats for displaying and specifying time
|
|
|
|
|
|
|
|
|
|
Copyright (C) Lumiera.org
|
|
|
|
|
2010, 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_TIME_FORMATS_H
|
|
|
|
|
#define LIB_TIME_FORMATS_H
|
|
|
|
|
|
|
|
|
|
#include "lib/time/timevalue.hpp"
|
2011-01-16 15:41:34 +01:00
|
|
|
#include "lib/meta/no-instance.hpp"
|
|
|
|
|
#include "lib/meta/typelist.hpp"
|
|
|
|
|
#include "lib/meta/generator.hpp"
|
2011-01-16 19:50:42 +01:00
|
|
|
#include "lib/typed-counter.hpp"
|
2011-01-02 01:21:39 +01:00
|
|
|
|
2011-01-15 00:52:02 +01:00
|
|
|
#include <tr1/memory>
|
2011-01-16 19:50:42 +01:00
|
|
|
#include <bitset>
|
2011-01-02 01:21:39 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace lib {
|
|
|
|
|
namespace time {
|
|
|
|
|
|
|
|
|
|
|
2011-01-13 23:56:52 +01:00
|
|
|
// ====== forward declarations of concrete Timecode types
|
|
|
|
|
|
|
|
|
|
class FrameNr;
|
|
|
|
|
class SmpteTC;
|
|
|
|
|
class HmsTC;
|
|
|
|
|
class Secs;
|
|
|
|
|
|
|
|
|
|
|
2011-01-15 00:52:02 +01:00
|
|
|
class Quantiser; // API for grid aligning
|
|
|
|
|
typedef Quantiser const& QuantR;
|
|
|
|
|
typedef std::tr1::shared_ptr<const Quantiser> PQuant;
|
2011-01-13 23:56:52 +01:00
|
|
|
|
|
|
|
|
|
2011-01-02 01:21:39 +01:00
|
|
|
namespace format {
|
|
|
|
|
|
2011-01-16 15:41:34 +01:00
|
|
|
using lib::meta::NoInstance; // the following types are for metaprogramming only...
|
|
|
|
|
|
|
|
|
|
|
2011-01-02 01:21:39 +01:00
|
|
|
/**
|
|
|
|
|
* Frame count as timecode format.
|
|
|
|
|
* An integral number used to count frames
|
|
|
|
|
* can be used as a simple from of time code.
|
|
|
|
|
* Indeed the Lumiera backend mostly relies on
|
|
|
|
|
* these frame counts. As with any timecode, the
|
|
|
|
|
* underlying framerate/quantisation remains implicit.
|
|
|
|
|
*/
|
2011-01-14 05:33:50 +01:00
|
|
|
struct Frames
|
2011-01-16 15:41:34 +01:00
|
|
|
: NoInstance<Frames>
|
2011-01-02 01:21:39 +01:00
|
|
|
{
|
2011-01-15 00:52:02 +01:00
|
|
|
static void rebuild (FrameNr&, QuantR, TimeValue const&);
|
|
|
|
|
static TimeValue evaluate (FrameNr const&, QuantR);
|
2011-01-02 01:21:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Widely used standard media timecode format.
|
|
|
|
|
* A SMPTE timestamp addresses individual frames,
|
|
|
|
|
* by specifying time as hour-minute-second plus the
|
|
|
|
|
* frame number within the actual second.
|
|
|
|
|
*/
|
2011-01-14 05:33:50 +01:00
|
|
|
struct Smpte
|
2011-01-16 15:41:34 +01:00
|
|
|
: NoInstance<Smpte>
|
2011-01-02 01:21:39 +01:00
|
|
|
{
|
2011-01-18 05:01:25 +01:00
|
|
|
static void rebuild (SmpteTC&, QuantR, TimeValue const&);
|
2011-01-15 00:52:02 +01:00
|
|
|
static TimeValue evaluate (SmpteTC const&, QuantR);
|
2011-01-21 11:42:29 +01:00
|
|
|
static uint getFramerate (QuantR, TimeValue const&);
|
2011-04-29 04:04:48 +02:00
|
|
|
static void applyRangeLimitStrategy (SmpteTC&);
|
2011-01-02 01:21:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The informal hours-minutes-seconds-millisecond timecode.
|
|
|
|
|
* As such, this timecode is quantisation agnostic, but usually
|
|
|
|
|
* it is used to address some frame or block or otherwise quantised
|
|
|
|
|
* entity in time. HMS-Timecode is similar to SMPTE, but uses a
|
|
|
|
|
* floating point milliseconds value instead of the frame count
|
|
|
|
|
*/
|
2011-01-14 05:33:50 +01:00
|
|
|
struct Hms
|
2011-01-16 15:41:34 +01:00
|
|
|
: NoInstance<Hms>
|
2011-01-02 01:21:39 +01:00
|
|
|
{
|
2011-01-18 05:01:25 +01:00
|
|
|
static void rebuild (HmsTC&, QuantR, TimeValue const&);
|
2011-01-15 00:52:02 +01:00
|
|
|
static TimeValue evaluate (HmsTC const&, QuantR);
|
2011-01-02 01:21:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Simple timecode specification as fractional seconds.
|
|
|
|
|
* Similar to HMS, a specification of seconds is quantisation agnostic,
|
|
|
|
|
* but usually some implicit quantisation is used anyway, be it on actual
|
|
|
|
|
* data frames, audio frames, or just on some smaller time interval, e.g.
|
|
|
|
|
* full milliseconds.
|
|
|
|
|
* @note Seconds is implemented as rational number and thus uses
|
|
|
|
|
* decimal format, not the usual sexagesimal time format
|
|
|
|
|
*/
|
2011-01-14 05:33:50 +01:00
|
|
|
struct Seconds
|
2011-01-16 15:41:34 +01:00
|
|
|
: NoInstance<Seconds>
|
2011-01-02 01:21:39 +01:00
|
|
|
{
|
2011-01-18 05:01:25 +01:00
|
|
|
static void rebuild (Secs&, QuantR, TimeValue const&);
|
2011-01-15 00:52:02 +01:00
|
|
|
static TimeValue evaluate (Secs const&, QuantR);
|
2011-01-02 01:21:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 02:43:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class FMT>
|
|
|
|
|
struct Traits;
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct Traits<Frames>
|
|
|
|
|
{
|
|
|
|
|
typedef FrameNr TimeCode;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct Traits<Smpte>
|
|
|
|
|
{
|
|
|
|
|
typedef SmpteTC TimeCode;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct Traits<Hms>
|
|
|
|
|
{
|
|
|
|
|
typedef HmsTC TimeCode;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct Traits<Seconds>
|
|
|
|
|
{
|
|
|
|
|
typedef Secs TimeCode;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-16 19:50:42 +01:00
|
|
|
/* == Descriptor to define Support for specific formats == */
|
|
|
|
|
|
2011-01-16 15:41:34 +01:00
|
|
|
using lumiera::typelist::Types;
|
2011-01-16 19:50:42 +01:00
|
|
|
using lumiera::typelist::Node;
|
|
|
|
|
using lumiera::typelist::NullType;
|
|
|
|
|
|
2011-01-16 15:41:34 +01:00
|
|
|
/**
|
2011-01-16 19:50:42 +01:00
|
|
|
* Descriptor to denote support for a specific (timecode) format.
|
2011-01-16 15:41:34 +01:00
|
|
|
* 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.
|
|
|
|
|
*
|
2011-01-16 19:50:42 +01:00
|
|
|
* @note preconfigured limit #MAXID on the absolute number of
|
|
|
|
|
* different Format types; maybe needs to be increased accordingly.
|
|
|
|
|
* @warning the actual numeric IDs might vary on each run
|
|
|
|
|
* @see TypedContext
|
2011-01-16 15:41:34 +01:00
|
|
|
*/
|
|
|
|
|
class Supported
|
|
|
|
|
{
|
2011-01-16 19:50:42 +01:00
|
|
|
enum { MAXID = 8 };
|
|
|
|
|
|
|
|
|
|
std::bitset<MAXID> flags_;
|
|
|
|
|
|
|
|
|
|
template<class F>
|
|
|
|
|
size_t
|
2011-01-16 22:19:48 +01:00
|
|
|
typeID() const
|
2011-01-16 19:50:42 +01:00
|
|
|
{
|
|
|
|
|
return TypedContext<Supported>::ID<F>::get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class F, class FS>
|
|
|
|
|
Supported
|
|
|
|
|
define(Node<F,FS>) ///< @internal set the flag for one Format in the typelist
|
|
|
|
|
{
|
|
|
|
|
flags_.set (typeID<F>());
|
|
|
|
|
return define(FS());
|
|
|
|
|
}
|
2011-04-26 06:11:31 +02:00
|
|
|
Supported define(NullType) { return *this;} ///< @internal recursion end
|
2011-01-16 19:50:42 +01:00
|
|
|
|
|
|
|
|
Supported() { } ///< @note use #formats to set up a new descriptor
|
|
|
|
|
|
|
|
|
|
|
2011-01-16 15:41:34 +01:00
|
|
|
public:
|
2011-01-16 19:50:42 +01:00
|
|
|
/** build a new Descriptor to denote support for all the Formats,
|
|
|
|
|
* @param TY typelist holding all the Format types to support
|
|
|
|
|
*/
|
2011-01-16 15:41:34 +01:00
|
|
|
template<typename TY>
|
|
|
|
|
static Supported
|
2011-01-16 19:50:42 +01:00
|
|
|
formats()
|
|
|
|
|
{
|
|
|
|
|
typedef typename TY::List SupportedFormats;
|
|
|
|
|
return Supported().define(SupportedFormats());
|
|
|
|
|
}
|
2011-01-16 15:41:34 +01:00
|
|
|
|
2011-01-16 19:50:42 +01:00
|
|
|
/** check if a specific Format is supported */
|
2011-01-16 15:41:34 +01:00
|
|
|
template<class F>
|
|
|
|
|
bool
|
2011-01-16 22:19:48 +01:00
|
|
|
check() const
|
2011-01-16 19:50:42 +01:00
|
|
|
{
|
|
|
|
|
return flags_[typeID<F>()];
|
|
|
|
|
}
|
2011-01-16 15:41:34 +01:00
|
|
|
};
|
|
|
|
|
|
2011-01-16 19:50:42 +01:00
|
|
|
/**
|
|
|
|
|
* predefined standard configuration:
|
|
|
|
|
* Descriptor for supporting all the classical timecode formats
|
|
|
|
|
*/
|
2011-01-16 15:41:34 +01:00
|
|
|
struct SupportStandardTimecode
|
|
|
|
|
: Supported
|
|
|
|
|
{
|
|
|
|
|
SupportStandardTimecode()
|
2011-01-16 19:50:42 +01:00
|
|
|
: Supported(formats< Types<Hms,Smpte,Frames,Seconds> >())
|
2011-01-16 15:41:34 +01:00
|
|
|
{ }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2011-01-02 01:21:39 +01:00
|
|
|
}}} // lib::time::format
|
|
|
|
|
#endif
|