XML_TAG_INFO = { 'image': 'Bins Image Description', 'freevo': 'Freevo XML Definition' } class XMLInfo(mediainfo.MediaInfo): def __init__(self,file): mediainfo.MediaInfo.__init__(self) self.valid = 0 if not file.name.endswith('.xml') and not file.name.endswith('.fxd'): return self.mime = 'text/xml' self.type = '' try: parser = qp_xml.Parser() tree = parser.parse(file) except: return 0 if tree.name in XML_TAG_INFO: self.type = XML_TAG_INFO[tree.name] else: self.type = 'XML file' self.valid = 1 mmpython.registertype( 'text/xml', ('xml', 'fxd'), mediainfo.TYPE_MISC, XMLInfo )
tags = [] size = 4 # Length of 'INFO' # Build String List and compute req. size for key in hash.keys(): tag = self.buildTag(key, hash[key]) if (len(tag)) % 2 == 1: tag += '\0' tags.append(tag) size += len(tag) _print("Tag [%i]: %s" % (len(tag), tag)) if self.infoStart != None: _print("Infostart found. %i" % (self.infoStart)) # Read current info size file.seek(self.infoStart, 0) s = file.read(12) (list, oldsize, info) = struct.unpack('<4sI4s', s) self.junkSize += oldsize + 8 else: self.infoStart = self.junkStart _print("Infostart computed. %i" % (self.infoStart)) file.seek(self.infoStart, 0) if (size > self.junkSize - 8): raise "Too large" file.write("LIST" + struct.pack('<I', size) + "INFO") for tag in tags: file.write(tag) _print("Junksize %i" % (self.junkSize - size - 8)) file.write("JUNK" + struct.pack('<I', self.junkSize - size - 8)) mmpython.registertype('video/avi', ('avi', ), mediainfo.TYPE_AV, RiffInfo)
def _extractHeaderString(self,f): len = struct.unpack( '<I', f.read(4) )[0] return unicode(f.read(len), 'utf-8') def _calculateTrackLength(self,f): # seek to the end of the stream, to avoid scanning the whole file if (os.stat(f.name)[stat.ST_SIZE] > 20000): f.seek(os.stat(f.name)[stat.ST_SIZE]-10000) # read the rest of the file into a buffer h = f.read() granule_position = 0 # search for each 'OggS' in h if len(h): idx = h.rfind('OggS') if idx < 0: return 0 pageSize = 0 h = h[idx+4:] (check, type, granule_position, absPos, serial, pageN, crc, segs) = struct.unpack( '<BBIIIIIB', h[:23] ) if check != 0: _print(h[:10]) return _print("granule = %d / %d" % (granule_position, absPos)) # the last one is the one we are interested in return (granule_position / self.samplerate) mmpython.registertype( 'application/ogg', ('ogg',), mediainfo.TYPE_MUSIC, OggInfo )
f.close() if buffer.find('SVCD') > 0 and buffer.find('TRACKS.SVD') > 0 and \ buffer.find('ENTRIES.SVD') > 0: type = 'SVCD' elif buffer.find('INFO.VCD') > 0 and buffer.find('ENTRIES.VCD') > 0: type = 'VCD' else: return 0 counter = 0 while 1: buffer = file.readline() if not len(buffer): return 1 if buffer[:8] == ' TRACK ': counter += 1 # the first track is the directory, that doesn't count if counter > 1: vi = mediainfo.VideoInfo() if type == 'VCD': vi.codec = 'MPEG1' else: vi.codec = 'MPEG2' self.tracks.append(vi) mmpython.registertype( 'video/vcd', ('cue',), mediainfo.TYPE_AV, VCDInfo )
# with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # ----------------------------------------------------------------------- */ #endif from mmpython import mediainfo import mmpython from discinfo import DiscInfo class DataDiscInfo(DiscInfo): def __init__(self,device): DiscInfo.__init__(self) self.context = 'unknown' self.offset = 0 self.valid = self.isDisc(device) self.mime = 'unknown/unknown' self.type = 'CD' self.subtype = 'data' def isDisc(self, device): if DiscInfo.isDisc(self, device) != 2: return 0 return 1 mmpython.registertype( 'cd/unknown', mediainfo.EXTENSION_DEVICE, mediainfo.TYPE_NONE, DataDiscInfo )
pass elif atomtype == 'mdat': pos = file.tell() + atomsize - 8 # maybe there is data inside the mdat if ATOM_DEBUG: print 'parsing mdat' while self._readatom(file): pass if ATOM_DEBUG: print 'end of mdat' file.seek(pos, 0) else: if ATOM_DEBUG and not atomtype in ('wide', 'free'): print 'unhandled base atom %s' % atomtype # Skip unknown atoms try: file.seek(atomsize-8,1) except IOError: return 0 return atomsize mmpython.registertype( 'video/quicktime', ('mov', 'qt'), mediainfo.TYPE_AV, MovInfo ) # doc links: # [1] http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap4/chapter_5_section_2.html#//apple_ref/doc/uid/TP40000939-CH206-BBCBIICE
object.type = i.format_description if i.info.has_key('dpi'): object['dpi'] = '%sx%s' % i.info['dpi'] if DEBUG: for info in i.info: if not info == 'exif': print '%s: %s' % (info, i.info[info]) object.mode = i.mode if not object.height: object.width, object.height = i.size return 1 class ImageInfo(mediainfo.ImageInfo): def __init__(self,file): mediainfo.ImageInfo.__init__(self) self.mime = '' self.type = '' self.valid = add(file.name, self) mmpython.registertype( 'image/gif', ('gif',), mediainfo.TYPE_IMAGE, ImageInfo ) mmpython.registertype( 'image/bmp', ('bmp',), mediainfo.TYPE_IMAGE, ImageInfo )
(type_specific_len,) = struct.unpack('>I', s[pos:pos+4]) type_specific = s[pos+4:pos+4+type_specific_len] pos += 4+type_specific_len if mime[:5] == 'audio': ai = mediainfo.AudioInfo() ai.id = mdpr[0] ai.bitrate = mdpr[2] self.audio.append(ai) elif mime[:5] == 'video': vi = mediainfo.VideoInfo() vi.id = mdpr[0] vi.bitrate = mdpr[2] self.video.append(vi) else: _print("Unknown: %s" % mime) if object_id == 'CONT': pos = 0 (title_len,) = struct.unpack('>H', s[pos:pos+2]) self.title = s[2:title_len+2] pos += title_len+2 (author_len,) = struct.unpack('>H', s[pos:pos+2]) self.artist = s[pos+2:pos+author_len+2] pos += author_len+2 (copyright_len,) = struct.unpack('>H', s[pos:pos+2]) self.copyright = s[pos+2:pos+copyright_len+2] pos += copyright_len+2 (comment_len,) = struct.unpack('>H', s[pos:pos+2]) self.comment = s[pos+2:pos+comment_len+2] mmpython.registertype( 'video/real', ('rm', 'ra', 'ram'), mediainfo.TYPE_AV, RealInfo )
(first, last) = cdrom.toc_header(device) lmin = 0 lsec = 0 num = 0 for i in range(first, last + 2): if i == last + 1: min, sec, frames = cdrom.leadout(device) else: min, sec, frames = cdrom.toc_entry(device, i) if num: vi = mediainfo.VideoInfo() # XXX add more static information here, it's also possible # XXX to scan for more informations like fps # XXX Settings to MPEG1/2 is a wild guess, maybe the track # XXX isn't playable at all (e.g. the menu) if type == 'VCD': vi.codec = 'MPEG1' else: vi.codec = 'MPEG2' vi.length = (min-lmin) * 60 + (sec-lsec) self.tracks.append(vi) num += 1 lmin, lsec = min, sec device.close() return 1 mmpython.registertype( 'video/vcd', mediainfo.EXTENSION_DEVICE, mediainfo.TYPE_AV, VCDInfo )
iptc = IPTC.flatten(IPTC.parseiptc(file.read(1000))) elif tag == 0x0100: if value != 0: self.width = value else: self.width = offset elif tag == 0x0101: if value != 0: self.height = value else: self.height = offset else: ImageInfo.add(file.name, self) return if iptc: self.setitem( 'title', iptc, 517 ) self.setitem( 'date' , iptc, 567 ) self.setitem( 'comment', iptc, 617 ) self.setitem( 'keywords', iptc, 537 ) self.setitem( 'artist', iptc, 592 ) self.setitem( 'country', iptc, 612 ) self.setitem( 'caption', iptc, 632 ) self.appendtable('IPTC', iptc) ImageInfo.add(file.name, self) return mmpython.registertype( 'image/tiff', ('tif','tiff'), mediainfo.TYPE_IMAGE, TIFFInfo )
if i == last + 1: min, sec, frames = cdrom.leadout(device) else: min, sec, frames = cdrom.toc_entry(device, i) if num: self.tracks[num-1].length = (min-lmin)*60 + (sec-lsec) num += 1 lmin, lsec = min, sec device.close() # correct bad titles for the tracks, containing also the artist for t in self.tracks: if not self.artist or not t.title.startswith(self.artist): break else: for t in self.tracks: t.title = t.title[len(self.artist):].lstrip('/ \t-_') # correct bad titles for the tracks, containing also the title for t in self.tracks: if not self.title or not t.title.startswith(self.title): break else: for t in self.tracks: t.title = t.title[len(self.title):].lstrip('/ \t-_') return 1 mmpython.registertype( 'audio/cd', mediainfo.EXTENSION_DEVICE, mediainfo.TYPE_AUDIO, AudioDiscInfo )
f.close() if buffer.find('SVCD') > 0 and buffer.find('TRACKS.SVD') > 0 and \ buffer.find('ENTRIES.SVD') > 0: type = 'SVCD' elif buffer.find('INFO.VCD') > 0 and buffer.find('ENTRIES.VCD') > 0: type = 'VCD' else: return 0 counter = 0 while 1: buffer = file.readline() if not len(buffer): return 1 if buffer[:8] == ' TRACK ': counter += 1 # the first track is the directory, that doesn't count if counter > 1: vi = mediainfo.VideoInfo() if type == 'VCD': vi.codec = 'MPEG1' else: vi.codec = 'MPEG2' self.tracks.append(vi) mmpython.registertype('video/vcd', ('cue', ), mediainfo.TYPE_AV, VCDInfo)
lmin = 0 lsec = 0 num = 0 for i in range(first, last + 2): if i == last + 1: min, sec, frames = cdrom.leadout(device) else: min, sec, frames = cdrom.toc_entry(device, i) if num: vi = mediainfo.VideoInfo() # XXX add more static information here, it's also possible # XXX to scan for more informations like fps # XXX Settings to MPEG1/2 is a wild guess, maybe the track # XXX isn't playable at all (e.g. the menu) if type == 'VCD': vi.codec = 'MPEG1' else: vi.codec = 'MPEG2' vi.length = (min - lmin) * 60 + (sec - lsec) self.tracks.append(vi) num += 1 lmin, lsec = min, sec device.close() return 1 mmpython.registertype('video/vcd', mediainfo.EXTENSION_DEVICE, mediainfo.TYPE_AV, VCDInfo)
_print("Language: %d/%d: %s" % (i+1, count, idstring)) lang.append(idstring) pos += 1+idlen if len(lang) == 1: self.language = lang[0] else: self.language = tuple(lang) # TODO: Find the stream in self.audio and self.video and # set it there instead of here elif guid == GUIDS['ASF_Stream_Bitrate_Properties_Object']: (count,) = struct.unpack('<H', s[24:26]) pos = 26 for i in range(0,count): strno, avbitrate = struct.unpack('<HI', s[pos:pos+6]) strno &= 63 _print("Stream %d Bitrate: %d" % (strno, avbitrate)) # TODO: Find the stream in self.audio and self.video and # set it there instead of here else: # Just print the type: bfail = 1 for h in GUIDS.keys(): if GUIDS[h] == guid: _print("Unparsed %s [%d]" % (h,objsize)) bfail = 0 if bfail: _print("unknown: %s [%d]" % (self._printguid(guid), objsize)) return r mmpython.registertype( 'video/asf', ('asf','wmv','wma'), mediainfo.TYPE_AV, AsfInfo )
if buffer.find('VIDEO_TS') == -1 and \ buffer.find('VIDEO_TS.IFO') == -1 and \ buffer.find('OSTA UDF Compliant') == -1: return 0 ret = self.lsdvd(device) if not ret: # we are very sure this is a DVD, maybe the drive was not # ready, let's try again return self.lsdvd(device) return 1 if os.environ.has_key('LSDVD') and os.environ['LSDVD']: LSDVD_EXE = os.environ['LSDVD'] else: for path in os.environ['PATH'].split(':'): if os.path.isfile(os.path.join(path, 'lsdvd')): LSDVD_EXE = os.path.join(path, 'lsdvd') break else: if mediainfo.DEBUG: print 'ImportError: lsdvd not found' raise ImportError mmpython.registertype( 'video/dvd', mediainfo.EXTENSION_DEVICE, mediainfo.TYPE_AV, DVDInfo ) mmpython.registertype( 'video/dvd', mediainfo.EXTENSION_DIRECTORY, mediainfo.TYPE_AV, DVDInfo )
ai['language'] = 'en' try: elem = tabelem[MATROSKA_CODEC_ID] ai.codec = elem.get_data() except: ai.codec = "Unknown" try: ainfo = tabelem[MATROSKA_AUDIO_SETTINGS_ID] audtab = self.process_one_level(vinfo) ai.samplerate = unpack( '!f', audtab[MATROSKA_AUDIO_SAMPLERATE_ID].get_value())[0] ai.channels = audtab[MATROSKA_AUDIO_CHANNELS_ID].get_value() except: _print("No other info about audio track !!!") self.audio.append(ai) elif (mytype == MATROSKA_SUBTITLES_TRACK): try: elem = tabelem[MATROSKA_TRACK_LANGUAGE_ID] language = elem.get_data() _print("Subtitle language found : %s" % elem.get_data()) except: language = "en" # By default self.subtitles.append(language) #_print("Found %d elem for this track" % len(tabelem) ) mmpython.registertype('application/mkv', ( 'mkv', 'mka', ), mediainfo.TYPE_AV, MkvInfo)
self.bitrate = FRMSIZCOD[(info[1] & 0x3F) >> 1] * 1000 bsmod = info[2] & 0x7 channels = ACMOD[info[3] >> 5] acmod = info[3] >> 5 self.channels = ACMOD[acmod][1] bits = 0 if acmod & 0x01 and not acmod == 0x01: bits += 2 if acmod & 0x04: bits += 2 if acmod == 0x02: bits += 2 # info is now 5 bits of info[3] and all bits of info[4] ( == 13 bits) # 'bits' bits (0-6) bits are information we don't need, after that, # the bit we need is lfeon. info = (((info[3] & 0x1F) << 8) + info[4]) # now we create the mask we need (based on 'bits') # the bit number 13 - 'bits' is what we want to read for i in range(13 - bits - 1): info = info >> 1 if info & 1: # subwover self.channels += 1 self.valid = True self.codec = 'AC3' self.mime = 'audio/ac3' mmpython.registertype( 'audio/ac3', ('ac3',), mediainfo.TYPE_MUSIC, AC3Info )
(key, value) = data.split("\0") self.meta[key] = value _print("%s -> %s" % (key, value)) elif type == "zTXt": _print("Compressed Text found.") (data, crc) = struct.unpack(">%isI" % length, file.read(length + 4)) split = data.split("\0") key = split[0] value = "".join(split[1:]) compression = ord(value[0]) value = value[1:] if compression == 0: decompressed = zlib.decompress(value) _print("%s (Compressed %i) -> %s" % (key, compression, decompressed)) else: _print("%s has unknown Compression %c" % (key, compression)) self.meta[key] = value elif type == "iTXt": _print("International Text found.") (data, crc) = struct.unpack(">%isI" % length, file.read(length + 4)) (key, value) = data.split("\0") self.meta[key] = value _print("%s -> %s" % (key, value)) else: file.seek(length + 4, 1) _print("%s of length %d ignored." % (type, length)) return 1 mmpython.registertype("image/png", ("png",), mediainfo.TYPE_IMAGE, PNGInfo)
layer = (bytes >> 17) & 3 bitrate = (bytes >> 12) & 15 samplerate = (bytes >> 10) & 3 mode = (bytes >> 6) & 3 if mpeg_version == 0: self.version = 2.5 elif mpeg_version == 2: self.version = 2 elif mpeg_version == 3: self.version = 1 else: return if layer > 0: layer = 4 - layer else: return self.bitrate = _bitrates[mpeg_version & 1][layer - 1][bitrate] self.samplerate = _samplerates[mpeg_version][samplerate] if self.bitrate is None or self.samplerate is None: return self.mode = _modes[mode] self.keys.append('mode') mmpython.registertype( 'audio/mp3', ('mp3',), mediainfo.TYPE_MUSIC, eyeD3Info )
# with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # ----------------------------------------------------------------------- */ #endif from mmpython import mediainfo import mmpython from discinfo import DiscInfo class DataDiscInfo(DiscInfo): def __init__(self, device): DiscInfo.__init__(self) self.context = 'unknown' self.offset = 0 self.valid = self.isDisc(device) self.mime = 'unknown/unknown' self.type = 'CD' self.subtype = 'data' def isDisc(self, device): if DiscInfo.isDisc(self, device) != 2: return 0 return 1 mmpython.registertype('cd/unknown', mediainfo.EXTENSION_DEVICE, mediainfo.TYPE_NONE, DataDiscInfo)
pos += 4 + type_specific_len if mime[:5] == 'audio': ai = mediainfo.AudioInfo() ai.id = mdpr[0] ai.bitrate = mdpr[2] self.audio.append(ai) elif mime[:5] == 'video': vi = mediainfo.VideoInfo() vi.id = mdpr[0] vi.bitrate = mdpr[2] self.video.append(vi) else: _print("Unknown: %s" % mime) if object_id == 'CONT': pos = 0 (title_len, ) = struct.unpack('>H', s[pos:pos + 2]) self.title = s[2:title_len + 2] pos += title_len + 2 (author_len, ) = struct.unpack('>H', s[pos:pos + 2]) self.artist = s[pos + 2:pos + author_len + 2] pos += author_len + 2 (copyright_len, ) = struct.unpack('>H', s[pos:pos + 2]) self.copyright = s[pos + 2:pos + copyright_len + 2] pos += copyright_len + 2 (comment_len, ) = struct.unpack('>H', s[pos:pos + 2]) self.comment = s[pos + 2:pos + comment_len + 2] mmpython.registertype('video/real', ('rm', 'ra', 'ram'), mediainfo.TYPE_AV, RealInfo)
XML_TAG_INFO = { 'image': 'Bins Image Description', 'freevo': 'Freevo XML Definition' } class XMLInfo(mediainfo.MediaInfo): def __init__(self, file): mediainfo.MediaInfo.__init__(self) self.valid = 0 if not file.name.endswith('.xml') and not file.name.endswith('.fxd'): return self.mime = 'text/xml' self.type = '' try: parser = qp_xml.Parser() tree = parser.parse(file) except: return 0 if tree.name in XML_TAG_INFO: self.type = XML_TAG_INFO[tree.name] else: self.type = 'XML file' self.valid = 1 mmpython.registertype('text/xml', ('xml', 'fxd'), mediainfo.TYPE_MISC, XMLInfo)
self.title = header['TITLE'] if header.has_key('ALBUM'): self.album = header['ALBUM'] if header.has_key('ARTIST'): self.artist = header['ARTIST'] if header.has_key('COMMENT'): self.comment = header['COMMENT'] if header.has_key('DATE'): self.date = header['DATE'] if header.has_key('ENCODER'): self.encoder = header['ENCODER'] if header.has_key('TRACKNUMBER'): self.trackno = header['TRACKNUMBER'] self.appendtable('VORBISCOMMENT', header) elif type == 5: # CUESHEET pass else: # UNKNOWN TYPE pass if lastblock: break def _extractHeaderString(self,header): len = struct.unpack( '<I', header[:4] )[0] return (len+4,unicode(header[4:4+len], 'utf-8')) mmpython.registertype( 'application/flac', ('flac',), mediainfo.TYPE_MUSIC, FlacInfo )
self.type = 'audio' self.subtype = 'mp3' # grab any headers for a max of 10 lines linecnt = 0 tab = {} lines = fi.readlines(512) for linecnt in range(0, 11): icyline = lines[linecnt] icyline = icyline.rstrip('\r\n') if len(icyline) < 4: break cidx = icyline.find(':') if cidx != -1: # break on short line (ie. really should be a blank line) # strip leading and trailing whitespace tab[icyline[:cidx].strip()] = icyline[cidx + 2:].strip() if fi: fi.close() self.appendtable('ICY', tab) self.tag_map = {('ICY', 'en'): ICY_tags} # Copy Metadata from tables into the main set of attributes for k in self.tag_map.keys(): map( lambda x: self.setitem(x, self.gettable(k[0], k[1]), self. tag_map[k][x]), self.tag_map[k].keys()) self.bitrate = string.atoi(self.bitrate) * 1000 mmpython.registertype('text/plain', mediainfo.EXTENSION_STREAM, mediainfo.TYPE_MUSIC, WebRadioInfo)
# ----------------------------------------------------------------------- #endif import sndhdr from mmpython import mediainfo import mmpython class PCMInfo(mediainfo.AudioInfo): def _what(self,f): """Recognize sound headers""" h = f.read(512) for tf in sndhdr.tests: res = tf(h, f) if res: return res return None def __init__(self,file): mediainfo.AudioInfo.__init__(self) t = self._what(file) if t: (self.type, self.samplerate, self.channels, self.bitrate, self.samplebits) = t self.mime = "audio/%s" % self.type self.valid = 1 else: self.valid = 0 return mmpython.registertype( 'application/pcm', ('wav','aif','voc','au'), mediainfo.TYPE_AUDIO, PCMInfo )
self.valid = 1 if name == '\xa9ART': self.artist = data[8:] self.valid = 1 if name == '\xa9alb': self.album = data[8:] self.valid = 1 if name == 'trkn': # Fix this self.trackno = data self.valid = 1 if name == '\xa9day': self.year = data[8:] self.valid = 1 if name == '\xa9too': self.encoder = data[8:] self.valid = 1 return 0 def read(self, b, file): data = file.read(b) if len(data) < b: raise ValueError, "EOF" return data def readInt(self, file): return struct.unpack('>I', self.read(4, file))[0] mmpython.registertype( 'application/m4a', ('m4a',), mediainfo.TYPE_MUSIC, Mpeg4 )
elif (type == 'zTXt'): _print('Compressed Text found.') (data, crc) = struct.unpack('>%isI' % length, file.read(length + 4)) split = data.split('\0') key = split[0] value = "".join(split[1:]) compression = ord(value[0]) value = value[1:] if compression == 0: decompressed = zlib.decompress(value) _print("%s (Compressed %i) -> %s" % (key, compression, decompressed)) else: _print("%s has unknown Compression %c" % (key, compression)) self.meta[key] = value elif (type == 'iTXt'): _print('International Text found.') (data, crc) = struct.unpack('>%isI' % length, file.read(length + 4)) (key, value) = data.split('\0') self.meta[key] = value _print("%s -> %s" % (key, value)) else: file.seek(length + 4, 1) _print("%s of length %d ignored." % (type, length)) return 1 mmpython.registertype('image/png', ('png', ), mediainfo.TYPE_IMAGE, PNGInfo)
self.setitem('date', exif_info, 'Image DateTime', True) self.setitem('artist', exif_info, 'Image Artist', True) self.setitem('hardware', exif_info, 'Image Model', True) self.setitem('software', exif_info, 'Image Software', True) self.setitem('thumbnail', exif_info, 'JPEGThumbnail', True) self.appendtable('EXIF', exif_info) if iptc_info: self.setitem('title', iptc_info, 517, True) self.setitem('date', iptc_info, 567, True) self.setitem('comment', iptc_info, 617, True) self.setitem('keywords', iptc_info, 537, True) self.setitem('artist', iptc_info, 592, True) self.setitem('country', iptc_info, 612, True) self.setitem('caption', iptc_info, 632, True) self.appendtable('IPTC', iptc_info) if len(self.meta.keys()): self.appendtable('JPGMETA', self.meta) for key, value in self.meta.items(): if key.startswith('Thumb:') or key == 'Software': setattr(self, key, value) if not key in self.keys: self.keys.append(key) ImageInfo.add(file.name, self) return mmpython.registertype('image/jpeg', ('jpg', 'jpeg'), mediainfo.TYPE_IMAGE, JPGInfo)
# Set the info fields for tag in id3.tags.keys(): if tag == "TT2" or tag == "TIT2": self.title = id3.tags[tag] elif tag == "TP1" or tag == "TPE1": self.artist = id3.tags[tag] elif tag == "TRK" or tag == "TRCK": self.trackno = id3.tags[tag] elif tag == "TYE" or tag == "TYER": self.date = id3.tags[tag] elif tag == "COM" or tag == "COMM": self.comment = id3.tags[tag] elif tag == "TCM": self.composer = id3.tags[tag] elif tag == "TAL" or tag == "TALB": self.album = id3.tags[tag] elif tag == "TPA": self.disc = id3.tags[tag] elif tag == "TCO" or tag == "TCON": genre = self.genre = id3.tags[tag] if genre and genre[0] == "(" and genre[-1] == ")": try: self.info["genre"] = _genres[int(genre[1:-1])] except IndexError: self.info["genre"] = "" elif tag == "TEN" or tag == "TENC": self.encoder = id3.tags[tag] mmpython.registertype("audio/mp3", ("mp3",), mediainfo.TYPE_MUSIC, MP3Info)
size = 4 # Length of 'INFO' # Build String List and compute req. size for key in hash.keys(): tag = self.buildTag(key, hash[key]) if (len(tag)) % 2 == 1: tag += "\0" tags.append(tag) size += len(tag) _print("Tag [%i]: %s" % (len(tag), tag)) if self.infoStart != None: _print("Infostart found. %i" % (self.infoStart)) # Read current info size file.seek(self.infoStart, 0) s = file.read(12) (list, oldsize, info) = struct.unpack("<4sI4s", s) self.junkSize += oldsize + 8 else: self.infoStart = self.junkStart _print("Infostart computed. %i" % (self.infoStart)) file.seek(self.infoStart, 0) if size > self.junkSize - 8: raise "Too large" file.write("LIST" + struct.pack("<I", size) + "INFO") for tag in tags: file.write(tag) _print("Junksize %i" % (self.junkSize - size - 8)) file.write("JUNK" + struct.pack("<I", self.junkSize - size - 8)) mmpython.registertype("video/avi", ("avi",), mediainfo.TYPE_AV, RiffInfo)
pos += 1 + idlen if len(lang) == 1: self.language = lang[0] else: self.language = tuple(lang) # TODO: Find the stream in self.audio and self.video and # set it there instead of here elif guid == GUIDS['ASF_Stream_Bitrate_Properties_Object']: (count, ) = struct.unpack('<H', s[24:26]) pos = 26 for i in range(0, count): strno, avbitrate = struct.unpack('<HI', s[pos:pos + 6]) strno &= 63 _print("Stream %d Bitrate: %d" % (strno, avbitrate)) # TODO: Find the stream in self.audio and self.video and # set it there instead of here else: # Just print the type: bfail = 1 for h in GUIDS.keys(): if GUIDS[h] == guid: _print("Unparsed %s [%d]" % (h, objsize)) bfail = 0 if bfail: _print("unknown: %s [%d]" % (self._printguid(guid), objsize)) return r mmpython.registertype('video/asf', ('asf', 'wmv', 'wma'), mediainfo.TYPE_AV, AsfInfo)
elif htype[:5] == 'audio': streamheader = struct.unpack( STREAM_HEADER_AUDIO, header[9:struct.calcsize(STREAM_HEADER_AUDIO)+9] ) ai = mediainfo.AudioInfo() (type, ssize, timeunit, ai.samplerate, ai.length, buffersize, ai.bitrate, ai.channels, bloc, ai.bitrate) = streamheader self.samplerate = ai.samplerate _print("Samplerate %d" % self.samplerate) self.audio.append(ai) self.all_streams.append(ai) elif htype[:4] == 'text': subtitle = mediainfo.MediaInfo() subtitle.keys.append('language') subtitle.type = 'subtitle' subtitle.length = 0 self.all_streams.append(subtitle) else: _print("Unknown Header") def _extractHeaderString(self,header): len = struct.unpack( '<I', header[:4] )[0] try: return (len+4,unicode(header[4:4+len], 'utf-8')) except: return (len+4,None) mmpython.registertype( 'application/ogg', ('ogm', 'ogg',), mediainfo.TYPE_AV, OgmInfo )
seek_to = file.tell() file.close() return seek_to def __scan__(self): """ scan file for timestamps (may take a long time) """ if not hasattr(self, 'filename') or not hasattr(self, 'start'): return 0 file = open(self.filename) print 'scanning file...' while 1: file.seek(self.__seek_size__ * 10, 1) buffer = file.read(self.__sample_size__) if len(buffer) < 10000: break pos = self.__search__(buffer) if pos == -1: continue print self.get_time(buffer[pos:]) file.close() print 'done' print mmpython.registertype('video/mpeg', ('mpeg', 'mpg', 'mp4', 'ts'), mediainfo.TYPE_AV, MpegInfo)
ai = mediainfo.AudioInfo() (type, ssize, timeunit, ai.samplerate, ai.length, buffersize, ai.bitrate, ai.channels, bloc, ai.bitrate) = streamheader self.samplerate = ai.samplerate _print("Samplerate %d" % self.samplerate) self.audio.append(ai) self.all_streams.append(ai) elif htype[:4] == 'text': subtitle = mediainfo.MediaInfo() subtitle.keys.append('language') subtitle.type = 'subtitle' subtitle.length = 0 self.all_streams.append(subtitle) else: _print("Unknown Header") def _extractHeaderString(self, header): len = struct.unpack('<I', header[:4])[0] try: return (len + 4, unicode(header[4:4 + len], 'utf-8')) except: return (len + 4, None) mmpython.registertype('application/ogg', ( 'ogm', 'ogg', ), mediainfo.TYPE_AV, OgmInfo)
if exif_info: self.setitem( 'date', exif_info, 'Image DateTime', True ) self.setitem( 'artist', exif_info, 'Image Artist', True ) self.setitem( 'hardware', exif_info, 'Image Model', True ) self.setitem( 'software', exif_info, 'Image Software', True ) self.setitem( 'thumbnail', exif_info, 'JPEGThumbnail', True ) self.appendtable( 'EXIF', exif_info ) if iptc_info: self.setitem( 'title', iptc_info, 517, True ) self.setitem( 'date' , iptc_info, 567, True ) self.setitem( 'comment', iptc_info, 617, True ) self.setitem( 'keywords', iptc_info, 537, True ) self.setitem( 'artist', iptc_info, 592, True ) self.setitem( 'country', iptc_info, 612, True ) self.setitem( 'caption', iptc_info, 632, True ) self.appendtable( 'IPTC', iptc_info ) if len(self.meta.keys()): self.appendtable( 'JPGMETA', self.meta ) for key, value in self.meta.items(): if key.startswith('Thumb:') or key == 'Software': setattr(self, key, value) if not key in self.keys: self.keys.append(key) ImageInfo.add(file.name, self) return mmpython.registertype( 'image/jpeg', ('jpg','jpeg'), mediainfo.TYPE_IMAGE, JPGInfo )
ai.language = elem.get_data() ai['language'] = elem.get_data() except: ai.language = 'en' ai['language'] = 'en' try: elem = tabelem[MATROSKA_CODEC_ID] ai.codec = elem.get_data() except: ai.codec = "Unknown" try: ainfo = tabelem[MATROSKA_AUDIO_SETTINGS_ID] audtab = self.process_one_level(vinfo) ai.samplerate = unpack('!f', audtab[MATROSKA_AUDIO_SAMPLERATE_ID].get_value())[0] ai.channels = audtab[MATROSKA_AUDIO_CHANNELS_ID].get_value() except: _print("No other info about audio track !!!") self.audio.append(ai) elif (mytype == MATROSKA_SUBTITLES_TRACK): try: elem = tabelem[MATROSKA_TRACK_LANGUAGE_ID] language = elem.get_data() _print ("Subtitle language found : %s" % elem.get_data() ) except: language = "en" # By default self.subtitles.append(language) #_print("Found %d elem for this track" % len(tabelem) ) mmpython.registertype( 'application/mkv', ('mkv', 'mka',), mediainfo.TYPE_AV, MkvInfo )
len = struct.unpack('<I', f.read(4))[0] return unicode(f.read(len), 'utf-8') def _calculateTrackLength(self, f): # seek to the end of the stream, to avoid scanning the whole file if (os.stat(f.name)[stat.ST_SIZE] > 20000): f.seek(os.stat(f.name)[stat.ST_SIZE] - 10000) # read the rest of the file into a buffer h = f.read() granule_position = 0 # search for each 'OggS' in h if len(h): idx = h.rfind('OggS') if idx < 0: return 0 pageSize = 0 h = h[idx + 4:] (check, type, granule_position, absPos, serial, pageN, crc, segs) = struct.unpack('<BBIIIIIB', h[:23]) if check != 0: _print(h[:10]) return _print("granule = %d / %d" % (granule_position, absPos)) # the last one is the one we are interested in return (granule_position / self.samplerate) mmpython.registertype('application/ogg', ('ogg', ), mediainfo.TYPE_MUSIC, OggInfo)
if not object.mime: object.mime = "image/%s" % i.format.lower() object.type = i.format_description if i.info.has_key("dpi"): object["dpi"] = "%sx%s" % i.info["dpi"] if DEBUG: for info in i.info: if not info == "exif": print "%s: %s" % (info, i.info[info]) object.mode = i.mode if not object.height: object.width, object.height = i.size return 1 class ImageInfo(mediainfo.ImageInfo): def __init__(self, file): mediainfo.ImageInfo.__init__(self) self.mime = "" self.type = "" self.valid = add(file.name, self) mmpython.registertype("image/gif", ("gif",), mediainfo.TYPE_IMAGE, ImageInfo) mmpython.registertype("image/bmp", ("bmp",), mediainfo.TYPE_IMAGE, ImageInfo)
if buffer.find('VIDEO_TS') == -1 and \ buffer.find('VIDEO_TS.IFO') == -1 and \ buffer.find('OSTA UDF Compliant') == -1: return 0 ret = self.lsdvd(device) if not ret: # we are very sure this is a DVD, maybe the drive was not # ready, let's try again return self.lsdvd(device) return 1 if os.environ.has_key('LSDVD') and os.environ['LSDVD']: LSDVD_EXE = os.environ['LSDVD'] else: for path in os.environ['PATH'].split(':'): if os.path.isfile(os.path.join(path, 'lsdvd')): LSDVD_EXE = os.path.join(path, 'lsdvd') break else: if mediainfo.DEBUG: print 'ImportError: lsdvd not found' raise ImportError mmpython.registertype('video/dvd', mediainfo.EXTENSION_DEVICE, mediainfo.TYPE_AV, DVDInfo) mmpython.registertype('video/dvd', mediainfo.EXTENSION_DIRECTORY, mediainfo.TYPE_AV, DVDInfo)
file.close() return seek_to def __scan__(self): """ scan file for timestamps (may take a long time) """ if not hasattr(self, 'filename') or not hasattr(self, 'start'): return 0 file = open(self.filename) print 'scanning file...' while 1: file.seek(self.__seek_size__ * 10, 1) buffer = file.read(self.__sample_size__) if len(buffer) < 10000: break pos = self.__search__(buffer) if pos == -1: continue print self.get_time(buffer[pos:]) file.close() print 'done' print mmpython.registertype( 'video/mpeg', ('mpeg','mpg','mp4', 'ts'), mediainfo.TYPE_AV, MpegInfo )
if name == '\xa9ART': self.artist = data[8:] self.valid = 1 if name == '\xa9alb': self.album = data[8:] self.valid = 1 if name == 'trkn': # Fix this self.trackno = data self.valid = 1 if name == '\xa9day': self.year = data[8:] self.valid = 1 if name == '\xa9too': self.encoder = data[8:] self.valid = 1 return 0 def read(self, b, file): data = file.read(b) if len(data) < b: raise ValueError, "EOF" return data def readInt(self, file): return struct.unpack('>I', self.read(4, file))[0] mmpython.registertype('application/m4a', ('m4a', ), mediainfo.TYPE_MUSIC, Mpeg4)
if header.has_key('ALBUM'): self.album = header['ALBUM'] if header.has_key('ARTIST'): self.artist = header['ARTIST'] if header.has_key('COMMENT'): self.comment = header['COMMENT'] if header.has_key('DATE'): self.date = header['DATE'] if header.has_key('ENCODER'): self.encoder = header['ENCODER'] if header.has_key('TRACKNUMBER'): self.trackno = header['TRACKNUMBER'] self.appendtable('VORBISCOMMENT', header) elif type == 5: # CUESHEET pass else: # UNKNOWN TYPE pass if lastblock: break def _extractHeaderString(self, header): len = struct.unpack('<I', header[:4])[0] return (len + 4, unicode(header[4:4 + len], 'utf-8')) mmpython.registertype('application/flac', ('flac', ), mediainfo.TYPE_MUSIC, FlacInfo)
return self.valid = 1 self.type = 'audio' self.subtype = 'mp3' # grab any headers for a max of 10 lines linecnt = 0 tab = {} lines = fi.readlines(512) for linecnt in range(0,11): icyline = lines[linecnt] icyline = icyline.rstrip('\r\n') if len(icyline) < 4: break cidx = icyline.find(':') if cidx != -1: # break on short line (ie. really should be a blank line) # strip leading and trailing whitespace tab[icyline[:cidx].strip()] = icyline[cidx+2:].strip() if fi: fi.close() self.appendtable('ICY', tab) self.tag_map = { ('ICY', 'en') : ICY_tags } # Copy Metadata from tables into the main set of attributes for k in self.tag_map.keys(): map(lambda x:self.setitem(x,self.gettable(k[0],k[1]),self.tag_map[k][x]), self.tag_map[k].keys()) self.bitrate = string.atoi(self.bitrate)*1000 mmpython.registertype( 'text/plain', mediainfo.EXTENSION_STREAM, mediainfo.TYPE_MUSIC, WebRadioInfo )
pass elif atomtype == "mdat": pos = file.tell() + atomsize - 8 # maybe there is data inside the mdat if ATOM_DEBUG: print "parsing mdat" while self._readatom(file): pass if ATOM_DEBUG: print "end of mdat" file.seek(pos, 0) else: if ATOM_DEBUG and not atomtype in ("wide", "free"): print "unhandled base atom %s" % atomtype # Skip unknown atoms try: file.seek(atomsize - 8, 1) except IOError: return 0 return atomsize mmpython.registertype("video/quicktime", ("mov", "qt"), mediainfo.TYPE_AV, MovInfo) # doc links: # [1] http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap4/chapter_5_section_2.html#//apple_ref/doc/uid/TP40000939-CH206-BBCBIICE