def useHeader(self, header): self.width = header["width"].value self.height = header["height"].value # Read number of colors and pixel format if "/palette/size" in header: nb_colors = header["/palette/size"].value // 3 else: nb_colors = None if not header["has_palette"].value: if header["has_alpha"].value: self.pixel_format = _("RGBA") else: self.pixel_format = _("RGB") elif "/transparency" in header: self.pixel_format = _("Color index with transparency") if nb_colors: nb_colors -= 1 else: self.pixel_format = _("Color index") self.bits_per_pixel = pngBitsPerPixel(header) if nb_colors: self.nb_colors = nb_colors # Read compression, timestamp, etc. self.compression = header["compression"].display
def useHeader(self, header): self.width = header["width"].value self.height = header["height"].value # Read number of colors and pixel format if "/palette/size" in header: nb_colors = header["/palette/size"].value // 3 else: nb_colors = None if not header["has_palette"].value: if header["has_alpha"].value: self.pixel_format = _("RGBA") else: self.pixel_format = _("RGB") elif "/transparency" in header: self.pixel_format = _("Color index with transparency") if nb_colors: nb_colors -= 1 else: self.pixel_format = _("Color index") self.bits_per_pixel = pngBitsPerPixel(header) if nb_colors: self.nb_colors = nb_colors # Read compression, timestamp, etc. self.compression = header["compression"].display
def getHachoirOptions(parser): """ Create an option group (type optparse.OptionGroup) of Hachoir library options. """ def setLogFilename(*args): log.setFilename(args[2]) common = OptionGroup(parser, _("Hachoir library"), \ "Configure Hachoir library") common.add_option("--verbose", help=_("Verbose mode"), default=False, action="store_true") common.add_option("--log", help=_("Write log in a file"), type="string", action="callback", callback=setLogFilename) common.add_option("--quiet", help=_("Quiet mode (don't display warning)"), default=False, action="store_true") common.add_option("--debug", help=_("Debug mode"), default=False, action="store_true") return common
def setFilename(self, filename, append=True): """ Use a file to store all messages. The UTF-8 encoding will be used. Write an informative message if the file can't be created. @param filename: C{L{string}} """ # Look if file already exists or not filename = os.path.expanduser(filename) filename = os.path.realpath(filename) append = os.access(filename, os.F_OK) # Create log file (or open it in append mode, if it already exists) try: import codecs if append: self.__file = codecs.open(filename, "a", "utf-8") else: self.__file = codecs.open(filename, "w", "utf-8") self._writeIntoFile(_("Starting Hachoir")) except IOError, err: if err.errno == 2: self.__file = None self.info(_("[Log] setFilename(%s) fails: no such file") % filename) else: raise
def __init__(self, size, address, got=None): self.size = size self.address = address self.got = got if self.got is not None: msg = _("Can't read %u bits at address %u (got %u bits)") % (self.size, self.address, self.got) else: msg = _("Can't read %u bits at address %u") % (self.size, self.address) InputStreamError.__init__(self, msg)
def processMovieHeader(self, hdr): self.creation_date = hdr["creation_date"].value self.last_modification = hdr["lastmod_date"].value self.duration = timedelta(seconds=float(hdr["duration"].value) / hdr["time_scale"].value) self.comment = _("Play speed: %.1f%%") % (hdr["play_speed"].value * 100) self.comment = _("User volume: %.1f%%") % (float(hdr["volume"].value) * 100 // 255)
def __init__(self, size, address, got=None): self.size = size self.address = address self.got = got if self.got is not None: msg = _("Can't read %u bits at address %u (got %u bits)") % ( self.size, self.address, self.got) else: msg = _("Can't read %u bits at address %u") % (self.size, self.address) InputStreamError.__init__(self, msg)
def extract(self, gif): self.useScreen(gif["/screen"]) if self.has("bits_per_pixel"): self.nb_colors = (1 << self.get('bits_per_pixel')) self.compression = _("LZW") self.format_version = "GIF version %s" % gif["version"].value for comments in gif.array("comments"): for comment in gif.array(comments.name + "/comment"): self.comment = comment.value if "graphic_ctl/has_transp" in gif and gif["graphic_ctl/has_transp"].value: self.pixel_format = _("Color index with transparency") else: self.pixel_format = _("Color index")
def extract(self, tar): max_nb = maxNbFile(self) for index, field in enumerate(tar.array("file")): if max_nb is not None and max_nb <= index: self.warning("TAR archive contains many files, but only first %s files are processed" % max_nb) break meta = Metadata(self) self.extractFile(field, meta) if meta.has("filename"): title = _('File "%s"') % meta.getText('filename') else: title = _("File") self.addGroup(field.name, meta, title)
def useFile(self, field): meta = Metadata(self) meta.filename = field["filename"].value meta.file_size = field["filesize"].value meta.creation_date = field["timestamp"].value attr = field["attributes"].value if attr != "(none)": meta.file_attr = attr if meta.has("filename"): title = _("File \"%s\"") % meta.getText('filename') else: title = _("File") self.addGroup(field.name, meta, title)
def __init__(self, stream, **args): validate = args.pop("validate", False) self._mime_type = None while validate: nbits = self.getParserTags()["min_size"] if stream.sizeGe(nbits): res = self.validate() if res is True: break res = makeUnicode(res) else: res = _("stream is smaller than %s.%s bytes" % divmod(nbits, 8)) raise ValidateError(res or _("no reason given")) self._autofix = True
def extract(self, gif): self.useScreen(gif["/screen"]) if self.has("bits_per_pixel"): self.nb_colors = (1 << self.get('bits_per_pixel')) self.compression = _("LZW") self.format_version = "GIF version %s" % gif["version"].value for comments in gif.array("comments"): for comment in gif.array(comments.name + "/comment"): self.comment = comment.value if "graphic_ctl/has_transp" in gif and gif[ "graphic_ctl/has_transp"].value: self.pixel_format = _("Color index with transparency") else: self.pixel_format = _("Color index")
def startOfFrame(self, sof): # Set compression method key = sof["../type"].value self.compression = "JPEG (%s)" % JpegChunk.START_OF_FRAME[key] # Read image size and bits/pixel self.width = sof["width"].value self.height = sof["height"].value nb_components = sof["nr_components"].value self.bits_per_pixel = 8 * nb_components if nb_components == 3: self.pixel_format = _("YCbCr") elif nb_components == 1: self.pixel_format = _("Grayscale") self.nb_colors = 256
def __delitem__(self, index): """ Delete item at position index. May raise IndexError. >>> d=Dict( ((6, 'six'), (9, 'neuf'), (4, 'quatre')) ) >>> del d[1] >>> d {6: 'six', 4: 'quatre'} """ if index < 0: index += len(self._value_list) if not (0 <= index < len(self._value_list)): raise IndexError( _("list assignment index out of range (%s/%s)") % (index, len(self._value_list))) del self._value_list[index] del self._key_list[index] # First loop which may alter self._index for key, item_index in self._index.iteritems(): if item_index == index: del self._index[key] break # Second loop update indexes for key, item_index in self._index.iteritems(): if index < item_index: self._index[key] -= 1
def computeVariableBitrate(self, mp3): if self.quality <= QUALITY_FAST: return count = 0 if QUALITY_BEST <= self.quality: self.warning("Process all MPEG audio frames to compute exact duration") max_count = None else: max_count = 500 * self.quality total_bit_rate = 0.0 for index, frame in enumerate(mp3.array("frames/frame")): if index < 3: continue bit_rate = frame.getBitRate() if bit_rate: total_bit_rate += float(bit_rate) count += 1 if max_count and max_count <= count: break if not count: return bit_rate = total_bit_rate / count self.bit_rate = (bit_rate, _("%s (Variable bit rate)") % humanBitRate(bit_rate)) duration = timedelta(seconds=float(mp3["frames"].size) / bit_rate) self.duration = duration
def extract(self, icon): for index, header in enumerate(icon.array("icon_header")): image = Metadata(self) # Read size and colors from header image.width = header["width"].value image.height = header["height"].value bpp = header["bpp"].value nb_colors = header["nb_color"].value if nb_colors != 0: image.nb_colors = nb_colors if bpp == 0 and nb_colors in self.color_to_bpp: bpp = self.color_to_bpp[nb_colors] elif bpp == 0: bpp = 8 image.bits_per_pixel = bpp image.setHeader(_("Icon #%u (%sx%s)") % (1+index, image.get("width", "?"), image.get("height", "?"))) # Read compression from data (if available) key = "icon_data[%u]/header/codec" % index if key in icon: image.compression = icon[key].display key = "icon_data[%u]/pixels" % index if key in icon: computeComprRate(image, icon[key].size) # Store new image self.addGroup("image[%u]" % index, image)
def extract(self, icon): for index, header in enumerate(icon.array("icon_header")): image = Metadata(self) # Read size and colors from header image.width = header["width"].value image.height = header["height"].value bpp = header["bpp"].value nb_colors = header["nb_color"].value if nb_colors != 0: image.nb_colors = nb_colors if bpp == 0 and nb_colors in self.color_to_bpp: bpp = self.color_to_bpp[nb_colors] elif bpp == 0: bpp = 8 image.bits_per_pixel = bpp image.setHeader( _("Icon #%u (%sx%s)") % (1 + index, image.get("width", "?"), image.get("height", "?"))) # Read compression from data (if available) key = "icon_data[%u]/header/codec" % index if key in icon: image.compression = icon[key].display key = "icon_data[%u]/pixels" % index if key in icon: computeComprRate(image, icon[key].size) # Store new image self.addGroup("image[%u]" % index, image)
def extractAVI(self, headers): audio_index = 1 for stream in headers.array("stream"): if "stream_hdr/stream_type" not in stream: continue stream_type = stream["stream_hdr/stream_type"].value if stream_type == "vids": if "stream_hdr" in stream: meta = Metadata(self) self.extractAVIVideo(stream["stream_hdr"], meta) self.addGroup("video", meta, "Video stream") elif stream_type == "auds": if "stream_fmt" in stream: meta = Metadata(self) self.extractAVIAudio(stream["stream_fmt"], meta) self.addGroup("audio[%u]" % audio_index, meta, "Audio stream") audio_index += 1 if "avi_hdr" in headers: self.useAviHeader(headers["avi_hdr"]) # Compute global bit rate if self.has("duration") and "/movie/size" in headers: self.bit_rate = float( headers["/movie/size"].value) * 8 / timedelta2seconds( self.get('duration')) # Video has index? if "/index" in headers: self.comment = _("Has audio/video index (%s)") \ % humanFilesize(headers["/index"].size/8)
def displayStat(self, stat): """ Display statistics to stdout: - best time (minimum) - average time (arithmetic average) - worst time (maximum) - total time (sum) Use arithmetic avertage instead of geometric average because geometric fails if any value is zero (returns zero) and also because floating point multiplication lose precision with many values. """ average = stat.getSum() / len(stat) values = (stat.getMin(), average, stat.getMax(), stat.getSum()) values = tuple(self.formatTime(value) for value in values) print _("Benchmark: best=%s average=%s worst=%s total=%s") \ % values
def append(self, key, value): """ Append new value """ if key in self._index: raise UniqKeyError(_("Key '%s' already exists") % key) self._index[key] = len(self._value_list) self._key_list.append(key) self._value_list.append(value)
def getHachoirOptions(parser): """ Create an option group (type optparse.OptionGroup) of Hachoir library options. """ def setLogFilename(*args): log.setFilename(args[2]) common = OptionGroup(parser, _("Hachoir library"), \ "Configure Hachoir library") common.add_option("--verbose", help=_("Verbose mode"), default=False, action="store_true") common.add_option("--log", help=_("Write log in a file"), type="string", action="callback", callback=setLogFilename) common.add_option("--quiet", help=_("Quiet mode (don't display warning)"), default=False, action="store_true") common.add_option("--debug", help=_("Debug mode"), default=False, action="store_true") return common
def __setattr__(self, key, value): """ Add a new value to data with name 'key'. Skip duplicates. """ # Invalid key? if key not in self.__data: raise KeyError(_("%s has no metadata '%s'") % (self.__class__.__name__, key)) # Skip duplicates self.__data[key].add(value)
def extract(self, pcx): self.width = 1 + pcx["xmax"].value self.height = 1 + pcx["ymax"].value self.width_dpi = pcx["horiz_dpi"].value self.height_dpi = pcx["vert_dpi"].value self.bits_per_pixel = pcx["bpp"].value if 1 <= pcx["bpp"].value <= 8: self.nb_colors = 2 ** pcx["bpp"].value self.compression = _("Run-length encoding (RLE)") self.format_version = "PCX: %s" % pcx["version"].display if "image_data" in pcx: computeComprRate(self, pcx["image_data"].size)
def extract(self, pcx): self.width = 1 + pcx["xmax"].value self.height = 1 + pcx["ymax"].value self.width_dpi = pcx["horiz_dpi"].value self.height_dpi = pcx["vert_dpi"].value self.bits_per_pixel = pcx["bpp"].value if 1 <= pcx["bpp"].value <= 8: self.nb_colors = 2**pcx["bpp"].value self.compression = _("Run-length encoding (RLE)") self.format_version = "PCX: %s" % pcx["version"].display if "image_data" in pcx: computeComprRate(self, pcx["image_data"].size)
def insert(self, index, key, value): """ Insert an item at specified position index. >>> d=Dict( ((6, 'six'), (9, 'neuf'), (4, 'quatre')) ) >>> d.insert(1, '40', 'quarante') >>> d {6: 'six', '40': 'quarante', 9: 'neuf', 4: 'quatre'} """ if key in self: raise UniqKeyError(_("Insert error: key '%s' ready exists") % key) _index = index if index < 0: index += len(self._value_list) if not (0 <= index <= len(self._value_list)): raise IndexError(_("Insert error: index '%s' is invalid") % _index) for item_key, item_index in self._index.iteritems(): if item_index >= index: self._index[item_key] += 1 self._index[key] = index self._key_list.insert(index, key) self._value_list.insert(index, value)
def humanFilesize(size): """ Convert a file size in byte to human natural representation. It uses the values: 1 KB is 1024 bytes, 1 MB is 1024 KB, etc. The result is an unicode string. >>> humanFilesize(1) u'1 byte' >>> humanFilesize(790) u'790 bytes' >>> humanFilesize(256960) u'250.9 KB' """ if size < 10000: return ngettext("%u byte", "%u bytes", size) % size units = [_("KB"), _("MB"), _("GB"), _("TB")] size = float(size) divisor = 1024 for unit in units: size = size / divisor if size < divisor: return "%.1f %s" % (size, unit) return "%u %s" % (size, unit)
def humanFilesize(size): """ Convert a file size in byte to human natural representation. It uses the values: 1 KB is 1024 bytes, 1 MB is 1024 KB, etc. The result is an unicode string. >>> humanFilesize(1) u'1 byte' >>> humanFilesize(790) u'790 bytes' >>> humanFilesize(256960) u'250.9 KB' """ if size < 10000: return ngettext("%u byte", "%u bytes", size) % size units = [_("KB"), _("MB"), _("GB"), _("TB")] size = float(size) divisor = 1024 for unit in units: size = size / divisor if size < divisor: return "%.1f %s" % (size, unit) return "%u %s" % (size, unit)
def timestampMac32(value): """ Convert an Mac (32-bit) timestamp to string. The format is the number of seconds since the 1st January 1904 (to 2040). Returns unicode string. >>> timestampMac32(0) datetime.datetime(1904, 1, 1, 0, 0) >>> timestampMac32(2843043290) datetime.datetime(1994, 2, 2, 14, 14, 50) """ if not isinstance(value, (float, int, long)): raise TypeError("an integer or float is required") if not(0 <= value <= 4294967295): return _("invalid Mac timestamp (%s)") % value return MAC_TIMESTAMP_T0 + timedelta(seconds=value)
def timestampMac32(value): """ Convert an Mac (32-bit) timestamp to string. The format is the number of seconds since the 1st January 1904 (to 2040). Returns unicode string. >>> timestampMac32(0) datetime.datetime(1904, 1, 1, 0, 0) >>> timestampMac32(2843043290) datetime.datetime(1994, 2, 2, 14, 14, 50) """ if not isinstance(value, (float, int, long)): raise TypeError("an integer or float is required") if not (0 <= value <= 4294967295): return _("invalid Mac timestamp (%s)") % value return MAC_TIMESTAMP_T0 + timedelta(seconds=value)
def timestampWin64(value): """ Convert Windows 64-bit timestamp to string. The timestamp format is a 64-bit number which represents number of 100ns since the 1st January 1601 at 00:00. Result is an unicode string. See also durationWin64(). Maximum date is 28 may 60056. >>> timestampWin64(0) datetime.datetime(1601, 1, 1, 0, 0) >>> timestampWin64(127840491566710000) datetime.datetime(2006, 2, 10, 12, 45, 56, 671000) """ try: return WIN64_TIMESTAMP_T0 + durationWin64(value) except OverflowError: raise ValueError(_("date newer than year %s (value=%s)") % (MAXYEAR, value))
def timestampWin64(value): """ Convert Windows 64-bit timestamp to string. The timestamp format is a 64-bit number which represents number of 100ns since the 1st January 1601 at 00:00. Result is an unicode string. See also durationWin64(). Maximum date is 28 may 60056. >>> timestampWin64(0) datetime.datetime(1601, 1, 1, 0, 0) >>> timestampWin64(127840491566710000) datetime.datetime(2006, 2, 10, 12, 45, 56, 671000) """ try: return WIN64_TIMESTAMP_T0 + durationWin64(value) except OverflowError: raise ValueError( _("date newer than year %s (value=%s)") % (MAXYEAR, value))
def __init__(self, input, size=None, **args): if not hasattr(input, "seek"): if size is None: input = InputPipe(input, self._setSize) else: input = InputPipe(input) elif size is None: try: input.seek(0, 2) size = input.tell() * 8 except IOError, err: if err.errno == ESPIPE: input = InputPipe(input, self._setSize) else: charset = getTerminalCharset() errmsg = unicode(str(err), charset) source = args.get("source", "<inputio:%r>" % input) raise InputStreamError(_("Unable to get size of %s: %s") % (source, errmsg))
def _get(self, index): if index >= len(self.buffers): return '' buf = self.buffers[index] if buf is None: raise InputStreamError(_("Error: Buffers too small. Can't seek backward.")) if self.last != index: next = buf[1] prev = buf[2] self.buffers[next][2] = prev self.buffers[prev][1] = next first = self.buffers[self.last][1] buf[1] = first buf[2] = self.last self.buffers[first][2] = index self.buffers[self.last][1] = index self.last = index return buf[0]
def FileInputStream(filename, real_filename=None, **args): """ Create an input stream of a file. filename must be unicode. real_filename is an optional argument used to specify the real filename, its type can be 'str' or 'unicode'. Use real_filename when you are not able to convert filename to real unicode string (ie. you have to use unicode(name, 'replace') or unicode(name, 'ignore')). """ assert isinstance(filename, unicode) if not real_filename: real_filename = filename try: inputio = open(real_filename, 'rb') except IOError, err: charset = getTerminalCharset() errmsg = unicode(str(err), charset) raise InputStreamError(_("Unable to open file %s: %s") % (filename, errmsg))
def _get(self, index): if index >= len(self.buffers): return '' buf = self.buffers[index] if buf is None: raise InputStreamError( _("Error: Buffers too small. Can't seek backward.")) if self.last != index: next = buf[1] prev = buf[2] self.buffers[next][2] = prev self.buffers[prev][1] = next first = self.buffers[self.last][1] buf[1] = first buf[2] = self.last self.buffers[first][2] = index self.buffers[self.last][1] = index self.last = index return buf[0]
def createDisplay(self, human=True): if not human: if self._raw_value is None: self._raw_value = GenericString.createValue(self, False) value = makePrintable(self._raw_value, "ASCII", to_unicode=True) elif self._charset: value = makePrintable(self.value, "ISO-8859-1", to_unicode=True) else: value = self.value if config.max_string_length < len(value): # Truncate string if needed value = "%s(...)" % value[:config.max_string_length] if not self._charset or not human: return makePrintable(value, "ASCII", quote='"', to_unicode=True) else: if value: return '"%s"' % value.replace('"', '\\"') else: return _("(empty)")
def __init__(self, input, size=None, **args): if not hasattr(input, "seek"): if size is None: input = InputPipe(input, self._setSize) else: input = InputPipe(input) elif size is None: try: input.seek(0, 2) size = input.tell() * 8 except IOError, err: if err.errno == ESPIPE: input = InputPipe(input, self._setSize) else: charset = getTerminalCharset() errmsg = unicode(str(err), charset) source = args.get("source", "<inputio:%r>" % input) raise InputStreamError( _("Unable to get size of %s: %s") % (source, errmsg))
def timestampUUID60(value): """ Convert UUID 60-bit timestamp to string. The timestamp format is a 60-bit number which represents number of 100ns since the the 15 October 1582 at 00:00. Result is an unicode string. >>> timestampUUID60(0) datetime.datetime(1582, 10, 15, 0, 0) >>> timestampUUID60(130435676263032368) datetime.datetime(1996, 2, 14, 5, 13, 46, 303236) """ if not isinstance(value, (float, int, long)): raise TypeError("an integer or float is required") if value < 0: raise ValueError("value have to be a positive or nul integer") try: return UUID60_TIMESTAMP_T0 + timedelta(microseconds=value / 10) except OverflowError: raise ValueError(_("timestampUUID60() overflow (value=%s)") % value)
def timestampUUID60(value): """ Convert UUID 60-bit timestamp to string. The timestamp format is a 60-bit number which represents number of 100ns since the the 15 October 1582 at 00:00. Result is an unicode string. >>> timestampUUID60(0) datetime.datetime(1582, 10, 15, 0, 0) >>> timestampUUID60(130435676263032368) datetime.datetime(1996, 2, 14, 5, 13, 46, 303236) """ if not isinstance(value, (float, int, long)): raise TypeError("an integer or float is required") if value < 0: raise ValueError("value have to be a positive or nul integer") try: return UUID60_TIMESTAMP_T0 + timedelta(microseconds=value/10) except OverflowError: raise ValueError(_("timestampUUID60() overflow (value=%s)") % value)
def createDisplay(self, human=True): if not human: if self._raw_value is None: self._raw_value = GenericString.createValue(self, False) value = makePrintable(self._raw_value, "ASCII", to_unicode=True) elif self._charset: value = makePrintable(self.value, "ISO-8859-1", to_unicode=True) else: value = self.value if config.max_string_length < len(value): # Truncate string if needed value = "%s(...)" % value[:config.max_string_length] if not self._charset or not human: return makePrintable(value, "ASCII", quote='"', to_unicode=True) else: if value: return '"%s"' % value.replace('"', '\\"') else: return _("(empty)")
def computeQuality(self, jpeg): # This function is an adaption to Python of ImageMagick code # to compute JPEG quality using quantization tables # Read quantization tables qtlist = [] for dqt in jpeg.array("quantization"): for qt in dqt.array("content/qt"): # TODO: Take care of qt["index"].value? qtlist.append(qt) if not qtlist: return # Compute sum of all coefficients sumcoeff = 0 for qt in qtlist: coeff = qt.array("coeff") for index in xrange(64): sumcoeff += coeff[index].value # Choose the right quality table and compute hash value try: hashval= qtlist[0]["coeff[2]"].value + qtlist[0]["coeff[53]"].value if 2 <= len(qtlist): hashval += qtlist[1]["coeff[0]"].value + qtlist[1]["coeff[63]"].value hashtable = QUALITY_HASH_COLOR sumtable = QUALITY_SUM_COLOR else: hashtable = QUALITY_HASH_GRAY sumtable = QUALITY_SUM_GRAY except (MissingField, IndexError): # A coefficient is missing, so don't compute JPEG quality return # Find the JPEG quality for index in xrange(100): if (hashval >= hashtable[index]) or (sumcoeff >= sumtable[index]): quality = "%s%%" % (index + 1) if (hashval > hashtable[index]) or (sumcoeff > sumtable[index]): quality += " " + _("(approximate)") self.comment = "JPEG quality: %s" % quality return
def registerAllItems(meta): meta.register(Data("title", 100, _("Title"), type=unicode)) meta.register(Data("artist", 101, _("Artist"), type=unicode)) meta.register(Data("author", 102, _("Author"), type=unicode)) meta.register(Data("music_composer", 103, _("Music composer"), type=unicode)) meta.register(Data("album", 200, _("Album"), type=unicode)) meta.register(Data("duration", 201, _("Duration"), # integer in milliseconde type=timedelta, text_handler=humanDuration, filter=DURATION_FILTER)) meta.register(Data("nb_page", 202, _("Nb page"), filter=NumberFilter(1, MAX_NB_PAGE))) meta.register(Data("music_genre", 203, _("Music genre"), type=unicode)) meta.register(Data("language", 204, _("Language"), conversion=setLanguage, type=Language)) meta.register(Data("track_number", 205, _("Track number"), conversion=setTrackNumber, filter=NumberFilter(1, MAX_TRACK), type=(int, long))) meta.register(Data("track_total", 206, _("Track total"), conversion=setTrackTotal, filter=NumberFilter(1, MAX_TRACK), type=(int, long))) meta.register(Data("organization", 210, _("Organization"), type=unicode)) meta.register(Data("version", 220, _("Version"))) meta.register(Data("width", 301, _("Image width"), filter=NumberFilter(1, MAX_WIDTH), type=(int, long), text_handler=humanPixelSize)) meta.register(Data("height", 302, _("Image height"), filter=NumberFilter(1, MAX_HEIGHT), type=(int, long), text_handler=humanPixelSize)) meta.register(Data("nb_channel", 303, _("Channel"), text_handler=humanAudioChannel, filter=NumberFilter(1, MAX_NB_CHANNEL), type=(int, long))) meta.register(Data("sample_rate", 304, _("Sample rate"), text_handler=humanFrequency, filter=NumberFilter(MIN_SAMPLE_RATE, MAX_SAMPLE_RATE), type=(int, long, float))) meta.register(Data("bits_per_sample", 305, _("Bits/sample"), text_handler=humanBitSize, filter=NumberFilter(1, 64), type=(int, long))) meta.register(Data("image_orientation", 306, _("Image orientation"))) meta.register(Data("nb_colors", 307, _("Number of colors"), filter=NumberFilter(1, MAX_NB_COLOR), type=(int, long))) meta.register(Data("bits_per_pixel", 308, _("Bits/pixel"), filter=NumberFilter(1, MAX_BITS_PER_PIXEL), type=(int, long))) meta.register(Data("filename", 309, _("File name"), type=unicode)) meta.register(Data("file_size", 310, _("File size"), text_handler=humanFilesize, type=(int, long))) meta.register(Data("pixel_format", 311, _("Pixel format"))) meta.register(Data("compr_size", 312, _("Compressed file size"), text_handler=humanFilesize, type=(int, long))) meta.register(Data("compr_rate", 313, _("Compression rate"), text_handler=humanComprRate, filter=NumberFilter(MIN_COMPR_RATE, MAX_COMPR_RATE), type=(int, long, float))) meta.register(Data("width_dpi", 320, _("Image DPI width"), filter=NumberFilter(1, MAX_DPI_WIDTH), type=(int, long), text_handler=humanDPI)) meta.register(Data("height_dpi", 321, _("Image DPI height"), filter=NumberFilter(1, MAX_DPI_HEIGHT), type=(int, long), text_handler=humanDPI)) meta.register(Data("file_attr", 400, _("File attributes"))) meta.register(Data("file_type", 401, _("File type"))) meta.register(Data("subtitle_author", 402, _("Subtitle author"), type=unicode)) meta.register(Data("creation_date", 500, _("Creation date"), text_handler=humanDatetime, filter=DATETIME_FILTER, type=(datetime, date), conversion=setDatetime)) meta.register(Data("last_modification", 501, _("Last modification"), text_handler=humanDatetime, filter=DATETIME_FILTER, type=(datetime, date), conversion=setDatetime)) meta.register(Data("latitude", 510, _("Latitude"), type=float)) meta.register(Data("longitude", 511, _("Longitude"), type=float)) meta.register(Data("altitude", 511, _("Altitude"), type=float, text_handler=humanAltitude)) meta.register(Data("location", 530, _("Location"), type=unicode)) meta.register(Data("city", 531, _("City"), type=unicode)) meta.register(Data("country", 532, _("Country"), type=unicode)) meta.register(Data("charset", 540, _("Charset"), type=unicode)) meta.register(Data("font_weight", 550, _("Font weight"))) meta.register(Data("camera_aperture", 520, _("Camera aperture"))) meta.register(Data("camera_focal", 521, _("Camera focal"))) meta.register(Data("camera_exposure", 522, _("Camera exposure"))) meta.register(Data("camera_brightness", 530, _("Camera brightness"))) meta.register(Data("camera_model", 531, _("Camera model"), type=unicode)) meta.register(Data("camera_manufacturer", 532, _("Camera manufacturer"), type=unicode)) meta.register(Data("compression", 600, _("Compression"))) meta.register(Data("copyright", 601, _("Copyright"), type=unicode)) meta.register(Data("url", 602, _("URL"), type=unicode)) meta.register(Data("frame_rate", 603, _("Frame rate"), text_handler=humanFrameRate, filter=NumberFilter(1, MAX_FRAME_RATE), type=(int, long, float))) meta.register(Data("bit_rate", 604, _("Bit rate"), text_handler=humanBitRate, filter=NumberFilter(1, MAX_BIT_RATE), type=(int, long, float))) meta.register(Data("aspect_ratio", 604, _("Aspect ratio"), type=(int, long, float))) meta.register(Data("os", 900, _("OS"), type=unicode)) meta.register(Data("producer", 901, _("Producer"), type=unicode)) meta.register(Data("comment", 902, _("Comment"), type=unicode)) meta.register(Data("format_version", 950, _("Format version"), type=unicode)) meta.register(Data("mime_type", 951, _("MIME type"), type=unicode)) meta.register(Data("endian", 952, _("Endianness"), type=unicode))
for key, value in self.parser_args.iteritems(): setattr(parser_obj, key, value) return parser_obj except ValidateError, err: res = unicode(err) if fallback and self.fallback: fb = parser except HACHOIR_ERRORS, err: res = unicode(err) if warn: if parser == self.other: warn = info warn(_("Skip parser '%s': %s") % (parser.__name__, res)) fallback = False if self.use_fallback and fb: warning(_("Force use of parser '%s'") % fb.__name__) return fb(stream) def guessParser(stream): return QueryParser(stream.tags).parse(stream) def createParser(filename, real_filename=None, tags=None): """ Create a parser from a file or returns None on error. Options: - filename (unicode): Input file name ; - real_filename (str|unicode): Real file name. """
def humanFrameRate(value): if isinstance(value, (int, long, float)): return _("%.1f fps") % value else: return value
def computeBitrate(self, frame): bit_rate = frame.getBitRate() # may returns None on error if not bit_rate: return self.bit_rate = (bit_rate, _("%s (constant)") % humanBitRate(bit_rate)) self.duration = timedelta(seconds=float(frame["/frames"].size) / bit_rate)
""" Constant values about endian. """ from resources.lib.externals.hachoir.hachoir_core.i18n import _ BIG_ENDIAN = "ABCD" LITTLE_ENDIAN = "DCBA" NETWORK_ENDIAN = BIG_ENDIAN endian_name = { BIG_ENDIAN: _("Big endian"), LITTLE_ENDIAN: _("Little endian"), }
def __init__(self, source): self.source = source msg = _("Input size is nul (source='%s')!") % self.source InputStreamError.__init__(self, msg)
def _getValue(self): try: value = self.createValue() except HACHOIR_ERRORS, err: self.error(_("Unable to create value: %s") % unicode(err)) value = None
def print_(self, title=None, out=None, verbose=False, format="one-line"): """Display a list of parser with its title * out: output file * title : title of the list to display * format: "rest", "trac", "file-ext", "mime" or "one_line" (default) """ if out is None: out = sys.stdout if format in ("file-ext", "mime"): # Create file extension set extensions = set() for parser in self: file_ext = parser.getParserTags().get(format, ()) file_ext = list(file_ext) try: file_ext.remove("") except ValueError: pass extensions |= set(file_ext) # Remove empty extension extensions -= set(('',)) # Convert to list and sort by ASCII order extensions = list(extensions) extensions.sort() # Print list text = ", ".join( str(item) for item in extensions ) if format == "file-ext": print >>out, "File extensions: %s." % text print >>out print >>out, "Total: %s file extensions." % len(extensions) else: print >>out, "MIME types: %s." % text print >>out print >>out, "Total: %s MIME types." % len(extensions) return if format == "trac": print >>out, "== List of parsers ==" print >>out print >>out, "Total: %s parsers" % len(self.parser_list) print >>out elif format == "one_line": if title: print >>out, title else: print >>out, _("List of Hachoir parsers.") print >>out # Create parser list sorted by module bycategory = self.bytag["category"] for category in sorted(bycategory.iterkeys()): if format == "one_line": parser_list = [ parser.PARSER_TAGS["id"] for parser in bycategory[category] ] parser_list.sort() print >>out, "- %s: %s" % (category.title(), ", ".join(parser_list)) else: if format == "rest": print >>out, category.replace("_", " ").title() print >>out, "-" * len(category) print >>out elif format == "trac": print >>out, "=== %s ===" % category.replace("_", " ").title() print >>out else: print >>out, "[%s]" % category parser_list = sorted(bycategory[category], key=lambda parser: parser.PARSER_TAGS["id"]) if format == "rest": for parser in parser_list: tags = parser.getParserTags() print >>out, "* %s: %s" % (tags["id"], tags["description"]) elif format == "trac": for parser in parser_list: tags = parser.getParserTags() desc = tags["description"] desc = re.sub(r"([A-Z][a-z]+[A-Z][^ ]+)", r"!\1", desc) print >>out, " * %s: %s" % (tags["id"], desc) else: for parser in parser_list: parser.print_(out, verbose) print >>out if format != "trac": print >>out, "Total: %s parsers" % len(self.parser_list)
def createDisplay(self): if self._size < config.max_bit_length: return unicode(self.value) else: return _("<%s size=%u>" % (self.__class__.__name__, self._size))
def processMovieHeader(self, hdr): self.creation_date = hdr["creation_date"].value self.last_modification = hdr["lastmod_date"].value self.duration = timedelta(seconds=float(hdr["duration"].value) / hdr["time_scale"].value) self.comment = _("Play speed: %.1f%%") % (hdr["play_speed"].value*100) self.comment = _("User volume: %.1f%%") % (float(hdr["volume"].value)*100//255)
from resources.lib.externals.hachoir.hachoir_core.i18n import _, ngettext NB_CHANNEL_NAME = {1: _("mono"), 2: _("stereo")} def humanAudioChannel(value): return NB_CHANNEL_NAME.get(value, unicode(value)) def humanFrameRate(value): if isinstance(value, (int, long, float)): return _("%.1f fps") % value else: return value def humanComprRate(rate): return u"%.1fx" % rate def humanAltitude(value): return ngettext("%.1f meter", "%.1f meters", value) % value def humanPixelSize(value): return ngettext("%s pixel", "%s pixels", value) % value def humanDPI(value): return u"%s DPI" % value