def add_image(self, image): if (image.type == 0): self['Cover Art (front)'] = self.ITEM.external( 'Cover Art (front)', construct.CString(None).build( image.description.encode('utf-8', 'replace')) + image.data) elif (image.type == 1): self['Cover Art (back)'] = self.ITEM.binary( 'Cover Art (back)', construct.CString(None).build( image.description.encode('utf-8', 'replace')) + image.data)
def l_tag_value(cls, file, tag): subtype = {1:construct.Byte("data"), 2:construct.CString("data"), 3:construct.ULInt16("data"), 4:construct.ULInt32("data"), 5:construct.Struct("data", construct.ULInt32("high"), construct.ULInt32("low"))}[tag.type] data = construct.StrictRepeater(tag.count, subtype) if ((tag.type != 2) and (data.sizeof() <= 4)): return tag.offset else: file.seek(tag.offset,0) return data.parse_stream(file)
class ApeTagItem: APEv2_FLAGS = construct.BitStruct("APEv2_FLAGS", construct.Bits("undefined1", 5), construct.Flag("read_only"), construct.Bits("encoding", 2), construct.Bits("undefined2", 16), construct.Flag("contains_header"), construct.Flag("contains_no_footer"), construct.Flag("is_header"), construct.Bits("undefined3", 5)) APEv2_TAG = construct.Struct( "APEv2_TAG", construct.ULInt32("length"), construct.Embed(APEv2_FLAGS), construct.CString("key"), construct.MetaField("value", lambda ctx: ctx["length"])) #item_type is an int (0 = UTF-8, 1 = binary, 2 = external, 3 = reserved) #read_only is a boolean, True if the item is read only #key is an ASCII string #data is a binary string of the data itself def __init__(self, item_type, read_only, key, data): self.type = item_type self.read_only = read_only self.key = key self.data = data def __repr__(self): return "ApeTagItem(%s,%s,%s,%s)" % \ (repr(self.type), repr(self.read_only), repr(self.key), repr(self.data)) def __str__(self): return self.data def __unicode__(self): return self.data.rstrip(chr(0)).decode('utf-8', 'replace') def build(self): return self.APEv2_TAG.build( construct.Container(key=self.key, value=self.data, length=len(self.data), encoding=self.type, undefined1=0, undefined2=0, undefined3=0, read_only=self.read_only, contains_header=False, contains_no_footer=False, is_header=False)) #takes an ASCII key and string of binary data #returns an ApeTagItem of that data @classmethod def binary(cls, key, data): return cls(1, False, key, data) #takes an ASCII key and string of binary data #returns an ApeTagItem of that data @classmethod def external(cls, key, data): return cls(2, False, key, data) #takes an ASCII key and a unicode string of data #returns an ApeTagItem of that data @classmethod def string(cls, key, data): return cls(0, False, key, data.encode('utf-8', 'replace'))
def __parse_image__(self, key, type): data = cStringIO.StringIO(str(self[key])) description = construct.CString(None).parse_stream(data).decode( 'utf-8', 'replace') data = data.read() return Image.new(data, description, type)