X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/4f5547ad4cd06de77bdf0607e38aab2d45080bfc..14fef303c668733a4ff0458bc468595e4a1629ab:/lib/mutagen/oggvorbis.py diff --git a/lib/mutagen/oggvorbis.py b/lib/mutagen/oggvorbis.py new file mode 100644 index 000000000..e1de1bd0d --- /dev/null +++ b/lib/mutagen/oggvorbis.py @@ -0,0 +1,119 @@ +# Ogg Vorbis support. +# +# Copyright 2006 Joe Wreschnig +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# $Id: oggvorbis.py 4275 2008-06-01 06:32:37Z piman $ + +"""Read and write Ogg Vorbis comments. + +This module handles Vorbis files wrapped in an Ogg bitstream. The +first Vorbis stream found is used. + +Read more about Ogg Vorbis at http://vorbis.com/. This module is based +on the specification at http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html. +""" + +__all__ = ["OggVorbis", "Open", "delete"] + +import struct + +from mutagen._vorbis import VCommentDict +from mutagen.ogg import OggPage, OggFileType, error as OggError + +class error(OggError): pass +class OggVorbisHeaderError(error): pass + +class OggVorbisInfo(object): + """Ogg Vorbis stream information. + + Attributes: + length - file length in seconds, as a float + bitrate - nominal ('average') bitrate in bits per second, as an int + """ + + length = 0 + + def __init__(self, fileobj): + page = OggPage(fileobj) + while not page.packets[0].startswith("\x01vorbis"): + page = OggPage(fileobj) + if not page.first: + raise OggVorbisHeaderError( + "page has ID header, but doesn't start a stream") + (self.channels, self.sample_rate, max_bitrate, nominal_bitrate, + min_bitrate) = struct.unpack(" nominal_bitrate: + self.bitrate = min_bitrate + else: + self.bitrate = nominal_bitrate + + def pprint(self): + return "Ogg Vorbis, %.2f seconds, %d bps" % (self.length, self.bitrate) + +class OggVCommentDict(VCommentDict): + """Vorbis comments embedded in an Ogg bitstream.""" + + def __init__(self, fileobj, info): + pages = [] + complete = False + while not complete: + page = OggPage(fileobj) + if page.serial == info.serial: + pages.append(page) + complete = page.complete or (len(page.packets) > 1) + data = OggPage.to_packets(pages)[0][7:] # Strip off "\x03vorbis". + super(OggVCommentDict, self).__init__(data) + + def _inject(self, fileobj): + """Write tag data into the Vorbis comment packet/page.""" + + # Find the old pages in the file; we'll need to remove them, + # plus grab any stray setup packet data out of them. + fileobj.seek(0) + page = OggPage(fileobj) + while not page.packets[0].startswith("\x03vorbis"): + page = OggPage(fileobj) + + old_pages = [page] + while not (old_pages[-1].complete or len(old_pages[-1].packets) > 1): + page = OggPage(fileobj) + if page.serial == old_pages[0].serial: + old_pages.append(page) + + packets = OggPage.to_packets(old_pages, strict=False) + + # Set the new comment packet. + packets[0] = "\x03vorbis" + self.write() + + new_pages = OggPage.from_packets(packets, old_pages[0].sequence) + OggPage.replace(fileobj, old_pages, new_pages) + +class OggVorbis(OggFileType): + """An Ogg Vorbis file.""" + + _Info = OggVorbisInfo + _Tags = OggVCommentDict + _Error = OggVorbisHeaderError + _mimes = ["audio/vorbis", "audio/x-vorbis"] + + def score(filename, fileobj, header): + return (header.startswith("OggS") * ("\x01vorbis" in header)) + score = staticmethod(score) + +Open = OggVorbis + +def delete(filename): + """Remove tags from a file.""" + OggVorbis(filename).delete()