示例#1
0
    def render_full(self, asf, fileobj, available, padding_func):
        # Render everything except padding
        num_objects = 0
        data = bytearray()
        for obj in self.objects:
            if obj.GUID == PaddingObject.GUID:
                continue
            data += obj.render(asf)
            num_objects += 1

        # calculate how much space we need at least
        padding_obj = PaddingObject()
        header_size = len(HeaderObject.GUID) + 14
        padding_overhead = len(padding_obj.render(asf))
        needed_size = len(data) + header_size + padding_overhead

        # ask the user for padding adjustments
        file_size = get_size(fileobj)
        content_size = file_size - available
        assert content_size >= 0
        info = PaddingInfo(available - needed_size, content_size)

        # add padding
        padding = info._get_padding(padding_func)
        padding_obj.parse(asf, b"\x00" * padding)
        data += padding_obj.render(asf)
        num_objects += 1

        data = (HeaderObject.GUID +
                struct.pack("<QL", len(data) + 30, num_objects) +
                b"\x01\x02" + data)

        return data
    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)
示例#3
0
    def render_full(self, asf, fileobj, available, padding_func):
        # Render everything except padding
        num_objects = 0
        data = bytearray()
        for obj in self.objects:
            if obj.GUID == PaddingObject.GUID:
                continue
            data += obj.render(asf)
            num_objects += 1

        # calculate how much space we need at least
        padding_obj = PaddingObject()
        header_size = len(HeaderObject.GUID) + 14
        padding_overhead = len(padding_obj.render(asf))
        needed_size = len(data) + header_size + padding_overhead

        # ask the user for padding adjustments
        file_size = get_size(fileobj)
        content_size = file_size - available
        assert content_size >= 0
        info = PaddingInfo(available - needed_size, content_size)

        # add padding
        padding = info._get_padding(padding_func)
        padding_obj.parse(asf, b"\x00" * padding)
        data += padding_obj.render(asf)
        num_objects += 1

        data = (HeaderObject.GUID + struct.pack("<QL",
                                                len(data) + 30, num_objects) +
                b"\x01\x02" + data)

        return data
示例#4
0
    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 _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)
示例#6
0
    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 _prepare_data(self, fileobj, start, available, v2_version, v23_sep,
                      pad_func):
        if v2_version == 3:
            version = ID3Header._V23
        elif v2_version == 4:
            version = ID3Header._V24
        else:
            raise ValueError("Only 3 or 4 allowed for v2_version")

        # Sort frames by 'importance'
        order = ["TIT2", "TPE1", "TRCK", "TALB", "TPOS", "TDRC", "TCON"]
        order = dict((b, a) for a, b in enumerate(order))
        last = len(order)
        frames = sorted(self.items(),
                        key=lambda a: (order.get(a[0][:4], last), a[0]))

        framedata = [
            self.__save_frame(frame, version=version, v23_sep=v23_sep)
            for (key, frame) in frames
        ]

        # only write unknown frames if they were loaded from the version
        # we are saving with or upgraded to it
        if self.__unknown_version == version[:2]:
            framedata.extend(data for data in self.unknown_frames
                             if len(data) > 10)

        needed = sum(map(len, framedata)) + 10

        fileobj.seek(0, 2)
        trailing_size = fileobj.tell() - start

        info = PaddingInfo(available - needed, trailing_size)
        new_padding = info._get_padding(pad_func)
        if new_padding < 0:
            raise error("invalid padding")
        new_size = needed + new_padding

        new_framesize = BitPaddedInt.to_str(new_size - 10, width=4)
        header = pack('>3sBBB4s', b'ID3', v2_version, 0, 0, new_framesize)

        data = bytearray(header)
        for frame in framedata:
            data += frame
        assert new_size >= len(data)
        data += (new_size - len(data)) * b'\x00'
        assert new_size == len(data)

        return data
示例#8
0
    def _prepare_data(self, fileobj, start, available, v2_version, v23_sep,
                      pad_func):
        if v2_version == 3:
            version = ID3Header._V23
        elif v2_version == 4:
            version = ID3Header._V24
        else:
            raise ValueError("Only 3 or 4 allowed for v2_version")

        # Sort frames by 'importance'
        order = ["TIT2", "TPE1", "TRCK", "TALB", "TPOS", "TDRC", "TCON"]
        order = dict((b, a) for a, b in enumerate(order))
        last = len(order)
        frames = sorted(self.items(),
                        key=lambda a: (order.get(a[0][:4], last), a[0]))

        framedata = [self.__save_frame(frame, version=version, v23_sep=v23_sep)
                     for (key, frame) in frames]

        # only write unknown frames if they were loaded from the version
        # we are saving with or upgraded to it
        if self.__unknown_version == version[:2]:
            framedata.extend(data for data in self.unknown_frames
                             if len(data) > 10)

        needed = sum(map(len, framedata)) + 10

        fileobj.seek(0, 2)
        trailing_size = fileobj.tell() - start

        info = PaddingInfo(available - needed, trailing_size)
        new_padding = info._get_padding(pad_func)
        if new_padding < 0:
            raise error("invalid padding")
        new_size = needed + new_padding

        new_framesize = BitPaddedInt.to_str(new_size - 10, width=4)
        header = pack('>3sBBB4s', b'ID3', v2_version, 0, 0, new_framesize)

        data = bytearray(header)
        for frame in framedata:
            data += frame
        assert new_size >= len(data)
        data += (new_size - len(data)) * b'\x00'
        assert new_size == len(data)

        return data
    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)
示例#10
0
    def _writeblocks(cls, blocks, available, cont_size, padding_func):
        """Render metadata block as a byte string."""

        # write everything except padding
        data = bytearray()
        for block in blocks:
            if isinstance(block, Padding):
                continue
            data += cls._writeblock(block)
        blockssize = len(data)

        # take the padding overhead into account. we always add one
        # to make things simple.
        padding_block = Padding()
        blockssize += len(cls._writeblock(padding_block))

        # finally add a padding block
        info = PaddingInfo(available - blockssize, cont_size)
        padding_block.length = min(info._get_padding(padding_func),
                                   cls._MAX_SIZE)
        data += cls._writeblock(padding_block, is_last=True)

        return data
示例#11
0
    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)