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 + bchr(rem)) lacing_data = b"".join(lacing_data) if not self.complete and lacing_data.endswith(b"\x00"): lacing_data = lacing_data[:-1] data.append(bchr(len(lacing_data))) data.append(lacing_data) data.extend(self.packets) data = b"".join(data) # Python's CRC is swapped relative to Ogg's needs. # crc32 returns uint prior to py2.6 on some platforms, so force uint crc = (~zlib.crc32(data.translate(cdata.bitswap), -1)) & 0xffffffff # Although we're using to_uint_be, this actually makes the CRC # a proper le integer, since Python's CRC is byteswapped. crc = cdata.to_uint_be(crc).translate(cdata.bitswap) data = data[:22] + crc + data[26:] return data
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(bchr(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(bchr(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()
def MakeID3v1(id3): """Return an ID3v1.1 tag string from a dict of ID3v2.4 frames.""" v1 = {} for v2id, name in { "TIT2": "title", "TPE1": "artist", "TALB": "album" }.items(): if v2id in id3: text = id3[v2id].text[0].encode('latin1', 'replace')[:30] else: text = b"" v1[name] = text + (b"\x00" * (30 - len(text))) if "COMM" in id3: cmnt = id3["COMM"].text[0].encode('latin1', 'replace')[:28] else: cmnt = b"" v1["comment"] = cmnt + (b"\x00" * (29 - len(cmnt))) if "TRCK" in id3: try: v1["track"] = bchr(+id3["TRCK"]) except ValueError: v1["track"] = b"\x00" else: v1["track"] = b"\x00" if "TCON" in id3: try: genre = id3["TCON"].genres[0] except IndexError: pass else: if genre in TCON.GENRES: v1["genre"] = bchr(TCON.GENRES.index(genre)) if "genre" not in v1: v1["genre"] = b"\xff" if "TDRC" in id3: year = str(id3["TDRC"]).encode('ascii') elif "TYER" in id3: year = str(id3["TYER"]).encode('ascii') else: year = b"" v1["year"] = (year + b"\x00\x00\x00\x00")[:4] return (b"TAG" + v1["title"] + v1["artist"] + v1["album"] + v1["year"] + v1["comment"] + v1["track"] + v1["genre"])
def __render_bool(self, key, value): return self.__render_data(key, 0, AtomDataType.INTEGER, [bchr(bool(value))])