with her finger and her thumb

This commit is contained in:
Connor Olding 2014-04-27 12:03:52 -07:00
parent 6ae05ac68d
commit 14014e2e93
2 changed files with 113 additions and 47 deletions

84
mutaext.py Normal file
View File

@ -0,0 +1,84 @@
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)

View File

@ -7,45 +7,7 @@ import os
import os.path
import sys
import mutagen
import mutagen.id3
import mutagen.easyid3
def popm_any(id3):
for k, v in id3.iteritems():
if k.startswith('POPM'):
return 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 rating_get(id3, key):
try:
return list(id3['TXXX:RATING'])
except KeyError:
try:
return list(unicode(byte2rating(popm_any(id3).rating)))
except AttributeError:
return
def rating_set(id3, key, val):
# TODO: test
try:
frame = id3["TXXX:RATING"]
except KeyError:
id3.add(mutagen.id3.TXXX(encoding=3, desc=u'RATING', text=val))
else:
frame.encoding = 3
frame.text = val
def rating_delete(id3, key):
# TODO: delete POPM too?
del(id3["TXXX:RATING"])
mutagen.easyid3.EasyID3.RegisterTXXXKey('sync', 'SYNC')
mutagen.easyid3.EasyID3.RegisterKey('rating', rating_get, rating_set, rating_delete)
import mutaext
def G(d, k):
try:
@ -67,11 +29,8 @@ def filterext(paths, exts):
def shouldsync(md):
rating = G(md, 'rating')
sync = G(md, 'sync')
if rating != None:
try:
rating = int(rating[0])
except ValueError:
rating = None
if rating:
rating = rating[0]
if sync:
sync = sync[0].lower()
else:
@ -93,7 +52,7 @@ def fixmetadata(md):
if 'title' not in md:
fn = os.path.basename(md.path)
fn = os.path.splitext(fn)[0]
# TODO: attempt to infer trackNum/diskNum from fn
# TODO: attempt to infer trackNum/discNum from fn
md['title'] = fn
def findmatching(haystack, needle):
@ -116,6 +75,28 @@ def findmatching(haystack, needle):
break
return match
def updatemetadata(mdold, mdnew):
modified = False
updatabletags = ('rating', 'sync', 'comment')
# TODO:
# composer : probably safe
# genre : might need deep equal?
# trackNum : TRCK with optional /[total]
# discNum : TPOS " " "
# total tracks : ?
# total discs : ?
# [replaygain] : TXXX:* in id3
# albumArtist : TPE2 in id3
for tag in updatabletags:
if tag in mdnew:
if not tag in mdold or mdnew[tag] != mdold[tag]:
mdold[tag] = mdnew[tag]
modified = True
elif tag in mdold:
del mdold[tag]
modified = True
return modified
def run(args):
if not len(args) in (2, 3):
print("I need a path or two!", file=sys.stderr)
@ -151,8 +132,9 @@ def run(args):
md = mutagen.File(p, easy=True)
match = findmatching(tosync, md)
if match:
print("UPD", p)
# update tags here if updatemetadata returns true
if updatemetadata(md, match):
print("UPD", p)
# save here
else:
print("DEL", p)
# delete files here