Пример #1
0
def Tags(path, fileformat=None):
    """
    Loader for file metadata tags. Tag reading and writing for various
    file formats is implemented by tag formatter classes in module
    soundforest.tags.formats, initialized automatically by this class.
    """
    if not os.path.isfile(path):
        raise TagError('No such file: %s' % path)

    path = normalized(os.path.realpath(path))

    if fileformat is None:
        fileformat = AudioFileFormat(path)

    if not isinstance(fileformat, AudioFileFormat):
        raise TagError('File format must be AudioFileFormat instance')

    fileformat = fileformat
    if fileformat.is_metadata:
        raise TagError('Attempting to load audio tags from metadata file')

    if fileformat.codec is None:
        raise TagError('Unsupported audio file: %s' % path)

    tag_parser = fileformat.get_tag_parser()
    if tag_parser is None:
        return None

    return tag_parser(fileformat.codec, path)
Пример #2
0
 def import_albumart(self, albumart):
     """
     Parent method to set albumart tag. Child class must
     implement actual embedding of the tag to file.
     """
     if not isinstance(albumart, AlbumArt):
         raise TagError('Albumart must be AlbumArt instance')
     if not albumart.is_loaded:
         raise TagError('Albumart to import is not loaded with image.')
     self.albumart = albumart
Пример #3
0
    def __getitem__(self, item):
        """
        Return tags formatted to unicode, decimal.Decimal or
        other supported types.
        Does not include albumart images, which are accessed
        by self.__getattr__('albumart')
        """
        if item == 'tracknumber':
            return [unicode('%d' % self.track_numbering.value)]
        if item == 'totaltracks':
            return [unicode('%d' % self.track_numbering.total)]
        if item == 'disknumber':
            return [unicode('%d' % self.disk_numbering.value)]
        if item == 'totaldisks':
            return [unicode('%d' % self.disk_numbering.total)]

        if item[:5] == 'APIC:':
            return self.albumart_obj

        fields = self.__tag2fields__(item)
        for field in fields:
            if not self.entry.has_key(field):
                continue
            tag = self.entry[field]
            if not isinstance(tag, list):
                tag = [tag]
            values = []
            for value in tag:
                matched = False
                for field in ['text', 'url']:
                    if hasattr(value, field):
                        value = getattr(value, field)
                        if isinstance(value, list):
                            value = value[0]
                        matched = True
                        break

                if value is None:
                    continue

                if not matched:
                    raise TagError('Error parsing %s: %s' % (tag, dir(value)))

                if not isinstance(value, unicode):
                    try:
                        value = '%d' % int(str(value))
                    except ValueError, emsg:
                        pass
                    try:
                        value = unicode(value, 'utf-8')
                    except UnicodeDecodeError, emsg:
                        raise TagError('Error decoding %s tag %s: %s' %
                                       (self.path, field, emsg))
                values.append(value)
Пример #4
0
    def get_tag(self, item):
        """
        Return tag from file. Raises TagError if tag is not found.
        """
        if not self.has_key(item):
            raise TagError('No such tag: %s' % item)

        value = self.__normalized_tag__(item)
        if value is None:
            raise TagError('No such string tag: %s' % item)

        return value
Пример #5
0
    def __getitem__(self, item):
        """
        Return tags formatted to unicode, decimal.Decimal or
        other supported types.
        Does not include albumart images, which are accessed
        via self.albumart attribute
        """
        fields = self.__tag2fields__(item)
        for field in fields:
            if field not in self.entry:
                continue

            tag = self.entry[field]
            if not isinstance(tag, list):
                tag = [tag]

            values = []
            for value in tag:
                if not isinstance(value, unicode):
                    if isinstance(value, int):
                        value = unicode('%d' % value)

                    else:
                        try:
                            value = unicode(value, 'utf-8')
                        except UnicodeDecodeError, emsg:
                            raise TagError('Error decoding %s tag %s: %s' %
                                           (self.path, field, emsg))

                values.append(value)

            return values
Пример #6
0
 def save(self, path):
     """
     Save current albumart to given pathname
     """
     if self.albumart is None:
         raise TagError('Error saving albumart: albumart is not loaded')
     self.albumart.save(path)
Пример #7
0
 def as_base64_tag(self):
     """
     Return albumart image data as base64_tag tag
     """
     if self.albumart is None:
         raise TagError('Albumart is not loaded')
     return base64_tag(base64.b64encode(self.albumart.dump()))
Пример #8
0
    def update_tags(self, data):
        if not isinstance(data, dict):
            raise TagError('Updated tags must be a dictionary instance')

        for k, v in data.items():
            self.set_tag(k, v)

        return self.modified
Пример #9
0
    def __init__(self, track):
        if not isinstance(track, mp3):
            raise TagError('Track is not instance of mp3')
        TrackAlbumart.__init__(self, track)

        try:
            self.tag = filter(lambda k: k[:5] == 'APIC:',
                              self.track.entry.keys())[0]
        except IndexError:
            self.tag = None
            return

        try:
            albumart = AlbumArt()
            albumart.import_data(self.track.entry[self.tag].data)
        except AlbumArtError, emsg:
            raise TagError('Error reading mp3 albumart tag: %s' % emsg)
Пример #10
0
    def replace_tags(self, data):
        """Replace tags

        Set tags given in data dictionary, removing any existing tags.
        """
        if not isinstance(data, dict):
            raise TagError('Updated tags must be a dictionary instance')

        self.clear_tags()

        return self.update_tags(data)
Пример #11
0
def encode_frame(tag, value):
    """
    Return a mp3 frame object matching tag
    """
    try:
        m = __import__('mutagen.id3', globals(), {}, tag)
        tagclass = getattr(m, tag)
        if tagclass is None:
            raise AttributeError
    except AttributeError, emsg:
        raise TagError('Error importing ID3 frame %s: %s' % (tag, emsg))
Пример #12
0
    def __init__(self, codec, path):
        TagParser.__init__(self, codec, path, tag_map=MP3_STANDARD_TAGS)

        try:
            self.entry = MP3(self.path, ID3=ID3)
        except IOError:
            raise TagError('No ID3 header in %s' % self.path)
        except ID3NoHeaderError:
            raise TagError('No ID3 header in %s' % self.path)
        except RuntimeError:
            raise TagError('Runtime error loading %s' % self.path)

        try:
            self.entry.add_tags()
        except ID3Error:
            pass

        self.albumart_obj = MP3AlbumArt(self)
        self.track_numbering = MP3NumberingTag(self, 'TRCK')
        self.disk_numbering = MP3NumberingTag(self, 'TPOS')
Пример #13
0
    def __setattr__(self, attr, value):
        if attr in ['value', 'total']:
            if isinstance(value, list):
                value = value[0]

            try:
                if value is not None:
                    value = int(value)
            except ValueError:
                raise TagError('TrackNumberingTag values must be integers')
            except TypeError:
                raise TagError('TrackNumberingTag values must be integers')

            if attr == 'value':
                self.f_value = value

            if attr == 'total':
                self.f_total = value

        else:
            object.__setattr__(self, attr, value)
Пример #14
0
    def __init__(self, track, tag):
        TrackNumberingTag.__init__(self, track, tag)

        if not self.track.entry.has_key(self.tag):
            return

        try:
            self.value, self.total = self.track.entry[self.tag].text[0].split(
                '/')
        except ValueError:
            self.value = self.track.entry[self.tag].text[0]
            self.total = self.value

        try:
            self.value = int(self.value)
            self.total = int(self.total)
        except ValueError:
            raise TagError('Unsupported tag value for %s: %s' %
                           (self.tag, self.track.entry[self.tag].text[0]))
Пример #15
0
        """
        try:
            for attr in ('track_numbering', 'disk_numbering'):
                try:
                    tag = getattr(self, attr)
                    tag.save_tag()
                except ValueError, emsg:
                    logger.debug('Error processing %s: %s' % (attr, emsg))

            if not self.modified:
                return

            self.entry.save()

        except OSError, (ecode, emsg):
            raise TagError(emsg)

        except IOError, (ecode, emsg):
            raise TagError(emsg)


class TrackAlbumart(object):
    """
    Parent class for common albumart operations
    """
    def __init__(self, track):
        self.track = track
        self.modified = False
        self.albumart = None

    def __repr__(self):
Пример #16
0
 def remove_tag(self, item):
     if not self.has_key(item):
         raise TagError('No such tag: %s' % item)
     del self[tag]
Пример #17
0
 def set_albumart(self, albumart):
     if not self.supports_albumart:
         raise TagError('Format does not support albumart')
     return self.albumart.import_albumart(albumart)
Пример #18
0
 def __setitem__(self, item, value):
     if isinstance(item, AlbumArt):
         try:
             self.albumart_obj.import_albumart(value)
         except AlbumArtError, emsg:
             raise TagError('Error setting albumart: %s' % emsg)