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 
197  // Supporting totally_ordered
198  friend bool operator< (TimeValue const& t1, TimeValue const& t2) { return t1.t_ < t2.t_; }
199  friend bool operator< (TimeValue const& t1, gavl_time_t t2) { return t1.t_ < t2 ; }
200  friend bool operator> (TimeValue const& t1, gavl_time_t t2) { return t1.t_ > t2 ; }
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  };
204 
205 
206 
207 
208 
209 
210 
211  /* ======= specific Time entities ==================== */
212 
222  using FrameCnt = int64_t;
223 
226  using FSecs = boost::rational<int64_t>;
227 
228 
229 
238  class TimeVar
239  : public TimeValue
240  , boost::additive<TimeVar,
241  boost::additive<TimeVar, TimeValue,
242  boost::multipliable<TimeVar, int>
243  > >
244  {
245  public:
246  TimeVar (TimeValue const& time = TimeValue(0))
247  : TimeValue(time)
248  { }
249 
252  TimeVar (FSecs const&);
253 
255  TimeVar (TimeVar const& o)
256  : TimeValue(o)
257  { }
258 
259  TimeVar&
260  operator= (TimeValue const& o)
261  {
262  t_ = TimeVar(o);
263  return *this;
264  }
265 
267  operator gavl_time_t() const { return t_; }
269  operator FSecs() const { return FSecs{t_, TimeValue::SCALE}; }
270 
272  TimeVar& operator+= (TimeVar const& tx) { t_ += tx.t_; return *this; }
273  TimeVar& operator-= (TimeVar const& tx) { t_ -= tx.t_; return *this; }
274 
276  TimeVar& operator*= (int64_t fact) { t_ *= fact; return *this; }
277 
279  TimeVar operator- () const { return TimeVar(*this)*=-1; }
280 
281  // baseclass TimeValue is already totally_ordered
282  };
283 
284 
285 
286 
287  /**********************************************************/
305  class Time
306  : public TimeValue
307  {
309  Time& operator= (Time const);
310 
312  Time(int);
313 
314  public:
315  static const Time MAX ;
316  static const Time MIN ;
317  static const Time ZERO;
318 
319  static const Time ANYTIME;
320  static const Time NEVER;
321 
322  explicit
323  Time (TimeValue const& val =TimeValue(0))
324  : TimeValue(val)
325  { }
326 
327  Time (TimeVar const& calcResult)
328  : TimeValue(calcResult)
329  { }
330 
331  explicit
332  Time (FSecs const& fractionalSeconds);
333 
334  Time ( long millis
335  , uint secs
336  , uint mins =0
337  , uint hours=0
338  );
339 
341  operator std::string () const;
342 
344  TimeVar operator+ (TimeValue const& tval) const { return TimeVar(*this) + tval; }
345  TimeVar operator- (TimeValue const& tval) const { return TimeVar(*this) - tval; }
346  TimeVar operator- () const { return -TimeVar(*this); }
347  };
348 
349 
350 
351 
364  class Offset
365  : public TimeValue
366  {
367  protected:
371  Offset&
372  operator= (Offset const& o)
373  {
375  return *this;
376  }
377 
378  public:
379  explicit
380  Offset (TimeValue const& distance =Time::ZERO);
381 
382  explicit
383  Offset (FSecs const& delta_in_secs);
384 
385  Offset (FrameCnt count, FrameRate const& fps);
386 
387  Offset (TimeValue const& origin, TimeValue const& target)
388  : TimeValue{origin, target}
389  { }
390 
391  static const Offset ZERO;
392 
394  Duration abs() const;
395 
398  Offset stretchedByRationalFactor (boost::rational<int64_t>) const;
399  Offset stretchedByFloatFactor (double) const;
400 
402  operator std::string () const;
403 
404  // Supporting sign flip
405  Offset operator- () const;
406  };
407 
408  //-- support linear offset chaining ---------------
409 
410  inline Offset
411  operator+ (Offset const& start, Offset const& toChain)
412  {
413  TimeVar distance(start);
414  distance += toChain;
415  return Offset(distance);
416  }
417 
418  inline Offset
419  operator- (Offset const& start, Offset const& toSubtract)
420  {
421  TimeVar distance(start);
422  distance -= toSubtract;
423  return Offset(distance);
424  }
425 
426  template<typename FAC>
427  inline Offset
428  operator* (Offset const& distance, FAC factor)
429  {
430  return factor*distance;
431  }
432 
433  template<typename INT>
434  inline Offset
435  operator* (INT factor, Offset const& o)
436  {
437  TimeVar distance(o);
438  distance *= factor;
439  return Offset(distance);
440  }
441 
442  template<typename INTX>
443  inline Offset
444  operator* (boost::rational<INTX> factor, Offset const& offset)
445  {
446  return offset.stretchedByRationalFactor (boost::rational<int64_t>(factor.numerator(), factor.denominator()));
447  }
448 
449  inline Offset
450  operator* (double factor, Offset const& offset)
451  {
452  return offset.stretchedByFloatFactor (factor);
453  }
454 
455 
457  inline Offset
459  {
460  return -1 * (*this);
461  }
462 
463 
464 
465 
474  class Duration
475  : public TimeValue
476  {
478  Duration& operator= (Duration const&);
479 
480  public:
481  Duration()
482  : TimeValue{Time::ZERO}
483  { }
484 
485  Duration (Offset const& distance)
486  : TimeValue{buildRaw_(llabs (_raw(distance)))}
487  { }
488 
489  explicit
490  Duration (TimeValue const& timeSpec)
491  : Duration{Offset{timeSpec}}
492  { }
493 
494  Duration (FSecs const& timeSpan_in_secs)
495  : Duration{Offset{timeSpan_in_secs}}
496  { }
497 
500  Duration (FrameCnt count, FrameRate const& fps)
501  : Duration{Offset{count,fps}}
502  { }
503 
504  Duration (TimeSpan const& interval);
505 
506  Duration (Duration const& o)
507  : TimeValue{o}
508  {// assuming that negative Duration can not be constructed....
509  REQUIRE (t_ >= 0, "Copy rejected: negative Duration %lu", o.t_);
510  }
511 
512  static const Duration NIL;
513  static const Duration MAX ;
514 
515  void accept (Mutation const&);
516 
517 
519  operator std::string () const;
520 
522  Offset operator- () const;
523 
524  };
525 
526  //-- support combining and Durations ---------------
527 
528  inline Duration
529  operator+ (Duration const& base, Duration const& toAdd)
530  {
531  return Offset(base) + Offset(toAdd);
532  }
533 
534  inline Duration
535  operator- (Duration const& base, Duration const& toRemove)
536  {
537  return base > toRemove? Offset(base) - Offset(toRemove)
538  : Duration::NIL;
539  }
540 
541  template<typename INT>
542  inline Offset
543  operator* (INT factor, Duration const& dur)
544  {
545  return factor * Offset(dur);
546  }
547 
548  template<typename INT>
549  inline Offset
550  operator* (Duration const& dur, INT factor)
551  {
552  return factor*dur;
553  }
554 
555  inline Offset
557  {
558  return -1 * (*this);
559  }
560 
561 
562 
579  class TimeSpan
580  : public Time
581  , boost::totally_ordered<TimeSpan>
582  {
583  Duration dur_;
584 
585  public:
586  TimeSpan(TimeValue const& start, Duration const& length)
587  : Time(start)
588  , dur_(length)
589  { }
590 
591  TimeSpan(TimeValue const& start, FSecs(duration_in_secs))
592  : Time(start)
593  , dur_(duration_in_secs)
594  { }
595 
596  TimeSpan(TimeValue const& start, TimeValue const& end)
597  : Time(start<=end? start:end)
598  , dur_(Offset(start,end))
599  { }
600 
601  TimeSpan(TimeValue const& start, Offset const& reference_distance)
602  : TimeSpan{start, Time{start} + reference_distance}
603  { }
604 
605  TimeSpan()
606  : TimeSpan(Time::ZERO, Time::ZERO)
607  { }
608 
609  TimeSpan conform() const;
610 
611  static const TimeSpan ALL;
612 
613  Duration&
614  duration()
615  {
616  return dur_;
617  }
618 
619  Duration
620  duration() const
621  {
622  return dur_;
623  }
624 
625  Time
626  start() const
627  {
628  return *this;
629  }
630 
631  Time
632  end() const
633  {
634  return TimeVar(*this) += dur_;
635  }
636 
637  bool
638  contains (TimeValue const& tp) const
639  {
640  return *this <= tp
641  && tp < end();
642  }
643 
645  void accept (Mutation const&);
646 
648  operator std::string () const;
649 
651  friend bool operator== (TimeSpan const& t1, TimeSpan const& t2) { return t1.t_==t2.t_ && t1.dur_==t2.dur_; }
652  friend bool operator< (TimeSpan const& t1, TimeSpan const& t2) { return t1.t_< t2.t_ ||
653  (t1.t_==t2.t_ && t1.dur_< t2.dur_);}
654  };
655 
656 
661  class FrameRate
662  : public boost::rational<uint>
663  {
664  public:
665  FrameRate (uint fps) ;
666  FrameRate (uint num, uint denom);
667  FrameRate (boost::rational<uint> const& fractionalRate);
668 
669  // standard copy acceptable;
670 
671  double asDouble() const;
672 
673  static const FrameRate PAL;
674  static const FrameRate NTSC;
675 
676  static const FrameRate HALTED;
677 
679  Duration duration() const;
680 
681  operator std::string() const;
682  };
683 
685  inline FSecs
686  operator/ (int n, FrameRate rate)
687  {
688  return FSecs{ n*rate.denominator(), rate.numerator()};
689  }
690 
691 
692 
693 
694  /* == implementations == */
695 
696  namespace { // implementation helpers...
697 
698  template<typename NUM>
699  inline NUM
700  __ensure_nonzero (NUM n)
701  {
702  if (n == NUM{0})
703  throw error::Logic ("Degenerated frame grid not allowed"
704  , error::LERR_(BOTTOM_VALUE));
705  return n;
706  }
707 
708  inline gavl_time_t
709  symmetricLimit (gavl_time_t raw, TimeValue lim)
710  {
711  return raw > lim? _raw(lim)
712  : -raw > lim? -_raw(lim)
713  : raw;
714  }
715  }//(End) implementation helpers
716 
717 
718 
719 
725  inline HashVal
727  {
728  HashVal x = _raw(time); // possibly cap to size of hash
729  const uint width = sizeof(HashVal) * CHAR_BIT;
730  const uint mask = width-1;
731  const uint n = width / 2;
732 
733  static_assert (0 < n and n <= mask);
734  return (x<<n) | (x>>((-n)&mask ));
735  }
736 
737 
744  inline gavl_time_t
745  TimeValue::limitedTime (gavl_time_t raw)
746  {
747  return symmetricLimit (raw, Time::MAX);
748  }
749 
750  inline gavl_time_t
751  TimeValue::limitedDelta (gavl_time_t origin, gavl_time_t target)
752  {
753  if (0 > (origin^target))
754  {// prevent possible numeric wrap
755  origin = symmetricLimit (origin, Duration::MAX);
756  target = symmetricLimit (target, Duration::MAX);
757  }
758  gavl_time_t res = target - origin;
759  return symmetricLimit (res, Duration::MAX);
760  }
761 
762  inline TimeSpan
764  {
765  Offset extension{dur_};
766  TimeValue start{_raw(*this)};
767  return Offset{start} + extension > Time::MAX? TimeSpan{Time::MAX-extension, Time::MAX}
768  : TimeSpan{start, extension};
769  }
770 
771 
772  inline
773  TimeVar::TimeVar (FSecs const& fractionalSeconds)
774  : TimeVar{Time(fractionalSeconds)}
775  { }
776 
777  inline
778  Offset::Offset (TimeValue const& distance)
779  : TimeValue{buildRaw_(symmetricLimit(_raw(distance)
780  , Duration::MAX))}
781  { }
782 
783  inline
784  Duration::Duration (TimeSpan const& interval)
785  : Duration{interval.duration()}
786  { }
787 
788  inline
789  FrameRate::FrameRate (uint fps)
790  : boost::rational<uint> (__ensure_nonzero(fps))
791  { }
792 
793  inline
794  FrameRate::FrameRate (uint num, uint denom)
795  : boost::rational<uint> (__ensure_nonzero(num), denom)
796  { }
797 
798  inline
799  FrameRate::FrameRate (boost::rational<uint> const& fractionalRate)
800  : boost::rational<uint> (__ensure_nonzero(fractionalRate))
801  { }
802 
803  inline double
804  FrameRate::asDouble() const
805  {
806  return boost::rational_cast<double> (*this);
807  }
808 
809  inline Duration
810  Offset::abs() const
811  {
812  return Duration{*this};
813  }
814 
815 
816 
817 }} // lib::time
818 
819 
820 namespace util {
821 
822  inline bool
823  isnil (lib::time::Duration const& dur)
824  {
825  return 0 == dur;
826  }
827 
828  // repeated or forward declaration, see meta/util.hpp
829  template<typename X, typename COND>
830  struct StringConv;
831 
833  template<>
834  struct StringConv<lib::time::FSecs, void>
835  {
836  static std::string
837  invoke (lib::time::FSecs) noexcept;
838  };
839 }
840 #endif /*LIB_TIME_TIMEVALUE_H*/
static const Time ANYTIME
border condition marker value. ANYTIME <= any time value
Definition: timevalue.hpp:319
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:238
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:513
TimeValue(gavl_time_t val)
Definition: timevalue.hpp:180
Framerate specified as frames per second.
Definition: timevalue.hpp:661
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:271
Duration(FrameCnt count, FrameRate const &fps)
duration of the given number of frames.
Definition: timevalue.hpp:500
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:512
Implementation namespace for support and library code.
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:305
std::string operator+(std::string str, Literal const &sym)
string concatenation
Definition: symbol.hpp:212
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:196
TimeSpan conform() const
<
Definition: timevalue.hpp:763
Duration abs() const
interpret the distance given by this offset as a time duration
Definition: timevalue.hpp:810
TimeValue(TimeValue const &origin, TimeValue const &target)
Definition: timevalue.hpp:170
static TimeValue buildRaw_(gavl_time_t)
Definition: time.cpp:241
boost::rational< int64_t > FSecs
rational representation of fractional seconds
Definition: timevalue.hpp:226
Offset operator-() const
Supporting backwards use as offset.
Definition: timevalue.hpp:556
friend HashVal hash_value(TimeValue const &)
derive a hash from the µ-tick value
Definition: timevalue.hpp:726
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:320
Offset measures a distance in time.
Definition: timevalue.hpp:364
static gavl_time_t limitedTime(gavl_time_t raw)
explicit limit of allowed time range
Definition: timevalue.hpp:745
Duration is the internal Lumiera time metric.
Definition: timevalue.hpp:474
static gavl_time_t limitedDelta(gavl_time_t origin, gavl_time_t target)
safe calculation of explicitly limited time offset
Definition: timevalue.hpp:751
abstract entry, not yet allocated
A time interval anchored at a specific point in time.
Definition: timevalue.hpp:579
int64_t FrameCnt
relative framecount or frame number.
Definition: digxel.hpp:322
Offset operator-() const
flip offset direction
Definition: timevalue.hpp:458
basic constant internal time value.
Definition: timevalue.hpp:142
failsafe invocation of custom string conversion.
Definition: meta/util.hpp:371
static const Time MAX
Definition: timevalue.hpp:315
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:673
TimeVar(TimeVar const &o)
Allowing copy and assignment.
Definition: timevalue.hpp:255