Created
December 26, 2016 21:23
-
-
Save mgoral/091c3899d1654a79be517ec0c2dbc53e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#-*- coding: utf-8 -*- | |
""" | |
Copyright (C) 2011, 2012, 2013 Michal Goral. | |
This file is part of Subconvert | |
Subconvert is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
Subconvert is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with Subconvert. If not, see <http://www.gnu.org/licenses/>. | |
""" | |
import re | |
from subconvert.utils.SubException import SubAssert | |
from subconvert.utils.Locale import _ | |
class FrameTimeType: | |
"""Used to determine if frame or time should be changed on FPS change.""" | |
Undefined = 0 | |
Frame = 1 | |
Time = 2 | |
class FrameTime(): | |
"""Class defining a FrameTime object which consists of frame and time metrics (and fps as well).""" | |
def __init__(self, fps, ms=None, frames=None, time=None): | |
"""Constructs FrameTime object with a given FPS value. Constructor accepts only one value | |
from the following ones: time (properly formatted string), number of frames (int) or number | |
of total milliseconds. | |
Examples: | |
FrameTime(time="1:01:01.100", fps=25) | |
FrameTime(frames=100, fps=25) | |
FrameTime(ms=3600001, fps=25) | |
""" | |
if fps <= 0: | |
raise ValueError("Incorrect FPS value: %s." % fps) | |
self._fps = float(fps) | |
if frames is None and time is None and ms is None: | |
self._origin = FrameTimeType.Undefined | |
self._frame = 0 | |
self._ms = 0 | |
else: | |
exclusiveArgs = [frames, time, ms] | |
if exclusiveArgs.count(None) != 2: | |
raise AttributeError("FrameTime can obly be initialized by one type.") | |
if frames is not None: | |
self._origin = FrameTimeType.Frame | |
self._set_frame(int(frames)) | |
elif time is not None: | |
self._origin = FrameTimeType.Time | |
self._set_time(str(time)) | |
elif ms is not None: | |
self._origin = FrameTimeType.Time | |
self._set_ms(int(ms)) | |
def clone(self): | |
other = FrameTime(fps = self.fps) | |
other._origin = self._origin | |
other._frame = self._frame | |
other._ms = self._ms | |
return other | |
@property | |
def fps(self): | |
return self._fps | |
@fps.setter | |
def fps(self, newFps): | |
SubAssert(newFps > 0, "Incorrect FPS value: %s." % newFps, ValueError) | |
self._fps = float(newFps) | |
self._set_ms(self._ms) | |
@property | |
def frame(self): | |
"""Get Frame (and FPS) value)""" | |
return int(round(self._frame)) | |
@property | |
def ms(self): | |
return self._ms | |
@property | |
def time(self): | |
hours = int(self._ms / 3600000) | |
counted = hours * 3600000 | |
minutes = int((self._ms - counted) / 60000) | |
counted += minutes * 60000 | |
seconds = int((self._ms - counted) / 1000) | |
counted += seconds * 1000 | |
ms = int(self._ms - counted) | |
return { | |
'hours': hours, | |
'minutes': minutes, | |
'seconds': seconds, | |
'milliseconds': ms, | |
} | |
def toStr(self, strType="time"): | |
"""Convert FrameTime to string representation""" | |
if strType == "time": | |
return "%(hours)d:%(minutes)02d:%(seconds)02d.%(milliseconds)03d" \ | |
% self.time | |
elif strType == "frame": | |
return "%d" % self._frame | |
else: | |
raise AttributeError("Incorrect string type: '%s'" % strType) | |
def _set_time(self, value): | |
time = re.match(r"(?P<h>\d+):(?P<m>[0-5][0-9]):(?P<s>[0-5][0-9])(?:$|\.(?P<ms>\d{1,3}))", value) | |
if time is None: | |
raise ValueError("Incorrect time format.") | |
if time.group('ms') is not None: | |
# ljust explenation: | |
# 10.1 != 10.001 | |
# 10.1 == 10.100 | |
ms = int(time.group('ms').ljust(3, '0')) | |
else: | |
ms = 0 | |
seconds = int(time.group('s')) | |
minutes = int(time.group('m')) | |
hours = int(time.group('h')) | |
self._set_ms(int(1000 * (3600*hours + 60*minutes + seconds) + ms)) | |
def _set_ms(self, ms): | |
SubAssert(ms >= 0, 'Incorrect milliseconds value', ValueError) | |
self._ms = ms | |
self._frame = int(round(ms * self.fps / 1000)) | |
def _set_frame(self, frame): | |
SubAssert(frame >= 0, 'Incorrect frame value', ValueError) | |
self._frame = frame | |
self._ms = int(round(frame / self._fps * 1000)) | |
def __eq__(self, other): | |
SubAssert(self._fps == other._fps, _("FPS values are not equal")) | |
return self._ms == other._ms | |
def __ne__(self, other): | |
SubAssert(self._fps == other._fps, _("FPS values are not equal")) | |
return self._ms != other._ms | |
def __lt__(self, other): | |
SubAssert(self._fps == other._fps, _("FPS values are not equal")) | |
return self._ms < other._ms | |
def __gt__(self, other): | |
SubAssert(self._fps == other._fps, _("FPS values are not equal")) | |
return self._ms > other._ms | |
def __add__(self, other): | |
"""Defines FrameTime + FrameTime""" | |
SubAssert(self._fps == other._fps, _("FPS values are not equal")) | |
result = self._ms + other._ms | |
return FrameTime(fps = self._fps, ms = result) | |
def __sub__(self, other): | |
"""Defines FrameTime - FrameTime""" | |
SubAssert(self._fps == other._fps, _("FPS values are not equal")) | |
SubAssert(self._ms >= other._ms, | |
_("Cannot substract higher time from lower")) | |
result = self._ms - other._ms | |
return FrameTime(fps = self._fps, ms = result) | |
def __mul__(self, val): | |
"""Defines FrameTime * number""" | |
result = self._ms * val | |
return FrameTime(fps = self._fps, ms = result) | |
def __div__(self, val): | |
"""Defines FrameTime / number""" | |
result = self._ms / val | |
return FrameTime(fps = self._fps, ms = result) | |
def __str__(self): | |
"""Defines str(FrameTime)""" | |
fmt = self.time | |
fmt['frame'] = self.frame | |
return "t: %(hours)s:%(minutes)s:%(seconds)s.%(milliseconds)s; " \ | |
"f: %(frame)s" % fmt | |
def __repr__(self): | |
return "FrameTime(id=%s, s=%s, f=%s, fps=%s)" % \ | |
(id(self), self.ms, self.frame, self.fps) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment