clean-up: remove gavl_time_t as external dependency
Indeed — this change set is kind of sad.
Because I still admire the design of the GAVL library,
and would love to use it for processing of raw video.
However, up to now, we never got to the point of actually
doing so. For the future, I am not sure if there remains
room to rely on lib-GAVL, since FFmpeg roughly covers
a similar ground (and a lot beyond that). And providing
a plug-in for FFmpeg is unavoidable, practically speaking.
So I still retain the nominal dependency on lib-GAVL
in the Build system (since it is still packaged in Debian).
But it is pointless to rely on this library just for an
external type-def `gavl_time_t`. We owe much to this
inspiration, but it can be expected that we'll wrap
these raw time-values into a dedicated marker type
soon, and we certainly won't be exposing any C-style
interface for time calculations in future, since
we do not want anyone to side-step the Lumiera
time handling framework in favour of working
„just with plain numbers“
NOTE: lib-GAVL hompage has moved to Github:
https://github.com/bplaum/gavl
This commit is contained in:
parent
ee6e720d00
commit
d31d4295a4
22 changed files with 308 additions and 161 deletions
|
|
@ -85,7 +85,7 @@ def configure(env):
|
||||||
|
|
||||||
|
|
||||||
if not conf.CheckPkgConfig('gavl', '1.4'):
|
if not conf.CheckPkgConfig('gavl', '1.4'):
|
||||||
problems.append('Did not find Gmerlin Audio Video Lib [http://gmerlin.sourceforge.net/gavl.html].')
|
problems.append('Did not find Gmerlin Audio Video Lib [https://github.com/bplaum/gavl].')
|
||||||
else:
|
else:
|
||||||
conf.env.mergeConf('gavl')
|
conf.env.mergeConf('gavl')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ Description
|
||||||
* We use an uniform time type. Time is time, not frames, samples etc.
|
* We use an uniform time type. Time is time, not frames, samples etc.
|
||||||
* All timings in Lumiera are based on integral datatypes
|
* All timings in Lumiera are based on integral datatypes
|
||||||
* We use a fixed, very fine grid, something of the sort of microseconds
|
* We use a fixed, very fine grid, something of the sort of microseconds
|
||||||
* The internal representation is based on a `typedef int64_t gavl_time_t`
|
* The internal representation is based on a `using raw_time_64 = int64_t`
|
||||||
* We use a set of library routines and convenience-methods to
|
* We use a set of library routines and convenience-methods to
|
||||||
- Get time in different formats (fractional seconds, frame counts)
|
- Get time in different formats (fractional seconds, frame counts)
|
||||||
- Calculate with time values (overloaded operators)
|
- Calculate with time values (overloaded operators)
|
||||||
|
|
|
||||||
|
|
@ -493,10 +493,10 @@ NOTE: At the time when Lumiera project started, the standard library provided
|
||||||
Time
|
Time
|
||||||
~~~~
|
~~~~
|
||||||
Time values are represented by a family of opaque date types
|
Time values are represented by a family of opaque date types
|
||||||
with overloaded operators. The implementation is based on `gavl_time_t`,
|
with overloaded operators. The implementation was inspired by `gavl_time_t`
|
||||||
an integral (µsec) time tick value. Thus, the arithmetic on time values
|
and is thus based on a µ-seccond time grid, represented as 64-bit integer.
|
||||||
and time spans is limited and any Time handling and conversion is
|
Thus, the arithmetic on time values and time spans is limited and any Time
|
||||||
centralised in library routines.
|
handling and conversion is centralised in library routines.
|
||||||
|
|
||||||
We distinguish between time values and a _quantisation_ into a frame
|
We distinguish between time values and a _quantisation_ into a frame
|
||||||
or sample grid. In any case, quantisation has to be done once, explicitly
|
or sample grid. In any case, quantisation has to be done once, explicitly
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,12 @@
|
||||||
** this model are defined to be a special kind of timecode, and thus dependent on
|
** this model are defined to be a special kind of timecode, and thus dependent on
|
||||||
** a preceding time quantisation.
|
** a preceding time quantisation.
|
||||||
**
|
**
|
||||||
|
** @deprecated 2025 this should not be a "simple" C library set aside from the Lumiera
|
||||||
|
** time handling framework, rather it should be clarified that these are
|
||||||
|
** implementation helpers and must not be used by any application code.
|
||||||
|
** It should be checked which of these functions actually need to be
|
||||||
|
** exposed through an interface header, since these are typically
|
||||||
|
** used to implement parts of the time handling framework.
|
||||||
**
|
**
|
||||||
** @see lib::time::Time
|
** @see lib::time::Time
|
||||||
** @see timequant.hpp
|
** @see timequant.hpp
|
||||||
|
|
@ -43,11 +49,12 @@
|
||||||
#define LUMIERA_TIME_H
|
#define LUMIERA_TIME_H
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <gavl/gavl.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus /*=================== C++ facilities ===================== */
|
#ifdef __cplusplus /*=================== C++ facilities ===================== */
|
||||||
#include "lib/time/timevalue.hpp"
|
#include "lib/time/timevalue.hpp"
|
||||||
|
|
||||||
|
using lib::time::raw_time_64;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a fraction of seconds to Lumiera's internal opaque time scale.
|
* Converts a fraction of seconds to Lumiera's internal opaque time scale.
|
||||||
|
|
@ -56,7 +63,7 @@
|
||||||
* here negative fractional micro-ticks are truncated towards zero.
|
* here negative fractional micro-ticks are truncated towards zero.
|
||||||
* This was deemed irrelevant in practice.
|
* This was deemed irrelevant in practice.
|
||||||
*/
|
*/
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_rational_to_time (lib::time::FSecs const& fractionalSeconds);
|
lumiera_rational_to_time (lib::time::FSecs const& fractionalSeconds);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -66,7 +73,7 @@ lumiera_rational_to_time (lib::time::FSecs const& fractionalSeconds);
|
||||||
* @note handles only positive frame counts and assumes the
|
* @note handles only positive frame counts and assumes the
|
||||||
* origin to be at zero.
|
* origin to be at zero.
|
||||||
*/
|
*/
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_framecount_to_time (uint64_t frameCount, lib::time::FrameRate const& fps);
|
lumiera_framecount_to_time (uint64_t frameCount, lib::time::FrameRate const& fps);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -75,7 +82,7 @@ lumiera_framecount_to_time (uint64_t frameCount, lib::time::FrameRate const& fps
|
||||||
* @param framerate underlying framerate as rational number
|
* @param framerate underlying framerate as rational number
|
||||||
* @throw error::Logic on zero framerate
|
* @throw error::Logic on zero framerate
|
||||||
*/
|
*/
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_frame_duration (lib::time::FrameRate const& fps);
|
lumiera_frame_duration (lib::time::FrameRate const& fps);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -91,15 +98,15 @@ extern "C" { /* ===================== C interface ======================== */
|
||||||
* The time grid used for quantisation is comprised of equally spaced intervals,
|
* The time grid used for quantisation is comprised of equally spaced intervals,
|
||||||
* rooted at the given origin. The interval starting with the origin is numbered
|
* rooted at the given origin. The interval starting with the origin is numbered
|
||||||
* as zero. Each interval includes its lower bound, but excludes its upper bound.
|
* as zero. Each interval includes its lower bound, but excludes its upper bound.
|
||||||
* @param grid spacing of the grid intervals, measured in GAVL_TIME_SCALE
|
* @param grid spacing of the grid intervals, measured in TimeValue::Scale (µ-ticks)
|
||||||
* @return number of the grid interval containing the given time.
|
* @return number of the grid interval containing the given time.
|
||||||
* @warning the resulting value is limited to (Time::Min, Time::MAX)
|
* @warning the resulting value is limited to (Time::Min, Time::MAX)
|
||||||
*/
|
*/
|
||||||
int64_t
|
int64_t
|
||||||
lumiera_quantise_frames (gavl_time_t time, gavl_time_t origin, gavl_time_t grid);
|
lumiera_quantise_frames (raw_time_64 time, raw_time_64 origin, raw_time_64 grid);
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
lumiera_quantise_frames_fps (gavl_time_t time, gavl_time_t origin, uint framerate);
|
lumiera_quantise_frames_fps (raw_time_64 time, raw_time_64 origin, uint framerate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to #lumiera_quantise_frames, but returns a grid aligned _relative time_.
|
* Similar to #lumiera_quantise_frames, but returns a grid aligned _relative time_.
|
||||||
|
|
@ -110,17 +117,17 @@ lumiera_quantise_frames_fps (gavl_time_t time, gavl_time_t origin, uint framerat
|
||||||
* origin = Time::MIN, then all original time values above zero will be
|
* origin = Time::MIN, then all original time values above zero will be
|
||||||
* clipped, because the result, relative to origin, needs to be <= Time::MAX
|
* clipped, because the result, relative to origin, needs to be <= Time::MAX
|
||||||
*/
|
*/
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_quantise_time (gavl_time_t time, gavl_time_t origin, gavl_time_t grid);
|
lumiera_quantise_time (raw_time_64 time, raw_time_64 origin, raw_time_64 grid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate time of a grid point (frame start)
|
* Calculate time of a grid point (frame start)
|
||||||
* @param nr index number of the grid point (0 is at origin)
|
* @param nr index number of the grid point (0 is at origin)
|
||||||
* @param grid spacing of the grid intervals, measured in GAVL_TIME_SCALE
|
* @param grid spacing of the grid intervals, measured in TimeValue::Scale (µ-ticks)
|
||||||
* @return time point (frame start) on the Lumiera internal time scale
|
* @return time point (frame start) on the Lumiera internal time scale
|
||||||
*/
|
*/
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_time_of_gridpoint (int64_t nr, gavl_time_t origin, gavl_time_t grid);
|
lumiera_time_of_gridpoint (int64_t nr, raw_time_64 origin, raw_time_64 grid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a time value by summing up the given components.
|
* Build a time value by summing up the given components.
|
||||||
|
|
@ -129,7 +136,7 @@ lumiera_time_of_gridpoint (int64_t nr, gavl_time_t origin, gavl_time_t grid);
|
||||||
* @param mins number of minutes
|
* @param mins number of minutes
|
||||||
* @param hours number of hours
|
* @param hours number of hours
|
||||||
*/
|
*/
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_build_time (long millis, uint secs, uint mins, uint hours);
|
lumiera_build_time (long millis, uint secs, uint mins, uint hours);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -140,7 +147,7 @@ lumiera_build_time (long millis, uint secs, uint mins, uint hours);
|
||||||
* @param mins number of minutes
|
* @param mins number of minutes
|
||||||
* @param hours number of hours
|
* @param hours number of hours
|
||||||
*/
|
*/
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours);
|
lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -148,59 +155,59 @@ lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours)
|
||||||
* The components are interpreted as a NTSC drop-frame timecode.
|
* The components are interpreted as a NTSC drop-frame timecode.
|
||||||
* @warning take care not to specify time codes that are illegal NTSC drop-frame times.
|
* @warning take care not to specify time codes that are illegal NTSC drop-frame times.
|
||||||
*/
|
*/
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours);
|
lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours);
|
||||||
|
|
||||||
|
|
||||||
/** Extract the hour part of given time. */
|
/** Extract the hour part of given time. */
|
||||||
int
|
int
|
||||||
lumiera_time_hours (gavl_time_t time);
|
lumiera_time_hours (raw_time_64 time);
|
||||||
|
|
||||||
|
|
||||||
/** Extract the minute part of given time. */
|
/** Extract the minute part of given time. */
|
||||||
int
|
int
|
||||||
lumiera_time_minutes (gavl_time_t time);
|
lumiera_time_minutes (raw_time_64 time);
|
||||||
|
|
||||||
|
|
||||||
/** Extract the seconds part of given time. */
|
/** Extract the seconds part of given time. */
|
||||||
int
|
int
|
||||||
lumiera_time_seconds (gavl_time_t time);
|
lumiera_time_seconds (raw_time_64 time);
|
||||||
|
|
||||||
|
|
||||||
/** Extract the milliseconds part of given time. */
|
/** Extract the milliseconds part of given time. */
|
||||||
int
|
int
|
||||||
lumiera_time_millis (gavl_time_t time);
|
lumiera_time_millis (raw_time_64 time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the remaining frame part of given time.
|
* Extract the remaining frame part of given time.
|
||||||
* @param fps frame rate (frames per second)
|
* @param fps frame rate (frames per second)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
lumiera_time_frames (gavl_time_t time, uint fps);
|
lumiera_time_frames (raw_time_64 time, uint fps);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the frame part of given time, using NTSC drop-frame timecode.
|
* Extract the frame part of given time, using NTSC drop-frame timecode.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
lumiera_time_ntsc_drop_frames (gavl_time_t time);
|
lumiera_time_ntsc_drop_frames (raw_time_64 time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the second part of given time, using NTSC drop-frame timecode.
|
* Extract the second part of given time, using NTSC drop-frame timecode.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
lumiera_time_ntsc_drop_seconds (gavl_time_t time);
|
lumiera_time_ntsc_drop_seconds (raw_time_64 time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the minute part of given time, using NTSC drop-frame timecode.
|
* Extract the minute part of given time, using NTSC drop-frame timecode.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
lumiera_time_ntsc_drop_minutes (gavl_time_t time);
|
lumiera_time_ntsc_drop_minutes (raw_time_64 time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the hour part of given time, using NTSC drop-frame timecode.
|
* Extract the hour part of given time, using NTSC drop-frame timecode.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
lumiera_time_ntsc_drop_hours (gavl_time_t time);
|
lumiera_time_ntsc_drop_hours (raw_time_64 time);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -210,7 +217,7 @@ lumiera_time_ntsc_drop_hours (gavl_time_t time);
|
||||||
* by rendering into a suitable timecode format.
|
* by rendering into a suitable timecode format.
|
||||||
*/
|
*/
|
||||||
char*
|
char*
|
||||||
lumiera_tmpbuf_print_time (gavl_time_t time);
|
lumiera_tmpbuf_print_time (raw_time_64 time);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,9 @@
|
||||||
/** @file time.cpp
|
/** @file time.cpp
|
||||||
** Lumiera time handling core implementation unit.
|
** Lumiera time handling core implementation unit.
|
||||||
** This translation unit generates code for the Lumiera internal time wrapper,
|
** This translation unit generates code for the Lumiera internal time wrapper,
|
||||||
** based on gavl_time_t, associated constants, marker classes for the derived
|
** based on 64bit integral µ-tick values, associated constants, marker classes
|
||||||
** time entities (TimeVar, Offset, Duration, TimeSpan, FrameRate) and for the
|
** for the derived time entities (TimeVar, Offset, Duration, TimeSpan, FrameRate)
|
||||||
** basic time and frame rate conversion functions.
|
** and for the basic time and frame rate conversion functions.
|
||||||
**
|
**
|
||||||
** Client code includes either time.h (for basics and conversion functions)
|
** Client code includes either time.h (for basics and conversion functions)
|
||||||
** or timevalue.hpp (for the time entities), timequant.hpp for grid aligned
|
** or timevalue.hpp (for the time entities), timequant.hpp for grid aligned
|
||||||
|
|
@ -75,11 +75,11 @@ namespace meta {
|
||||||
namespace time {
|
namespace time {
|
||||||
|
|
||||||
|
|
||||||
const gavl_time_t TimeValue::SCALE = GAVL_TIME_SCALE;
|
const raw_time_64 TimeValue::SCALE = 1'000'000;
|
||||||
|
|
||||||
|
|
||||||
/** @note the allowed time range is explicitly limited to help overflow protection */
|
/** @note the allowed time range is explicitly limited to help overflow protection */
|
||||||
const Time Time::MAX ( TimeValue::buildRaw_(+std::numeric_limits<gavl_time_t>::max() / 30) );
|
const Time Time::MAX ( TimeValue::buildRaw_(+std::numeric_limits<raw_time_64>::max() / 30) );
|
||||||
const Time Time::MIN ( TimeValue::buildRaw_(-_raw(Time::MAX) ) );
|
const Time Time::MIN ( TimeValue::buildRaw_(-_raw(Time::MAX) ) );
|
||||||
const Time Time::ZERO;
|
const Time Time::ZERO;
|
||||||
|
|
||||||
|
|
@ -94,8 +94,8 @@ namespace time {
|
||||||
|
|
||||||
|
|
||||||
/** scale factor _used locally within this implementation header_.
|
/** scale factor _used locally within this implementation header_.
|
||||||
* GAVL_TIME_SCALE rsp. TimeValue::SCALE is the correct factor or dividend when using
|
* TimeValue::SCALE (µ-ticks, i.e. 1e6) is the correct factor or dividend when using
|
||||||
* gavl_time_t for display on a scale with seconds. Since we want to use milliseconds,
|
* raw_time_64 for display on a scale with seconds. Since we want to use milliseconds,
|
||||||
* we need to multiply or divide by 1000 to get correct results. */
|
* we need to multiply or divide by 1000 to get correct results. */
|
||||||
#define TIME_SCALE_MS (lib::time::TimeValue::SCALE / 1000)
|
#define TIME_SCALE_MS (lib::time::TimeValue::SCALE / 1000)
|
||||||
|
|
||||||
|
|
@ -138,7 +138,7 @@ namespace time {
|
||||||
* of any "time-like" value, it is meant to be compact. */
|
* of any "time-like" value, it is meant to be compact. */
|
||||||
TimeValue::operator string() const
|
TimeValue::operator string() const
|
||||||
{
|
{
|
||||||
gavl_time_t time = t_;
|
raw_time_64 time = t_;
|
||||||
int64_t millis, seconds;
|
int64_t millis, seconds;
|
||||||
bool negative = (time < 0);
|
bool negative = (time < 0);
|
||||||
|
|
||||||
|
|
@ -163,7 +163,7 @@ namespace time {
|
||||||
*/
|
*/
|
||||||
Time::operator string() const
|
Time::operator string() const
|
||||||
{
|
{
|
||||||
gavl_time_t time = t_;
|
raw_time_64 time = t_;
|
||||||
int millis, seconds, minutes, hours;
|
int millis, seconds, minutes, hours;
|
||||||
bool negative = (time < 0);
|
bool negative = (time < 0);
|
||||||
|
|
||||||
|
|
@ -233,7 +233,7 @@ namespace time {
|
||||||
/** @internal backdoor to sneak in a raw time value
|
/** @internal backdoor to sneak in a raw time value
|
||||||
* bypassing any normalisation and limiting */
|
* bypassing any normalisation and limiting */
|
||||||
TimeValue
|
TimeValue
|
||||||
TimeValue::buildRaw_ (gavl_time_t raw)
|
TimeValue::buildRaw_ (raw_time_64 raw)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<TimeValue const&> (raw);
|
return reinterpret_cast<TimeValue const&> (raw);
|
||||||
}
|
}
|
||||||
|
|
@ -326,7 +326,7 @@ namespace time {
|
||||||
{
|
{
|
||||||
boost::rational<int64_t> distance (this->t_);
|
boost::rational<int64_t> distance (this->t_);
|
||||||
distance *= factor;
|
distance *= factor;
|
||||||
gavl_time_t microTicks = floordiv (distance.numerator(), distance.denominator());
|
raw_time_64 microTicks = floordiv (distance.numerator(), distance.denominator());
|
||||||
return Offset{buildRaw_(microTicks)};
|
return Offset{buildRaw_(microTicks)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -337,7 +337,7 @@ namespace time {
|
||||||
{
|
{
|
||||||
double distance(this->t_);
|
double distance(this->t_);
|
||||||
distance *= factor;
|
distance *= factor;
|
||||||
gavl_time_t microTicks = floor (distance);
|
raw_time_64 microTicks = floor (distance);
|
||||||
return Offset{buildRaw_(microTicks)};
|
return Offset{buildRaw_(microTicks)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -383,7 +383,7 @@ namespace util {
|
||||||
|
|
||||||
|
|
||||||
char*
|
char*
|
||||||
lumiera_tmpbuf_print_time (gavl_time_t time)
|
lumiera_tmpbuf_print_time (raw_time_64 time)
|
||||||
{
|
{
|
||||||
int milliseconds, seconds, minutes, hours;
|
int milliseconds, seconds, minutes, hours;
|
||||||
bool negative = (time < 0);
|
bool negative = (time < 0);
|
||||||
|
|
@ -409,7 +409,7 @@ lumiera_tmpbuf_print_time (gavl_time_t time)
|
||||||
|
|
||||||
|
|
||||||
/// @todo this utility function could be factored out into a `FSecs` or `RSec` class ///////////////////////TICKET #1262
|
/// @todo this utility function could be factored out into a `FSecs` or `RSec` class ///////////////////////TICKET #1262
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_rational_to_time (FSecs const& fractionalSeconds)
|
lumiera_rational_to_time (FSecs const& fractionalSeconds)
|
||||||
{
|
{
|
||||||
// avoid numeric wrap from values not representable as 64bit µ-ticks
|
// avoid numeric wrap from values not representable as 64bit µ-ticks
|
||||||
|
|
@ -417,22 +417,22 @@ lumiera_rational_to_time (FSecs const& fractionalSeconds)
|
||||||
return (fractionalSeconds < 0? -1:+1)
|
return (fractionalSeconds < 0? -1:+1)
|
||||||
* std::numeric_limits<int64_t>::max();
|
* std::numeric_limits<int64_t>::max();
|
||||||
|
|
||||||
return gavl_time_t(util::reQuant (fractionalSeconds.numerator()
|
return raw_time_64(util::reQuant (fractionalSeconds.numerator()
|
||||||
,fractionalSeconds.denominator()
|
,fractionalSeconds.denominator()
|
||||||
,lib::time::TimeValue::SCALE
|
,lib::time::TimeValue::SCALE
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_framecount_to_time (uint64_t frameCount, FrameRate const& fps)
|
lumiera_framecount_to_time (uint64_t frameCount, FrameRate const& fps)
|
||||||
{
|
{
|
||||||
// convert to 64bit
|
// convert to 64bit
|
||||||
boost::rational<uint64_t> framerate (fps.numerator(), fps.denominator());
|
boost::rational<uint64_t> framerate (fps.numerator(), fps.denominator());
|
||||||
|
|
||||||
return rational_cast<gavl_time_t> (lib::time::TimeValue::SCALE * frameCount / framerate);
|
return rational_cast<raw_time_64> (lib::time::TimeValue::SCALE * frameCount / framerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_frame_duration (FrameRate const& fps)
|
lumiera_frame_duration (FrameRate const& fps)
|
||||||
{
|
{
|
||||||
if (!fps)
|
if (!fps)
|
||||||
|
|
@ -447,20 +447,20 @@ lumiera_frame_duration (FrameRate const& fps)
|
||||||
namespace { // implementation: basic frame quantisation....
|
namespace { // implementation: basic frame quantisation....
|
||||||
|
|
||||||
inline int64_t
|
inline int64_t
|
||||||
calculate_quantisation (gavl_time_t time, gavl_time_t origin, gavl_time_t grid)
|
calculate_quantisation (raw_time_64 time, raw_time_64 origin, raw_time_64 grid)
|
||||||
{
|
{
|
||||||
time -= origin;
|
time -= origin;
|
||||||
return floordiv (time,grid);
|
return floordiv (time,grid);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int64_t
|
inline int64_t
|
||||||
calculate_quantisation (gavl_time_t time, gavl_time_t origin, uint framerate, uint framerate_divisor=1)
|
calculate_quantisation (raw_time_64 time, raw_time_64 origin, uint framerate, uint framerate_divisor=1)
|
||||||
{
|
{
|
||||||
REQUIRE (framerate);
|
REQUIRE (framerate);
|
||||||
REQUIRE (framerate_divisor);
|
REQUIRE (framerate_divisor);
|
||||||
|
|
||||||
const int64_t limit_num = std::numeric_limits<gavl_time_t>::max() / framerate;
|
const int64_t limit_num = std::numeric_limits<raw_time_64>::max() / framerate;
|
||||||
const int64_t limit_den = std::numeric_limits<gavl_time_t>::max() / framerate_divisor;
|
const int64_t limit_den = std::numeric_limits<raw_time_64>::max() / framerate_divisor;
|
||||||
const int64_t microScale {lib::time::TimeValue::SCALE};
|
const int64_t microScale {lib::time::TimeValue::SCALE};
|
||||||
|
|
||||||
// protect against numeric overflow
|
// protect against numeric overflow
|
||||||
|
|
@ -474,7 +474,7 @@ namespace { // implementation: basic frame quantisation....
|
||||||
{
|
{
|
||||||
// direct calculation will overflow.
|
// direct calculation will overflow.
|
||||||
// use the less precise method instead...
|
// use the less precise method instead...
|
||||||
gavl_time_t frameDuration = microScale / framerate; // truncated to µs
|
raw_time_64 frameDuration = microScale / framerate; // truncated to µs
|
||||||
return calculate_quantisation (time,origin, frameDuration);
|
return calculate_quantisation (time,origin, frameDuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -482,37 +482,37 @@ namespace { // implementation: basic frame quantisation....
|
||||||
|
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
lumiera_quantise_frames (gavl_time_t time, gavl_time_t origin, gavl_time_t grid)
|
lumiera_quantise_frames (raw_time_64 time, raw_time_64 origin, raw_time_64 grid)
|
||||||
{
|
{
|
||||||
return calculate_quantisation (time, origin, grid);
|
return calculate_quantisation (time, origin, grid);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
lumiera_quantise_frames_fps (gavl_time_t time, gavl_time_t origin, uint framerate)
|
lumiera_quantise_frames_fps (raw_time_64 time, raw_time_64 origin, uint framerate)
|
||||||
{
|
{
|
||||||
return calculate_quantisation (time, origin, framerate);
|
return calculate_quantisation (time, origin, framerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_quantise_time (gavl_time_t time, gavl_time_t origin, gavl_time_t grid)
|
lumiera_quantise_time (raw_time_64 time, raw_time_64 origin, raw_time_64 grid)
|
||||||
{
|
{
|
||||||
int64_t count = calculate_quantisation (time, origin, grid);
|
int64_t count = calculate_quantisation (time, origin, grid);
|
||||||
gavl_time_t alignedTime = count * grid;
|
raw_time_64 alignedTime = count * grid;
|
||||||
return alignedTime;
|
return alignedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_time_of_gridpoint (int64_t nr, gavl_time_t origin, gavl_time_t grid)
|
lumiera_time_of_gridpoint (int64_t nr, raw_time_64 origin, raw_time_64 grid)
|
||||||
{
|
{
|
||||||
gavl_time_t offset = nr * grid;
|
raw_time_64 offset = nr * grid;
|
||||||
return origin + offset;
|
return origin + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_build_time(long millis, uint secs, uint mins, uint hours)
|
lumiera_build_time(long millis, uint secs, uint mins, uint hours)
|
||||||
{
|
{
|
||||||
gavl_time_t time = millis
|
raw_time_64 time = millis
|
||||||
+ 1000 * secs
|
+ 1000 * secs
|
||||||
+ 1000 * 60 * mins
|
+ 1000 * 60 * mins
|
||||||
+ 1000 * 60 * 60 * hours;
|
+ 1000 * 60 * 60 * hours;
|
||||||
|
|
@ -520,10 +520,10 @@ lumiera_build_time(long millis, uint secs, uint mins, uint hours)
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours)
|
lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours)
|
||||||
{
|
{
|
||||||
gavl_time_t time = 1000LL * frames/fps
|
raw_time_64 time = 1000LL * frames/fps
|
||||||
+ 1000 * secs
|
+ 1000 * secs
|
||||||
+ 1000 * 60 * mins
|
+ 1000 * 60 * mins
|
||||||
+ 1000 * 60 * 60 * hours;
|
+ 1000 * 60 * 60 * hours;
|
||||||
|
|
@ -532,31 +532,31 @@ lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
lumiera_time_hours (gavl_time_t time)
|
lumiera_time_hours (raw_time_64 time)
|
||||||
{
|
{
|
||||||
return time / TIME_SCALE_MS / 1000 / 60 / 60;
|
return time / TIME_SCALE_MS / 1000 / 60 / 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
lumiera_time_minutes (gavl_time_t time)
|
lumiera_time_minutes (raw_time_64 time)
|
||||||
{
|
{
|
||||||
return (time / TIME_SCALE_MS / 1000 / 60) % 60;
|
return (time / TIME_SCALE_MS / 1000 / 60) % 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
lumiera_time_seconds (gavl_time_t time)
|
lumiera_time_seconds (raw_time_64 time)
|
||||||
{
|
{
|
||||||
return (time / TIME_SCALE_MS / 1000) % 60;
|
return (time / TIME_SCALE_MS / 1000) % 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
lumiera_time_millis (gavl_time_t time)
|
lumiera_time_millis (raw_time_64 time)
|
||||||
{
|
{
|
||||||
return (time / TIME_SCALE_MS) % 1000;
|
return (time / TIME_SCALE_MS) % 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
lumiera_time_frames (gavl_time_t time, uint fps)
|
lumiera_time_frames (raw_time_64 time, uint fps)
|
||||||
{
|
{
|
||||||
REQUIRE (fps < uint(std::numeric_limits<int>::max()));
|
REQUIRE (fps < uint(std::numeric_limits<int>::max()));
|
||||||
return floordiv<int> (lumiera_time_millis(time) * int(fps), TIME_SCALE_MS);
|
return floordiv<int> (lumiera_time_millis(time) * int(fps), TIME_SCALE_MS);
|
||||||
|
|
@ -581,7 +581,7 @@ namespace { // implementation helper
|
||||||
* @todo I doubt this works correct for negative times!!
|
* @todo I doubt this works correct for negative times!!
|
||||||
*/
|
*/
|
||||||
inline int64_t
|
inline int64_t
|
||||||
calculate_drop_frame_number (gavl_time_t time)
|
calculate_drop_frame_number (raw_time_64 time)
|
||||||
{
|
{
|
||||||
int64_t frameNr = calculate_quantisation (time, 0, 30000, 1001);
|
int64_t frameNr = calculate_quantisation (time, 0, 30000, 1001);
|
||||||
|
|
||||||
|
|
@ -599,30 +599,30 @@ namespace { // implementation helper
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
lumiera_time_ntsc_drop_frames (gavl_time_t time)
|
lumiera_time_ntsc_drop_frames (raw_time_64 time)
|
||||||
{
|
{
|
||||||
return calculate_drop_frame_number(time) % 30;
|
return calculate_drop_frame_number(time) % 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
lumiera_time_ntsc_drop_seconds (gavl_time_t time)
|
lumiera_time_ntsc_drop_seconds (raw_time_64 time)
|
||||||
{
|
{
|
||||||
return calculate_drop_frame_number(time) / 30 % 60;
|
return calculate_drop_frame_number(time) / 30 % 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
lumiera_time_ntsc_drop_minutes (gavl_time_t time)
|
lumiera_time_ntsc_drop_minutes (raw_time_64 time)
|
||||||
{
|
{
|
||||||
return calculate_drop_frame_number(time) / 30 / 60 % 60;
|
return calculate_drop_frame_number(time) / 30 / 60 % 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
lumiera_time_ntsc_drop_hours (gavl_time_t time)
|
lumiera_time_ntsc_drop_hours (raw_time_64 time)
|
||||||
{
|
{
|
||||||
return calculate_drop_frame_number(time) / 30 / 60 / 60 % 24;
|
return calculate_drop_frame_number(time) / 30 / 60 / 60 % 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours)
|
lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours)
|
||||||
{
|
{
|
||||||
uint64_t total_mins = 60 * hours + mins;
|
uint64_t total_mins = 60 * hours + mins;
|
||||||
|
|
@ -631,7 +631,7 @@ lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours)
|
||||||
+ 30 * secs
|
+ 30 * secs
|
||||||
+ frames
|
+ frames
|
||||||
- 2 * (total_mins - total_mins / 10);
|
- 2 * (total_mins - total_mins / 10);
|
||||||
gavl_time_t result = lumiera_framecount_to_time (total_frames, FrameRate::NTSC);
|
raw_time_64 result = lumiera_framecount_to_time (total_frames, FrameRate::NTSC);
|
||||||
|
|
||||||
if (0 != result) // compensate for truncating down on conversion
|
if (0 != result) // compensate for truncating down on conversion
|
||||||
result += 1; // without this adjustment the frame number
|
result += 1; // without this adjustment the frame number
|
||||||
|
|
|
||||||
|
|
@ -350,7 +350,7 @@ namespace time {
|
||||||
/** */
|
/** */
|
||||||
Secs::Secs (QuTime const& quantisedTime)
|
Secs::Secs (QuTime const& quantisedTime)
|
||||||
: TCode(quantisedTime)
|
: TCode(quantisedTime)
|
||||||
// : sec_(TimeVar(quantisedTime) / GAVL_TIME_SCALE) //////////////////////////////////////////////////////TICKET #736 implement Seconds format
|
// : sec_(TimeVar(quantisedTime) / TimeValue::SCALE) /////////////////////////////////////////////////////TICKET #736 implement Seconds format
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@
|
||||||
/** @file timevalue.hpp
|
/** @file timevalue.hpp
|
||||||
** a family of time value like entities and their relationships.
|
** a family of time value like entities and their relationships.
|
||||||
** This is the foundation for the Lumiera time handling framework. On the implementation
|
** This is the foundation for the Lumiera time handling framework. On the implementation
|
||||||
** level, time values are represented as 64bit integer values `gavl_time_t`. But for the
|
** level, time values are represented as 64bit integer values `raw_time_64`, similar to
|
||||||
|
** and inspired by `gavl_time_t` from the raw-video handling [Lib-GAVL]. But for the
|
||||||
** actual use, we create several kinds of time "values", based on their logical properties.
|
** actual use, we create several kinds of time "values", based on their logical properties.
|
||||||
** These time values are considered to be fixed (immutable) values, which may only be
|
** These time values are considered to be fixed (immutable) values, which may only be
|
||||||
** created through some limited construction paths, and any time based calculation
|
** created through some limited construction paths, and any time based calculation
|
||||||
|
|
@ -30,7 +31,7 @@
|
||||||
** way to retrieve such a value is by formatting it into a time code format.
|
** way to retrieve such a value is by formatting it into a time code format.
|
||||||
**
|
**
|
||||||
** The lib::time::TimeValue serves as foundation for all further time calculations;
|
** The lib::time::TimeValue serves as foundation for all further time calculations;
|
||||||
** in fact it is implemented as a single 64bit µ-tick value (`gavl_time_t`). The
|
** in fact it is implemented as a single 64bit µ-tick value (`raw_time_64`). The
|
||||||
** further time entities are implemented as value objects (without virtual functions):
|
** further time entities are implemented as value objects (without virtual functions):
|
||||||
** - lib::time::Time represents a time instant and is the reference for any usage
|
** - lib::time::Time represents a time instant and is the reference for any usage
|
||||||
** - lib::time::TimeVar is a mutable time variable and can be used for calculations
|
** - lib::time::TimeVar is a mutable time variable and can be used for calculations
|
||||||
|
|
@ -87,6 +88,7 @@
|
||||||
** @see timequant.hpp
|
** @see timequant.hpp
|
||||||
** @see TimeValue_test
|
** @see TimeValue_test
|
||||||
**
|
**
|
||||||
|
** [Lib-GAVL]: https://github.com/bplaum/gavl
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -100,11 +102,6 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <gavl/gavltime.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
namespace lib {
|
namespace lib {
|
||||||
namespace time {
|
namespace time {
|
||||||
|
|
@ -118,11 +115,22 @@ namespace time {
|
||||||
class Mutation;
|
class Mutation;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw µ-tick time representation used in Lumiera.
|
||||||
|
* @remark this representation was inspired by [Lib-GAVL].
|
||||||
|
* @todo 2025 a mere type alias is up to debate -- very likely we'll use a wrapper soon /////////////////TICKET #1258
|
||||||
|
* @warning application logic should avoid handling any raw time value
|
||||||
|
* directly and rather treat time data as an opaque entity.
|
||||||
|
* [Lib-GAVL]: https://github.com/bplaum/gavl
|
||||||
|
*/
|
||||||
|
using raw_time_64 = int64_t;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* basic constant internal time value.
|
* basic constant internal time value.
|
||||||
* These time values provide the implementation base
|
* These time values provide the implementation base
|
||||||
* for all further time types. They can be created by
|
* for all further time types. They can be created by
|
||||||
* wrapping up a raw micro tick value (gavl_time_t),
|
* wrapping up a raw micro tick value (raw_time_64),
|
||||||
* are totally ordered, but besides that,
|
* are totally ordered, but besides that,
|
||||||
* they are opaque and non-mutable.
|
* they are opaque and non-mutable.
|
||||||
* @note clients should prefer to use Time instances,
|
* @note clients should prefer to use Time instances,
|
||||||
|
|
@ -132,12 +140,12 @@ namespace time {
|
||||||
*/
|
*/
|
||||||
class TimeValue
|
class TimeValue
|
||||||
: boost::totally_ordered<TimeValue,
|
: boost::totally_ordered<TimeValue,
|
||||||
boost::totally_ordered<TimeValue, gavl_time_t>>
|
boost::totally_ordered<TimeValue, raw_time_64>>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
/** the raw (internal) time value
|
/** the raw (internal) time value
|
||||||
* used to implement the time types */
|
* used to implement the time types */
|
||||||
gavl_time_t t_;
|
raw_time_64 t_;
|
||||||
|
|
||||||
|
|
||||||
/** Assigning of time values is not allowed,
|
/** Assigning of time values is not allowed,
|
||||||
|
|
@ -153,9 +161,9 @@ namespace time {
|
||||||
friend class Mutation;
|
friend class Mutation;
|
||||||
|
|
||||||
/** explicit limit of allowed time range */
|
/** explicit limit of allowed time range */
|
||||||
static gavl_time_t limitedTime (gavl_time_t raw);
|
static raw_time_64 limitedTime (raw_time_64 raw);
|
||||||
/** safe calculation of explicitly limited time offset */
|
/** safe calculation of explicitly limited time offset */
|
||||||
static gavl_time_t limitedDelta (gavl_time_t origin, gavl_time_t target);
|
static raw_time_64 limitedDelta (raw_time_64 origin, raw_time_64 target);
|
||||||
|
|
||||||
/** @internal for Offset and Duration entities built on top */
|
/** @internal for Offset and Duration entities built on top */
|
||||||
TimeValue (TimeValue const& origin, TimeValue const& target)
|
TimeValue (TimeValue const& origin, TimeValue const& target)
|
||||||
|
|
@ -164,11 +172,11 @@ namespace time {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Number of micro ticks (µs) per second as basic time scale */
|
/** Number of micro ticks (µs) per second as basic time scale */
|
||||||
static const gavl_time_t SCALE;
|
static const raw_time_64 SCALE;
|
||||||
|
|
||||||
|
|
||||||
explicit
|
explicit
|
||||||
TimeValue (gavl_time_t val) ///< time given in µ ticks here
|
TimeValue (raw_time_64 val) ///< time given in µ ticks here
|
||||||
: t_{limitedTime (val)}
|
: t_{limitedTime (val)}
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
@ -178,9 +186,9 @@ namespace time {
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/** @internal to pass Time values to C functions */
|
/** @internal to pass Time values to C functions */
|
||||||
friend gavl_time_t _raw (TimeValue const& time) { return time.t_; }
|
friend raw_time_64 _raw (TimeValue const& time) { return time.t_; }
|
||||||
friend HashVal hash_value (TimeValue const&);
|
friend HashVal hash_value (TimeValue const&);
|
||||||
static TimeValue buildRaw_(gavl_time_t);
|
static TimeValue buildRaw_(raw_time_64);
|
||||||
|
|
||||||
/** @internal diagnostics */
|
/** @internal diagnostics */
|
||||||
operator std::string () const;
|
operator std::string () const;
|
||||||
|
|
@ -190,10 +198,10 @@ namespace time {
|
||||||
|
|
||||||
// Supporting totally_ordered
|
// Supporting totally_ordered
|
||||||
friend bool operator< (TimeValue const& t1, TimeValue const& t2) { return t1.t_ < t2.t_; }
|
friend bool operator< (TimeValue const& t1, TimeValue const& t2) { return t1.t_ < t2.t_; }
|
||||||
friend bool operator< (TimeValue const& t1, gavl_time_t t2) { return t1.t_ < t2 ; }
|
friend bool operator< (TimeValue const& t1, raw_time_64 t2) { return t1.t_ < t2 ; }
|
||||||
friend bool operator> (TimeValue const& t1, gavl_time_t t2) { return t1.t_ > t2 ; }
|
friend bool operator> (TimeValue const& t1, raw_time_64 t2) { return t1.t_ > t2 ; }
|
||||||
friend bool operator== (TimeValue const& t1, TimeValue const& t2) { return t1.t_ == t2.t_; }
|
friend bool operator== (TimeValue const& t1, TimeValue const& t2) { return t1.t_ == t2.t_; }
|
||||||
friend bool operator== (TimeValue const& t1, gavl_time_t t2) { return t1.t_ == t2 ; }
|
friend bool operator== (TimeValue const& t1, raw_time_64 t2) { return t1.t_ == t2 ; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -207,7 +215,7 @@ namespace time {
|
||||||
/** relative framecount or frame number.
|
/** relative framecount or frame number.
|
||||||
* Used within the engine at places where the underlying
|
* Used within the engine at places where the underlying
|
||||||
* grid and origin is obvious from the call context.
|
* grid and origin is obvious from the call context.
|
||||||
* @warning do not mix up gavl_time_t and FrameCnt.
|
* @warning do not mix up raw_time_64 and FrameCnt.
|
||||||
* @warning use 64bit consistently.
|
* @warning use 64bit consistently.
|
||||||
* beware: `long` is 32bit on i386
|
* beware: `long` is 32bit on i386
|
||||||
* @note any conversion to frame numbers should go through
|
* @note any conversion to frame numbers should go through
|
||||||
|
|
@ -216,7 +224,7 @@ namespace time {
|
||||||
using FrameCnt = int64_t;
|
using FrameCnt = int64_t;
|
||||||
|
|
||||||
/** rational representation of fractional seconds
|
/** rational representation of fractional seconds
|
||||||
* @warning do not mix up gavl_time_t and FSecs */
|
* @warning do not mix up raw_time_64 and FSecs */
|
||||||
using FSecs = boost::rational<int64_t>;
|
using FSecs = boost::rational<int64_t>;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -226,7 +234,7 @@ namespace time {
|
||||||
* allowing copy and re-accessing
|
* allowing copy and re-accessing
|
||||||
* @note supports scaling by a factor,
|
* @note supports scaling by a factor,
|
||||||
* which _deliberately_ is chosen
|
* which _deliberately_ is chosen
|
||||||
* as int, not gavl_time_t, because the
|
* as int, not raw_time_64, because the
|
||||||
* multiplying of times is meaningless.
|
* multiplying of times is meaningless.
|
||||||
*/
|
*/
|
||||||
class TimeVar
|
class TimeVar
|
||||||
|
|
@ -258,7 +266,7 @@ namespace time {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Support mixing with plain 64bit int arithmetics
|
/// Support mixing with plain 64bit int arithmetics
|
||||||
operator gavl_time_t() const { return t_; }
|
operator raw_time_64() const { return t_; }
|
||||||
/// Support for micro-tick precise time arithmetics
|
/// Support for micro-tick precise time arithmetics
|
||||||
operator FSecs() const { return FSecs{t_, TimeValue::SCALE}; }
|
operator FSecs() const { return FSecs{t_, TimeValue::SCALE}; }
|
||||||
|
|
||||||
|
|
@ -708,8 +716,8 @@ namespace time {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline gavl_time_t
|
inline raw_time_64
|
||||||
symmetricLimit (gavl_time_t raw, TimeValue lim)
|
symmetricLimit (raw_time_64 raw, TimeValue lim)
|
||||||
{
|
{
|
||||||
return raw > lim? _raw(lim)
|
return raw > lim? _raw(lim)
|
||||||
: -raw > lim? -_raw(lim)
|
: -raw > lim? -_raw(lim)
|
||||||
|
|
@ -744,21 +752,21 @@ namespace time {
|
||||||
* While Time entities are \c not a "safeInt"
|
* While Time entities are \c not a "safeInt"
|
||||||
* implementation, we limit new values to
|
* implementation, we limit new values to
|
||||||
* lower the likelihood of wrap-around */
|
* lower the likelihood of wrap-around */
|
||||||
inline gavl_time_t
|
inline raw_time_64
|
||||||
TimeValue::limitedTime (gavl_time_t raw)
|
TimeValue::limitedTime (raw_time_64 raw)
|
||||||
{
|
{
|
||||||
return symmetricLimit (raw, Time::MAX);
|
return symmetricLimit (raw, Time::MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline gavl_time_t
|
inline raw_time_64
|
||||||
TimeValue::limitedDelta (gavl_time_t origin, gavl_time_t target)
|
TimeValue::limitedDelta (raw_time_64 origin, raw_time_64 target)
|
||||||
{
|
{
|
||||||
if (0 > (origin^target))
|
if (0 > (origin^target))
|
||||||
{// prevent possible numeric wrap
|
{// prevent possible numeric wrap
|
||||||
origin = symmetricLimit (origin, Duration::MAX);
|
origin = symmetricLimit (origin, Duration::MAX);
|
||||||
target = symmetricLimit (target, Duration::MAX);
|
target = symmetricLimit (target, Duration::MAX);
|
||||||
}
|
}
|
||||||
gavl_time_t res = target - origin;
|
raw_time_64 res = target - origin;
|
||||||
return symmetricLimit (res, Duration::MAX);
|
return symmetricLimit (res, Duration::MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "stage/widget/timecode-widget.hpp"
|
#include "stage/widget/timecode-widget.hpp"
|
||||||
|
#include "lib/time/timevalue.hpp"
|
||||||
#include "lib/time/diagnostics.hpp" ////////////TODO: temporary solution to get H:M:S components. Use TimeCode instead!
|
#include "lib/time/diagnostics.hpp" ////////////TODO: temporary solution to get H:M:S components. Use TimeCode instead!
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
@ -40,9 +40,6 @@
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <gavl/gavl.h>
|
|
||||||
#include <sigc++/bind.h>
|
|
||||||
|
|
||||||
|
|
||||||
using boost::lexical_cast;
|
using boost::lexical_cast;
|
||||||
using sigc::mem_fun;
|
using sigc::mem_fun;
|
||||||
|
|
@ -433,7 +430,7 @@ namespace widget {
|
||||||
// void
|
// void
|
||||||
// TimeCode::smpte_offset_changed()
|
// TimeCode::smpte_offset_changed()
|
||||||
// {
|
// {
|
||||||
// gavl_time_t current;
|
// raw_time_64 current;
|
||||||
|
|
||||||
// switch (_mode) {
|
// switch (_mode) {
|
||||||
// case SMPTE:
|
// case SMPTE:
|
||||||
|
|
@ -1278,7 +1275,7 @@ namespace widget {
|
||||||
Time
|
Time
|
||||||
TimeCode::audio_time_from_display () const
|
TimeCode::audio_time_from_display () const
|
||||||
{
|
{
|
||||||
gavl_time_t parsedAudioFrames = lexical_cast<int>(audio_frames_label.get_text());
|
raw_time_64 parsedAudioFrames = lexical_cast<int>(audio_frames_label.get_text());
|
||||||
return Time(TimeValue(parsedAudioFrames));
|
return Time(TimeValue(parsedAudioFrames));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@
|
||||||
** the referenced libraries, though. This will be done with adapter implementations,
|
** the referenced libraries, though. This will be done with adapter implementations,
|
||||||
** where the interface MediaImplLip defines those aspects actually used and required
|
** where the interface MediaImplLip defines those aspects actually used and required
|
||||||
** by our internal processing.
|
** by our internal processing.
|
||||||
|
** @deprecated 2025 -- this is an architecture draft, and shows the direction to take
|
||||||
|
** for the integration with external libraries. Yet in reality, this task
|
||||||
|
** can not conceivably be thus simple; take everything here with a grain
|
||||||
|
** of salt (since this code is not yet actually used in any way).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
24
src/steam/external/libgavl.hpp
vendored
24
src/steam/external/libgavl.hpp
vendored
|
|
@ -13,11 +13,31 @@
|
||||||
|
|
||||||
|
|
||||||
/** @file libgavl.hpp
|
/** @file libgavl.hpp
|
||||||
** Concrete implementation of the MediaImplLib facade to work with `libGAVL`
|
** Concrete implementation of the MediaImplLib facade to work with [lib-GAVL],
|
||||||
|
** a library for handling basic raw video data formats.
|
||||||
** @todo a draft and placeholder code from 2008, at which time the intention was
|
** @todo a draft and placeholder code from 2008, at which time the intention was
|
||||||
** to rely on libGAVL for processing of raw media data. This seemed like a
|
** to rely on libGAVL for processing of raw media data. This seemed like a
|
||||||
** good idea at that time, but we should re-evaluate if libGAVL is maintained
|
** good idea at that time, but we should re-evaluate if libGAVL is maintained
|
||||||
** and in actual use, before we start really relying on it
|
** and in actual use, before we start really relying on it.
|
||||||
|
** @todo 2025 this code is a kind of _architecture placeholder_ — it is clear that
|
||||||
|
** a solution can can not be _that simple_, but any viable solution will
|
||||||
|
** rely onto an approach like outlined here: provide a façade interface,
|
||||||
|
** which has to be implemented by any plug-in component to provide access
|
||||||
|
** to the processing capabilities of a specific library. The access point
|
||||||
|
** functions exposed on the facade however must be shaped by the specific
|
||||||
|
** way how the builder and the render engine interacts with and delegates
|
||||||
|
** back to the media-handling library. Such an interface can not be based
|
||||||
|
** on first principles alone.
|
||||||
|
** @todo 2025 I still retain the dependency on lib-GAVL for now, even while we
|
||||||
|
** never got into actually using it. Simply because I still consider this
|
||||||
|
** library exemplary, and would love to use it for real. Yet it remains
|
||||||
|
** to be seen if the project actually gets a chance to do so, simply
|
||||||
|
** because FFmpeg roughly covers the same ground. Presumably it turns
|
||||||
|
** out to be a basic requirement to ship a plug-in with FFmpeg binding.
|
||||||
|
** Furthermore, one especially tricky aspect is how to support displays
|
||||||
|
** with extended dynamic range -- a requirement which has the potential
|
||||||
|
** to blur the notion of »raw video«...
|
||||||
|
** [Lib-GAVL]: https://github.com/bplaum/gavl
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -434,7 +434,7 @@ namespace gear {
|
||||||
adjustEpochStep (double factor)
|
adjustEpochStep (double factor)
|
||||||
{
|
{
|
||||||
double stretched = _raw(epochStep_) * factor;
|
double stretched = _raw(epochStep_) * factor;
|
||||||
gavl_time_t microTicks(floor (stretched));
|
raw_time_64 microTicks(floor (stretched));
|
||||||
epochStep_ = TimeValue{microTicks};
|
epochStep_ = TimeValue{microTicks};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ union InvocationInstanceID
|
||||||
*/
|
*/
|
||||||
struct lumiera_jobParameter_struct
|
struct lumiera_jobParameter_struct
|
||||||
{
|
{
|
||||||
gavl_time_t nominalTime; /////////////////////////////////////////////////////////////////////////TICKET #1295 job invocation parameter: framework to interpret this time
|
raw_time_64 nominalTime; /////////////////////////////////////////////////////////////////////////TICKET #1295 job invocation parameter: framework to interpret this time
|
||||||
InvocationInstanceID invoKey;
|
InvocationInstanceID invoKey;
|
||||||
//////////////////////////////////////////////////////////////TODO: place an additional parameter value here, or make the instanceID globally unique?
|
//////////////////////////////////////////////////////////////TODO: place an additional parameter value here, or make the instanceID globally unique?
|
||||||
////////////////////////////////////////////////////////////////////////////////////TICKET #1293 job invocation identity
|
////////////////////////////////////////////////////////////////////////////////////TICKET #1293 job invocation identity
|
||||||
|
|
@ -166,7 +166,7 @@ typedef lumiera_jobDefinition* LumieraJobDefinition;
|
||||||
*/
|
*/
|
||||||
struct lumiera_jobDescriptor_struct
|
struct lumiera_jobDescriptor_struct
|
||||||
{
|
{
|
||||||
gavl_time_t deadline; ///< given in real wall clock time
|
raw_time_64 deadline; ///< given in real wall clock time
|
||||||
JobState jobState;
|
JobState jobState;
|
||||||
|
|
||||||
lumiera_jobDefinition jobDefinition; ///< of interest only to Steam-Layer
|
lumiera_jobDefinition jobDefinition; ///< of interest only to Steam-Layer
|
||||||
|
|
|
||||||
|
|
@ -362,7 +362,7 @@ namespace gear {
|
||||||
{
|
{
|
||||||
auto scatter = [&](Duration horizon)
|
auto scatter = [&](Duration horizon)
|
||||||
{
|
{
|
||||||
gavl_time_t wrap = hash_value(now) % _raw(horizon);
|
lib::time::raw_time_64 wrap = hash_value(now) % _raw(horizon);
|
||||||
ENSURE (0 <= wrap and wrap < _raw(horizon));
|
ENSURE (0 <= wrap and wrap < _raw(horizon));
|
||||||
return TimeValue{wrap};
|
return TimeValue{wrap};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ namespace test{
|
||||||
CHECK (!(var < ref) );
|
CHECK (!(var < ref) );
|
||||||
CHECK ( (var > ref) );
|
CHECK ( (var > ref) );
|
||||||
|
|
||||||
gavl_time_t gat(var);
|
raw_time_64 gat(var);
|
||||||
CHECK (!(gat == ref) );
|
CHECK (!(gat == ref) );
|
||||||
CHECK ( (gat != ref) );
|
CHECK ( (gat != ref) );
|
||||||
CHECK ( (gat >= ref) );
|
CHECK ( (gat >= ref) );
|
||||||
|
|
|
||||||
|
|
@ -123,13 +123,13 @@ namespace test{
|
||||||
*/
|
*/
|
||||||
class TimeControl_test : public Test
|
class TimeControl_test : public Test
|
||||||
{
|
{
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
random_or_get (string arg)
|
random_or_get (string arg)
|
||||||
{
|
{
|
||||||
if (isnil(arg))
|
if (isnil(arg))
|
||||||
return gavl_time_t(1 + rani (100000)) * TimeValue::SCALE;
|
return raw_time_64(1 + rani (100000)) * TimeValue::SCALE;
|
||||||
else
|
else
|
||||||
return lexical_cast<gavl_time_t> (arg);
|
return lexical_cast<raw_time_64> (arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,13 +61,13 @@ namespace test{
|
||||||
*/
|
*/
|
||||||
class TimeMutation_test : public Test
|
class TimeMutation_test : public Test
|
||||||
{
|
{
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
random_or_get (string arg)
|
random_or_get (string arg)
|
||||||
{
|
{
|
||||||
if (isnil(arg))
|
if (isnil(arg))
|
||||||
return gavl_time_t(1 + rani (100000)) * TimeValue::SCALE;
|
return raw_time_64(1 + rani (100000)) * TimeValue::SCALE;
|
||||||
else
|
else
|
||||||
return lexical_cast<gavl_time_t> (arg);
|
return lexical_cast<raw_time_64> (arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestValues
|
struct TestValues
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ namespace test{
|
||||||
*/
|
*/
|
||||||
class TimeValue_test : public Test
|
class TimeValue_test : public Test
|
||||||
{
|
{
|
||||||
gavl_time_t
|
raw_time_64
|
||||||
random_or_get (Arg arg)
|
random_or_get (Arg arg)
|
||||||
{
|
{
|
||||||
if (isnil(arg))
|
if (isnil(arg))
|
||||||
|
|
@ -53,7 +53,7 @@ namespace test{
|
||||||
return 1 + rani(10000);
|
return 1 + rani(10000);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return lexical_cast<gavl_time_t> (arg[1]);
|
return lexical_cast<raw_time_64> (arg[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ namespace test{
|
||||||
CHECK (val < max);
|
CHECK (val < max);
|
||||||
|
|
||||||
// mixed comparisons with raw numeric time
|
// mixed comparisons with raw numeric time
|
||||||
gavl_time_t g2 (-2);
|
raw_time_64 g2 (-2);
|
||||||
CHECK (zero > g2);
|
CHECK (zero > g2);
|
||||||
CHECK (one > g2);
|
CHECK (one > g2);
|
||||||
CHECK (one >= g2);
|
CHECK (one >= g2);
|
||||||
|
|
@ -142,7 +142,7 @@ namespace test{
|
||||||
CHECK (var < Time::MAX);
|
CHECK (var < Time::MAX);
|
||||||
CHECK (var > Time::MIN);
|
CHECK (var > Time::MIN);
|
||||||
|
|
||||||
gavl_time_t raw (var);
|
raw_time_64 raw (var);
|
||||||
CHECK (raw == org);
|
CHECK (raw == org);
|
||||||
CHECK (raw > org - two);
|
CHECK (raw > org - two);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,7 @@ namespace test {
|
||||||
{
|
{
|
||||||
Time frame{pipeline.currPoint}; // can access the embedded PipeFrameTick core to get "currPoint" (nominal time)
|
Time frame{pipeline.currPoint}; // can access the embedded PipeFrameTick core to get "currPoint" (nominal time)
|
||||||
Job job = pipeline->ticket().createJobFor(frame); // looking always at the second element, which is the current JobTicket
|
Job job = pipeline->ticket().createJobFor(frame); // looking always at the second element, which is the current JobTicket
|
||||||
TimeValue nominalTime{job.parameter.nominalTime}; // job parameter holds the microseconds (gavl_time_t)
|
TimeValue nominalTime{job.parameter.nominalTime}; // job parameter holds the microseconds (raw_time_64)
|
||||||
int32_t mark = job.parameter.invoKey.part.a; // the MockDispatcher places the given "mark" here
|
int32_t mark = job.parameter.invoKey.part.a; // the MockDispatcher places the given "mark" here
|
||||||
return _Fmt{"J(%d|%s)"} % mark % nominalTime;
|
return _Fmt{"J(%d|%s)"} % mark % nominalTime;
|
||||||
};
|
};
|
||||||
|
|
@ -309,7 +309,7 @@ namespace test {
|
||||||
auto visualise = [](auto& pipeline) -> string
|
auto visualise = [](auto& pipeline) -> string
|
||||||
{
|
{
|
||||||
Job job = pipeline.buildJob(); // let the JobPlanning construct the »current job«
|
Job job = pipeline.buildJob(); // let the JobPlanning construct the »current job«
|
||||||
TimeValue nominalTime{job.parameter.nominalTime}; // job parameter holds the microseconds (gavl_time_t)
|
TimeValue nominalTime{job.parameter.nominalTime}; // job parameter holds the microseconds (raw_time_64)
|
||||||
int32_t mark = job.parameter.invoKey.part.a; // the MockDispatcher places the given "mark" here
|
int32_t mark = job.parameter.invoKey.part.a; // the MockDispatcher places the given "mark" here
|
||||||
TimeValue deadline{pipeline.determineDeadline()};
|
TimeValue deadline{pipeline.determineDeadline()};
|
||||||
return _Fmt{"J(%d|%s⧐%s)"}
|
return _Fmt{"J(%d|%s⧐%s)"}
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,18 @@
|
||||||
|
|
||||||
|
|
||||||
#include "lib/test/test.h"
|
#include "lib/test/test.h"
|
||||||
#include "lib/time.h"
|
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <nobug.h>
|
#include <nobug.h>
|
||||||
|
|
||||||
|
typedef int64_t raw_time_64; //////////////////////////////////////////////////////////////////////////////TICKET #1259 turn time.h in to a C++ implementation header
|
||||||
|
|
||||||
|
#include "lib/time.h" /////////////////////////////////////////////////////////////////////////////////////TICKET #1259 this should not be a general purpose library, but rather an implementation base
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
calculate_framecount (gavl_time_t t, uint fps)
|
calculate_framecount (raw_time_64 t, uint fps)
|
||||||
{
|
{
|
||||||
return lumiera_quantise_frames_fps (t,0,fps);
|
return lumiera_quantise_frames_fps (t,0,fps);
|
||||||
}
|
}
|
||||||
|
|
@ -48,9 +53,9 @@ const int FPS = 24;
|
||||||
TEST (basic)
|
TEST (basic)
|
||||||
{
|
{
|
||||||
// Zero
|
// Zero
|
||||||
gavl_time_t t = lumiera_build_time (0,0,0,0);
|
raw_time_64 t = lumiera_build_time (0,0,0,0);
|
||||||
|
|
||||||
CHECK ((gavl_time_t) t == 0);
|
CHECK ((raw_time_64) t == 0);
|
||||||
CHECK (lumiera_time_millis (t) == 0);
|
CHECK (lumiera_time_millis (t) == 0);
|
||||||
CHECK (lumiera_time_seconds (t) == 0);
|
CHECK (lumiera_time_seconds (t) == 0);
|
||||||
CHECK (lumiera_time_minutes (t) == 0);
|
CHECK (lumiera_time_minutes (t) == 0);
|
||||||
|
|
@ -83,7 +88,7 @@ TEST (basic)
|
||||||
|
|
||||||
TEST (fps)
|
TEST (fps)
|
||||||
{
|
{
|
||||||
gavl_time_t t = lumiera_build_time_fps (FPS, FRAMES, SECONDS, MINUTES, HOURS);
|
raw_time_64 t = lumiera_build_time_fps (FPS, FRAMES, SECONDS, MINUTES, HOURS);
|
||||||
|
|
||||||
CHECK (lumiera_time_millis (t) == FRAMES * 1000 / FPS);
|
CHECK (lumiera_time_millis (t) == FRAMES * 1000 / FPS);
|
||||||
CHECK (lumiera_time_seconds (t) == SECONDS);
|
CHECK (lumiera_time_seconds (t) == SECONDS);
|
||||||
|
|
@ -102,9 +107,9 @@ TEST (fps)
|
||||||
TEST (ntsc_drop_frame)
|
TEST (ntsc_drop_frame)
|
||||||
{
|
{
|
||||||
// Make sure frame 0 begins at 0
|
// Make sure frame 0 begins at 0
|
||||||
gavl_time_t t = lumiera_build_time_ntsc_drop (0, 0, 0, 0);
|
raw_time_64 t = lumiera_build_time_ntsc_drop (0, 0, 0, 0);
|
||||||
|
|
||||||
CHECK ((gavl_time_t) t == 0);
|
CHECK ((raw_time_64) t == 0);
|
||||||
CHECK (lumiera_time_millis (t) == 0);
|
CHECK (lumiera_time_millis (t) == 0);
|
||||||
CHECK (lumiera_time_seconds (t) == 0);
|
CHECK (lumiera_time_seconds (t) == 0);
|
||||||
CHECK (lumiera_time_minutes (t) == 0);
|
CHECK (lumiera_time_minutes (t) == 0);
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ namespace stage{
|
||||||
namespace model{
|
namespace model{
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
|
using lib::time::raw_time_64;
|
||||||
|
|
||||||
namespace { // simplified notation for expected results...
|
namespace { // simplified notation for expected results...
|
||||||
|
|
||||||
|
|
@ -577,7 +578,7 @@ namespace test {
|
||||||
CHECK (2_r/3 < poison and poison < 1); // looks innocuous...
|
CHECK (2_r/3 < poison and poison < 1); // looks innocuous...
|
||||||
CHECK (poison + Time::SCALE < 0); // simple calculations fail due to numeric overflow
|
CHECK (poison + Time::SCALE < 0); // simple calculations fail due to numeric overflow
|
||||||
CHECK (poison * Time::SCALE < 0);
|
CHECK (poison * Time::SCALE < 0);
|
||||||
CHECK (-6 == rational_cast<gavl_time_t>(poison * Time::SCALE)); // naive conversion to µ-ticks would lead to overflow
|
CHECK (-6 == rational_cast<raw_time_64>(poison * Time::SCALE)); // naive conversion to µ-ticks would lead to overflow
|
||||||
CHECK (671453 == _raw(Time(FSecs(poison)))); // however the actual conversion routine is safeguarded
|
CHECK (671453 == _raw(Time(FSecs(poison)))); // however the actual conversion routine is safeguarded
|
||||||
CHECK (671453.812f == rational_cast<float>(poison)*Time::SCALE);
|
CHECK (671453.812f == rational_cast<float>(poison)*Time::SCALE);
|
||||||
|
|
||||||
|
|
@ -667,7 +668,7 @@ namespace test {
|
||||||
CHECK (win.overallSpan().duration() == TimeValue{307445734561825860}); // However, all base values turn out unaffected
|
CHECK (win.overallSpan().duration() == TimeValue{307445734561825860}); // However, all base values turn out unaffected
|
||||||
CHECK (win.visible().duration() == TimeValue{856350691});
|
CHECK (win.visible().duration() == TimeValue{856350691});
|
||||||
|
|
||||||
TimeValue targetPos{gavl_time_t(_raw(win.overallSpan().duration()) // based on the overall span...
|
TimeValue targetPos{raw_time_64(_raw(win.overallSpan().duration()) // based on the overall span...
|
||||||
* rational_cast<double> (poison))}; // the given toxic factor would point at that target position
|
* rational_cast<double> (poison))}; // the given toxic factor would point at that target position
|
||||||
|
|
||||||
CHECK (targetPos == TimeValue{206435633551724864});
|
CHECK (targetPos == TimeValue{206435633551724864});
|
||||||
|
|
|
||||||
|
|
@ -339,7 +339,7 @@ namespace test {
|
||||||
{
|
{
|
||||||
auto N = AVERAGE_EPOCHS;
|
auto N = AVERAGE_EPOCHS;
|
||||||
auto averageTicks = double(_raw(old))*(N-1)/N + contribution/N;
|
auto averageTicks = double(_raw(old))*(N-1)/N + contribution/N;
|
||||||
return TimeValue{gavl_time_t (floor (averageTicks))};
|
return TimeValue{raw_time_64 (floor (averageTicks))};
|
||||||
};
|
};
|
||||||
|
|
||||||
TimeVar step = bFlow.getEpochStep();
|
TimeVar step = bFlow.getEpochStep();
|
||||||
|
|
@ -396,8 +396,8 @@ namespace test {
|
||||||
{
|
{
|
||||||
const size_t FPS = 200;
|
const size_t FPS = 200;
|
||||||
const size_t TICK_P_S = FPS * ACTIVITIES_P_FR; // Simulated throughput 200 frames per second
|
const size_t TICK_P_S = FPS * ACTIVITIES_P_FR; // Simulated throughput 200 frames per second
|
||||||
const gavl_time_t STP = Time::SCALE / TICK_P_S; // Simulation stepping (here 2 steps per ms)
|
const raw_time_64 STP = Time::SCALE / TICK_P_S; // Simulation stepping (here 2 steps per ms)
|
||||||
const gavl_time_t RUN = _raw(Time{0,0,3}); // nominal length of the simulation time axis
|
const raw_time_64 RUN = _raw(Time{0,0,3}); // nominal length of the simulation time axis
|
||||||
Offset BASE_DEADLINE{FSecs{1,2}}; // base pre-roll before deadline
|
Offset BASE_DEADLINE{FSecs{1,2}}; // base pre-roll before deadline
|
||||||
Offset SPREAD_DEAD{FSecs{2,100}}; // random spread of deadline around base
|
Offset SPREAD_DEAD{FSecs{2,100}}; // random spread of deadline around base
|
||||||
const uint INVOKE_LAG = _raw(Time{250,0}) /STP; // „invoke“ the Activity after simulated 250ms (≙ 500 steps)
|
const uint INVOKE_LAG = _raw(Time{250,0}) /STP; // „invoke“ the Activity after simulated 250ms (≙ 500 steps)
|
||||||
|
|
|
||||||
|
|
@ -129698,8 +129698,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
||||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1746196449003" ID="ID_1070775068" MODIFIED="1746196453932" TEXT="Video-Display">
|
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1746196449003" ID="ID_1070775068" MODIFIED="1746196453932" TEXT="Video-Display">
|
||||||
<icon BUILTIN="flag-yellow"/>
|
<icon BUILTIN="flag-yellow"/>
|
||||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1746196482500" ID="ID_1819581335" LINK="https://issues.lumiera.org/ticket/1403" MODIFIED="1747342428317" TEXT=" #1403 Invesitgate if XV displayer can be revived ">
|
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1746196482500" ID="ID_1819581335" LINK="https://issues.lumiera.org/ticket/1403" MODIFIED="1747342428317" TEXT=" #1403 Invesitgate if XV displayer can be revived ">
|
||||||
<linktarget COLOR="#fefeb4" DESTINATION="ID_1819581335" ENDARROW="Default" ENDINCLINATION="-2783;152;" ID="Arrow_ID_1160980366" SOURCE="ID_1219347509" STARTARROW="None" STARTINCLINATION="-4870;297;"/>
|
|
||||||
<linktarget COLOR="#fdebca" DESTINATION="ID_1819581335" ENDARROW="Default" ENDINCLINATION="-2783;152;" ID="Arrow_ID_421873944" SOURCE="ID_150758489" STARTARROW="None" STARTINCLINATION="1417;60;"/>
|
<linktarget COLOR="#fdebca" DESTINATION="ID_1819581335" ENDARROW="Default" ENDINCLINATION="-2783;152;" ID="Arrow_ID_421873944" SOURCE="ID_150758489" STARTARROW="None" STARTINCLINATION="1417;60;"/>
|
||||||
|
<linktarget COLOR="#fefeb4" DESTINATION="ID_1819581335" ENDARROW="Default" ENDINCLINATION="-2783;152;" ID="Arrow_ID_1160980366" SOURCE="ID_1219347509" STARTARROW="None" STARTINCLINATION="-4870;297;"/>
|
||||||
<icon BUILTIN="hourglass"/>
|
<icon BUILTIN="hourglass"/>
|
||||||
<node COLOR="#338800" CREATED="1746196518190" ID="ID_411481779" MODIFIED="1747013174739" TEXT="Research-Setup">
|
<node COLOR="#338800" CREATED="1746196518190" ID="ID_411481779" MODIFIED="1747013174739" TEXT="Research-Setup">
|
||||||
<icon BUILTIN="button_ok"/>
|
<icon BUILTIN="button_ok"/>
|
||||||
|
|
@ -159479,18 +159479,21 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo
|
||||||
</html></richcontent>
|
</html></richcontent>
|
||||||
<icon BUILTIN="yes"/>
|
<icon BUILTIN="yes"/>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1742256149038" FOLDED="true" ID="ID_1347393646" MODIFIED="1742256644046" TEXT="welche Rolle können andere Libraries hier noch spielen?">
|
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1742256149038" ID="ID_1347393646" MODIFIED="1747523933091" TEXT="welche Rolle können andere Libraries hier noch spielen?">
|
||||||
<font NAME="SansSerif" SIZE="12"/>
|
<font NAME="SansSerif" SIZE="12"/>
|
||||||
<icon BUILTIN="help"/>
|
<icon BUILTIN="help"/>
|
||||||
<node CREATED="1742256164252" ID="ID_798828861" MODIFIED="1742256311817" TEXT="konkret: Gavl und Gmerlin">
|
<node CREATED="1742256164252" ID="ID_798828861" LINK="https://github.com/bplaum/gavl" MODIFIED="1747524023410" TEXT="konkret: Gavl und Gmerlin">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
<head/>
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p>
|
<p>
|
||||||
Christian kannte bereits Burkart Pflaum, und hat uns auf dessen Libraries aufmerksam gemacht. Die Libraries sind vorbildlich in iherer Struktur und in dem beschränkten Scope. Wahrscheinlich sind sie problemloser einzubinden als FFmpeg. Aber das Kernproblem bleibt: das ist eine one-Man-Show, und wir werden trotzdem auf FFmpeg nicht verzichten können....
|
Christian kannte bereits Burkart Pflaum, und hat uns auf dessen Libraries aufmerksam gemacht. Die Libraries sind vorbildlich in iherer Struktur und in dem beschränkten Scope. Wahrscheinlich sind sie problemloser einzubinden als FFmpeg. Aber das Kernproblem bleibt: das ist eine one-Man-Show, und wir werden trotzdem auf FFmpeg nicht verzichten können....
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html></richcontent>
|
</html>
|
||||||
|
</richcontent>
|
||||||
<node CREATED="1742256340945" ID="ID_457200888" MODIFIED="1742256484596" TEXT="denkbar als Ergänzung, sollte FFmpeg tatsächliche Schwächen zeigen">
|
<node CREATED="1742256340945" ID="ID_457200888" MODIFIED="1742256484596" TEXT="denkbar als Ergänzung, sollte FFmpeg tatsächliche Schwächen zeigen">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
<head/>
|
<head/>
|
||||||
|
|
@ -162285,7 +162288,8 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
<icon BUILTIN="button_ok"/>
|
<icon BUILTIN="button_ok"/>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1742168602576" ID="ID_871737890" MODIFIED="1742168698565" TEXT="Gmerlin">
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1742168602576" ID="ID_871737890" MODIFIED="1742168698565" TEXT="Gmerlin">
|
||||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1742249270854" ID="ID_1347801315" MODIFIED="1742249278755" TEXT="falsch! es ist Gavl">
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1742249270854" ID="ID_1347801315" MODIFIED="1747524127181" TEXT="falsch! es ist Gavl">
|
||||||
|
<arrowlink COLOR="#c95974" DESTINATION="ID_219954631" ENDARROW="Default" ENDINCLINATION="813;-128;" ID="Arrow_ID_889384701" STARTARROW="None" STARTINCLINATION="1093;150;"/>
|
||||||
<icon BUILTIN="broken-line"/>
|
<icon BUILTIN="broken-line"/>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1742249279746" ID="ID_1189167261" MODIFIED="1742249293729" TEXT="Vorsicht: Upgrade auf Version-2">
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1742249279746" ID="ID_1189167261" MODIFIED="1742249293729" TEXT="Vorsicht: Upgrade auf Version-2">
|
||||||
|
|
@ -162713,8 +162717,7 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
man hat ein time::Control (was auch immer das in Zukunft sein wird), welches mit einem Change-Signal verbunden wird. GUI-seitig verdrahtet man dieses Signal mit dem Code, der die tatsächliche Änderung des Presentation-State macht
|
man hat ein time::Control (was auch immer das in Zukunft sein wird), welches mit einem Change-Signal verbunden wird. GUI-seitig verdrahtet man dieses Signal mit dem Code, der die tatsächliche Änderung des Presentation-State macht
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html></richcontent>
|
||||||
</richcontent>
|
|
||||||
<arrowlink COLOR="#7f6a74" DESTINATION="ID_1446567013" ENDARROW="Default" ENDINCLINATION="-1578;239;" ID="Arrow_ID_590507558" STARTARROW="None" STARTINCLINATION="-2460;177;"/>
|
<arrowlink COLOR="#7f6a74" DESTINATION="ID_1446567013" ENDARROW="Default" ENDINCLINATION="-1578;239;" ID="Arrow_ID_590507558" STARTARROW="None" STARTINCLINATION="-2460;177;"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
|
@ -162775,8 +162778,7 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
Abgesehen davon ist der Code inzwischen auch technologisch überholt und wird mit GTK-4 nicht mehr funktionieren
|
Abgesehen davon ist der Code inzwischen auch technologisch überholt und wird mit GTK-4 nicht mehr funktionieren
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html></richcontent>
|
||||||
</richcontent>
|
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1747355273449" ID="ID_1703747958" MODIFIED="1747355286397" TEXT="ehrlich gesagt: wegwerfen und neuschreiben">
|
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1747355273449" ID="ID_1703747958" MODIFIED="1747355286397" TEXT="ehrlich gesagt: wegwerfen und neuschreiben">
|
||||||
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
|
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
|
||||||
|
|
@ -162785,10 +162787,11 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1742249461535" ID="ID_1554376708" MODIFIED="1742256553530" TEXT="Rolle der lib-Gavl überprüfen">
|
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1742249461535" ID="ID_1554376708" MODIFIED="1747524255970" TEXT="Rolle der lib-Gavl überprüfen">
|
||||||
<linktarget COLOR="#a41b18" DESTINATION="ID_1554376708" ENDARROW="Default" ENDINCLINATION="440;-36;" ID="Arrow_ID_608156847" SOURCE="ID_1683248748" STARTARROW="None" STARTINCLINATION="193;12;"/>
|
<linktarget COLOR="#a41b18" DESTINATION="ID_1554376708" ENDARROW="Default" ENDINCLINATION="440;-36;" ID="Arrow_ID_608156847" SOURCE="ID_1683248748" STARTARROW="None" STARTINCLINATION="193;12;"/>
|
||||||
<icon BUILTIN="flag-yellow"/>
|
<linktarget COLOR="#4c3b8b" DESTINATION="ID_1554376708" ENDARROW="Default" ENDINCLINATION="219;519;" ID="Arrow_ID_589652743" SOURCE="ID_219954631" STARTARROW="None" STARTINCLINATION="326;-188;"/>
|
||||||
<node CREATED="1742256560103" ID="ID_1579484179" MODIFIED="1742266889152" TEXT="so traurig es ist: Gavl ist nicht erste Wahl">
|
<icon BUILTIN="pencil"/>
|
||||||
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#95060e" CREATED="1742256560103" ID="ID_1579484179" MODIFIED="1747524214221" TEXT="so traurig es ist: Gavl ist nicht erste Wahl">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
<head/>
|
<head/>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -162801,8 +162804,9 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
</body>
|
</body>
|
||||||
</html></richcontent>
|
</html></richcontent>
|
||||||
<arrowlink COLOR="#592f6e" DESTINATION="ID_450633851" ENDARROW="Default" ENDINCLINATION="338;12;" ID="Arrow_ID_637755539" STARTARROW="None" STARTINCLINATION="466;0;"/>
|
<arrowlink COLOR="#592f6e" DESTINATION="ID_450633851" ENDARROW="Default" ENDINCLINATION="338;12;" ID="Arrow_ID_637755539" STARTARROW="None" STARTINCLINATION="466;0;"/>
|
||||||
|
<icon BUILTIN="yes"/>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1744719728307" ID="ID_1783840760" MODIFIED="1744719819653" TEXT="siehe steam/external/libgavl.hpp">
|
<node COLOR="#435e98" CREATED="1744719728307" ID="ID_1783840760" MODIFIED="1747524201441" TEXT="siehe steam/external/libgavl.hpp">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
<head/>
|
<head/>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -162812,6 +162816,98 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
</body>
|
</body>
|
||||||
</html></richcontent>
|
</html></richcontent>
|
||||||
<icon BUILTIN="flag-yellow"/>
|
<icon BUILTIN="flag-yellow"/>
|
||||||
|
<node CREATED="1747489068132" ID="ID_491604266" MODIFIED="1747489074061" TEXT="wird derzeit überhaupt nicht verwendet"/>
|
||||||
|
<node CREATED="1747489084369" ID="ID_1779252669" MODIFIED="1747489105751" TEXT="wohl auch gar nicht implementierbar"/>
|
||||||
|
<node CREATED="1747489074724" ID="ID_663261791" MODIFIED="1747489124777" TEXT="ist eine bloße leere Hülle"/>
|
||||||
|
<node CREATED="1747489111527" ID="ID_229720543" MODIFIED="1747489130041" TEXT="zeigt aber die Richtung"/>
|
||||||
|
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1747489138341" ID="ID_621636330" MODIFIED="1747489143519" TEXT="dokumentieren">
|
||||||
|
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
|
||||||
|
<icon BUILTIN="yes"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#166d3d" CREATED="1747489147636" ID="ID_1626357015" MODIFIED="1747524236658" TEXT="gavl_time_t ersetzen">
|
||||||
|
<icon BUILTIN="yes"/>
|
||||||
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1747489190149" ID="ID_395347682" LINK="https://issues.lumiera.org/ticket/1261" MODIFIED="1747489218934" TEXT="siehe Design-Skizze in #1261">
|
||||||
|
<icon BUILTIN="idea"/>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1747489228725" ID="ID_397750077" MODIFIED="1747489369180" TEXT="verwende einen Namen exakt gleicher Länge">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
raw_time_64
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1747489254856" ID="ID_971197875" MODIFIED="1747489345064" TEXT="danach können alle Includes des C-Headers time.h weg">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
schon seit langem will ich von der "C-Time-Library" weg, denn diese ist gradezu eine Einladung, Timecode-Operationen ad-hoc zu implementieren
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1747489277561" ID="ID_1782395866" MODIFIED="1747489284084" TEXT="einzige Ausnahme: Time.cpp"/>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1747520420088" ID="ID_1585137684" MODIFIED="1747524248767" TEXT="C-Library für Time-Handling auflösen">
|
||||||
|
<icon BUILTIN="flag-yellow"/>
|
||||||
|
<node CREATED="1747520433501" ID="ID_1627011016" MODIFIED="1747520503864" TEXT="die ist mir schon lange ein »Dorn im Auge«">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
....weil eine solche Library gradezu dazu einläd, sich nicht mit den „mühsamen“ Abstraktionen des Time-Handling-Frameworks herumzuschlagen, sondern stattessen <i>einfach mit Zahlen zu rechnen.</i>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1747520507617" ID="ID_391130031" MODIFIED="1747520575548" TEXT="sollte die konkreten Verwendungen durchsehen">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
...möglicherweise lassen sich diese Funktionen nämlich in Gruppen einteilen und dann direkt in einen anonymen namespace in die jeweilige Translation-Unit schieben....
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1747520518579" ID="ID_1232667630" MODIFIED="1747520531129" TEXT="müßte dann auch den C-Test (test-time) auflösen">
|
||||||
|
<node CREATED="1747520690709" ID="ID_920147641" MODIFIED="1747520695437" TEXT="der ist eigentlich nicht lang"/>
|
||||||
|
<node CREATED="1747520696080" ID="ID_1610185152" MODIFIED="1747520880755" TEXT="und bei näherer Betrachtung ziemlich banal">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Der Test täuscht: weil er in C geschrieben ist, sieht er so komplex aus. Dabei besteht die erste Hälfte lediglich draus, eine Konstruktor-Funktion zu testen. Der sinnvolle Kern daran ist die decimator-Sequenz zum Herunterbrechen von Zeiten. Die wird hier aber nur oberflächlich getestet. Da sollte man, wenn schon, wirklich auf die Grenzfälle losgehen ⟹ Test neu schreiben!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Der zweite Teil besteht im <i>Antesten</i> der drop-Frame-Umwandlung ⟹ auch das in eigenständigen neuen Test packen
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1746059853111" ID="ID_975342117" MODIFIED="1746059870062" TEXT="auch altes RenderNode-Framework zurückbauen">
|
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1746059853111" ID="ID_975342117" MODIFIED="1746059870062" TEXT="auch altes RenderNode-Framework zurückbauen">
|
||||||
|
|
@ -163898,6 +163994,15 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1742313583059" ID="ID_580462484" MODIFIED="1742313592747" TEXT="Dependency-Liste aktualisieren">
|
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1742313583059" ID="ID_580462484" MODIFIED="1742313592747" TEXT="Dependency-Liste aktualisieren">
|
||||||
<icon BUILTIN="flag-yellow"/>
|
<icon BUILTIN="flag-yellow"/>
|
||||||
|
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1747524067725" ID="ID_219954631" MODIFIED="1747524193833" TEXT="Abhängigkeit GAVL">
|
||||||
|
<arrowlink COLOR="#4c3b8b" DESTINATION="ID_1554376708" ENDARROW="Default" ENDINCLINATION="219;519;" ID="Arrow_ID_589652743" STARTARROW="None" STARTINCLINATION="326;-188;"/>
|
||||||
|
<linktarget COLOR="#c95974" DESTINATION="ID_219954631" ENDARROW="Default" ENDINCLINATION="813;-128;" ID="Arrow_ID_889384701" SOURCE="ID_1347801315" STARTARROW="None" STARTINCLINATION="1093;150;"/>
|
||||||
|
<icon BUILTIN="flag-yellow"/>
|
||||||
|
<node CREATED="1747524076555" ID="ID_1964951178" MODIFIED="1747524084106" TEXT="behalte das vorerst noch bei">
|
||||||
|
<icon BUILTIN="yes"/>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1747524085359" ID="ID_976130232" LINK="https://github.com/bplaum/gavl" MODIFIED="1747524093250" TEXT="Achtung: umgezogen auf Gitub"/>
|
||||||
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1742313577420" ID="ID_527584176" MODIFIED="1742313592746" TEXT="Bau-Anleitung überarbeiten">
|
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1742313577420" ID="ID_527584176" MODIFIED="1742313592746" TEXT="Bau-Anleitung überarbeiten">
|
||||||
<icon BUILTIN="flag-yellow"/>
|
<icon BUILTIN="flag-yellow"/>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue