示例#1
0
 def __render_freeform(self, key, value):
     if isinstance(value, text_type):
         value = value.encode('utf-8')
     dummy, mean, name = key.split(b":", 2)
     mean = struct_pack(">I4sI", len(mean) + 12, b"mean", 0) + mean
     name = struct_pack(">I4sI", len(name) + 12, b"name", 0) + name
     value = struct_pack(">I4s2I", len(value) + 16, b"data", 0x1, 0) + value
     return Atom.render("----", mean + name + value)
示例#2
0
文件: asf.py 项目: mattbun/sift
 def render(self, asf):
     def render_text(name):
         value = asf.tags.get(name, [])
         if value:
             return value[0].encode("utf-16-le") + b"\x00\x00"
         else:
             return b""
     texts = list(map(render_text, _standard_attribute_names))
     data = struct_pack("<HHHHH", *map(len, texts)) + b"".join(texts)
     return self.GUID + struct_pack("<Q", 24 + len(data)) + data
示例#3
0
文件: mp4.py 项目: mattbun/sift
 def render(name, data):
     """Render raw atom data."""
     # this raises OverflowError if Py_ssize_t can't handle the atom data
     size = len(data) + 8
     if isinstance(name, text_type):
         name = name.encode('UTF-8')
     if size <= 0xFFFFFFFF:
         return struct_pack(">I4s", size, name) + data
     else:
         return struct_pack(">I4sQ", 1, name, size + 8) + data
示例#4
0
文件: mp4.py 项目: mattbun/sift
 def __render_freeform(self, key, value):
     if isinstance(key, text_type):
         key = key.encode()
     dummy, mean, name = key.split(b":", 2)
     mean = struct_pack(">I4sI", len(mean) + 12, b"mean", 0) + mean
     name = struct_pack(">I4sI", len(name) + 12, b"name", 0) + name
     if isinstance(value, byte_types):
         value = [value]
     return Atom.render(b"----", mean + name + bytearray().join([
         struct_pack(">I4s2I", len(data) + 16, b"data", 1, 0) + data
         for data in value]))
示例#5
0
 def write(self):
     f = BytesIO()
     mime = self.mime.encode('UTF-8')
     f.write(struct_pack('>2I', self.type, len(mime)))
     f.write(mime)
     desc = self.desc.encode('UTF-8')
     f.write(struct_pack('>I', len(desc)))
     f.write(desc)
     f.write(struct_pack('>5I', self.width, self.height, self.depth,
                         self.colors, len(self.data)))
     f.write(self.data)
     return f.getvalue()
示例#6
0
文件: flac.py 项目: mattbun/sift
 def write(self):
     f = BytesIO()
     mime = self.mime.encode('UTF-8')
     f.write(struct_pack('>2I', self.type, len(mime)))
     f.write(mime)
     desc = self.desc.encode('UTF-8')
     f.write(struct_pack('>I', len(desc)))
     f.write(desc)
     f.write(
         struct_pack('>5I', self.width, self.height, self.depth,
                     self.colors, len(self.data)))
     f.write(self.data)
     return f.getvalue()
示例#7
0
文件: ogg.py 项目: Sophist-UK/mutagen
    def write(self):
        """Return a string encoding of the page header and data.

        A ValueError is raised if the data is too big to fit in a
        single page.
        """

        data = [
            struct_pack("<4sBBqIIi", b"OggS", self.version, self.__type_flags,
                        self.position, self.serial, self.sequence, 0)
            ]

        lacing_data = []
        for datum in self.packets:
            quot, rem = divmod(len(datum), 255)
            lacing_data.append(b"\xff" * quot + bytearray([rem]))
        lacing_data = bytearray().join(lacing_data)
        if not self.complete and lacing_data.endswith(b"\x00"):
            lacing_data = lacing_data[:-1]
        data.append(bytearray([len(lacing_data)]))
        data.append(lacing_data)
        data.extend(self.packets)
        data = bytearray().join(data)

        # Python's CRC is swapped relative to Ogg's needs.
        crc = zlib.crc32(buffer(data.translate(cdata.bitswap)), -1) & 0xffffffff
        crc = ((crc & 0x80000000) <<1) - crc - 1
        # Although we're using to_int_be, this actually makes the CRC
        # a proper le integer, since Python's CRC is byteswapped.
        crc = cdata.to_int_be(crc).translate(cdata.bitswap)
        data = data[:22] + crc + data[26:]
        return data
示例#8
0
    def _inject(self, fileobj):
        """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()
        data = bytearray([packets[0][0]]) + 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)
示例#9
0
    def write(self):
        """Return a string encoding of the page header and data.

        A ValueError is raised if the data is too big to fit in a
        single page.
        """

        data = [
            struct_pack("<4sBBqIIi", b"OggS", self.version, self.__type_flags,
                        self.position, self.serial, self.sequence, 0)
        ]

        lacing_data = []
        for datum in self.packets:
            quot, rem = divmod(len(datum), 255)
            lacing_data.append(b"\xff" * quot + bytearray([rem]))
        lacing_data = bytearray().join(lacing_data)
        if not self.complete and lacing_data.endswith(b"\x00"):
            lacing_data = lacing_data[:-1]
        data.append(bytearray([len(lacing_data)]))
        data.append(lacing_data)
        data.extend(self.packets)
        data = bytearray().join(data)

        # Python's CRC is swapped relative to Ogg's needs.
        crc = zlib.crc32(buffer(data.translate(cdata.bitswap)),
                         -1) & 0xffffffff
        crc = ((crc & 0x80000000) << 1) - crc - 1
        # Although we're using to_int_be, this actually makes the CRC
        # a proper le integer, since Python's CRC is byteswapped.
        crc = cdata.to_int_be(crc).translate(cdata.bitswap)
        data = data[:22] + crc + data[26:]
        return data
示例#10
0
    def _inject(self, fileobj):
        """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()
        data = bytearray([packets[0][0]]) + 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)
示例#11
0
 def __render_cover(self, key, value):
     try: imageformat = value.imageformat
     except AttributeError: imageformat = M4ACover.FORMAT_JPEG
     if isinstance(value, text_type):
         value = value.encode('utf-8')
     data = Atom.render("data", struct_pack(">2I", imageformat, 0) + value)
     return Atom.render(key, data)
示例#12
0
 def __render_pair_no_trailing(self, key, value):
     track, total = value
     if 0 <= track < 1 << 16 and 0 <= total < 1 << 16:
         data = struct_pack(">3H", 0, track, total)
         return self.__render_data(key, 0, data)
     else:
         raise M4AMetadataValueError("invalid numeric pair %r" % (value,))
示例#13
0
 def write(self):
     f = BytesIO()
     for seekpoint in self.seekpoints:
         packed = struct_pack(self.__SEEKPOINT_FORMAT,
             seekpoint.first_sample, seekpoint.byte_offset,
             seekpoint.num_samples)
         f.write(packed)
     return f.getvalue()
示例#14
0
文件: flac.py 项目: mattbun/sift
 def write(self):
     f = BytesIO()
     for seekpoint in self.seekpoints:
         packed = struct_pack(self.__SEEKPOINT_FORMAT,
                              seekpoint.first_sample, seekpoint.byte_offset,
                              seekpoint.num_samples)
         f.write(packed)
     return f.getvalue()
示例#15
0
文件: asf.py 项目: mattbun/sift
 def render_ml(self, name):
     name = name.encode("utf-16-le") + b"\x00\x00"
     if self.TYPE == 2:
         data = self._render(dword=False)
     else:
         data = self._render()
     return (struct_pack("<HHHHI", self.language or 0, self.stream or 0,
                         len(name), self.TYPE, len(data)) + name + data)
示例#16
0
文件: mp4.py 项目: mattbun/sift
 def __render_cover(self, key, value):
     atom_data = []
     for cover in value:
         try: imageformat = cover.imageformat
         except AttributeError: imageformat = MP4Cover.FORMAT_JPEG
         atom_data.append(
             Atom.render(b"data", struct_pack(">2I", imageformat, 0) + cover))
     return Atom.render(key, b"".join(atom_data))
示例#17
0
文件: asf.py 项目: mattbun/sift
    def save(self):
        # Move attributes to the right objects
        self.to_extended_content_description = {}
        self.to_metadata = {}
        self.to_metadata_library = []
        for name, value in self.tags:
            if name in _standard_attribute_names:
                continue
            large_value = value.data_size() > 0xFFFF
            if (value.language is None and value.stream is None and
                name not in self.to_extended_content_description and
                not large_value):
                self.to_extended_content_description[name] = value
            elif (value.language is None and value.stream is not None and
                  name not in self.to_metadata and not large_value):
                self.to_metadata[name] = value
            else:
                self.to_metadata_library.append((name, value))

        # Add missing objects
        if not self.content_description_obj:
            self.content_description_obj = \
                ContentDescriptionObject()
            self.objects.append(self.content_description_obj)
        if not self.extended_content_description_obj:
            self.extended_content_description_obj = \
                ExtendedContentDescriptionObject()
            self.objects.append(self.extended_content_description_obj)
        if not self.header_extension_obj:
            self.header_extension_obj = \
                HeaderExtensionObject()
            self.objects.append(self.header_extension_obj)
        if not self.metadata_obj:
            self.metadata_obj = \
                MetadataObject()
            self.header_extension_obj.objects.append(self.metadata_obj)
        if not self.metadata_library_obj:
            self.metadata_library_obj = \
                MetadataLibraryObject()
            self.header_extension_obj.objects.append(self.metadata_library_obj)

        # Render the header
        data = b"".join([obj.render(self) for obj in self.objects])
        data = (HeaderObject.GUID +
                struct_pack("<QL", len(data) + 30, len(self.objects)) +
                b"\x01\x02" + data)

        fileobj = open(self.filename, "rb+")
        try:
            size = len(data)
            if size > self.size:
                insert_bytes(fileobj, size - self.size, self.size)
            if size < self.size:
                delete_bytes(fileobj, self.size - size, 0)
            fileobj.seek(0)
            fileobj.write(data)
        finally:
            fileobj.close()
示例#18
0
文件: flac.py 项目: mattbun/sift
    def write(self):
        f = BytesIO()
        f.write(struct_pack(">I", self.min_blocksize)[-2:])
        f.write(struct_pack(">I", self.max_blocksize)[-2:])
        f.write(struct_pack(">I", self.min_framesize)[-3:])
        f.write(struct_pack(">I", self.max_framesize)[-3:])

        # first 16 bits of sample rate
        f.write(struct_pack(">I", self.sample_rate >> 4)[-2:])
        # 4 bits sample, 3 channel, 1 bps
        byte = (self.sample_rate & 0xF) << 4
        byte += ((self.channels - 1) & 7) << 1
        byte += ((self.bits_per_sample - 1) >> 4) & 1
        f.write(bytearray([byte]))
        # 4 bits of bps, 4 of sample count
        byte = ((self.bits_per_sample - 1) & 0xF) << 4
        byte += (self.total_samples >> 32) & 0xF
        f.write(bytearray([byte]))
        # last 32 of sample count
        f.write(struct_pack(">I", self.total_samples & 0xFFFFFFFF))
        # MD5 signature
        sig = self.md5_signature
        f.write(
            struct_pack(">4I", (sig >> 96) & 0xFFFFFFFF,
                        (sig >> 64) & 0xFFFFFFFF, (sig >> 32) & 0xFFFFFFFF,
                        sig & 0xFFFFFFFF))
        return f.getvalue()
示例#19
0
    def write(self):
        f = BytesIO()
        f.write(struct_pack(">I", self.min_blocksize)[-2:])
        f.write(struct_pack(">I", self.max_blocksize)[-2:])
        f.write(struct_pack(">I", self.min_framesize)[-3:])
        f.write(struct_pack(">I", self.max_framesize)[-3:])

        # first 16 bits of sample rate
        f.write(struct_pack(">I", self.sample_rate >> 4)[-2:])
        # 4 bits sample, 3 channel, 1 bps
        byte = (self.sample_rate & 0xF) << 4
        byte += ((self.channels - 1) & 7) << 1
        byte += ((self.bits_per_sample - 1) >> 4) & 1
        f.write(bytearray([byte]))
        # 4 bits of bps, 4 of sample count
        byte = ((self.bits_per_sample - 1) & 0xF)  << 4
        byte += (self.total_samples >> 32) & 0xF
        f.write(bytearray([byte]))
        # last 32 of sample count
        f.write(struct_pack(">I", self.total_samples & 0xFFFFFFFF))
        # MD5 signature
        sig = self.md5_signature
        f.write(struct_pack(
            ">4I", (sig >> 96) & 0xFFFFFFFF, (sig >> 64) & 0xFFFFFFFF,
            (sig >> 32) & 0xFFFFFFFF, sig & 0xFFFFFFFF))
        return f.getvalue()
示例#20
0
文件: mp4.py 项目: mattbun/sift
 def __render_pair_no_trailing(self, key, value):
     data = []
     for (track, total) in value:
         if 0 <= track < 1 << 16 and 0 <= total < 1 << 16:
             data.append(struct_pack(">3H", 0, track, total))
         else:
             raise MP4MetadataValueError(
                 "invalid numeric pair %r" % ((track, total),))
     return self.__render_data(key, 0, data)
示例#21
0
    def save(self, filename=None):
        """Save changes to a file.

        If no filename is given, the one most recently loaded is used.

        Tags are always written at the end of the file, and include
        a header and a footer.
        """

        filename = filename or self.filename
        try:
            fileobj = open(filename, "r+b")
        except IOError:
            fileobj = open(filename, "w+b")
        data = _APEv2Data(fileobj)

        if data.is_at_start:
            delete_bytes(fileobj, data.end - data.start, data.start)
        elif data.start is not None:
            fileobj.seek(data.start)
            # Delete an ID3v1 tag if present, too.
            fileobj.truncate()
        fileobj.seek(0, 2)

        # "APE tags items should be sorted ascending by size... This is
        # not a MUST, but STRONGLY recommended. Actually the items should
        # be sorted by importance/byte, but this is not feasible."
        tags = sorted((v._internal(k) for k, v in list(self.items())), key=len)
        num_tags = len(tags)
        tags = bytearray().join(tags)

        # tag string, version, tag size, item count, flags
        header = struct_pack("<8s 4I 8x", b"APETAGEX", 2000, len(tags)+32,
                             num_tags, HAS_HEADER|IS_HEADER)
        fileobj.write(header)

        fileobj.write(tags)

        # tag string, version, tag size, item count, flags
        footer = struct_pack("<8s 4I 8x", b"APETAGEX", 2000, len(tags) + 32,
                             num_tags, HAS_HEADER)
        fileobj.write(footer)
        fileobj.close()
示例#22
0
文件: apev2.py 项目: mattbun/sift
    def save(self, filename=None):
        """Save changes to a file.

        If no filename is given, the one most recently loaded is used.

        Tags are always written at the end of the file, and include
        a header and a footer.
        """

        filename = filename or self.filename
        try:
            fileobj = open(filename, "r+b")
        except IOError:
            fileobj = open(filename, "w+b")
        data = _APEv2Data(fileobj)

        if data.is_at_start:
            delete_bytes(fileobj, data.end - data.start, data.start)
        elif data.start is not None:
            fileobj.seek(data.start)
            # Delete an ID3v1 tag if present, too.
            fileobj.truncate()
        fileobj.seek(0, 2)

        # "APE tags items should be sorted ascending by size... This is
        # not a MUST, but STRONGLY recommended. Actually the items should
        # be sorted by importance/byte, but this is not feasible."
        tags = sorted((v._internal(k) for k, v in list(self.items())), key=len)
        num_tags = len(tags)
        tags = bytearray().join(tags)

        # tag string, version, tag size, item count, flags
        header = struct_pack("<8s 4I 8x", b"APETAGEX", 2000,
                             len(tags) + 32, num_tags, HAS_HEADER | IS_HEADER)
        fileobj.write(header)

        fileobj.write(tags)

        # tag string, version, tag size, item count, flags
        footer = struct_pack("<8s 4I 8x", b"APETAGEX", 2000,
                             len(tags) + 32, num_tags, HAS_HEADER)
        fileobj.write(footer)
        fileobj.close()
示例#23
0
文件: mp4.py 项目: mattbun/sift
 def __update_offset_table(self, fileobj, fmt, atom, delta, offset):
     """Update offset table in the specified atom."""
     if atom.offset > offset:
         atom.offset += delta
     fileobj.seek(atom.offset + 12)
     data = fileobj.read(atom.length - 12)
     fmt = fmt % cdata.uint_be(data[:4])
     offsets = struct_unpack(fmt, data[4:])
     offsets = [o + (0, delta)[offset < o] for o in offsets]
     fileobj.seek(atom.offset + 16)
     fileobj.write(struct_pack(fmt, *offsets))
示例#24
0
 def writeblocks(blocks):
     """Render metadata block as a byte string."""
     data = []
     codes = [[block.code, block.write()] for block in blocks]
     codes[-1][0] |= 128
     for code, datum in codes:
         byte = bytearray([code])
         if len(datum) > 2**24:
             raise error("block is too long to write")
         length = struct_pack(">I", len(datum))[-3:]
         data.append(byte + length + datum)
     return bytearray().join(data)
示例#25
0
文件: flac.py 项目: mattbun/sift
 def writeblocks(blocks):
     """Render metadata block as a byte string."""
     data = []
     codes = [[block.code, block.write()] for block in blocks]
     codes[-1][0] |= 128
     for code, datum in codes:
         byte = bytearray([code])
         if len(datum) > 2**24:
             raise error("block is too long to write")
         length = struct_pack(">I", len(datum))[-3:]
         data.append(byte + length + datum)
     return bytearray().join(data)
示例#26
0
文件: flac.py 项目: mattbun/sift
 def write(self):
     f = BytesIO()
     flags = 0
     if self.compact_disc: flags |= 0x80
     packed = struct_pack(self.__CUESHEET_FORMAT, self.media_catalog_number,
                          self.lead_in_samples, flags, len(self.tracks))
     f.write(packed)
     for track in self.tracks:
         track_flags = 0
         track_flags |= (track.type & 1) << 7
         if track.pre_emphasis: track_flags |= 0x40
         track_packed = struct_pack(self.__CUESHEET_TRACK_FORMAT,
                                    track.start_offset, track.track_number,
                                    track.isrc, track_flags,
                                    len(track.indexes))
         f.write(track_packed)
         for index in track.indexes:
             index_packed = struct_pack(self.__CUESHEET_TRACKINDEX_FORMAT,
                                        index.index_offset,
                                        index.index_number)
             f.write(index_packed)
     return f.getvalue()
示例#27
0
 def write(self):
     f = BytesIO()
     flags = 0
     if self.compact_disc: flags |= 0x80
     packed = struct_pack(
         self.__CUESHEET_FORMAT, self.media_catalog_number,
         self.lead_in_samples, flags, len(self.tracks))
     f.write(packed)
     for track in self.tracks:
         track_flags = 0
         track_flags |= (track.type & 1) << 7
         if track.pre_emphasis: track_flags |= 0x40
         track_packed = struct_pack(
             self.__CUESHEET_TRACK_FORMAT, track.start_offset,
             track.track_number, track.isrc, track_flags,
             len(track.indexes))
         f.write(track_packed)
         for index in track.indexes:
             index_packed = struct_pack(
                 self.__CUESHEET_TRACKINDEX_FORMAT,
                 index.index_offset, index.index_number)
             f.write(index_packed)
     return f.getvalue()
示例#28
0
文件: asf.py 项目: mattbun/sift
 def render(self, asf):
     attrs = list(asf.to_extended_content_description.items())
     data = b"".join([attr.render(name) for (name, attr) in attrs])
     data = struct_pack("<QH", 26 + len(data), len(attrs)) + data
     return self.GUID + data
示例#29
0
文件: asf.py 项目: mattbun/sift
 def render(self, name):
     name = name.encode("utf-16-le") + b"\x00\x00"
     data = self._render()
     return (struct_pack("<H", len(name)) + name +
             struct_pack("<HH", self.TYPE, len(data)) + data)
示例#30
0
 def _internal(self, key):
     if isinstance(key, text_type):
         key = key.encode('utf-8')
     return struct_pack("<2I", len(self.value), self.kind << 1) + \
         key + b"\0" + self.value
示例#31
0
文件: mp4.py 项目: mattbun/sift
 def __render_data(self, key, flags, value):
     return Atom.render(key, bytearray().join([
         Atom.render(b"data", struct_pack(">2I", flags, 0) + data)
         for data in value]))
示例#32
0
文件: asf.py 项目: mattbun/sift
 def _render(self, dword=True):
     if dword:
         return struct_pack("<I", int(self.value))
     else:
         return struct_pack("<H", int(self.value))
示例#33
0
文件: asf.py 项目: mattbun/sift
 def _render(self):
     return struct_pack("<H", self.value)
示例#34
0
文件: asf.py 项目: mattbun/sift
 def render(self, asf):
     data = self.GUID + struct_pack("<Q", len(self.data) + 24) + self.data
     return data
示例#35
0
文件: asf.py 项目: mattbun/sift
 def render(self, asf):
     data = b"".join([obj.render(asf) for obj in self.objects])
     return (self.GUID + struct_pack("<Q", 24 + 16 + 6 + len(data)) +
             b"\x11\xD2\xD3\xAB\xBA\xA9\xcf\x11" +
             b"\x8E\xE6\x00\xC0\x0C\x20\x53\x65" +
             b"\x06\x00" + struct_pack("<I", len(data)) + data)
示例#36
0
文件: asf.py 项目: mattbun/sift
 def render(self, asf):
     attrs = list(asf.to_metadata.items())
     data = b"".join([attr.render_m(name) for (name, attr) in attrs])
     return (self.GUID + struct_pack("<QH", 26 + len(data), len(attrs)) +
             data)
示例#37
0
文件: asf.py 项目: mattbun/sift
 def render(self, asf):
     attrs = asf.to_metadata_library
     data = b"".join([attr.render_ml(name) for (name, attr) in attrs])
     return (self.GUID + struct_pack("<QH", 26 + len(data), len(attrs)) +
             data)
示例#38
0
文件: apev2.py 项目: mattbun/sift
 def _internal(self, key):
     if isinstance(key, text_type):
         key = key.encode('utf-8')
     return struct_pack("<2I", len(self.value), self.kind << 1) + \
         key + b"\0" + self.value
示例#39
0
 def __render_data(self, key, flags, data):
     data = struct_pack(">2I", flags, 0) + data
     return Atom.render(key, Atom.render("data", data))