From ec7e41a90440d1fa0efdafcf6806f02a39a0ad83 Mon Sep 17 00:00:00 2001 From: "adrian.sampson" Date: Sun, 6 Jul 2008 00:44:37 +0000 Subject: [PATCH] added FLAC support to MediaFile (with tests) --HG-- extra : convert_revision : svn%3A41726ec3-264d-0410-9c23-a9f1637257cc/trunk%4054 --- beets/mediafile.py | 105 ++++++++++++++++++++++++----------------- test/rsrc/full.flac | Bin 0 -> 21890 bytes test/rsrc/min.flac | Bin 0 -> 21890 bytes test/rsrc/partial.flac | Bin 0 -> 21890 bytes test/test_mediafile.py | 2 +- 5 files changed, 63 insertions(+), 44 deletions(-) create mode 100644 test/rsrc/full.flac create mode 100644 test/rsrc/min.flac create mode 100644 test/rsrc/partial.flac diff --git a/beets/mediafile.py b/beets/mediafile.py index 3f07f9062..5f3ad3c26 100644 --- a/beets/mediafile.py +++ b/beets/mediafile.py @@ -13,7 +13,7 @@ A field will always return a reasonable value of the correct type, even if no tag is present. If no value is available, the value will be false (e.g., zero or the empty string).""" -from mutagen import mp4, mp3, id3 +import mutagen import os.path __all__ = ['FileTypeError', 'MediaFile'] @@ -115,21 +115,28 @@ class MediaField(object): STYLE_RIGHT = 1 << 6 # likewise, in second entry # These are mutually exclusive and relevant only with SLASHED and 2PLE. - def __init__(self, id3key, mp4key, + def __init__(self, id3key, mp4key, flackey, # in ID3 tags, use only the frame with this "desc" field id3desc=None, # compositions of the TYPE_ flag above - id3type=TYPE_UNICODE|TYPE_LIST, mp4type=TYPE_UNICODE|TYPE_LIST, + id3type = TYPE_UNICODE|TYPE_LIST, + mp4type = TYPE_UNICODE|TYPE_LIST, + flactype = TYPE_UNICODE|TYPE_LIST, # compositions of STYLE_ flags - id3style=STYLE_UNICODE, mp4style=STYLE_UNICODE + id3style = STYLE_UNICODE, + mp4style = STYLE_UNICODE, + flacstyle = STYLE_UNICODE ): - self.keys = { 'mp3': id3key, - 'mp4': mp4key } - self.types = { 'mp3': id3type, - 'mp4': mp4type } - self.styles = { 'mp3': id3style, - 'mp4': mp4style } + self.keys = { 'mp3': id3key, + 'mp4': mp4key, + 'flac': flackey } + self.types = { 'mp3': id3type, + 'mp4': mp4type, + 'flac': flactype } + self.styles = { 'mp3': id3style, + 'mp4': mp4style, + 'flac': flacstyle } self.id3desc = id3desc def _fetchdata(self, obj): @@ -186,12 +193,12 @@ class MediaField(object): # need to make a new frame? if not found: - frame = id3.Frames[mykey](encoding=3, desc=self.id3desc, - text=val) + frame = mutagen.id3.Frames[mykey]( + encoding=3, desc=self.id3desc, text=val) obj.mgfile.tags.add(frame) else: # no match on desc; just replace based on key - frame = id3.Frames[mykey](encoding=3, text=val) + frame = mutagen.id3.Frames[mykey](encoding=3, text=val) obj.mgfile.tags.setall(mykey, [frame]) else: obj.mgfile[mykey] = out @@ -301,16 +308,19 @@ class MediaFile(object): metadata.""" def __init__(self, path): - root, ext = os.path.splitext(path) - if ext == '.mp3': - self.type = 'mp3' - self.mgfile = mp3.Open(path) - # mgfile = mutagen file = that which a MediaFile wraps - elif ext == '.m4a' or ext == '.mp4' or ext == '.m4b' or ext == '.m4p': + self.mgfile = mutagen.File(path) + if self.mgfile is None: # Mutagen couldn't guess the type + raise FileTypeError('file type unsupported by Mutagen') + elif type(self.mgfile).__name__ == 'M4A' or \ + type(self.mgfile).__name__ == 'MP4': self.type = 'mp4' - self.mgfile = mp4.Open(path) + elif type(self.mgfile).__name__ == 'ID3' or \ + type(self.mgfile).__name__ == 'MP3': + self.type = 'mp3' + elif type(self.mgfile).__name__ == 'FLAC': + self.type = 'flac' else: - raise FileTypeError('unsupported file extension: ' + ext) + raise FileTypeError('file type unsupported by MediaFile') # add a set of tags if it's missing if not self.mgfile.tags: @@ -322,39 +332,48 @@ class MediaFile(object): #### field definitions #### - title = MediaField('TIT2', "\xa9nam") - artist = MediaField('TPE1', "\xa9ART") - album = MediaField('TALB', "\xa9alb") - genre = MediaField('TCON', "\xa9gen") - composer = MediaField('TCOM', "\xa9wrt") - grouping = MediaField('TIT1', "\xa9grp") - year = MediaField('TDRC', "\xa9day", + title = MediaField('TIT2', "\xa9nam", 'title') + artist = MediaField('TPE1', "\xa9ART", 'artist') + album = MediaField('TALB', "\xa9alb", 'album') + genre = MediaField('TCON', "\xa9gen", 'genre') + composer = MediaField('TCOM', "\xa9wrt", 'composer') + grouping = MediaField('TIT1', "\xa9grp", 'grouping') + year = MediaField('TDRC', "\xa9day", 'date', id3style=MediaField.STYLE_INTEGER, - mp4style=MediaField.STYLE_INTEGER) - track = MediaField('TRCK', 'trkn', + mp4style=MediaField.STYLE_INTEGER, + flacstyle=MediaField.STYLE_INTEGER) + track = MediaField('TRCK', 'trkn', 'tracknumber', id3style=MediaField.STYLE_SLASHED | MediaField.STYLE_LEFT, mp4type=MediaField.TYPE_LIST, - mp4style=MediaField.STYLE_2PLE | MediaField.STYLE_LEFT) - maxtrack = MediaField('TRCK', 'trkn', + mp4style=MediaField.STYLE_2PLE | MediaField.STYLE_LEFT, + flacstyle=MediaField.STYLE_INTEGER) + maxtrack = MediaField('TRCK', 'trkn', 'tracktotal', id3style=MediaField.STYLE_SLASHED | MediaField.STYLE_RIGHT, mp4type=MediaField.TYPE_LIST, - mp4style=MediaField.STYLE_2PLE | MediaField.STYLE_RIGHT) - disc = MediaField('TPOS', 'disk', + mp4style=MediaField.STYLE_2PLE | MediaField.STYLE_RIGHT, + flacstyle=MediaField.STYLE_INTEGER) + disc = MediaField('TPOS', 'disk', 'disc', id3style=MediaField.STYLE_SLASHED | MediaField.STYLE_LEFT, mp4type=MediaField.TYPE_LIST, - mp4style=MediaField.STYLE_2PLE | MediaField.STYLE_LEFT) - maxdisc = MediaField('TPOS', 'disk', + mp4style=MediaField.STYLE_2PLE | MediaField.STYLE_LEFT, + flacstyle=MediaField.STYLE_INTEGER) + maxdisc = MediaField('TPOS', 'disk', 'disctotal', id3style=MediaField.STYLE_SLASHED | MediaField.STYLE_RIGHT, mp4type=MediaField.TYPE_LIST, - mp4style=MediaField.STYLE_2PLE | MediaField.STYLE_RIGHT) - lyrics = MediaField(u"USLT", "\xa9lyr", id3desc=u'', + mp4style=MediaField.STYLE_2PLE | MediaField.STYLE_RIGHT, + flacstyle=MediaField.STYLE_INTEGER) + lyrics = MediaField(u"USLT", "\xa9lyr", 'lyrics', + id3desc=u'', id3type=MediaField.TYPE_UNICODE) - comments = MediaField(u"COMM", "\xa9cmt", id3desc=u'') - bpm = MediaField('TBPM', 'tmpo', + comments = MediaField(u"COMM", "\xa9cmt", 'description', + id3desc=u'') + bpm = MediaField('TBPM', 'tmpo', 'bpm', id3style=MediaField.STYLE_INTEGER, mp4type=MediaField.TYPE_LIST | MediaField.TYPE_INTEGER, - mp4style=MediaField.STYLE_INTEGER) - comp = MediaField('TCMP', 'cpil', + mp4style=MediaField.STYLE_INTEGER, + flacstyle=MediaField.STYLE_INTEGER) + comp = MediaField('TCMP', 'cpil', 'compilation', id3style=MediaField.STYLE_BOOLEAN, mp4type=MediaField.TYPE_BOOLEAN, - mp4style=MediaField.STYLE_BOOLEAN) + mp4style=MediaField.STYLE_BOOLEAN, + flacstyle=MediaField.STYLE_BOOLEAN) diff --git a/test/rsrc/full.flac b/test/rsrc/full.flac new file mode 100644 index 0000000000000000000000000000000000000000..b88b276b472f94e64f2cb839bd83e151ba3bda69 GIT binary patch literal 21890 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 MxtBlsvp=o;A4{-DC;$Ke literal 0 HcmV?d00001 diff --git a/test/rsrc/partial.flac b/test/rsrc/partial.flac new file mode 100644 index 0000000000000000000000000000000000000000..365dd1db05ad0ce4e775f362c07affcce4deb70a GIT binary patch literal 21890 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