117 lines
2.9 KiB
Python
117 lines
2.9 KiB
Python
from collections import MutableMapping
|
|
import mutagenx
|
|
import mutagenx.id3
|
|
from mutagenx.easyid3 import EasyID3
|
|
|
|
def popms(id3):
|
|
for k, v in id3.items():
|
|
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):
|
|
if 'TXXX:RATING' in id3:
|
|
rating = id3['TXXX:RATING']
|
|
return list(rating.text)
|
|
else:
|
|
try:
|
|
_, popm = next(popms(id3))
|
|
except StopIteration:
|
|
return []
|
|
else:
|
|
return [str(byte2rating(popm.rating))]
|
|
|
|
def _canconv(r):
|
|
try:
|
|
ir = int(r)
|
|
if ir != str(ir):
|
|
return False
|
|
return ir >= 1 and ir <= 5
|
|
except (ValueError, TypeError):
|
|
return False
|
|
|
|
def rating_set(id3, key, val):
|
|
rating_delete(id3, key)
|
|
if _canconv(val):
|
|
popm = mutagenx.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(mutagenx.id3.TXXX(encoding=3, desc='RATING', text=str(val)))
|
|
|
|
def rating_delete(id3, key):
|
|
for k, v in popms(id3):
|
|
del(id3[k])
|
|
if 'TXXX:RATING' in id3:
|
|
del(id3['TXXX:RATING'])
|
|
|
|
replaygain_tags = ('replaygain_album_gain', 'replaygain_album_peak', \
|
|
'replaygain_track_gain', 'replaygain_track_peak')
|
|
for tag in replaygain_tags:
|
|
EasyID3.RegisterTXXXKey(tag, tag)
|
|
|
|
extra_tags = ('sync', 'totaltracks', 'totaldiscs')
|
|
for tag in extra_tags:
|
|
EasyID3.RegisterTXXXKey(tag, tag.upper())
|
|
|
|
EasyID3.RegisterTextKey('albumartist', 'TPE2')
|
|
EasyID3.RegisterKey('rating', rating_get, rating_set, rating_delete)
|
|
|
|
class SyncFile(MutableMapping):
|
|
def __init__(self, path):
|
|
self.md = mutagenx.File(path, easy=True)
|
|
self.path = path
|
|
self.seen = False
|
|
|
|
def __getitem__(self, key):
|
|
if self.md == None:
|
|
print(self.path)
|
|
d = self.md[key]
|
|
try:
|
|
return d[0]
|
|
except IndexError:
|
|
raise KeyError(key)
|
|
|
|
def __setitem__(self, key, value):
|
|
#if type(value) != str:
|
|
#raise ValueError
|
|
if type(value) is type(None):
|
|
raise ValueError
|
|
self.md[key] = [value]
|
|
|
|
def __delitem__(self, key):
|
|
del(self.md[key])
|
|
|
|
def __iter__(self):
|
|
for k in self.md:
|
|
try:
|
|
self.__getitem__(k)
|
|
except KeyError:
|
|
pass
|
|
else:
|
|
yield k
|
|
|
|
def __len__(self):
|
|
return len([k for k in self.__iter__()])
|
|
|
|
def save(self):
|
|
return self.md.save()
|