import mutagen import mutagen.id3 import mutagen.easyid3 # TODO: custom interface to tracknumber/tracktotal/disc... def popms(id3): for k, v in id3.iteritems(): if k.startswith('POPM'): yield k, v def byte2rating(b): if b >= 224: return 5 if b >= 160: return 4 if b >= 96: return 3 if b >= 32: return 2 if b >= 1: return 1 return 0 def rating2byte(r): if r == 5: return 256 if r == 4: return 192 if r == 3: return 128 if r == 2: return 64 if r == 1: return 1 return 0 def rating_get(id3, key): try: rating = id3['TXXX:RATING'] except KeyError: try: _, popm = popms(id3).next() except StopIteration: return [] else: return [byte2rating(popm.rating)] else: return list(rating.text) def _canconv(r): try: if int(r) != str(int(r)): return False return int(r) >= 1 and int(r) <= 5 except ValueError, TypeError: return False def rating_set(id3, key, val): rating_delete(id3, key) if _canconv(val): popm = mutagen.id3.POPM() popm.email = "Windows Media Player 9 Series" popm.count = 0 popm.rating = rating2byte(int(val)) id3.add(popm) else: if 'TXXX:RATING' in id3: del(id3['TXXX:RATING']) id3.add(mutagen.id3.TXXX(encoding=3, desc='RATING', text=unicode(val))) def rating_delete(id3, key): for k, v in popms(id3): del(id3[k]) if 'TXXX:RATING' in id3: del(id3['TXXX:RATING']) def tracknumber_get(id3, key): # TODO: use for both track and disc pass def tracknumber_set(id3, key, val): pass def tracknumber_delete(id3, key): pass replaygain_tags = ('replaygain_album_gain', 'replaygain_album_peak', \ 'replaygain_track_gain', 'replaygain_track_peak') for tag in replaygain_tags: mutagen.easyid3.EasyID3.RegisterTXXXKey(tag, tag) mutagen.easyid3.EasyID3.RegisterTXXXKey('sync', 'SYNC') mutagen.easyid3.EasyID3.RegisterKey('rating', rating_get, rating_set, rating_delete)