def to_disc_metadata(self):
        from audiotools import MetaData

        return MetaData(album_name=self.get(u"TITLE", None),
                        performer_name=self.get(u"PERFORMER", None),
                        artist_name=self.get(u"SONGWRITER", None),
                        composer_name=self.get(u"COMPOSER", None),
                        comment=self.get(u"MESSAGE", None))
    def delete_metadata(self):
        """deletes the track's MetaData

        this removes or unsets tags as necessary in order to remove all data
        raises IOError if unable to write the file"""

        from audiotools import MetaData

        self.set_metadata(MetaData())
Example #3
0
    def to_track_metadata(self):
        from audiotools import MetaData

        return MetaData(
            track_name=decode_string(self.get("TITLE", None)),
            performer_name=decode_string(self.get("PERFORMER", None)),
            artist_name=decode_string(self.get("SONGWRITER", None)),
            composer_name=decode_string(self.get("COMPOSER", None)),
            comment=decode_string(self.get("MESSAGE", None)),
            ISRC=decode_string(self.get("ISRC", None)))
Example #4
0
    def metadata(self):
        def get_track_metadata(track_node, album_metadata, track_number):
            try:
                #FIXME - not sure if name or sort-name should take precendence
                artist_name = get_xml_text_node(
                    get_xml_nodes(track_node, u'artist')[0], u'name')
            except IndexError:
                artist_name = album_metadata.artist_name

            track_metadata = MetaData(track_name=get_xml_text_node(
                track_node, u'title'),
                                      artist_name=artist_name,
                                      track_number=track_number)

            track_metadata.merge(album_metadata)
            return track_metadata

        try:
            release = self.dom.getElementsByTagName(u'release')[0]
        except IndexError:
            return AlbumMetaData([])

        album_name = get_xml_text_node(release, u'title')

        try:
            #FIXME - not sure if name or sort-name should take precendence
            artist_name = get_xml_text_node(
                get_xml_nodes(release, u'artist')[0], u'name')
        except IndexError:
            artist_name = u''

        try:
            tracks = get_xml_nodes(
                get_xml_nodes(release, u'track-list')[0], u'track')
        except IndexError:
            tracks = []

        album_metadata = MetaData(album_name=album_name,
                                  artist_name=artist_name,
                                  track_total=len(tracks))

        try:
            release_events = get_xml_nodes(release, u'release-event-list')[0]
            event = get_xml_nodes(release_events, u'event')[-1]
            album_metadata.year = event.getAttribute('date')[0:4]
            album_metadata.catalog = event.getAttribute('catalog-number')
        except IndexError:
            pass

        return AlbumMetaData([
            get_track_metadata(track_node=node,
                               album_metadata=album_metadata,
                               track_number=i + 1)
            for (i, node) in enumerate(tracks)
        ])
Example #5
0
    def delete_metadata(self):
        """deletes the track's MetaData

        raises IOError if unable to write the file"""

        if ((self.get_replay_gain() is not None) or
            (self.get_cuesheet() is not None)):
            # non-textual metadata is present and needs preserving
            self.set_metadata(MetaData())
        else:
            # no non-textual metadata, so wipe out the entire block
            from os import access, R_OK, W_OK
            from audiotools.bitstream import BitstreamReader
            from audiotools import transfer_data

            if not access(self.filename, R_OK | W_OK):
                raise IOError(self.filename)

            with open(self.filename, "rb") as f:
                f.seek(-32, 2)

                (preamble,
                 version,
                 tag_size,
                 item_count,
                 read_only,
                 item_encoding,
                 is_header,
                 no_footer,
                 has_header) = BitstreamReader(f, True).parse(
                    ApeTag.HEADER_FORMAT)

            if (preamble == b'APETAGEX') and (version == 2000):
                from audiotools import TemporaryFile
                from os.path import getsize

                # there's existing metadata to delete
                # so rewrite file without trailing metadata tag
                if has_header:
                    old_tag_size = 32 + tag_size
                else:
                    old_tag_size = tag_size

                # copy everything but the last "old_tag_size" bytes
                # from existing file to rewritten file
                new_apev2 = TemporaryFile(self.filename)
                old_apev2 = open(self.filename, "rb")

                limited_transfer_data(
                    old_apev2.read,
                    new_apev2.write,
                    getsize(self.filename) - old_tag_size)

                old_apev2.close()
                new_apev2.close()
Example #6
0
    def delete_metadata(self):
        """deletes the track's MetaData

        this removes or unsets tags as necessary in order to remove all data
        raises IOError if unable to write the file"""

        from audiotools import MetaData

        # the vorbis comment packet is required,
        # so simply zero out its contents
        self.set_metadata(MetaData())
Example #7
0
    def from_cuesheet(cls, cuesheet, total_frames, sample_rate, metadata=None):
        if (metadata is None):
            metadata = MetaData()

        return cls.from_files([
            DummyAudioFile(length=(pcm_frames * 75) / sample_rate,
                           metadata=metadata,
                           track_number=i + 1)
            for (i,
                 pcm_frames) in enumerate(cuesheet.pcm_lengths(total_frames))
        ])
Example #8
0
    def inject_metadata(self, format, version):
        """
        audiotools.MetaData
        """
        meta = MetaData()
        """
        prepare metadata object
        """
        # track-level metadata
        meta.track_name = self.name
        meta.track_number = self.tracknumber
        meta.media = 'DIGITAL'
        meta.isrc = self.isrc
        """ Needs fixing...
        for extra_artist in self.extra_artists.all():
            print extra_artist
        meta.performer_name =
        meta.composer_name =
        meta.conductor_name =
        """

        # release-level metadata
        if self.release:
            meta.album_name = self.release.name
            meta.catalog = self.release.catalognumber
            meta.track_total = len(self.release.media_release.all())

            if self.release.releasedate:
                try:
                    meta.year = str(self.release.releasedate.year)
                    meta.date = str(self.release.releasedate)

                except Exception, e:
                    print e

            try:

                cover_image = self.release.cover_image if self.release.cover_image else self.release.main_image

                if meta.supports_images() and cover_image:
                    for i in meta.images():
                        meta.delete_image(i)

                    opt = dict(size=(200, 200),
                               crop=True,
                               bw=False,
                               quality=80)
                    image = get_thumbnailer(cover_image).get_thumbnail(opt)
                    meta.add_image(get_raw_image(image.path, 0))

            except Exception, e:
                print e
Example #9
0
    def incect_metadata(self, path, media):

        log = logging.getLogger('util.process.Process.incect_metadata')
        log.debug('incect metadata to: %s' % (path))
        log.debug('source: %s' % (media))
        """
        audiotools.MetaData
        """
        meta = MetaData()
        """
        prepare metadata object
        """
        # track-level metadata
        meta.track_name = media.name
        meta.track_number = media.tracknumber
        meta.media = 'DIGITAL'
        meta.isrc = media.isrc
        meta.genre = 2

        # release-level metadata
        if media.release:
            meta.album_name = media.release.name
            meta.catalog = media.release.catalognumber
            meta.track_total = len(media.release.media_release.all())

            if media.release.releasedate:
                try:
                    meta.year = str(media.release.releasedate.year)
                    meta.date = str(media.release.releasedate)

                except Exception, e:
                    print e

            try:

                cover_image = media.release.cover_image if media.release.cover_image else media.release.main_image

                if meta.supports_images() and cover_image:
                    for i in meta.images():
                        meta.delete_image(i)

                    opt = dict(size=(200, 200),
                               crop=True,
                               bw=False,
                               quality=80)
                    image = get_thumbnailer(cover_image).get_thumbnail(opt)
                    meta.add_image(get_raw_image(image.path, 0))

            except Exception, e:
                print e
Example #10
0
        def get_track_metadata(track_node, album_metadata, track_number):
            try:
                #FIXME - not sure if name or sort-name should take precendence
                artist_name = get_xml_text_node(
                    get_xml_nodes(track_node, u'artist')[0], u'name')
            except IndexError:
                artist_name = album_metadata.artist_name

            track_metadata = MetaData(track_name=get_xml_text_node(
                track_node, u'title'),
                                      artist_name=artist_name,
                                      track_number=track_number)

            track_metadata.merge(album_metadata)
            return track_metadata
    def get_metadata(self):
        """returns SheetTrack's MetaData, or None"""

        from audiotools import MetaData

        isrc = self.first_flag(TOCFlag_ISRC)
        cd_text = self.first_flag(CDText)
        if (isrc is not None) and (cd_text is not None):
            metadata = cd_text.to_track_metadata()
            metadata.ISRC = decode_string(isrc.isrc())
            return metadata
        elif cd_text is not None:
            return cd_text.to_track_metadata()
        elif isrc is not None:
            return MetaData(ISRC=decode_string(isrc.isrc()))
        else:
            return None
    def get_metadata(self):
        """returns MetaData of Sheet, or None
        this metadata often contains information such as catalog number
        or CD-TEXT values"""

        from audiotools import MetaData

        if (self.__catalog__ is not None) and (self.__cd_text__ is not None):
            metadata = self.__cd_text__.to_disc_metadata()
            metadata.catalog = self.__catalog__
            return metadata
        elif self.__catalog__ is not None:
            return MetaData(catalog=self.__catalog__)
        elif self.__cd_text__ is not None:
            return self.__cd_text__.to_disc_metadata()
        else:
            return None
Example #13
0
    def set_cuesheet(self, cuesheet):
        import os.path
        import cue

        if (cuesheet is None):
            return

        metadata = self.get_metadata()
        if (metadata is None):
            metadata = WavePackAPEv2.converted(MetaData())

        metadata['Cuesheet'] = WavePackAPEv2.ITEM.string(
            'Cuesheet',
            cue.Cuesheet.file(cuesheet,
                              os.path.basename(self.filename)).decode(
                                  'ascii', 'replace'))
        self.set_metadata(metadata)
Example #14
0
def xmcd_metadata(freedb_file):
    """given a dict of KEY->value unicode strings,
    yields a MetaData object per track"""

    import re

    TTITLE = re.compile(r'TTITLE(\d+)')

    dtitle = freedb_file.get("DTITLE", "")
    if (" / " in dtitle):
        (album_artist, album_name) = dtitle.split(" / ", 1)
    else:
        album_artist = None
        album_name = dtitle

    year = freedb_file.get("DYEAR", None)

    ttitles = [(int(m.group(1)), value) for (m, value) in
               [(TTITLE.match(key), value) for (key, value) in
                freedb_file.items()] if m is not None]

    if (len(ttitles) > 0):
        track_total = max([tracknum for (tracknum, ttitle) in ttitles]) + 1
    else:
        track_total = 0

    for (tracknum, ttitle) in sorted(ttitles, key=lambda t: t[0]):
        if (" / " in ttitle):
            (track_artist,
             track_name) = ttitle.split(" / ", 1)
        else:
            track_artist = album_artist
            track_name = ttitle

        from audiotools import MetaData

        yield MetaData(
            track_name=track_name.decode('utf-8', 'replace'),
            track_number=tracknum + 1,
            track_total=track_total,
            album_name=album_name.decode('utf-8', 'replace'),
            artist_name=(track_artist.decode('utf-8', 'replace')
                         if track_artist is not None else None),
            year=(year.decode('utf-8', 'replace') if
                  year is not None else None))
Example #15
0
    def get_metadata(self):
        """returns SheetTrack's MetaData, or None"""

        from operator import or_
        from functools import reduce

        if (reduce(or_, [(attr is not None) for attr in [
                self.__isrc__, self.__title__, self.__performer__,
                self.__songwriter__
        ]], False)):
            from audiotools import MetaData

            return MetaData(ISRC=self.__isrc__,
                            track_name=self.__title__,
                            performer_name=self.__performer__,
                            artist_name=self.__songwriter__)
        else:
            return None
Example #16
0
    def get_metadata(self):
        """returns MetaData of Sheet, or None
        this metadata often contains information such as catalog number
        or CD-TEXT values"""

        from operator import or_
        from functools import reduce

        if (reduce(or_, [(attr is not None) for attr in [
                self.__catalog__, self.__title__, self.__performer__,
                self.__songwriter__
        ]], False)):
            from audiotools import MetaData

            return MetaData(catalog=self.__catalog__,
                            album_name=self.__title__,
                            performer_name=self.__performer__,
                            artist_name=self.__songwriter__)
        else:
            return None
    def set_cuesheet(self, cuesheet):
        """Imports cuesheet data from a Cuesheet-compatible object.

        This are objects with catalog(), ISRCs(), indexes(), and pcm_lengths()
        methods.  Raises IOError if an error occurs setting the cuesheet."""

        import os.path
        import cue

        if (cuesheet is None):
            return

        metadata = self.get_metadata()
        if (metadata is None):
            metadata = WavPackAPEv2.converted(MetaData())

        metadata['Cuesheet'] = WavPackAPEv2.ITEM.string(
            'Cuesheet',
            cue.Cuesheet.file(cuesheet,
                              os.path.basename(self.filename)).decode(
                                  'ascii', 'replace'))
        self.set_metadata(metadata)
Example #18
0
    def metadata(self):
        dtitle = self.get('DTITLE', u'')
        if (u' / ' in dtitle):
            (album_artist, album_name) = dtitle.split(u' / ', 1)
        else:
            (album_artist, album_name) = (dtitle, dtitle)

        dyear = self.get('DYEAR', u'')

        tracks = []

        for key in self.keys():
            if (key.startswith('TTITLE')):
                tracknum = self.key_digits(key)
                if (tracknum == -1):
                    continue

                ttitle = self[key]

                if (u' / ' in ttitle):
                    (track_artist, track_name) = ttitle.split(u' / ', 1)
                else:
                    track_name = ttitle
                    track_artist = album_artist

                tracks.append(
                    MetaData(track_name=track_name,
                             track_number=tracknum + 1,
                             album_name=album_name,
                             artist_name=track_artist,
                             year=dyear))

        track_total = max([t.track_number for t in tracks])
        for t in tracks:
            t.track_total = track_total
        tracks.sort(lambda t1, t2: cmp(t1.track_number, t2.track_number))
        return AlbumMetaData(tracks)
Example #19
0
def parse_release(release, disc_id):
    """given a <release> Element node and DiscID object
    yields a populated MetaData object per track
    may raise KeyError if the given DiscID is not found in the <release>"""

    # <release> may contain <title>
    try:
        album_name = text(get_node(release, u"title"))
    except KeyError:
        album_name = None

    # <release> may contain <artist-credit>
    try:
        album_artist = artist(get_node(release, u"artist-credit"))
    except KeyError:
        album_artist = None

    # <release> may contain <label-info-list>
    try:
        # <label-info-list> contains 0 or more <label-info>s
        for label_info in get_nodes(get_node(release, u"label-info-list"),
                                    u"label-info"):
            # <label-info> may contain <catalog-number>
            try:
                catalog = text(get_node(label_info, u"catalog-number"))
            except KeyError:
                catalog = None
            # <label-info> may contain <label>
            # and <label> may contain <name>
            try:
                publisher = text(get_node(label_info, u"label", u"name"))
            except KeyError:
                publisher = None

            # we'll use the first result found
            break
        else:
            # <label-info-list> with no <label-info> tags
            catalog = None
            publisher = None
    except KeyError:
        catalog = None
        publisher = None

    # <release> may contain <date>
    try:
        year = text(get_node(release, u"date"))[0:4]
    except:
        year = None

    # find exact disc in <medium-list> tag
    # depending on disc_id value
    try:
        medium_list = get_node(release, u"medium-list")
    except KeyError:
        # no media found for disc ID
        raise KeyError(disc_id)

    for medium in get_nodes(medium_list, u"medium"):
        try:
            if (disc_id.__unicode__() in
                [disc.getAttribute(u"id")
                 for disc in get_nodes(get_node(medium, u"disc-list"),
                                       u"disc")]):
                # found requested disc_id in <medium>'s list of <disc>s
                # so use that medium node to find additional info
                break
        except KeyError:
            # no <disc-list> tag found in <medium>
            continue
    else:
        # our disc_id wasn't found in any of the <release>'s <medium>s
        raise KeyError(disc_id)

    # if multiple discs in <medium-list>,
    # populate album number and album total
    if ((medium_list.hasAttribute(u"count") and
         (int(medium_list.getAttribute(u"count")) > 1))):
        album_total = int(medium_list.getAttribute(u"count"))
        try:
            album_number = int(text(get_node(medium, u"position")))
        except KeyError:
            album_number = None
    else:
        album_total = album_number = None

    # <medium> must contain <track-list>
    tracks = get_nodes(get_node(medium, u"track-list"), u"track")
    track_total = len(tracks)
    # and <track-list> contains 0 or more <track>s
    for (i, track) in enumerate(tracks, 1):
        # if <track> contains title use that for track_name
        try:
            track_name = text(get_node(track, u"title"))
        except KeyError:
            track_name = None

        # if <track> contains <artist-credit> use that for track_artist
        try:
            track_artist = artist(get_node(release, u"artist-credit"))
        except KeyError:
            track_artist = None

        # if <track> contains a <recording>
        # use that for track_name and track artist
        try:
            recording = get_node(track, u"recording")

            # <recording> may contain a <title>
            if track_name is None:
                try:
                    track_name = text(get_node(recording, u"title"))
                except KeyError:
                    track_name = None

            # <recording> may contain <artist-credit>
            if track_artist is None:
                try:
                    track_artist = artist(get_node(recording,
                                                   u"artist-credit"))
                except KeyError:
                    track_artist = album_artist
        except KeyError:
            # no <recording> in <track>

            if track_artist is None:
                track_artist = album_artist

        # <track> may contain a <position>
        try:
            track_number = int(text(get_node(track, u"position")))
        except KeyError:
            track_number = i

        # yield complete MetaData object
        from audiotools import MetaData

        yield MetaData(track_name=track_name,
                       track_number=track_number,
                       track_total=track_total,
                       album_name=album_name,
                       artist_name=track_artist,
                       performer_name=None,
                       composer_name=None,
                       conductor_name=None,
                       ISRC=None,
                       catalog=catalog,
                       copyright=None,
                       publisher=publisher,
                       year=year,
                       album_number=album_number,
                       album_total=album_total,
                       comment=None)