Exemple #1
0
 def test_encoding(self):
     tags = compatid3.CompatID3()
     tags.add(id3.TALB(encoding=2, text="abc"))
     tags.add(id3.TIT2(encoding=3, text="abc"))
     tags.update_to_v23()
     self.assertEqual(tags["TALB"].encoding, 1)
     self.assertEqual(tags["TIT2"].encoding, 1)
Exemple #2
0
 def test_tdrc(self):
     tags = compatid3.CompatID3()
     tags.add(id3.TDRC(encoding=1, text="2003-04-05 12:03"))
     tags.update_to_v23()
     self.assertEqual(tags["TYER"].text, ["2003"])
     self.assertEqual(tags["TDAT"].text, ["0504"])
     self.assertEqual(tags["TIME"].text, ["1203"])
Exemple #3
0
 def test_keep_some_v24_tag(self):
     tags = compatid3.CompatID3()
     tags.add(id3.TSOP(encoding=0, text=["foo"]))
     tags.add(id3.TSOA(encoding=0, text=["foo"]))
     tags.add(id3.TSOT(encoding=0, text=["foo"]))
     tags.update_to_v23()
     self.assertEqual(tags["TSOP"].text, ["foo"])
     self.assertEqual(tags["TSOA"].text, ["foo"])
     self.assertEqual(tags["TSOT"].text, ["foo"])
Exemple #4
0
 def _get_tags(self, filename):
     try:
         return compatid3.CompatID3(encode_filename(filename))
     except mutagen.id3.ID3NoHeaderError:
         return compatid3.CompatID3()
Exemple #5
0
 def test_genre_from_v23_2(self):
     tags = compatid3.CompatID3()
     tags.add(id3.TCON(encoding=1, text=["(RX)(3)(CR)"]))
     tags.update_to_v23()
     self.assertEqual(tags["TCON"].text, ["Remix", "Dance", "Cover"])
Exemple #6
0
 def test_genre_from_v23_1(self):
     tags = compatid3.CompatID3()
     tags.add(id3.TCON(encoding=1, text=["(4)Rock"]))
     tags.update_to_v23()
     self.assertEqual(tags["TCON"].text, ["Disco", "Rock"])
Exemple #7
0
 def test_tdor(self):
     tags = compatid3.CompatID3()
     tags.add(id3.TDOR(encoding=1, text="2003-04-05 12:03"))
     tags.update_to_v23()
     self.assertEqual(tags["TORY"].text, ["2003"])
Exemple #8
0
 def test_genre_from_v24_2(self):
     tags = compatid3.CompatID3()
     tags.add(id3.TCON(encoding=Id3Encoding.UTF16, text=["RX", "3", "CR"]))
     tags.update_to_v23()
     self.assertEqual(tags["TCON"].text, ["Remix", "Dance", "Cover"])
Exemple #9
0
 def test_multiple_text_values(self):
     tags = compatid3.CompatID3()
     tags.add(id3.TALB(encoding=0, text=["123", "abc"]))
     tags.update_to_v23()
     self.assertEqual(tags["TALB"].text, ["123/abc"])
Exemple #10
0
    def _save(self, filename, metadata):
        """Save metadata to the file."""
        log.debug("Saving file %r", filename)
        try:
            tags = compatid3.CompatID3(encode_filename(filename))
        except mutagen.id3.ID3NoHeaderError:
            tags = compatid3.CompatID3()

        if config.setting['clear_existing_tags']:
            tags.clear()
        if metadata.images_to_be_saved_to_tags:
            tags.delall('APIC')

        if config.setting['write_id3v1']:
            v1 = 2
        else:
            v1 = 0
        encoding = {
            'utf-8': 3,
            'utf-16': 1
        }.get(config.setting['id3v2_encoding'], 0)

        if 'tracknumber' in metadata:
            if 'totaltracks' in metadata:
                text = '%s/%s' % (metadata['tracknumber'],
                                  metadata['totaltracks'])
            else:
                text = metadata['tracknumber']
            tags.add(id3.TRCK(encoding=0, text=text))

        if 'discnumber' in metadata:
            if 'totaldiscs' in metadata:
                text = '%s/%s' % (metadata['discnumber'],
                                  metadata['totaldiscs'])
            else:
                text = metadata['discnumber']
            tags.add(id3.TPOS(encoding=0, text=text))

        # This is necessary because mutagens HashKey for APIC frames only
        # includes the FrameID (APIC) and description - it's basically
        # impossible to save two images, even of different types, without
        # any description.
        counters = defaultdict(lambda: 0)
        for image in metadata.images_to_be_saved_to_tags:
            desc = desctag = image.comment
            if counters[desc] > 0:
                if desc:
                    desctag = "%s (%i)" % (desc, counters[desc])
                else:
                    desctag = "(%i)" % counters[desc]
            counters[desc] += 1
            tags.add(
                id3.APIC(encoding=0,
                         mime=image.mimetype,
                         type=image_type_as_id3_num(image.maintype),
                         desc=desctag,
                         data=image.data))

        tmcl = mutagen.id3.TMCL(encoding=encoding, people=[])
        tipl = mutagen.id3.TIPL(encoding=encoding, people=[])

        tags.delall('TCMP')
        for name, values in metadata.rawitems():
            if name.startswith('performer:'):
                role = name.split(':', 1)[1]
                for value in values:
                    tmcl.people.append([role, value])
            elif name.startswith('comment:'):
                desc = name.split(':', 1)[1]
                if desc.lower()[:4] == "itun":
                    tags.delall('COMM:' + desc)
                    tags.add(
                        id3.COMM(encoding=0,
                                 desc=desc,
                                 lang='eng',
                                 text=[v + u'\x00' for v in values]))
                else:
                    tags.add(
                        id3.COMM(encoding=encoding,
                                 desc=desc,
                                 lang='eng',
                                 text=values))
            elif name.startswith('lyrics:') or name == 'lyrics':
                if ':' in name:
                    desc = name.split(':', 1)[1]
                else:
                    desc = ''
                for value in values:
                    tags.add(id3.USLT(encoding=encoding, desc=desc,
                                      text=value))
            elif name in self._rtipl_roles:
                for value in values:
                    tipl.people.append([self._rtipl_roles[name], value])
            elif name == 'musicbrainz_recordingid':
                tags.add(
                    id3.UFID(owner='http://musicbrainz.org',
                             data=str(values[0])))
            elif name == '~rating':
                # Search for an existing POPM frame to get the current playcount
                for frame in tags.values():
                    if frame.FrameID == 'POPM' and frame.email == config.setting[
                            'rating_user_email']:
                        count = getattr(frame, 'count', 0)
                        break
                else:
                    count = 0

                # Convert rating to range between 0 and 255
                rating = int(
                    round(
                        float(values[0]) * 255 /
                        (config.setting['rating_steps'] - 1)))
                tags.add(
                    id3.POPM(email=config.setting['rating_user_email'],
                             rating=rating,
                             count=count))
            elif name in self.__rtranslate:
                frameid = self.__rtranslate[name]
                if frameid.startswith('W'):
                    valid_urls = all([all(urlparse(v)[:2]) for v in values])
                    if frameid == 'WCOP':
                        # Only add WCOP if there is only one license URL, otherwise use TXXX:LICENSE
                        if len(values) > 1 or not valid_urls:
                            tags.add(
                                id3.TXXX(encoding=encoding,
                                         desc=self.__rtranslate_freetext[name],
                                         text=values))
                        else:
                            tags.add(id3.WCOP(url=values[0]))
                    elif frameid == 'WOAR' and valid_urls:
                        for url in values:
                            tags.add(id3.WOAR(url=url))
                elif frameid.startswith('T'):
                    tags.add(
                        getattr(id3, frameid)(encoding=encoding, text=values))
                    if frameid == 'TSOA':
                        tags.delall('XSOA')
                    elif frameid == 'TSOP':
                        tags.delall('XSOP')
                    elif frameid == 'TSO2':
                        tags.delall('TXXX:ALBUMARTISTSORT')
            elif name in self.__rtranslate_freetext:
                tags.add(
                    id3.TXXX(encoding=encoding,
                             desc=self.__rtranslate_freetext[name],
                             text=values))
            elif name.startswith('~id3:'):
                name = name[5:]
                if name.startswith('TXXX:'):
                    tags.add(
                        id3.TXXX(encoding=encoding, desc=name[5:],
                                 text=values))
                else:
                    frameclass = getattr(id3, name[:4], None)
                    if frameclass:
                        tags.add(frameclass(encoding=encoding, text=values))
            # don't save private / already stored tags
            elif not name.startswith(
                    "~") and not name in self.__other_supported_tags:
                tags.add(id3.TXXX(encoding=encoding, desc=name, text=values))

        if tmcl.people:
            tags.add(tmcl)
        if tipl.people:
            tags.add(tipl)

        if config.setting['write_id3v23']:
            tags.update_to_v23(join_with=config.setting['id3v23_join_with'])
            tags.save(encode_filename(filename), v2=3, v1=v1)
        else:
            tags.update_to_v24()
            tags.save(encode_filename(filename), v2=4, v1=v1)

        if self._IsMP3 and config.setting["remove_ape_from_mp3"]:
            try:
                mutagen.apev2.delete(encode_filename(filename))
            except:
                pass
Exemple #11
0
    def _save(self, filename, metadata, settings):
        """Save metadata to the file."""
        self.log.debug("Saving file %r", filename)
        try:
            tags = compatid3.CompatID3(encode_filename(filename))
        except mutagen.id3.ID3NoHeaderError:
            tags = compatid3.CompatID3()

        if settings['clear_existing_tags']:
            tags.clear()
        if settings['save_images_to_tags'] and metadata.images:
            tags.delall('APIC')

        if settings['write_id3v1']:
            v1 = 2
        else:
            v1 = 0
        encoding = {'utf-8': 3, 'utf-16': 1}.get(settings['id3v2_encoding'], 0)

        if 'tracknumber' in metadata:
            if 'totaltracks' in metadata:
                text = '%s/%s' % (metadata['tracknumber'],
                                  metadata['totaltracks'])
            else:
                text = metadata['tracknumber']
            tags.add(id3.TRCK(encoding=0, text=text))

        if 'discnumber' in metadata:
            if 'totaldiscs' in metadata:
                text = '%s/%s' % (metadata['discnumber'],
                                  metadata['totaldiscs'])
            else:
                text = metadata['discnumber']
            tags.add(id3.TPOS(encoding=0, text=text))

        if settings['save_images_to_tags']:
            for mime, data in metadata.images:
                tags.add(
                    id3.APIC(encoding=0, mime=mime, type=3, desc='',
                             data=data))

        tmcl = mutagen.id3.TMCL(encoding=encoding, people=[])
        tipl = mutagen.id3.TIPL(encoding=encoding, people=[])

        id3.TCMP = compatid3.TCMP
        tags.delall('TCMP')
        for name, values in metadata.rawitems():
            if name.startswith('performer:'):
                role = name.split(':', 1)[1]
                for value in values:
                    tmcl.people.append([role, value])
            elif name.startswith('comment:'):
                desc = name.split(':', 1)[1]
                if desc.lower()[:4] == "itun":
                    tags.delall('COMM:' + desc)
                    tags.add(
                        id3.COMM(encoding=0,
                                 desc=desc,
                                 lang='eng',
                                 text=[v + u'\x00' for v in values]))
                else:
                    tags.add(
                        id3.COMM(encoding=encoding,
                                 desc=desc,
                                 lang='eng',
                                 text=values))
            elif name.startswith('lyrics:') or name == 'lyrics':
                if ':' in name:
                    desc = name.split(':', 1)[1]
                else:
                    desc = ''
                for value in values:
                    tags.add(id3.USLT(encoding=encoding, desc=desc,
                                      text=value))
            elif name in self.__rtipl_roles:
                for value in values:
                    tipl.people.append([self.__rtipl_roles[name], value])
            elif name == 'musicbrainz_trackid':
                tags.add(
                    id3.UFID(owner='http://musicbrainz.org',
                             data=str(values[0])))
            elif name == '~rating':
                # Search for an existing POPM frame to get the current playcount
                for frame in tags.values():
                    if frame.FrameID == 'POPM' and frame.email == settings[
                            'rating_user_email']:
                        count = getattr(frame, 'count', 0)
                        break
                else:
                    count = 0

                # Convert rating to range between 0 and 255
                rating = int(
                    round(
                        float(values[0]) * 255 /
                        (settings['rating_steps'] - 1)))
                tags.add(
                    id3.POPM(email=settings['rating_user_email'],
                             rating=rating,
                             count=count))
            elif name in self.__rtranslate:
                frameid = self.__rtranslate[name]
                if frameid.startswith('W'):
                    tags.add(getattr(id3, frameid)(url=values[0]))
                elif frameid.startswith('T'):
                    tags.add(
                        getattr(id3, frameid)(encoding=encoding, text=values))
            elif name in self.__rtranslate_freetext:
                tags.add(
                    id3.TXXX(encoding=encoding,
                             desc=self.__rtranslate_freetext[name],
                             text=values))
            elif name.startswith('~id3:'):
                name = name[5:]
                if name.startswith('TXXX:'):
                    tags.add(
                        id3.TXXX(encoding=encoding, desc=name[5:],
                                 text=values))
                else:
                    frameclass = getattr(id3, name[:4], None)
                    if frameclass:
                        tags.add(frameclass(encoding=encoding, text=values))

        if tmcl.people:
            tags.add(tmcl)
        if tipl.people:
            tags.add(tipl)

        if settings['write_id3v23']:
            tags.update_to_v23()
            tags.save(encode_filename(filename), v2=3, v1=v1)
        else:
            # remove all custom 2.3 frames
            for old in self.__upgrade.keys():
                tags.delall(old)
            tags.update_to_v24()
            tags.save(encode_filename(filename), v2=4, v1=v1)

        if self._IsMP3 and settings["remove_ape_from_mp3"]:
            try:
                mutagen.apev2.delete(encode_filename(filename))
            except:
                pass
Exemple #12
0
 def test_genre_from_v24_2(self):
     tags = compatid3.CompatID3()
     tags.add(id3.TCON(encoding=1, text=["RX", "3", "CR"]))
     tags.update_to_v23()
     self.failUnlessEqual(tags["TCON"].text, ["Remix/Dance/Cover"])
Exemple #13
0
 def test_genre_from_v24_1(self):
     tags = compatid3.CompatID3()
     tags.add(id3.TCON(encoding=1, text=["4", "Rock"]))
     tags.update_to_v23()
     self.failUnlessEqual(tags["TCON"].text, ["Disco/Rock"])