Lumiera  0.pre.03
»edit your freedom«
timevalue.hpp
Go to the documentation of this file.
1 /*
2  TIMEVALUE.hpp - basic definitions for time values and time intervals
3 
4  Copyright (C)
5  2010, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
93 #ifndef LIB_TIME_TIMEVALUE_H
94 #define LIB_TIME_TIMEVALUE_H
95 
96 #include "lib/error.hpp"
97 
98 #include <boost/operators.hpp>
99 #include <boost/rational.hpp>
100 #include <cstdlib>
101 #include <string>
102 
103 extern "C" {
104 #include <stdint.h>
105 #include <gavl/gavltime.h>
106 }
107 
108 
109 namespace lib {
110 namespace time {
111 
112  namespace error = lumiera::error;
113 
114  // forwards...
115  class FrameRate;
116  class Duration;
117  class TimeSpan;
118  class Mutation;
119 
120 
133  class TimeValue
134  : boost::totally_ordered<TimeValue,
135  boost::totally_ordered<TimeValue, gavl_time_t>>
136  {
137  protected:
140  gavl_time_t t_;
141 
142 
145  TimeValue&
147  {
148  t_ = o.t_;
149  return *this;
150  }
151 
153  friend class Mutation;
154 
156  static gavl_time_t limitedTime (gavl_time_t raw);
158  static gavl_time_t limitedDelta (gavl_time_t origin, gavl_time_t target);
159 
161  TimeValue (TimeValue const& origin, TimeValue const& target)
162  : t_{limitedDelta (origin.t_, target.t_)}
163  { }
164 
165  public:
167  static const gavl_time_t SCALE;
168 
169 
170  explicit
171  TimeValue (gavl_time_t val)
172  : t_{limitedTime (val)}
173  { }
174 
176  TimeValue (TimeValue const& o)
177  : t_(o.t_)
178  { }
179 
181  friend gavl_time_t _raw (TimeValue const& time) { return time.t_; }
182  friend HashVal hash_value (TimeValue const&);
183  static TimeValue buildRaw_(gavl_time_t);
184 
186  operator std::string () const;
187 
189  bool isRegular() const;
190 
191  // Supporting totally_ordered
192  friend bool operator< (TimeValue const& t1, TimeValue const& t2) { return t1.t_ < t2.t_; }
193  friend bool operator< (TimeValue const& t1, gavl_time_t t2) { return t1.t_ < t2 ; }
194  friend bool operator> (TimeValue const& t1, gavl_time_t t2) { return t1.t_ > t2 ; }
195  friend bool operator== (TimeValue const& t1, TimeValue const& t2) { return t1.t_ == t2.t_; }
196  friend bool operator== (TimeValue const& t1, gavl_time_t t2) { return t1.t_ == t2 ; }
197  };
198 
199 
200 
201 
202 
203 
204 
205  /* ======= specific Time entities ==================== */
206 
216  using FrameCnt = int64_t;
217 
220  using FSecs = boost::rational<int64_t>;
221 
222 
223 
232  class TimeVar
233  : public TimeValue
234  , boost::additive<TimeVar,
235  boost::additive<TimeVar, TimeValue,
236  boost::multipliable<TimeVar, int>
237  > >
238  {
239  public:
240  TimeVar (TimeValue const& time = TimeValue(0))
241  : TimeValue(time)
242  { }
243 
246  TimeVar (FSecs const&);
247 
249  TimeVar (TimeVar const& o)
250  : TimeValue(o)
251  { }
252 
253  TimeVar&
254  operator= (TimeValue const& o)
255  {
256  t_ = TimeVar(o);
257  return *this;
258  }
259 
261  operator gavl_time_t() const { return t_; }
263  operator FSecs() const { return FSecs{t_, TimeValue::SCALE}; }
264 
266  TimeVar& operator+= (TimeVar const& tx) { t_ += tx.t_; return *this; }
267  TimeVar& operator-= (TimeVar const& tx) { t_ -= tx.t_; return *this; }
268 
270  TimeVar& operator*= (int64_t fact) { t_ *= fact; return *this; }
271 
273  TimeVar operator- () const { return TimeVar(*this)*=-1; }
274 
275  // baseclass TimeValue is already totally_ordered
276  };
277 
278 
279 
280 
281  /**********************************************************/
299  class Time
300  : public TimeValue
301  {
303  Time& operator= (Time const);
304 
306  Time(int);
307 
308  public:
309  static const Time MAX ;
310  static const Time MIN ;
311  static const Time ZERO;
312 
313  static const Time ANYTIME;
314  static const Time NEVER;
315 
316  explicit
317  Time (TimeValue const& val =TimeValue(0))
318  : TimeValue(val)
319  { }
320 
321  Time (TimeVar const& calcResult)
322  : TimeValue(calcResult)
323  { }
324 
325  explicit
326  Time (FSecs const& fractionalSeconds);
327 
328  Time ( long millis
329  , uint secs
330  , uint mins =0
331  , uint hours=0
332  );
333 
335  operator std::string () const;
336 
338  TimeVar operator+ (TimeValue const& tval) const { return TimeVar(*this) + tval; }
339  TimeVar operator- (TimeValue const& tval) const { return TimeVar(*this) - tval; }
340  TimeVar operator- () const { return -TimeVar(*this); }
341  };
342 
343 
344 
345 
358  class Offset
359  : public TimeValue
360  {
361  protected:
365  Offset&
366  operator= (Offset const& o)
367  {
369  return *this;
370  }
371 
372  public:
373  explicit
374  Offset (TimeValue const& distance =Time::ZERO);
375 
376  explicit
377  Offset (FSecs const& delta_in_secs);
378 
379  Offset (FrameCnt count, FrameRate const& fps);
380 
381  Offset (TimeValue const& origin, TimeValue const& target)
382  : TimeValue{origin, target}
383  { }
384 
385  static const Offset ZERO;
386 
388  Duration abs() const;
389 
392  Offset stretchedByRationalFactor (boost::rational<int64_t>) const;
393  Offset stretchedByFloatFactor (double) const;
394 
396  operator std::string () const;
397 
398  // Supporting sign flip
399  Offset operator- () const;
400  };
401 
402  //-- support linear offset chaining ---------------
403 
404  inline Offset
405  operator+ (Offset const& start, Offset const& toChain)
406  {
407  TimeVar distance(start);
408  distance += toChain;
409  return Offset(distance);
410  }
411 
412  inline Offset
413  operator- (Offset const& start, Offset const& toSubtract)
414  {
415  TimeVar distance(start);
416  distance -= toSubtract;
417  return Offset(distance);
418  }
419 
420  template<typename FAC>
421  inline Offset
422  operator* (Offset const& distance, FAC factor)
423  {
424  return factor*distance;
425  }
426 
427  template<typename INT>
428  inline Offset
429  operator* (INT factor, Offset const& o)
430  {
431  TimeVar distance(o);
432  distance *= factor;
433  return Offset(distance);
434  }
435 
436  template<typename INTX>
437  inline Offset
438  operator* (boost::rational<INTX> factor, Offset const& offset)
439  {
440  return offset.stretchedByRationalFactor (boost::rational<int64_t>(factor.numerator(), factor.denominator()));
441  }
442 
443  inline Offset
444  operator* (double factor, Offset const& offset)
445  {
446  return offset.stretchedByFloatFactor (factor);
447  }
448 
449 
451  inline Offset
453  {
454  return -1 * (*this);
455  }
456 
457 
458 
459 
468  class Duration
469  : public TimeValue
470  {
472  Duration& operator= (Duration const&);
473 
474  public:
475  Duration()
476  : TimeValue{Time::ZERO}
477  { }
478 
479  Duration (Offset const& distance)
480  : TimeValue{buildRaw_(llabs (_raw(distance)))}
481  { }
482 
483  explicit
484  Duration (TimeValue const& timeSpec)
485  : Duration{Offset{timeSpec}}
486  { }
487 
488  Duration (FSecs const& timeSpan_in_secs)
489  : Duration{Offset{timeSpan_in_secs}}
490  { }
491 
494  Duration (FrameCnt count, FrameRate const& fps)
495  : Duration{Offset{count,fps}}
496  { }
497 
498  Duration (TimeSpan const& interval);
499 
500  Duration (Duration const& o)
501  : TimeValue{o}
502  {// assuming that negative Duration can not be constructed....
503  REQUIRE (t_ >= 0, "Copy rejected: negative Duration %lu", o.t_);
504  }
505 
506  static const Duration NIL;
507  static const Duration MAX ;
508 
509  void accept (Mutation const&);
510 
511 
513  operator std::string () const;
514 
516  Offset operator- () const;
517 
518  };
519 
520  //-- support combining and Durations ---------------
521 
522  inline Duration
523  operator+ (Duration const& base, Duration const& toAdd)
524  {
525  return Offset(base) + Offset(toAdd);
526  }
527 
528  inline Duration
529  operator- (Duration const& base, Duration const& toRemove)
530  {
531  return base > toRemove? Offset(base) - Offset(toRemove)
532  : Duration::NIL;
533  }
534 
535  template<typename NUM>
536  inline Offset
537  operator* (NUM factor, Duration const& dur)
538  {
539  return factor * Offset(dur);
540  }
541 
542  template<typename NUM>
543  inline Offset
544  operator* (Duration const& dur, NUM factor)
545  {
546  return factor*dur;
547  }
548 
549  inline Offset
551  {
552  return -1 * (*this);
553  }
554 
555 
556 
573  class TimeSpan
574  : public Time
575  , boost::totally_ordered<TimeSpan>
576  {
577  Duration dur_;
578 
579  public:
580  TimeSpan(TimeValue const& start, Duration const& length)
581  : Time(start)
582  , dur_(length)
583  { }
584 
585  TimeSpan(TimeValue const& start, FSecs(duration_in_secs))
586  : Time(start)
587  , dur_(duration_in_secs)
588  { }
589 
590  TimeSpan(TimeValue const& start, TimeValue const& end)
591  : Time(start<=end? start:end)
592  , dur_(Offset(start,end))
593  { }
594 
595  TimeSpan(TimeValue const& start, Offset const& reference_distance)
596  : TimeSpan{start, Time{start} + reference_distance}
597  { }
598 
599  TimeSpan()
600  : TimeSpan(Time::ZERO, Time::ZERO)
601  { }
602 
603  TimeSpan conform() const;
604 
605  static const TimeSpan ALL;
606 
607  Duration&
608  duration()
609  {
610  return dur_;
611  }
612 
613  Duration
614  duration() const
615  {
616  return dur_;
617  }
618 
619  Time
620  start() const
621  {
622  return *this;
623  }
624 
625  Time
626  end() const
627  {
628  return TimeVar(*this) += dur_;
629  }
630 
631  bool
632  contains (TimeValue const& tp) const
633  {
634  return *this <= tp
635  && tp < end();
636  }
637 
639  void accept (Mutation const&);
640 
642  operator std::string () const;
643 
645  friend bool operator== (TimeSpan const& t1, TimeSpan const& t2) { return t1.t_==t2.t_ && t1.dur_==t2.dur_; }
646  friend bool operator< (TimeSpan const& t1, TimeSpan const& t2) { return t1.t_< t2.t_ ||
647  (t1.t_==t2.t_ && t1.dur_< t2.dur_);}
648  };
649 
650 
655  class FrameRate
656  : public boost::rational<uint>
657  {
658  public:
659  FrameRate (uint fps) ;
660  FrameRate (uint num, uint denom);
661  FrameRate (size_t count, Duration timeReference);
662  explicit
663  FrameRate (boost::rational<uint> fractionalRate);
664 
665  static FrameRate approx(double fps);
666 
667  // standard copy acceptable;
668 
669  double asDouble() const;
670 
671  static const FrameRate PAL;
672  static const FrameRate NTSC;
673  static const FrameRate STEP;
674 
675  static const FrameRate HALTED;
676 
678  Duration duration() const;
679 
680  operator std::string() const;
681  };
682 
684  inline FSecs
685  operator/ (int n, FrameRate rate)
686  {
687  return FSecs{ n*rate.denominator(), rate.numerator()};
688  }
689 
690 
691 
692 
693  /* == implementations == */
694 
695  namespace { // implementation helpers...
696 
697  template<typename NUM>
698  inline NUM
699  __ensure_nonzero (NUM n)
700  {
701  if (n == NUM{0})
702  throw error::Logic ("Degenerated frame grid not allowed"
703  , LERR_(BOTTOM_VALUE));
704  return n;
705  }
706 
707  inline gavl_time_t
708  symmetricLimit (gavl_time_t raw, TimeValue lim)
709  {
710  return raw > lim? _raw(lim)
711  : -raw > lim? -_raw(lim)
712  : raw;
713  }
714  }//(End) implementation helpers
715 
716 
717 
718 
724  inline HashVal
726  {
727  HashVal x = _raw(time); // possibly cap to size of hash
728  const uint width = sizeof(HashVal) * CHAR_BIT;
729  const uint mask = width-1;
730  const uint n = width / 2;
731 
732  static_assert (0 < n and n <= mask);
733  return (x<<n) | (x>>((-n)&mask ));
734  }
735 
736 
743  inline gavl_time_t
744  TimeValue::limitedTime (gavl_time_t raw)
745  {
746  return symmetricLimit (raw, Time::MAX);
747  }
748 
749  inline gavl_time_t
750  TimeValue::limitedDelta (gavl_time_t origin, gavl_time_t target)
751  {
752  if (0 > (origin^target))
753  {// prevent possible numeric wrap
754  origin = symmetricLimit (origin, Duration::MAX);
755  target = symmetricLimit (target, Duration::MAX);
756  }
757  gavl_time_t res = target - origin;
758  return symmetricLimit (res, Duration::MAX);
759  }
760 
761  inline TimeSpan
763  {
764  Offset extension{dur_};
765  TimeValue start{_raw(*this)};
766  return Offset{start} + extension > Time::MAX? TimeSpan{Time::MAX-extension, Time::MAX}
767  : TimeSpan{start, extension};
768  }
769 
770  inline bool
772  {
773  return Time::MIN < *this
774  and *this < Time::MAX;
775  }
776 
777 
778  inline
779  TimeVar::TimeVar (FSecs const& fractionalSeconds)
780  : TimeVar{Time(fractionalSeconds)}
781  { }
782 
783  inline
784  Offset::Offset (TimeValue const& distance)
785  : TimeValue{buildRaw_(symmetricLimit(_raw(distance)
786  , Duration::MAX))}
787  { }
788 
789  inline
790  Duration::Duration (TimeSpan const& interval)
791  : Duration{interval.duration()}
792  { }
793 
794  inline
795  FrameRate::FrameRate (uint fps)
796  : boost::rational<uint> (__ensure_nonzero(fps))
797  { }
798 
799  inline
800  FrameRate::FrameRate (uint num, uint denom)
801  : boost::rational<uint> (__ensure_nonzero(num), denom)
802  { }
803 
804  inline
805  FrameRate::FrameRate (boost::rational<uint> fractionalRate)
806  : boost::rational<uint> (__ensure_nonzero(fractionalRate))
807  { }
808 
809  boost::rational<uint> __framerate_approximation (size_t, Duration);
810  boost::rational<uint> __framerate_approximation (double);
811 
812  inline
813  FrameRate::FrameRate (size_t count, Duration timeReference)
814  : FrameRate{__framerate_approximation (count, timeReference)}
815  { }
816 
817  inline FrameRate
818  FrameRate::approx (double fps)
819  {
820  return FrameRate{__framerate_approximation (fps)};
821  }
822 
823 
824  inline double
825  FrameRate::asDouble() const
826  {
827  return boost::rational_cast<double> (*this);
828  }
829 
830  inline Duration
831  Offset::abs() const
832  {
833  return Duration{*this};
834  }
835 
836 
837 
838 }} // lib::time
839 
840 
841 namespace util {
842 
843  inline bool
844  isnil (lib::time::Duration const& dur)
845  {
846  return 0 == dur;
847  }
848 
849  // repeated or forward declaration, see meta/util.hpp
850  template<typename X, typename COND>
851  struct StringConv;
852 
854  template<>
855  struct StringConv<lib::time::FSecs, void>
856  {
857  static std::string
858  invoke (lib::time::FSecs) noexcept;
859  };
860 }
861 #endif /*LIB_TIME_TIMEVALUE_H*/
static const Time ANYTIME
border condition marker value. ANYTIME <= any time value
Definition: timevalue.hpp:313
TimeValue(TimeValue const &o)
copy initialisation allowed
Definition: timevalue.hpp:176
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:232
TimeValue & operator=(TimeValue const &o)
Assigning of time values is not allowed, but derived classed might allow that.
Definition: timevalue.hpp:146
static const Duration MAX
maximum possible temporal extension
Definition: timevalue.hpp:507
TimeValue(gavl_time_t val)
Definition: timevalue.hpp:171
Framerate specified as frames per second.
Definition: timevalue.hpp:655
static const gavl_time_t SCALE
Number of micro ticks (µs) per second as basic time scale.
Definition: timevalue.hpp:167
Offset stretchedByRationalFactor(boost::rational< int64_t >) const
Definition: time.cpp:325
Duration(FrameCnt count, FrameRate const &fps)
duration of the given number of frames.
Definition: timevalue.hpp:494
Interface: an opaque change imposed onto some time value.
Definition: mutation.hpp:91
static const Duration NIL
constant to indicate "no duration"
Definition: timevalue.hpp:506
Implementation namespace for support and library code.
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:299
std::string operator+(std::string str, Literal const &sym)
string concatenation
Definition: symbol.hpp:213
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
static const FrameRate STEP
1 frame per second
Definition: timevalue.hpp:673
bool isRegular() const
Definition: timevalue.hpp:771
TimeSpan conform() const
<
Definition: timevalue.hpp:762
Duration abs() const
interpret the distance given by this offset as a time duration
Definition: timevalue.hpp:831
TimeValue(TimeValue const &origin, TimeValue const &target)
Definition: timevalue.hpp:161
static TimeValue buildRaw_(gavl_time_t)
Definition: time.cpp:236
boost::rational< int64_t > FSecs
rational representation of fractional seconds
Definition: timevalue.hpp:220
Offset operator-() const
Supporting backwards use as offset.
Definition: timevalue.hpp:550
friend HashVal hash_value(TimeValue const &)
derive a hash from the µ-tick value
Definition: timevalue.hpp:725
Lumiera error handling (C++ interface).
size_t HashVal
a STL compatible hash value
Definition: hash-value.h:52
static const Time NEVER
border condition marker value. NEVER >= any time value
Definition: timevalue.hpp:314
Offset measures a distance in time.
Definition: timevalue.hpp:358
static gavl_time_t limitedTime(gavl_time_t raw)
explicit limit of allowed time range
Definition: timevalue.hpp:744
Duration is the internal Lumiera time metric.
Definition: timevalue.hpp:468
static gavl_time_t limitedDelta(gavl_time_t origin, gavl_time_t target)
safe calculation of explicitly limited time offset
Definition: timevalue.hpp:750
boost::rational< uint > __framerate_approximation(double fps)
Definition: time.cpp:277
abstract entry, not yet allocated
A time interval anchored at a specific point in time.
Definition: timevalue.hpp:573
int64_t FrameCnt
relative framecount or frame number.
Definition: digxel.hpp:312
Offset operator-() const
flip offset direction
Definition: timevalue.hpp:452
basic constant internal time value.
Definition: timevalue.hpp:133
failsafe invocation of custom string conversion.
Definition: meta/util.hpp:390
static const Time MAX
Definition: timevalue.hpp:309
Offset stretchedByFloatFactor(double) const
Definition: time.cpp:336
gavl_time_t t_
the raw (internal) time value used to implement the time types
Definition: timevalue.hpp:140
friend gavl_time_t _raw(TimeValue const &time)
Definition: timevalue.hpp:181
static const FrameRate PAL
predefined constant for PAL framerate
Definition: timevalue.hpp:671
TimeVar(TimeVar const &o)
Allowing copy and assignment.
Definition: timevalue.hpp:249