Skip to content

Commit e5698ad

Browse files
Add convenience functions (#1825)
* Add convenience functions Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com> * Check for negative duration Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com> * Add comments about the time range duration Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com> --------- Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
1 parent 98840ac commit e5698ad

File tree

6 files changed

+112
-2
lines changed

6 files changed

+112
-2
lines changed

src/opentime/rationalTime.h

+9
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ class RationalTime
5454
return (std::isnan(_rate) || std::isnan(_value)) ? true : (_rate <= 0);
5555
}
5656

57+
/// @brief Returns true if the time is valid.
58+
///
59+
/// The time is considered valid if the value and rate are not NaN values,
60+
/// and the rate is greater than zero.
61+
bool is_valid_time() const noexcept
62+
{
63+
return !std::isnan(_rate) && !std::isnan(_value) && (_rate > 0);
64+
}
65+
5766
/// @brief Returns the time value.
5867
constexpr double value() const noexcept { return _value; }
5968

src/opentime/timeRange.h

+29-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ constexpr double DEFAULT_EPSILON_s = 1.0 / (2 * 192000.0);
3030
class TimeRange
3131
{
3232
public:
33-
explicit constexpr TimeRange() noexcept
33+
constexpr TimeRange() noexcept
3434
: _start_time{}
3535
, _duration{}
3636
{}
@@ -40,13 +40,40 @@ class TimeRange
4040
, _duration{ RationalTime{ 0, start_time.rate() } }
4141
{}
4242

43-
explicit constexpr TimeRange(
43+
constexpr TimeRange(
4444
RationalTime start_time,
4545
RationalTime duration) noexcept
4646
: _start_time{ start_time }
4747
, _duration{ duration }
4848
{}
4949

50+
constexpr TimeRange(
51+
double start_time,
52+
double duration,
53+
double rate) noexcept
54+
: _start_time{ start_time, rate }
55+
, _duration{ duration, rate }
56+
{}
57+
58+
/// @brief Returns true if the time range is invalid.
59+
///
60+
/// The time range is considered invalid if either the start time or
61+
/// duration is invalid, or if the duration is less than zero.
62+
bool is_invalid_range() const noexcept
63+
{
64+
return _start_time.is_invalid_time() || _duration.is_invalid_time() || _duration.value() < 0.0;
65+
}
66+
67+
/// @brief Returns true if the time range is valid.
68+
///
69+
/// The time range is considered valid if both the start time and
70+
/// duration are valid, and the duration is greater than or equal to
71+
/// zero.
72+
bool is_valid_range() const noexcept
73+
{
74+
return _start_time.is_valid_time() && _duration.is_valid_time() && _duration.value() >= 0.0;
75+
}
76+
5077
constexpr RationalTime start_time() const noexcept { return _start_time; }
5178

5279
constexpr RationalTime duration() const noexcept { return _duration; }

src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ It can be rescaled into another :class:`~RationalTime`'s rate.
6868
.def("is_invalid_time", &RationalTime::is_invalid_time, R"docstring(
6969
Returns true if the time is invalid. The time is considered invalid if the value or the rate are a NaN value
7070
or if the rate is less than or equal to zero.
71+
)docstring")
72+
.def("is_valid_time", &RationalTime::is_valid_time, R"docstring(
73+
Returns true if the time is valid. The time is considered valid if the value and rate are not NaN values
74+
and the rate is greater than zero.
7175
)docstring")
7276
.def_property_readonly("value", &RationalTime::value)
7377
.def_property_readonly("rate", &RationalTime::rate)

src/py-opentimelineio/opentime-bindings/opentime_timeRange.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ meaning that :meth:`end_time_inclusive` (last portion of a sample in the time ra
4242
return TimeRange(*start_time, *duration);
4343
}
4444
}), "start_time"_a=nullptr, "duration"_a=nullptr)
45+
.def(py::init<double, double, double>(), "start_time"_a, "duration"_a, "rate"_a)
46+
.def("is_invalid_range", &TimeRange::is_invalid_range, R"docstring(
47+
Returns true if the time range is invalid. The time range is considered invalid if either the start time or
48+
duration is invalid, or if the duration is less than zero.
49+
)docstring")
50+
.def("is_valid_range", &TimeRange::is_valid_range, R"docstring(
51+
Returns true if the time range is valid. The time range is considered valid if both the start time and
52+
duration are valid, and the duration is greater than or equal to zero.
53+
)docstring")
4554
.def_property_readonly("start_time", &TimeRange::start_time)
4655
.def_property_readonly("duration", &TimeRange::duration)
4756
.def("end_time_inclusive", &TimeRange::end_time_inclusive, R"docstring(

tests/test_opentime.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "utils.h"
55

66
#include <opentime/rationalTime.h>
7+
#include <opentime/timeRange.h>
78

89
namespace otime = opentime::OPENTIME_VERSION;
910

@@ -22,6 +23,15 @@ main(int argc, char** argv)
2223
assertEqual(t.rate(), 1.0);
2324
});
2425

26+
tests.add_test("test_valid", [] {
27+
otime::RationalTime t1(0.0, 0.0);
28+
assertTrue(t1.is_invalid_time());
29+
assertFalse(t1.is_valid_time());
30+
otime::RationalTime t2(0.0, 24.0);
31+
assertTrue(t2.is_valid_time());
32+
assertFalse(t2.is_invalid_time());
33+
});
34+
2535
tests.add_test("test_equality", [] {
2636
otime::RationalTime t1(30.2);
2737
assertEqual(t1, t1);
@@ -129,6 +139,34 @@ main(int argc, char** argv)
129139
assertTrue(t.almost_equal(time_obj, 0.001));
130140
});
131141

142+
tests.add_test("test_create_range", [] {
143+
otime::RationalTime start(0.0, 24.0);
144+
otime::RationalTime duration(24.0, 24.0);
145+
otime::TimeRange r(start, duration);
146+
assertEqual(r.start_time(), start);
147+
assertEqual(r.duration(), duration);
148+
149+
r = otime::TimeRange(0.0, 24.0, 24.0);
150+
assertEqual(r.start_time(), start);
151+
assertEqual(r.duration(), duration);
152+
153+
r = otime::TimeRange();
154+
assertEqual(r.start_time(), otime::RationalTime());
155+
assertEqual(r.duration(), otime::RationalTime());
156+
});
157+
158+
tests.add_test("test_valid_range", [] {
159+
otime::TimeRange r1(0.0, 0.0, 0.0);
160+
assertTrue(r1.is_invalid_range());
161+
assertFalse(r1.is_valid_range());
162+
otime::TimeRange r2(0.0, 24.0, 24.0);
163+
assertTrue(r2.is_valid_range());
164+
assertFalse(r2.is_invalid_range());
165+
otime::TimeRange r3(0.0, -24.0, 24.0);
166+
assertFalse(r3.is_valid_range());
167+
assertTrue(r3.is_invalid_range());
168+
});
169+
132170
tests.run(argc, argv);
133171
return 0;
134172
}

tests/test_opentime.py

+23
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ def test_create(self):
2626
self.assertEqual(t.value, 0)
2727
self.assertEqual(t.rate, 1.0)
2828

29+
def test_valid(self):
30+
t1 = otio.opentime.RationalTime(0, 0)
31+
self.assertTrue(t1.is_invalid_time())
32+
self.assertFalse(t1.is_valid_time())
33+
t2 = otio.opentime.RationalTime(24)
34+
self.assertTrue(t2.is_valid_time())
35+
self.assertFalse(t2.is_invalid_time())
36+
2937
def test_equality(self):
3038
t1 = otio.opentime.RationalTime(30.2)
3139
self.assertEqual(t1, t1)
@@ -870,6 +878,21 @@ def test_create(self):
870878
)
871879
self.assertEqual(tr2.start_time.rate, tr2.duration.rate)
872880

881+
tr3 = otio.opentime.TimeRange(0, 48, 24)
882+
self.assertEqual(tr3.start_time, otio.opentime.RationalTime(0, 24))
883+
self.assertEqual(tr3.duration, otio.opentime.RationalTime(48, 24))
884+
885+
def test_valid(self):
886+
tr = otio.opentime.TimeRange(0, 0, 0)
887+
self.assertTrue(tr.is_invalid_range())
888+
self.assertFalse(tr.is_valid_range())
889+
tr2 = otio.opentime.TimeRange(0, 48, 24)
890+
self.assertTrue(tr2.is_valid_range())
891+
self.assertFalse(tr2.is_invalid_range())
892+
tr3 = otio.opentime.TimeRange(0, -48, 24)
893+
self.assertFalse(tr3.is_valid_range())
894+
self.assertTrue(tr3.is_invalid_range())
895+
873896
def test_duration_validation(self):
874897
tr = otio.opentime.TimeRange()
875898
with self.assertRaises(AttributeError):

0 commit comments

Comments
 (0)