From 0309775a91d89bdec629c4be5e35235478e145ba Mon Sep 17 00:00:00 2001 From: Simon Luijk Date: Wed, 29 May 2013 21:25:23 +0200 Subject: [PATCH 1/3] Initial support for ALAC encoded audio files Both AAC and ALAC are normally embedded in an .m4a container. For this reason I have split the m4a type into aac and alac types. To distinguish between the two encodings I have taken advantage of the fact that, in my collection, ALAC don't have a sample_rate set. I could not find verification if this is always the case or not. Would bitrate be a more reliable determining factor? e.g. if bitrate > 320000: type = 'alac' Signed-off-by: Simon Luijk --- beets/mediafile.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/beets/mediafile.py b/beets/mediafile.py index e6648d757..b177e13b4 100644 --- a/beets/mediafile.py +++ b/beets/mediafile.py @@ -73,7 +73,8 @@ class FileTypeError(UnreadableFileError): # Human-readable type names. TYPES = { 'mp3': 'MP3', - 'mp4': 'AAC', + 'aac': 'AAC', + 'alac': 'ALAC', 'ogg': 'OGG', 'flac': 'FLAC', 'ape': 'APE', @@ -532,8 +533,10 @@ class MediaField(object): obj.mgfile[style.key] = out def _styles(self, obj): - if obj.type in ('mp3', 'mp4', 'asf'): + if obj.type in ('mp3', 'asf'): styles = self.styles[obj.type] + elif obj.type in ('aac', 'alac'): + styles = self.styles['mp4'] else: styles = self.styles['etc'] # Sane styles. @@ -568,7 +571,7 @@ class MediaField(object): out = out[:-len(style.suffix)] # MPEG-4 freeform frames are (should be?) encoded as UTF-8. - if obj.type == 'mp4' and style.key.startswith('----:') and \ + if obj.type in ('aac', 'alac') and style.key.startswith('----:') and \ isinstance(out, str): out = out.decode('utf8') @@ -636,7 +639,7 @@ class MediaField(object): # MPEG-4 "freeform" (----) frames must be encoded as UTF-8 # byte strings. - if obj.type == 'mp4' and style.key.startswith('----:') and \ + if obj.type in ('aac', 'alac') and style.key.startswith('----:') and \ isinstance(out, unicode): out = out.encode('utf8') @@ -723,7 +726,7 @@ class ImageField(object): return picframe.data - elif obj.type == 'mp4': + elif obj.type in ('aac', 'alac'): if 'covr' in obj.mgfile: covers = obj.mgfile['covr'] if covers: @@ -795,7 +798,7 @@ class ImageField(object): ) obj.mgfile['APIC'] = picframe - elif obj.type == 'mp4': + elif obj.type in ('aac', 'alac'): if val is None: if 'covr' in obj.mgfile: del obj.mgfile['covr'] @@ -880,7 +883,11 @@ class MediaFile(object): raise FileTypeError('file type unsupported by Mutagen') elif type(self.mgfile).__name__ == 'M4A' or \ type(self.mgfile).__name__ == 'MP4': - self.type = 'mp4' + if hasattr(self.mgfile.info, 'sample_rate') and \ + self.mgfile.info.sample_rate > 0: + self.type = 'aac' + else: + self.type = 'alac' elif type(self.mgfile).__name__ == 'ID3' or \ type(self.mgfile).__name__ == 'MP3': self.type = 'mp3' From ffe65648d2157ad6a1d57ee91265503240c0ac17 Mon Sep 17 00:00:00 2001 From: Simon Luijk Date: Thu, 30 May 2013 08:22:39 +0200 Subject: [PATCH 2/3] Style change Signed-off-by: Simon Luijk --- beets/mediafile.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/beets/mediafile.py b/beets/mediafile.py index b177e13b4..985f7fa72 100644 --- a/beets/mediafile.py +++ b/beets/mediafile.py @@ -83,6 +83,8 @@ TYPES = { 'asf': 'Windows Media', } +MP4_TYPES = ('aac', 'alac') + # Utility. @@ -535,7 +537,7 @@ class MediaField(object): def _styles(self, obj): if obj.type in ('mp3', 'asf'): styles = self.styles[obj.type] - elif obj.type in ('aac', 'alac'): + elif obj.type in MP4_TYPES: styles = self.styles['mp4'] else: styles = self.styles['etc'] # Sane styles. @@ -571,7 +573,7 @@ class MediaField(object): out = out[:-len(style.suffix)] # MPEG-4 freeform frames are (should be?) encoded as UTF-8. - if obj.type in ('aac', 'alac') and style.key.startswith('----:') and \ + if obj.type in MP4_TYPES and style.key.startswith('----:') and \ isinstance(out, str): out = out.decode('utf8') @@ -639,7 +641,7 @@ class MediaField(object): # MPEG-4 "freeform" (----) frames must be encoded as UTF-8 # byte strings. - if obj.type in ('aac', 'alac') and style.key.startswith('----:') and \ + if obj.type in MP4_TYPES and style.key.startswith('----:') and \ isinstance(out, unicode): out = out.encode('utf8') @@ -726,7 +728,7 @@ class ImageField(object): return picframe.data - elif obj.type in ('aac', 'alac'): + elif obj.type in MP4_TYPES: if 'covr' in obj.mgfile: covers = obj.mgfile['covr'] if covers: @@ -798,7 +800,7 @@ class ImageField(object): ) obj.mgfile['APIC'] = picframe - elif obj.type in ('aac', 'alac'): + elif obj.type in MP4_TYPES: if val is None: if 'covr' in obj.mgfile: del obj.mgfile['covr'] From 79f56adb124bc956cbbf762016f0f36bba7b70cf Mon Sep 17 00:00:00 2001 From: Simon Luijk Date: Thu, 30 May 2013 09:26:57 +0200 Subject: [PATCH 3/3] Add note about current approach of detecting aac vs alac Signed-off-by: Simon Luijk --- beets/mediafile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/beets/mediafile.py b/beets/mediafile.py index 985f7fa72..06b327e0d 100644 --- a/beets/mediafile.py +++ b/beets/mediafile.py @@ -885,6 +885,8 @@ class MediaFile(object): raise FileTypeError('file type unsupported by Mutagen') elif type(self.mgfile).__name__ == 'M4A' or \ type(self.mgfile).__name__ == 'MP4': + # This hack differentiates aac and alac until we find a more + # deterministic approach. if hasattr(self.mgfile.info, 'sample_rate') and \ self.mgfile.info.sample_rate > 0: self.type = 'aac'