Skip to content
Snippets Groups Projects
metadata.py 3.51 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
    class TagNotFound(KeyError):
        pass
    
    
    def get_id3_tag(f, k):
        # First we try to grab the standard key
        try:
            return f.tags[k].text[0]
        except KeyError:
            pass
        # then we fallback on parsing non standard tags
        all_tags = f.tags.getall('TXXX')
        try:
            matches = [
                t
                for t in all_tags
                if t.desc.lower() == k.lower()
            ]
            return matches[0].text[0]
        except (KeyError, IndexError):
            raise TagNotFound(k)
    
    
    def get_mp3_recording_id(f, k):
        try:
            return [
                t
                for t in f.tags.getall('UFID')
                if 'musicbrainz.org' in t.owner
            ][0].data.decode('utf-8')
        except IndexError:
            raise TagNotFound(k)
    
    
    
    def convert_track_number(v):
        try:
            return int(v)
        except ValueError:
            # maybe the position is of the form "1/4"
            pass
    
        try:
            return int(v.split('/')[0])
        except (ValueError, AttributeError, IndexError):
            pass
    
    
    CONF = {
        'OggVorbis': {
            'getter': lambda f, k: f[k][0],
            'fields': {
                'track_number': {
                    'field': 'TRACKNUMBER',
    
                    'to_application': convert_track_number
    
                },
                'title': {
                    'field': 'title'
                },
                'artist': {
                    'field': 'artist'
                },
                'album': {
                    'field': 'album'
                },
                'date': {
                    'field': 'date',
                    'to_application': lambda v: arrow.get(v).date()
                },
                'musicbrainz_albumid': {
                    'field': 'musicbrainz_albumid'
                },
                'musicbrainz_artistid': {
                    'field': 'musicbrainz_artistid'
                },
                'musicbrainz_recordingid': {
                    'field': 'musicbrainz_trackid'
                },
            }
        },
        'MP3': {
            'getter': get_id3_tag,
            'fields': {
                'track_number': {
                    'field': 'TPOS',
    
                    'to_application': convert_track_number
    
                },
                'title': {
                    'field': 'TIT2'
                },
                'artist': {
                    'field': 'TPE1'
                },
                'album': {
                    'field': 'TALB'
                },
                'date': {
                    'field': 'TDRC',
                    'to_application': lambda v: arrow.get(str(v)).date()
                },
                'musicbrainz_albumid': {
                    'field': 'MusicBrainz Album Id'
                },
                'musicbrainz_artistid': {
                    'field': 'MusicBrainz Artist Id'
                },
                'musicbrainz_recordingid': {
                    'field': 'UFID',
                    'getter': get_mp3_recording_id,
                },
            }
    
    
        def __init__(self, path):
            self._file = mutagen.File(path)
    
            self._conf = CONF[self.get_file_type(self._file)]
    
        def get_file_type(self, f):
            return f.__class__.__name__
    
        def get(self, key, default=NODEFAULT):
            field_conf = self._conf['fields'][key]
            real_key = field_conf['field']
    
                getter = field_conf.get('getter', self._conf['getter'])
                v = getter(self._file, real_key)
    
            converter = field_conf.get('to_application')
            if converter:
                v = converter(v)