def CopyTags(source_file, target_file): o = OggVorbis(source_file) m = EasyID3(target_file) for key in ["artist", "title", "album", "date", "genre", "tracknumber"]: if o.has_key(key): m[key] = o[key] m.save() if o.has_key("discnumber"): m = MP3(target_file) m["TPOS"] = TPOS(encoding=3, text=o["discnumber"]) m.save()
def CopyTags(source_file, target_file): o = OggVorbis(source_file) m = EasyID3(target_file) for key in ['artist', 'title', 'album', 'date', 'genre', 'tracknumber']: if o.has_key(key): m[key] = o[key] m.save() if o.has_key('discnumber'): m = MP3(target_file) m['TPOS'] = TPOS(encoding=3, text=o['discnumber']) m.save()
def get_ogg_tag_info(f): global blankstr ret = {"file":f,"length":"0"} try: i = OggVorbis(f) ret["length"] = str(i.info.length) for k in ["artist", "album", "year", "tracknumber", "title"]: if i.has_key(k): ret[k] = str(i[k]) except Exception, e: print("\r%s\rUnable to read OGG info for\n%s" %(blankstr, f)) print(str(e))
def walk_audio_files(): tag_count = 0 for root, dirs, files in os.walk('.'): for name in files: audio_set = False if name.lower().endswith(".mp3"): try: audio = ID3(os.path.join(root, name)) except Exception, e: print 'ERROR: ID3 Error %s : %s' % (e, os.path.join(root, name)) continue if not select_audio(audio): continue if tag_mode == TAG_MODE_NORMAL and audio.has_key('TPE1'): artist = audio["TPE1"] genre = artist_to_genre(artist[0]) grouping = artist_to_groupings(artist[0]) if genre != None: audio["TCON"] = TCON(encoding=3, text=genre) audio_set = True if grouping != None: audio["TIT1"] = TIT1(encoding=3, text=grouping) audio_set = True else: if audio.has_key("TIT1"): genre = refine_genre(audio["TIT1"].text[0].split(",")) if genre != "": print "Refining genre for artist %s from %s to %s" % (audio["TPE1"].text[0], audio["TCON"].text[0], genre) audio["TCON"] = TCON(encoding=3, text=genre) audio_set = True elif name.lower().endswith(".ogg"): try: audio = OggVorbis(os.path.join(root, name)) except Exception, e: print 'ERROR: Ogg Comment Error %s : %s' % (e, os.path.join(root, name)) continue if not audio.has_key('artist'): print 'ERROR: Vorbis comment has no "artist" key in file %s' % os.path.join(root, name) continue artist = audio['artist'] genre = artist_to_genre(artist[0]) if genre != None: audio["genre"] = genre audio_set = True
def test_ogg_file(self): ogg = OggVorbis(self.ogg_file) self.assertTrue(ogg.has_key('coverart')) self.assertTrue(ogg.has_key('coverartmime')) self.assertTrue(ogg.has_key('coverartdescription')) rm_ogg_cover(self.ogg_episode._episode) self.assertFalse(filecmp.cmp(self.ogg_file, self.ogg_file_save)) ogg = OggVorbis(self.ogg_file) self.assertFalse(ogg.has_key('coverart')) self.assertFalse(ogg.has_key('coverartmime')) self.assertFalse(ogg.has_key('coverartdescription'))
def process_metadata(self, metadata): Log('Reading OGG tags') try: tags = OggVorbis(self.filename) except: Log('An error occured while attempting to parse the OGG file: ' + self.filename) return # Posters valid_posters = [] if tags.has_key('coverart'): for poster in tags['coverart']: poster_data = base64.standard_b64decode(poster) poster_name = hashlib.md5(poster_data).hexdigest() valid_posters.append(poster_name) if poster_name not in metadata.posters: Log('Adding embedded art from OGG file: ' + self.filename) metadata.posters[poster_name] = Proxy.Media(poster_data) else: Log('Skipping embedded art since its already added') return valid_posters
class vorbis(TagParser): """ Class for processing Ogg Vorbis file tags """ def __init__(self, codec, path): super(vorbis, self).__init__(codec, path, tag_map=VORBIS_STANDARD_TAGS) try: self.entry = OggVorbis(path) except IOError as e: raise TagError('Error opening {0}: {1}'.format(path, str(e))) except OggVorbisHeaderError as e: raise TagError('Error opening {0}: {1}'.format(path, str(e))) self.albumart_obj = None self.track_numbering = VorbisNumberingTag(self, 'TRACKNUMBER') self.disk_numbering = VorbisNumberingTag(self, 'DISKNUMBER') def __getitem__(self, item): if item == 'tracknumber': return [unicode('{0:d}'.format(self.track_numbering.value))] if item == 'totaltracks': return [unicode('{0:d}'.format(self.track_numbering.total))] if item == 'disknumber': return [unicode('{0:d}'.format(self.disk_numbering.value))] if item == 'totaldisks': return [unicode('{0:d}'.format(self.disk_numbering.total))] return super(vorbis, self).__getitem__(item) def __delitem__(self, item): try: item, value = item.split('=', 1) except ValueError: value = None fields = self.__tag2fields__(item) for tag in fields: tag = self.__field2tag__(tag) if not self.has_key(tag): continue if value is None: del self.entry[tag] self.modified = True elif value in self.entry[tag]: self.entry[tag] = [x for x in self.entry[tag] if x != value] if not self.entry[tag]: del self.entry[tag] self.modified = True def __field2tag__(self, field): return super(vorbis, self).__field2tag__(field.upper()) def keys(self): """ Return tag names sorted with self.sort_keys() """ keys = super(vorbis, self).keys() if 'TOTALTRACKS' in keys: keys.remove('TOTALTRACKS') if 'TOTALDISKS' in keys: keys.remove('TOTALDISKS') if 'TRACKNUMBER' in [x.upper() for x in keys]: if self.track_numbering.total is not None: keys.append('totaltracks') if 'DISKNUMBER' in [x.upper() for x in keys]: if self.disk_numbering.total is not None: keys.append('totaldisks') if VORBIS_ALBUMART_TAG in [x.upper() for x in keys]: keys.remove(VORBIS_ALBUMART_TAG) for replaygain_tag_fields in VORBIS_REPLAYGAIN_TAGS.values(): for tag in replaygain_tag_fields: if tag in keys: keys.remove(tag) return [x for x in self.sort_keys(keys)] def items(self): return [(key, self[key]) for key in self.keys()] def has_key(self, tag): if tag is None: return False return tag.lower() in self.keys() def set_tag(self, item, value): """ All vorbis tags are unicode strings, and there can be multiple tags with same name. We do special precessing for track and disk numbering. """ if item == 'tracknumber': self.track_numbering.value = value self.modified = True return if item == 'totaltracks': self.track_numbering.total = value self.modified = True return if item == 'disknumber': self.disk_numbering.value = value self.modified = True return if item == 'totaldisks': self.disk_numbering.total = value self.modified = True return if not isinstance(value, list): value = [value] value = [x for x in set(value)] tags = self.__tag2fields__(item) item = tags[0] for tag in tags: if self.entry.has_key(tag): if tag.lower() in OGG_MULTIPLE_VALUES_TAGS: value = set(self.entry[tag] + value) del self.entry[tag] entries =[] for v in value: if VORBIS_TAG_FORMATTERS.has_key(item): entries.append(VORBIS_TAG_FORMATTERS[item](v)) else: if not isinstance(v, unicode): v = unicode(v, 'utf-8') entries.append(v) self.entry[item] = entries self.modified = True
class VorbisFile: def __init__(self, fn): self.config = config if fn is not None: self.SetFile(fn) def SetFile(self, fn): self.fn = fn self.filename = os.path.basename(self.fn) self.af = OggVorbis(self.fn) def read_comments(self): dic = {'title' : '', 'artist' : '', 'album' : '', 'license' : '', 'label' : '', 'comment' : '' } for tag in self.af.keys(): tag = tag.lower() val = self.af.get(tag).pop(0) if val <> '': dic[tag] = val return dic def write_comments(self, metadata, userInfo, cache=1, removeSpool=0): ''' Cache the file (copy it to a tmp dir) and write the tags there. ''' logger.debug99("called VorbisFile.write_comments()") # now write the comments to file (self.af) dic = {} for tag in metadata: tag = tag.lower() val = metadata[tag] # build up metadata object together with audio file object if val != '': self.af[tag] = val else: logger.debug3("Not writing tag: %s (was left empty)" % tag) self.af.save() logger.debug3( "in VorbisFile.write_comments() Done! Wrote tags successfully to %s!" % self.fn ) # FIXME : el ImportOGG en modo 'edit' es para que re-lea tags y actualice la DB # pero no deberia ir dentro de la clase VorbisFile ''' if not cache: logger.debug2("Should re-import/update: %s" % self.fn) ImportOGG(self, self.fn, userInfo, 'edit') ''' return self.fn def getFilepath(self): return self.fn def getFilename(self): return self.filename def getTag(self, tag): if self.af.has_key(tag) and self.af[tag] is not '': return self.af.get(tag).pop(0) else: return '' def getLength(self): return self.af.info.length def getBitrate(self): return self.af.info.bitrate def getSamplerate(self): return self.af.info.sample_rate def getInfo(self): '''Available info (for OGG/Vorbis) is: channels, bitrate, serial, sample_rate, length''' return self.af.info def listTags(self): return self.af.keys() def getSize(self): return os.stat(self.fn).st_size
class VorbisFile: def __init__(self, fn): self.config = config if fn is not None: self.SetFile(fn) def SetFile(self, fn): self.fn = fn self.filename = os.path.basename(self.fn) self.af = OggVorbis(self.fn) def read_comments(self): dic = { 'title': '', 'artist': '', 'album': '', 'license': '', 'label': '', 'comment': '' } for tag in self.af.keys(): tag = tag.lower() val = self.af.get(tag).pop(0) if val <> '': dic[tag] = val return dic def write_comments(self, metadata, userInfo, cache=1, removeSpool=0): ''' Cache the file (copy it to a tmp dir) and write the tags there. ''' logger.debug99("called VorbisFile.write_comments()") # now write the comments to file (self.af) dic = {} for tag in metadata: tag = tag.lower() val = metadata[tag] # build up metadata object together with audio file object if val != '': self.af[tag] = val else: logger.debug3("Not writing tag: %s (was left empty)" % tag) self.af.save() logger.debug3( "in VorbisFile.write_comments() Done! Wrote tags successfully to %s!" % self.fn) # FIXME : el ImportOGG en modo 'edit' es para que re-lea tags y actualice la DB # pero no deberia ir dentro de la clase VorbisFile ''' if not cache: logger.debug2("Should re-import/update: %s" % self.fn) ImportOGG(self, self.fn, userInfo, 'edit') ''' return self.fn def getFilepath(self): return self.fn def getFilename(self): return self.filename def getTag(self, tag): if self.af.has_key(tag) and self.af[tag] is not '': return self.af.get(tag).pop(0) else: return '' def getLength(self): return self.af.info.length def getBitrate(self): return self.af.info.bitrate def getSamplerate(self): return self.af.info.sample_rate def getInfo(self): '''Available info (for OGG/Vorbis) is: channels, bitrate, serial, sample_rate, length''' return self.af.info def listTags(self): return self.af.keys() def getSize(self): return os.stat(self.fn).st_size
def cleanAllTags(self, db, element, path_normalizado): """ Method to clean all rating and playcount tags from the file""" try: # Get the audio tagging format of the current element format = self._check_recognized_format(path_normalizado) if format is None: raise Exception("Unrecognized format") else: needsave = False if format == "id3v2": audio = ID3(path_normalizado) if audio.has_key("POPM"): audio.delall("POPM") needsave = True if audio.has_key("PCNT"): audio.delall("PCNT") needsave = True if audio.has_key(u"TXXX:FMPS_Rating"): audio.delall(u"TXXX:FMPS_Rating") needsave = True if audio.has_key(u"TXXX:FMPS_Playcount"): audio.delall(u"TXXX:FMPS_Playcount") needsave = True elif format == "oggvorbis": audio = OggVorbis(path_normalizado) if audio.has_key("FMPS_RATING"): del audio["FMPS_RATING"] needsave = True if audio.has_key("FMPS_PLAYCOUNT"): del audio["FMPS_PLAYCOUNT"] needsave = True elif format == "flac": audio = FLAC(path_normalizado) if audio.has_key("FMPS_RATING"): del audio["FMPS_RATING"] needsave = True if audio.has_key("FMPS_PLAYCOUNT"): del audio["FMPS_PLAYCOUNT"] needsave = True elif format == "mp4": audio = MP4(path_normalizado) if audio.has_key("----:com.apple.iTunes:FMPS_Rating"): del audio["----:com.apple.iTunes:FMPS_Rating"] needsave = True if audio.has_key("----:com.apple.iTunes:FMPS_Playcount"): del audio["----:com.apple.iTunes:FMPS_Playcount"] needsave = True elif format == "musepack": audio = Musepack(path_normalizado) if audio.has_key("FMPS_RATING"): del audio["FMPS_RATING"] needsave = True if audio.has_key("FMPS_PLAYCOUNT"): del audio["FMPS_PLAYCOUNT"] needsave = True elif format == "oggspeex": audio = OggSpeex(path_normalizado) if audio.has_key("FMPS_RATING"): del audio["FMPS_RATING"] needsave = True if audio.has_key("FMPS_PLAYCOUNT"): del audio["FMPS_PLAYCOUNT"] needsave = True if needsave: audio.save() self.num_cleaned += 1 else: self.num_already_done += 1 except Exception, e: self.num_failed += 1 print(e, path_normalizado)
def cleanAllTags(self, db, element, path_normalizado): """ Method to clean all rating and playcount tags from the file""" try: # Get the audio tagging format of the current element format = self._check_recognized_format(path_normalizado) if format is None: raise Exception("Unrecognized format") else: needsave = False if format == "id3v2": audio = ID3(path_normalizado) if audio.has_key('POPM'): audio.delall('POPM') needsave = True if audio.has_key('PCNT'): audio.delall('PCNT') needsave = True if audio.has_key(u'TXXX:FMPS_Rating'): audio.delall(u'TXXX:FMPS_Rating') needsave = True if audio.has_key(u'TXXX:FMPS_Playcount'): audio.delall(u'TXXX:FMPS_Playcount') needsave = True elif format == "oggvorbis": audio = OggVorbis(path_normalizado) if audio.has_key('FMPS_RATING'): del audio['FMPS_RATING'] needsave = True if audio.has_key('FMPS_PLAYCOUNT'): del audio['FMPS_PLAYCOUNT'] needsave = True elif format == "flac": audio = FLAC(path_normalizado) if audio.has_key('FMPS_RATING'): del audio['FMPS_RATING'] needsave = True if audio.has_key('FMPS_PLAYCOUNT'): del audio['FMPS_PLAYCOUNT'] needsave = True elif format == "mp4": audio = MP4(path_normalizado) if audio.has_key('----:com.apple.iTunes:FMPS_Rating'): del audio['----:com.apple.iTunes:FMPS_Rating'] needsave = True if audio.has_key('----:com.apple.iTunes:FMPS_Playcount'): del audio['----:com.apple.iTunes:FMPS_Playcount'] needsave = True elif format == "musepack": audio = Musepack(path_normalizado) if audio.has_key('FMPS_RATING'): del audio['FMPS_RATING'] needsave = True if audio.has_key('FMPS_PLAYCOUNT'): del audio['FMPS_PLAYCOUNT'] needsave = True elif format == "oggspeex": audio = OggSpeex(path_normalizado) if audio.has_key('FMPS_RATING'): del audio['FMPS_RATING'] needsave = True if audio.has_key('FMPS_PLAYCOUNT'): del audio['FMPS_PLAYCOUNT'] needsave = True if needsave: audio.save() self.num_cleaned += 1 else: self.num_already_done += 1 except Exception, e: self.num_failed += 1 print(e, path_normalizado)