MediaFile support for MusicBrainz track, album, and artist IDs

This commit is contained in:
Adrian Sampson 2010-07-10 14:05:01 -07:00
parent f8c317a2cd
commit ac98777adc
7 changed files with 78 additions and 14 deletions

View file

@ -68,8 +68,8 @@ class StorageStyle(object):
- key: The Mutagen key used to access the field's data.
- list_elem: Store item as a single object or as first element
of a list.
- as_type: Which type the value is stored as (unicode, int, or
bool).
- as_type: Which type the value is stored as (unicode, int,
bool, or str).
- packing: If this value is packed in a multiple-value storage
unit, which type of packing (in the packing enum). Otherwise,
None. (Makes as_type irrelevant).
@ -78,8 +78,8 @@ class StorageStyle(object):
- ID3 storage only: match against this 'desc' field as well
as the key.
"""
def __init__(self, key, list_elem = True, as_type = unicode, packing = None,
pack_pos = 0, id3_desc = None):
def __init__(self, key, list_elem = True, as_type = unicode,
packing = None, pack_pos = 0, id3_desc = None):
self.key = key
self.list_elem = list_elem
self.as_type = as_type
@ -214,10 +214,19 @@ class MediaField(object):
if entry is None: # no desc match
return None
else:
# Get the metadata frame object.
try:
entry = obj.mgfile[style.key].text
frame = obj.mgfile[style.key]
except KeyError:
return None
# For most frame types, the data is in the 'text' field.
# For UFID (used for the MusicBrainz track ID), it's in
# the 'data' field.
if isinstance(frame, mutagen.id3.UFID):
entry = frame.data
else:
entry = frame.text
else: # Not MP3.
try:
@ -244,7 +253,8 @@ class MediaField(object):
else: out = val
if obj.type == 'mp3':
if style.id3_desc is not None: # match on desc field
# Try to match on "desc" field.
if style.id3_desc is not None:
frames = obj.mgfile.tags.getall(style.key)
# try modifying in place
@ -258,10 +268,29 @@ class MediaField(object):
# need to make a new frame?
if not found:
frame = mutagen.id3.Frames[style.key](
encoding=3, desc=style.id3_desc, text=val)
encoding=3,
desc=style.id3_desc,
text=val
)
obj.mgfile.tags.add(frame)
else: # no match on desc; just replace based on key
# Try to match on "owner" field.
elif style.key.startswith('UFID:'):
owner = style.key.split(':', 1)[1]
frames = obj.mgfile.tags.getall(style.key)
for frame in frames:
# Replace existing frame data.
if frame.owner == owner:
frame.data = out
else:
# New frame.
frame = mutagen.id3.UFID(owner=owner, data=val)
obj.mgfile.tags.setall('UFID', [frame])
# Just replace based on key.
else:
frame = mutagen.id3.Frames[style.key](encoding=3, text=val)
obj.mgfile.tags.setall(style.key, [frame])
@ -366,8 +395,8 @@ class MediaField(object):
out = 0
else:
out = int(out)
elif style.as_type == bool:
out = bool(out)
elif style.as_type in (bool, str):
out = style.as_type(out)
# store the data
self._storedata(obj, out, style)
@ -592,6 +621,30 @@ class MediaFile(object):
as_type = bool),
etc = StorageStyle('compilation')
)
# MusicBrainz IDs.
mb_trackid = MediaField(
mp3 = StorageStyle('UFID:http://musicbrainz.org',
list_elem = False),
mp4 = StorageStyle(
'----:com.apple.iTunes:MusicBrainz Track Id',
as_type=str),
etc = StorageStyle('musicbrainz_trackid')
)
mb_albumid = MediaField(
mp3 = StorageStyle('TXXX', id3_desc='MusicBrainz Album Id'),
mp4 = StorageStyle(
'----:com.apple.iTunes:MusicBrainz Album Id',
as_type=str),
etc = StorageStyle('musicbrainz_albumid')
)
mb_artistid = MediaField(
mp3 = StorageStyle('TXXX', id3_desc='MusicBrainz Artist Id'),
mp4 = StorageStyle(
'----:com.apple.iTunes:MusicBrainz Artist Id',
as_type=str),
etc = StorageStyle('musicbrainz_artistid')
)
@property
def length(self):

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -66,6 +66,8 @@ def MakeWritingTest(path, correct_dict, field, testsuffix='_test'):
self.value = not correct_dict[field]
elif type(correct_dict[field]) is datetime.date:
self.value = correct_dict[field] + datetime.timedelta(42)
elif type(correct_dict[field]) is str:
self.value = 'TestValue-' + str(field)
else:
raise ValueError('unknown field type ' + \
str(type(correct_dict[field])))
@ -141,16 +143,22 @@ correct_dicts = {
'lyrics': u'the lyrics',
'comments': u'the comments',
'bpm': 6,
'comp': True
'comp': True,
'mb_trackid': '8b882575-08a5-4452-a7a7-cbb8a1531f9e',
'mb_albumid': '9e873859-8aa4-4790-b985-5a953e8ef628',
'mb_artistid':'7cf0ea9d-86b9-4dad-ba9e-2355a64899ea',
},
# Additional coverage for common cases when "total" fields are unset.
# Created with iTunes.
# Created with iTunes. (Also tests unset MusicBrainz fields.)
'partial': {
'track': 2,
'tracktotal': 0,
'disc': 4,
'disctotal': 0
'disctotal': 0,
'mb_trackid': '',
'mb_albumid': '',
'mb_artistid':'',
},
'min': {
'track': 0,
@ -178,7 +186,10 @@ correct_dicts = {
'lyrics': u'',
'comments': u'',
'bpm': 0,
'comp': False
'comp': False,
'mb_trackid': u'',
'mb_albumid': u'',
'mb_artistid':u'',
},
# Full release date.