aboutsummaryrefslogtreecommitdiffstats
path: root/mvc/utils.py
diff options
context:
space:
mode:
authorJesús Eduardo <heckyel@hyperbola.info>2017-09-11 17:47:17 -0500
committerJesús Eduardo <heckyel@hyperbola.info>2017-09-11 17:47:17 -0500
commit14738704ede6dfa6ac79f362a9c1f7f40f470cdc (patch)
tree31c83bdd188ae7b64d7169974d6f066ccfe95367 /mvc/utils.py
parenteb1896583afbbb622cadcde1a24e17173f61904f (diff)
downloadlibrevideoconverter-14738704ede6dfa6ac79f362a9c1f7f40f470cdc.tar.lz
librevideoconverter-14738704ede6dfa6ac79f362a9c1f7f40f470cdc.tar.xz
librevideoconverter-14738704ede6dfa6ac79f362a9c1f7f40f470cdc.zip
rename mvc at lvc
Diffstat (limited to 'mvc/utils.py')
-rw-r--r--mvc/utils.py230
1 files changed, 0 insertions, 230 deletions
diff --git a/mvc/utils.py b/mvc/utils.py
deleted file mode 100644
index e0a64f3..0000000
--- a/mvc/utils.py
+++ /dev/null
@@ -1,230 +0,0 @@
-import ctypes
-import itertools
-import logging
-import os
-import sys
-
-def hms_to_seconds(hours, minutes, seconds):
- return (hours * 3600 +
- minutes * 60 +
- seconds)
-
-
-def round_even(num):
- """This takes a number, converts it to an integer, then makes
- sure it's even.
-
- Additional rules: this helper always rounds down to avoid stray black
- pixels (see bz18122).
-
- This function makes sure that the value returned is always >= 0.
- """
- num = int(num)
- val = num - (num % 2)
- return val if val > 0 else 0
-
-
-def rescale_video((source_width, source_height),
- (target_width, target_height),
- dont_upsize=True):
- """
- Rescale a video given a (width, height) target. This returns the largest
- (width, height) which maintains the original aspect ratio while fitting
- within the target size.
-
- If dont_upsize is set, then don't resize it such that the rescaled size
- will be larger than the original size.
- """
- if source_width is None or source_height is None:
- return (round_even(target_width), round_even(target_height))
-
- if target_width is None or target_height is None:
- return (round_even(source_width), round_even(source_height))
-
- if (dont_upsize and
- (source_width <= target_width or source_height <= target_height)):
- return (round_even(source_width), round_even(source_height))
-
- width_ratio = float(source_width) / float(target_width)
- height_ratio = float(source_height) / float(target_height)
- ratio = max(width_ratio, height_ratio)
- return round_even(source_width / ratio), round_even(source_height / ratio)
-
-def line_reader(handle):
- """Builds a line reading generator for the given handle. This
- generator breaks on empty strings, \\r and \\n.
-
- This a little weird, but it makes it really easy to test error
- checking and progress monitoring.
- """
- def _readlines():
- chars = []
- c = handle.read(1)
- while True:
- if c in ["", "\r", "\n"]:
- if chars:
- yield "".join(chars)
- if not c:
- break
- chars = []
- else:
- chars.append(c)
- c = handle.read(1)
- return _readlines()
-
-
-class Matrix(object):
- """2 Dimensional matrix.
-
- Matrix objects are accessed like a list, except tuples are used as
- indices, for example:
-
- >>> m = Matrix(5, 5)
- >>> m[3, 4] = 'foo'
- >>> m
- None, None, None, None, None
- None, None, None, None, None
- None, None, None, None, None
- None, None, None, None, None
- None, None, None, 'foo', None
- """
-
- def __init__(self, columns, rows, initial_value=None):
- self.columns = columns
- self.rows = rows
- self.data = [ initial_value ] * (columns * rows)
-
- def __getitem__(self, key):
- return self.data[(key[0] * self.rows) + key[1]]
-
- def __setitem__(self, key, value):
- self.data[(key[0] * self.rows) + key[1]] = value
-
- def __iter__(self):
- return iter(self.data)
-
- def __repr__(self):
- return "\n".join([", ".join([repr(r)
- for r in list(self.row(i))])
- for i in xrange(self.rows)])
-
- def remove(self, value):
- """This sets the value to None--it does NOT remove the cell
- from the Matrix because that doesn't make any sense.
- """
- i = self.data.index(value)
- self.data[i] = None
-
- def row(self, row):
- """Iterator that yields all the objects in a row."""
- for i in xrange(self.columns):
- yield self[i, row]
-
- def column(self, column):
- """Iterator that yields all the objects in a column."""
- for i in xrange(self.rows):
- yield self[column, i]
-
-
-class Cache(object):
- def __init__(self, size):
- self.size = size
- self.dict = {}
- self.counter = itertools.count()
- self.access_times = {}
- self.invalidators = {}
-
- def get(self, key, invalidator=None):
- if key in self.dict:
- existing_invalidator = self.invalidators[key]
- if (existing_invalidator is None or
- not existing_invalidator(key)):
- self.access_times[key] = self.counter.next()
- return self.dict[key]
-
- value = self.create_new_value(key, invalidator=invalidator)
- self.set(key, value, invalidator=invalidator)
- return value
-
- def set(self, key, value, invalidator=None):
- if len(self.dict) == self.size:
- self.shrink_size()
- self.access_times[key] = self.counter.next()
- self.dict[key] = value
- self.invalidators[key] = invalidator
-
- def remove(self, key):
- if key in self.dict:
- del self.dict[key]
- del self.access_times[key]
- if key in self.invalidators:
- del self.invalidators[key]
-
- def keys(self):
- return self.dict.iterkeys()
-
- def shrink_size(self):
- # shrink by LRU
- to_sort = self.access_times.items()
- to_sort.sort(key=lambda m: m[1])
- new_dict = {}
- new_access_times = {}
- new_invalidators = {}
- latest_times = to_sort[len(self.dict) // 2:]
- for (key, time) in latest_times:
- new_dict[key] = self.dict[key]
- new_invalidators[key] = self.invalidators[key]
- new_access_times[key] = time
- self.dict = new_dict
- self.access_times = new_access_times
-
- def create_new_value(self, val, invalidator=None):
- raise NotImplementedError()
-
-
-def size_string(nbytes):
- # when switching from the enclosure reported size to the
- # downloader reported size, it takes a while to get the new size
- # and the downloader returns -1. the user sees the size go to -1B
- # which is weird.... better to return an empty string.
- if nbytes == -1 or nbytes == 0:
- return ""
-
- # FIXME this is a repeat of util.format_size_for_user ... should
- # probably ditch one of them.
- if nbytes >= (1 << 30):
- value = "%.1f" % (nbytes / float(1 << 30))
- return "%(size)s GB" % {"size": value}
- elif nbytes >= (1 << 20):
- value = "%.1f" % (nbytes / float(1 << 20))
- return "%(size)s MB" % {"size": value}
- elif nbytes >= (1 << 10):
- value = "%.1f" % (nbytes / float(1 << 10))
- return "%(size)s KB" % {"size": value}
- else:
- return "%(size)s B" % {"size": nbytes}
-
-def convert_path_for_subprocess(path):
- """Convert a path to a form suitable for passing to a subprocess.
-
- This method converts unicode paths to bytestrings according to the system
- fileencoding. On windows, it converts the path to a short filename for
- maximum compatibility
-
- This method should only be called on a path that exists on the filesystem.
- """
- if not os.path.exists(path):
- raise ValueError("path %r doesn't exist" % path)
- if not isinstance(path, unicode):
- # path already is a bytestring, just return it
- return path
- if sys.platform != 'win32':
- return path.encode(sys.getfilesystemencoding())
- else:
- buf_size = 1024
- short_path_buf = ctypes.create_unicode_buffer(buf_size)
- ctypes.windll.kernel32.GetShortPathNameW(path,
- short_path_buf, buf_size)
- logging.info("convert_path_for_subprocess: got short path %r",
- short_path_buf.value)
- return short_path_buf.value.encode('ascii')