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) Lumiera.org
5  2010, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
102 #ifndef LIB_TIME_TIMEVALUE_H
103 #define LIB_TIME_TIMEVALUE_H
104 
105 #include "lib/error.hpp"
106 
107 #include <boost/operators.hpp>
108 #include <boost/rational.hpp>
109 #include <cstdlib>
110 #include <string>
111 
112 extern "C" {
113 #include <stdint.h>
114 #include <gavl/gavltime.h>
115 }
116 
117 
118 namespace lib {
119 namespace time {
120 
121  namespace error = lumiera::error;
122 
123  // forwards...
124  class FrameRate;
125  class Duration;
126  class TimeSpan;
127  class Mutation;
128 
129 
142  class TimeValue
143  : boost::totally_ordered<TimeValue,
144  boost::totally_ordered<TimeValue, gavl_time_t>>
145  {
146  protected:
149  gavl_time_t t_;
150 
151 
154  TimeValue&
156  {
157  t_ = o.t_;
158  return *this;
159  }
160 
162  friend class Mutation;
163 
165  static gavl_time_t limitedTime (gavl_time_t raw);
167  static gavl_time_t limitedDelta (gavl_time_t origin, gavl_time_t target);
168 
170  TimeValue (TimeValue const& origin, TimeValue const& target)
171  : t_{limitedDelta (origin.t_, target.t_)}
172  { }
173 
174  public:
176  static const gavl_time_t SCALE;
177 
178 
179  explicit
180  TimeValue (gavl_time_t val)
181  : t_{limitedTime (val)}
182  { }
183 
185  TimeValue (TimeValue const& o)
186  : t_(o.t_)
187  { }
188 
190  friend gavl_time_t _raw (TimeValue const& time) { return time.t_; }
191  friend HashVal hash_value (TimeValue const&);
192  static TimeValue buildRaw_(gavl_time_t);
193 
195  operator std::string () const;
196 
198  bool isRegular() const;
199 
200  // Supporting totally_ordered
201  friend bool operator< (TimeValue const& t1, TimeValue const& t2) { return t1.t_ < t2.t_; }
202  friend bool operator< (TimeValue const& t1, gavl_time_t t2) { return t1.t_ < t2 ; }
203  friend bool operator> (TimeValue const& t1, gavl_time_t t2) { return t1.t_ > t2 ; }
204  friend bool operator== (TimeValue const& t1, TimeValue const& t2) { return t1.t_ == t2.t_; }
205  friend bool operator== (TimeValue const& t1, gavl_time_t t2) { return t1.t_ == t2 ; }
206  };
207 
208 
209 
210 
211 
212 
213 
214  /* ======= specific Time entities ==================== */
215 
225  using FrameCnt = int64_t;
226 
229  using FSecs = boost::rational<int64_t>;
230 
231 
232 
241  class TimeVar
242  : public TimeValue
243  , boost::additive<TimeVar,
244  boost::additive<TimeVar, TimeValue,
245  boost::multipliable<TimeVar, int>
246  > >
247  {
248  public:
249  TimeVar (TimeValue const& time = TimeValue(0))
250  : TimeValue(time)
251  { }
252 
255  TimeVar (FSecs const&);
256 
258  TimeVar (TimeVar const& o)
259  : TimeValue(o)
260  { }
261 
262  TimeVar&
263  operator= (TimeValue const& o)
264  {
265  t_ = TimeVar(o);
266  return *this;
267  }
268 
270  operator gavl_time_t() const { return t_; }
272  operator FSecs() const { return FSecs{t_, TimeValue::SCALE}; }
273 
275  TimeVar& operator+= (TimeVar const& tx) { t_ += tx.t_; return *this; }
276  TimeVar& operator-= (TimeVar const& tx) { t_ -= tx.t_; return *this; }
277 
279  TimeVar& operator*= (int64_t fact) { t_ *= fact; return *this; }
280 
282  TimeVar operator- () const { return TimeVar(*this)*=-1; }
283 
284  // baseclass TimeValue is already totally_ordered
285  };
286 
287 
288 
289 
290  /**********************************************************/
308  class Time
309  : public TimeValue
310  {
312  Time& operator= (Time const);
313 
315  Time(int);
316 
317  public:
318  static const Time MAX ;
319  static const Time MIN ;
320  static const Time ZERO;
321 
322  static const Time ANYTIME;
323  static const Time NEVER;
324 
325  explicit
326  Time (TimeValue const& val =TimeValue(0))
327  : TimeValue(val)
328  { }
329 
330  Time (TimeVar const& calcResult)
331  : TimeValue(calcResult)
332  { }
333 
334  explicit
335  Time (FSecs const& fractionalSeconds);
336 
337  Time ( long millis
338  , uint secs
339  , uint mins =0
340  , uint hours=0
341  );
342 
344  operator std::string () const;
345 
347  TimeVar operator+ (TimeValue const& tval) const { return TimeVar(*this) + tval; }
348  TimeVar operator- (TimeValue const& tval) const { return TimeVar(*this) - tval; }
349  TimeVar operator- () const { return -TimeVar(*this); }
350  };
351 
352 
353 
354 
367  class Offset
368  : public TimeValue
369  {
370  protected:
374  Offset&
375  operator= (Offset const& o)
376  {
378  return *this;
379  }
380 
381  public:
382  explicit
383  Offset (TimeValue const& distance =Time::ZERO);
384 
385  explicit
386  Offset (FSecs const& delta_in_secs);
387 
388  Offset (FrameCnt count, FrameRate const& fps);
389 
390  Offset (TimeValue const& origin, TimeValue const& target)
391  : TimeValue{origin, target}
392  { }
393 
394  static const Offset ZERO;
395 
397  Duration abs() const;
398 
401  Offset stretchedByRationalFactor (boost::rational<int64_t>) const;
402  Offset stretchedByFloatFactor (double) const;
403 
405  operator std::string () const;
406 
407  // Supporting sign flip
408  Offset operator- () const;
409  };
410 
411  //-- support linear offset chaining ---------------
412 
413  inline Offset
414  operator+ (Offset const& start, Offset const& toChain)
415  {
416  TimeVar distance(start);
417  distance += toChain;
418  return Offset(distance);
419  }
420 
421  inline Offset
422  operator- (Offset const& start, Offset const& toSubtract)
423  {
424  TimeVar distance(start);
425  distance -= toSubtract;
426  return Offset(distance);
427  }
428 
429  template<typename FAC>
430  inline Offset
431  operator* (Offset const& distance, FAC factor)
432  {
433  return factor*distance;
434  }
435 
436  template<typename INT>
437  inline Offset
438  operator* (INT factor, Offset const& o)
439  {
440  TimeVar distance(o);
441  distance *= factor;
442  return Offset(distance);
443  }
444 
445  template<typename INTX>
446  inline Offset
447  operator* (boost::rational<INTX> factor, Offset const& offset)
448  {
449  return offset.stretchedByRationalFactor (boost::rational<int64_t>(factor.numerator(), factor.denominator()));
450  }
451 
452  inline Offset
453  operator* (double factor, Offset const& offset)
454  {
455  return offset.stretchedByFloatFactor (factor);
456  }
457 
458 
460  inline Offset
462  {
463  return -1 * (*this);
464  }
465 
466 
467 
468 
477  class Duration
478  : public TimeValue
479  {
481  Duration& operator= (Duration const&);
482 
483  public:
484  Duration()
485  : TimeValue{Time::ZERO}
486  { }
487 
488  Duration (Offset const& distance)
489  : TimeValue{buildRaw_(llabs (_raw(distance)))}
490  { }
491 
492  explicit
493  Duration (TimeValue const& timeSpec)
494  : Duration{Offset{timeSpec}}
495  { }
496 
497  Duration (FSecs const& timeSpan_in_secs)
498  : Duration{Offset{timeSpan_in_secs}}
499  { }
500 
503  Duration (FrameCnt count, FrameRate const& fps)
504  : Duration{Offset{count,fps}}
505  { }
506 
507  Duration (TimeSpan const& interval);
508 
509  Duration (Duration const& o)
510  : TimeValue{o}
511  {// assuming that negative Duration can not be constructed....
512  REQUIRE (t_ >= 0, "Copy rejected: negative Duration %lu", o.t_);
513  }
514 
515  static const Duration NIL;
516  static const Duration MAX ;
517 
518  void accept (Mutation const&);
519 
520 
522  operator std::string () const;
523 
525  Offset operator- () const;
526 
527  };
528 
529  //-- support combining and Durations ---------------
530 
531  inline Duration
532  operator+ (Duration const& base, Duration const& toAdd)
533  {
534  return Offset(base) + Offset(toAdd);
535  }
536 
537  inline Duration
538  operator- (Duration const& base, Duration const& toRemove)
539  {
540  return base > toRemove? Offset(base) - Offset(toRemove)
541  : Duration::NIL;
542  }
543 
544  template<typename NUM>
545  inline Offset
546  operator* (NUM factor, Duration const& dur)
547  {
548  return factor * Offset(dur);
549  }
550 
551  template<typename NUM>
552  inline Offset
553  operator* (Duration const& dur, NUM factor)
554  {
555  return factor*dur;
556  }
557 
558  inline Offset
560  {
561  return -1 * (*this);
562  }
563 
564 
565 
582  class TimeSpan
583  : public Time
584  , boost::totally_ordered<TimeSpan>
585  {
586  Duration dur_;
587 
588  public:
589  TimeSpan(TimeValue const& start, Duration const& length)
590  : Time(start)
591  , dur_(length)
592  { }
593 
594  TimeSpan(TimeValue const& start, FSecs(duration_in_secs))
595  : Time(start)
596  , dur_(duration_in_secs)
597  { }
598 
599  TimeSpan(TimeValue const& start, TimeValue const& end)
600  : Time(start<=end? start:end)
601  , dur_(Offset(start,end))
602  { }
603 
604  TimeSpan(TimeValue const& start, Offset const& reference_distance)
605  : TimeSpan{start, Time{start} + reference_distance}
606  { }
607 
608  TimeSpan()
609  : TimeSpan(Time::ZERO, Time::ZERO)
610  { }
611 
612  TimeSpan conform() const;
613 
614  static const TimeSpan ALL;
615 
616  Duration&
617  duration()
618  {
619  return dur_;
620  }
621 
622  Duration
623  duration() const
624  {
625  return dur_;
626  }
627 
628  Time
629  start() const
630  {
631  return *this;
632  }
633 
634  Time
635  end() const
636  {
637  return TimeVar(*this) += dur_;
638  }
639 
640  bool
641  contains (TimeValue const& tp) const
642  {
643  return *this <= tp
644  && tp < end();
645  }
646 
648  void accept (Mutation const&);
649 
651  operator std::string () const;
652 
654  friend bool operator== (TimeSpan const& t1, TimeSpan const& t2) { return t1.t_==t2.t_ && t1.dur_==t2.dur_; }
655  friend bool operator< (TimeSpan const& t1, TimeSpan const& t2) { return t1.t_< t2.t_ ||
656  (t1.t_==t2.t_ && t1.dur_< t2.dur_);}
657  };
658 
659 
664  class FrameRate
665  : public boost::rational<uint>
666  {
667  public:
668  FrameRate (uint fps) ;
669  FrameRate (uint num, uint denom);
670  FrameRate (size_t count, Duration timeReference);
671  explicit
672  FrameRate (boost::rational<uint> fractionalRate);
673 
674  static FrameRate approx(double fps);
675 
676  // standard copy acceptable;
677 
678  double asDouble() const;
679 
680  static const FrameRate PAL;
681  static const FrameRate NTSC;
682  static const FrameRate STEP;
683 
684  static const FrameRate HALTED;
685 
687  Duration duration() const;
688 
689  operator std::string() const;
690  };
691 
693  inline FSecs
694  operator/ (int n, FrameRate rate)
695  {
696  return FSecs{ n*rate.denominator(), rate.numerator()};
697  }
698 
699 
700 
701 
702  /* == implementations == */
703 
704  namespace { // implementation helpers...
705 
706  template<typename NUM>
707  inline NUM
708  __ensure_nonzero (NUM n)
709  {
710  if (n == NUM{0})
711  throw error::Logic ("Degenerated frame grid not allowed"
712  , LERR_(BOTTOM_VALUE));
713  return n;
714  }
715 
716  inline gavl_time_t
717  symmetricLimit (gavl_time_t raw, TimeValue lim)
718  {
719  return raw > lim? _raw(lim)
720  : -raw > lim? -_raw(lim)
721  : raw;
722  }
723  }//(End) implementation helpers
724 
725 
726 
727 
733  inline HashVal
735  {
736  HashVal x = _raw(time); // possibly cap to size of hash
737  const uint width = sizeof(HashVal) * CHAR_BIT;
738  const uint mask = width-1;
739  const uint n = width / 2;
740 
741  static_assert (0 < n and n <= mask);
742  return (x<<n) | (x>>((-n)&mask ));
743  }
744 
745 
752  inline gavl_time_t
753  TimeValue::limitedTime (gavl_time_t raw)
754  {
755  return symmetricLimit (raw, Time::MAX);
756  }
757 
758  inline gavl_time_t
759  TimeValue::limitedDelta (gavl_time_t origin, gavl_time_t target)
760  {
761  if (0 > (origin^target))
762  {// prevent possible numeric wrap
763  origin = symmetricLimit (origin, Duration::MAX);
764  target = symmetricLimit (target, Duration::MAX);
765  }
766  gavl_time_t res = target - origin;
767  return symmetricLimit (res, Duration::MAX);
768  }
769 
770  inline TimeSpan
772  {
773  Offset extension{dur_};
774  TimeValue start{_raw(*this)};
775  return Offset{start} + extension > Time::MAX? TimeSpan{Time::MAX-extension, Time::MAX}
776  : TimeSpan{start, extension};
777  }
778 
779  inline bool
781  {
782  return Time::MIN < *this
783  and *this < Time::MAX;
784  }
785 
786 
787  inline
788  TimeVar::TimeVar (FSecs const& fractionalSeconds)
789  : TimeVar{Time(fractionalSeconds)}
790  { }
791 
792  inline
793  Offset::Offset (TimeValue const& distance)
794  : TimeValue{buildRaw_(symmetricLimit(_raw(distance)
795  , Duration::MAX))}
796  { }
797 
798  inline
799  Duration::Duration (TimeSpan const& interval)
800  : Duration{interval.duration()}
801  { }
802 
803  inline
804  FrameRate::FrameRate (uint fps)
805  : boost::rational<uint> (__ensure_nonzero(fps))
806  { }
807 
808  inline
809  FrameRate::FrameRate (uint num, uint denom)
810  : boost::rational<uint> (__ensure_nonzero(num), denom)
811  { }
812 
813  inline
814  FrameRate::FrameRate (boost::rational<uint> fractionalRate)
815  : boost::rational<uint> (__ensure_nonzero(fractionalRate))
816  { }
817 
818  boost::rational<uint> __framerate_approximation (size_t, Duration);
819  boost::rational<uint> __framerate_approximation (double);
820 
821  inline
822  FrameRate::FrameRate (size_t count, Duration timeReference)
823  : FrameRate{__framerate_approximation (count, timeReference)}
824  { }
825 
826  inline FrameRate
827  FrameRate::approx (double fps)
828  {
829  return FrameRate{__framerate_approximation (fps)};
830  }
831 
832 
833  inline double
834  FrameRate::asDouble() const
835  {
836  return boost::rational_cast<double> (*this);
837  }
838 
839  inline Duration
840  Offset::abs() const
841  {
842  return Duration{*this};
843  }
844 
845 
846 
847 }} // lib::time
848 
849 
850 namespace util {
851 
852  inline bool
853  isnil (lib::time::Duration const& dur)
854  {
855  return 0 == dur;
856  }
857 
858  // repeated or forward declaration, see meta/util.hpp
859  template<typename X, typename COND>
860  struct StringConv;
861 
863  template<>
864  struct StringConv<lib::time::FSecs, void>
865  {
866  static std::string
867  invoke (lib::time::FSecs) noexcept;
868  };
869 }
870 #endif /*LIB_TIME_TIMEVALUE_H*/
static const Time ANYTIME
border condition marker value. ANYTIME <= any time value
Definition: timevalue.hpp:322
TimeValue(TimeValue const &o)
copy initialisation allowed
Definition: timevalue.hpp:185
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:241
TimeValue & operator=(TimeValue const &o)
Assigning of time values is not allowed, but derived classed might allow that.
Definition: timevalue.hpp:155
static const Duration MAX
maximum possible temporal extension
Definition: timevalue.hpp:516
TimeValue(gavl_time_t val)
Definition: timevalue.hpp:180
Framerate specified as frames per second.
Definition: timevalue.hpp:664
static const gavl_time_t SCALE
Number of micro ticks (µs) per second as basic time scale.
Definition: timevalue.hpp:176
Offset stretchedByRationalFactor(boost::rational< int64_t >) const
Definition: time.cpp:334
Duration(FrameCnt count, FrameRate const &fps)
duration of the given number of frames.
Definition: timevalue.hpp:503
Interface: an opaque change imposed onto some time value.
Definition: mutation.hpp:100
static const Duration NIL
constant to indicate "no duration"
Definition: timevalue.hpp:515
Implementation namespace for support and library code.
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:308
std::string operator+(std::string str, Literal const &sym)
string concatenation
Definition: symbol.hpp:222
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
static const FrameRate STEP
1 frame per second
Definition: timevalue.hpp:682
bool isRegular() const
Definition: timevalue.hpp:780
TimeSpan conform() const
<
Definition: timevalue.hpp:771
Duration abs() const
interpret the distance given by this offset as a time duration
Definition: timevalue.hpp:840
TimeValue(TimeValue const &origin, TimeValue const &target)
Definition: timevalue.hpp:170
static TimeValue buildRaw_(gavl_time_t)
Definition: time.cpp:245
boost::rational< int64_t > FSecs
rational representation of fractional seconds
Definition: timevalue.hpp:229
Offset operator-() const
Supporting backwards use as offset.
Definition: timevalue.hpp:559
friend HashVal hash_value(TimeValue const &)
derive a hash from the µ-tick value
Definition: timevalue.hpp:734
Lumiera error handling (C++ interface).
size_t HashVal
a STL compatible hash value
Definition: hash-value.h:56
static const Time NEVER
border condition marker value. NEVER >= any time value
Definition: timevalue.hpp:323
Offset measures a distance in time.
Definition: timevalue.hpp:367
static gavl_time_t limitedTime(gavl_time_t raw)
explicit limit of allowed time range
Definition: timevalue.hpp:753
Duration is the internal Lumiera time metric.
Definition: timevalue.hpp:477
static gavl_time_t limitedDelta(gavl_time_t origin, gavl_time_t target)
safe calculation of explicitly limited time offset
Definition: timevalue.hpp:759
boost::rational< uint > __framerate_approximation(double fps)
Definition: time.cpp:286
abstract entry, not yet allocated
A time interval anchored at a specific point in time.
Definition: timevalue.hpp:582
int64_t FrameCnt
relative framecount or frame number.
Definition: digxel.hpp:321
Offset operator-() const
flip offset direction
Definition: timevalue.hpp:461
basic constant internal time value.
Definition: timevalue.hpp:142
failsafe invocation of custom string conversion.
Definition: meta/util.hpp:399
static const Time MAX
Definition: timevalue.hpp:318
Offset stretchedByFloatFactor(double) const
Definition: time.cpp:345
gavl_time_t t_
the raw (internal) time value used to implement the time types
Definition: timevalue.hpp:149
friend gavl_time_t _raw(TimeValue const &time)
Definition: timevalue.hpp:190
static const FrameRate PAL
predefined constant for PAL framerate
Definition: timevalue.hpp:680
TimeVar(TimeVar const &o)
Allowing copy and assignment.
Definition: timevalue.hpp:258