def _inject(self, fileobj, padding_func): """Write tag data into the FLAC Vorbis comment packet/page.""" # Ogg FLAC has no convenient data marker like Vorbis, but the # second packet - and second page - must be the comment data. fileobj.seek(0) page = OggPage(fileobj) while not page.packets[0].startswith(b"\x7FFLAC"): page = OggPage(fileobj) first_page = page while not (page.sequence == 1 and page.serial == first_page.serial): 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 == first_page.serial: old_pages.append(page) packets = OggPage.to_packets(old_pages, strict=False) # Set the new comment block. data = self.write(framing=False) data = packets[0][:1] + struct.pack(">I", len(data))[-3:] + data packets[0] = data new_pages = OggPage.from_packets(packets, old_pages[0].sequence) OggPage.replace(fileobj, old_pages, new_pages)
def _inject(self, fileobj, padding_func): """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(b"\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) content_size = get_size(fileobj) - len(packets[0]) # approx vcomment_data = b"\x03vorbis" + self.write() padding_left = len(packets[0]) - len(vcomment_data) info = PaddingInfo(padding_left, content_size) new_padding = info._get_padding(padding_func) # Set the new comment packet. packets[0] = vcomment_data + b"\x00" * new_padding new_pages = OggPage._from_packets_try_preserve(packets, old_pages) OggPage.replace(fileobj, old_pages, new_pages)
def __init__(self, fileobj): page = OggPage(fileobj) while not page.packets[0].startswith(b"\x7FFLAC"): page = OggPage(fileobj) major, minor, self.packets, flac = struct.unpack( ">BBH4s", page.packets[0][5:13]) if flac != b"fLaC": raise OggFLACHeaderError("invalid FLAC marker (%r)" % flac) elif (major, minor) != (1, 0): raise OggFLACHeaderError("unknown mapping version: %d.%d" % (major, minor)) self.serial = page.serial # Skip over the block header. stringobj = cBytesIO(page.packets[0][17:]) try: flac_info = FLACStreamInfo(stringobj) except FLACError as e: raise OggFLACHeaderError(e) for attr in [ "min_blocksize", "max_blocksize", "sample_rate", "channels", "bits_per_sample", "total_samples", "length" ]: setattr(self, attr, getattr(flac_info, attr))
def _inject(self, fileobj, padding_func): """Write tag data into the Theora comment packet/page.""" fileobj.seek(0) page = OggPage(fileobj) while not page.packets[0].startswith(b"\x81theora"): 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) content_size = get_size(fileobj) - len(packets[0]) # approx vcomment_data = b"\x81theora" + self.write(framing=False) padding_left = len(packets[0]) - len(vcomment_data) info = PaddingInfo(padding_left, content_size) new_padding = info._get_padding(padding_func) packets[0] = vcomment_data + b"\x00" * new_padding new_pages = OggPage._from_packets_try_preserve(packets, old_pages) OggPage.replace(fileobj, old_pages, new_pages)
def __init__(self, fileobj): page = OggPage(fileobj) while not page.packets[0].startswith(b"\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("<B4i", page.packets[0][11:28]) self.serial = page.serial max_bitrate = max(0, max_bitrate) min_bitrate = max(0, min_bitrate) nominal_bitrate = max(0, nominal_bitrate) if nominal_bitrate == 0: self.bitrate = (max_bitrate + min_bitrate) // 2 elif max_bitrate and max_bitrate < nominal_bitrate: # If the max bitrate is less than the nominal, we know # the nominal is wrong. self.bitrate = max_bitrate elif min_bitrate > nominal_bitrate: self.bitrate = min_bitrate else: self.bitrate = nominal_bitrate
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:] super(OggTheoraCommentDict, self).__init__(data, framing=False) self._padding = len(data) - self._size
def __init__(self, fileobj): page = OggPage(fileobj) while not page.packets[0].startswith(b"Speex "): page = OggPage(fileobj) if not page.first: raise OggSpeexHeaderError( "page has ID header, but doesn't start a stream") self.sample_rate = cdata.uint_le(page.packets[0][36:40]) self.channels = cdata.uint_le(page.packets[0][48:52]) self.bitrate = max(0, cdata.int_le(page.packets[0][52:56])) self.serial = page.serial
def __init__(self, fileobj, info): # data should be pointing at the start of an Ogg page, after # the first FLAC page. 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) comment = cBytesIO(OggPage.to_packets(pages)[0][4:]) super(OggFLACVComment, self).__init__(comment, framing=False)
def __get_comment_pages(self, fileobj, info): # find the first tags page with the right serial page = OggPage(fileobj) while ((info.serial != page.serial) or not page.packets[0].startswith(b"OpusTags")): page = OggPage(fileobj) # get all comment pages pages = [page] while not (pages[-1].complete or len(pages[-1].packets) > 1): page = OggPage(fileobj) if page.serial == pages[0].serial: pages.append(page) return pages
def __init__(self, fileobj): page = OggPage(fileobj) while not page.packets[0].startswith(b"\x80theora"): page = OggPage(fileobj) if not page.first: raise OggTheoraHeaderError( "page has ID header, but doesn't start a stream") data = page.packets[0] vmaj, vmin = struct.unpack("2B", data[7:9]) if (vmaj, vmin) != (3, 2): raise OggTheoraHeaderError("found Theora version %d.%d != 3.2" % (vmaj, vmin)) fps_num, fps_den = struct.unpack(">2I", data[22:30]) self.fps = fps_num / float(fps_den) self.bitrate = cdata.uint_be(b"\x00" + data[37:40]) self.granule_shift = (cdata.ushort_be(data[40:42]) >> 5) & 0x1F self.serial = page.serial
def __init__(self, fileobj): page = OggPage(fileobj) while not page.packets[0].startswith(b"OpusHead"): page = OggPage(fileobj) self.serial = page.serial if not page.first: raise OggOpusHeaderError( "page has ID header, but doesn't start a stream") (version, self.channels, pre_skip, orig_sample_rate, output_gain, channel_map) = struct.unpack("<BBHIhB", page.packets[0][8:19]) self.__pre_skip = pre_skip # only the higher 4 bits change on incombatible changes major = version >> 4 if major != 0: raise OggOpusHeaderError("version %r unsupported" % major)
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) self._padding = len(data) - self._size
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] super(OggSpeexVComment, self).__init__(data, framing=False) self._padding = len(data) - self._size
def _inject(self, fileobj, padding_func): fileobj.seek(0) info = OggOpusInfo(fileobj) old_pages = self.__get_comment_pages(fileobj, info) packets = OggPage.to_packets(old_pages) vcomment_data = b"OpusTags" + self.write(framing=False) if self._pad_data: # if we have padding data to preserver we can't add more padding # as long as we don't know the structure of what follows packets[0] = vcomment_data + self._pad_data else: content_size = get_size(fileobj) - len(packets[0]) # approx padding_left = len(packets[0]) - len(vcomment_data) info = PaddingInfo(padding_left, content_size) new_padding = info._get_padding(padding_func) packets[0] = vcomment_data + b"\x00" * new_padding new_pages = OggPage._from_packets_try_preserve(packets, old_pages) OggPage.replace(fileobj, old_pages, new_pages)
def __init__(self, fileobj, info): pages = self.__get_comment_pages(fileobj, info) data = OggPage.to_packets(pages)[0][8:] # Strip OpusTags fileobj = BytesIO(data) super(OggOpusVComment, self).__init__(fileobj, framing=False) self._padding = len(data) - self._size # in case the LSB of the first byte after v-comment is 1, preserve the # following data padding_flag = fileobj.read(1) if padding_flag and ord(padding_flag) & 0x1: self._pad_data = padding_flag + fileobj.read() self._padding = 0 # we have to preserve, so no padding else: self._pad_data = b""
def _inject(self, fileobj, padding_func): """Write tag data into the Speex comment packet/page.""" fileobj.seek(0) # Find the first header page, with the stream info. # Use it to get the serial number. page = OggPage(fileobj) while not page.packets[0].startswith(b"Speex "): page = OggPage(fileobj) # Look for the next page with that serial number, it'll start # the comment packet. serial = page.serial page = OggPage(fileobj) while page.serial != serial: page = OggPage(fileobj) # Then find all the pages with the comment packet. 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) content_size = get_size(fileobj) - len(packets[0]) # approx vcomment_data = self.write(framing=False) padding_left = len(packets[0]) - len(vcomment_data) info = PaddingInfo(padding_left, content_size) new_padding = info._get_padding(padding_func) # Set the new comment packet. packets[0] = vcomment_data + b"\x00" * new_padding new_pages = OggPage._from_packets_try_preserve(packets, old_pages) OggPage.replace(fileobj, old_pages, new_pages)
def _post_tags(self, fileobj): page = OggPage.find_last(fileobj, self.serial) self.length = (page.position - self.__pre_skip) / float(48000)
def _post_tags(self, fileobj): if self.length: return page = OggPage.find_last(fileobj, self.serial) self.length = page.position / float(self.sample_rate)
def _post_tags(self, fileobj): page = OggPage.find_last(fileobj, self.serial) self.length = page.position / float(self.sample_rate)
def _post_tags(self, fileobj): page = OggPage.find_last(fileobj, self.serial) position = page.position mask = (1 << self.granule_shift) - 1 frames = (position >> self.granule_shift) + (position & mask) self.length = frames / float(self.fps)