def __mmpython(self, file): meta = {} info = mmpython.parse(file) # print info if info: tables = ["video", "audio", "image"] not_save = ["dict", "i18ndir", "url", "name"] for table in tables: if info.has_key(table): mediums = info[table] for medium in mediums: for key in medium.keys: if medium[key] and key not in not_save: meta[table + "_" + key] = medium[key] for table in info._tables: mm = info._tables[table] for key, value in mm.__dict__.items(): if value and key not in not_save: meta[key] = value for key in info.keys: if info[key] and key not in not_save: meta[key] = info[key] return meta
def read(self, filename, metainfo): import mmpython try: minfo = mmpython.parse(filename) except TypeError: logger.exception("MP3 tag parse error") try: if minfo.title: metainfo["title"] = minfo.title if minfo.genre: metainfo["genre"] = minfo.genre if minfo.date: metainfo["year"] = minfo.date if minfo.trackno: metainfo["tracknr"] = minfo.trackno if minfo.album: metainfo["album"] = minfo.album if minfo.artist: metainfo["artist"] = minfo.artist if minfo.length: metainfo["length"] = "00:%02d:%02d" % \ (minfo.length / 60, minfo.length % 60) except: pass import mmpython.audio.eyeD3 file = mmpython.audio.eyeD3.Mp3AudioFile(filename) metainfo["bitrate"] = file.getBitRateString() metainfo["samplefreq"] = file.header.sampleFreq metainfo["audio_mode"] = file.header.mode metainfo["subtype"] = "MPEG %s layer %s" % (file.header.version, 'I' * file.header.layer) logger.info(str(metainfo))
def detailsFromDisk(self, filename, details): """Automagically load media metadata out of the provided filename, adding entries to details. This works on any file type mmpython recognizes, and other files should be tagged appropriately for Rio Taxi. """ info = mmpython.parse(filename) st = os.stat(filename) # Generic details for any file. Note that we start out assuming # all files are unreadable, and label everything for Rio Taxi. # Later we'll mark supported formats as music. details['length'] = st.st_size details['type'] = 'taxi' details['rid'] = RidCalculator().fromFile(filename, st.st_size, info) # We get the bulk of our metadata via mmpython if possible if info: self.detailsFromMM(info, details) if details['type'] == 'taxi': # All taxi files get their filename as their title, regardless of what mmpython said details['title'] = os.path.basename(filename) # Taxi files also always get a codec of 'taxi' details['codec'] = 'taxi' # Music files that still don't get a title get their filename minus the extension if not details.get('title'): details['title'] = os.path.splitext(os.path.basename(filename))[0]
def read(self, metainfo): import mmpython try: minfo = mmpython.parse(self.filename) except TypeError: logger.exception("MP3 tag parse error") try: if minfo.title: metainfo["title"] = minfo.title if minfo.genre: if metainfo.has_key('genre'): metainfo["genre"].append(minfo.genre) else: metainfo["genre"] = [minfo.genre] if minfo.date: metainfo["year"] = minfo.date if minfo.trackno: metainfo["tracknr"] = minfo.trackno if minfo.album: metainfo["album"] = minfo.album if minfo.artist: metainfo["artist"] = minfo.artist if minfo.length: metainfo["length"] = "00:%02d:%02d" % \ (minfo.length / 60, minfo.length % 60) except: pass file = mmpython.audio.eyeD3.Mp3AudioFile(self.filename) metainfo["bitrate"] = file.getBitRateString() metainfo["samplefreq"] = file.header.sampleFreq metainfo["audio_mode"] = file.header.mode metainfo["subtype"] = "MPEG %s layer %s" % (file.header.version, 'I' * file.header.layer) # Try get musicbrainz tags out of the file from mmpython.audio.eyeD3.frames import \ UserTextFrame, DateFrame for frame in file.tag.frames: print "Found frame id", frame.header.id if frame.header.id == "TXXX": print "TXXX:%s" % frame.description if self.TXXX_FIELD_MAP.has_key(frame.description): metainfo[self.TXXX_FIELD_MAP[frame.description]] = frame.text elif frame.header.id == "TSOP": metainfo["artist_sortname"] = frame.text elif frame.header.id == "UFID": ufid = UFIDFrame(frame.data, frame.header) metainfo["mb_track_id"] = ufid.id logger.info(str(metainfo)) return metainfo
def GetMetadata(self, fullPath): fullPath = ConvertPath(fullPath) if not self.__LegalPath(fullPath): return False try: fileType = self.GetFileType(fullPath) if not fileType: return False elif fileType == "pdf": # for pdfs return "Pages: " + str(countPDFpages.getPDFPageCount(fullPath)) else: # for all other types metadata = mmpython.parse(fullPath) if metadata: # metadata extracted successfully return unicode(metadata).encode('latin-1', 'replace') else: return False except: WriteLog(str(sys.exc_info()[0]) + " " + str(sys.exc_info()[1])) return False
def GetMetadata(self, fullPath): fullPath = ConvertPath(fullPath) if not self.__LegalPath(fullPath): return False try: fileType = self.GetFileType(fullPath) if not fileType: return False elif fileType == "pdf": # for pdfs return "Pages: "+str(countPDFpages.getPDFPageCount(fullPath)) else: # for all other types metadata = mmpython.parse(fullPath) if metadata: # metadata extracted successfully return unicode(metadata).encode('latin-1', 'replace') else: return False except: WriteLog( str(sys.exc_info()[0])+" "+str(sys.exc_info()[1]) ) return False
def fromFile(self, filename, length=None, mminfo=None): """Calculate the RID from a file, given its name. The file's length and mmpython results may be provided if they're known, to avoid duplicating work. """ if mminfo is None: mminfo = mmpython.parse(filename) f = open(filename, "rb") if length is None: f.seek(0, 2) length = f.tell() f.seek(0) # Is this an MP3 file? For some silliness we have to skip the header # and the last 128 bytes of the file. mmpython can tell us where the # header starts, but only in a somewhat ugly way. if isinstance(mminfo, mmpython.audio.eyed3info.eyeD3Info): try: offset = mp3info.MPEG(f)._find_header(f)[0] except ZeroDivisionError: # This is a bit of a kludge, since mmpython seems to crash # here on some MP3s for a currently-unknown reason. print "WARNING, mmpython got a div0 error on %r" % filename offset = 0 if offset < 0: # Hmm, it couldn't find the header? Set this to zero # so we still get a usable RID, but it probably # won't strictly be a correct RID. offset = 0 f.seek(0) return self.fromSection(f, offset, length-128) # Otherwise, use the whole file else: return self.fromSection(f, 0, length)