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)
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"])
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"])
def _get_tags(self, filename): try: return compatid3.CompatID3(encode_filename(filename)) except mutagen.id3.ID3NoHeaderError: return compatid3.CompatID3()
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"])
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"])
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"])
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"])
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"])
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
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
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"])
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"])