def test_tyer_tdat(self): id3 = ID3() id3.version = (2, 3) id3.add(TYER(encoding=0, text="2006")) id3.add(TDAT(encoding=0, text="0603")) id3.update_to_v24() self.failUnlessEqual(id3["TDRC"], "2006-03-06")
def setter(id3, key, value): try: frame = id3[frameid] except KeyError: id3.add(mutagen.id3.Frames[frameid](encoding=3, text=value)) else: frame.text = value
def genre_set(id3, key, value): try: frame = id3["TCON"] except KeyError: id3.add(mutagen.id3.TCON(encoding=3, text=value)) else: frame.encoding = 3 frame.genres = value
def test_chap_subframes(self): id3 = ID3() id3.version = (2, 3) id3.add(CHAP(element_id="foo", start_time=0, end_time=0, start_offset=0, end_offset=0, sub_frames=[TYER(encoding=0, text="2006")])) id3.update_to_v24() chap = id3.getall("CHAP:foo")[0] self.assertEqual(chap.sub_frames.getall("TDRC")[0], u"2006")
def setter(id3, key, value): enc = 0 # Store 8859-1 if we can, per MusicBrainz spec. for v in value: if v and max(v) > u"\x7f": enc = 3 break id3.add(mutagen.id3.TXXX(encoding=enc, text=value, desc=desc))
def gain_set(id3, key, value): if len(value) != 1: raise ValueError("there must be exactly one gain value, not %r.", value) gain = float(value[0].split()[0]) try: frame = id3["RVA2:" + key[11:-5]] except KeyError: frame = mutagen.id3.RVA2(desc=key[11:-5], gain=0, peak=0, channel=1) id3.add(frame) frame.gain = gain
def performer_set(id3, key, value): wanted_role = key.split(":", 1)[1] try: mcl = id3["TMCL"] except KeyError: mcl = mutagen.id3.TMCL(encoding=3, people=[]) id3.add(mcl) people = [p for p in mcl.people if p[0] != wanted_role] for v in value: people.append((wanted_role, v)) mcl.people = people
def test_ctoc_subframes(self): id3 = ID3() id3.version = (2, 3) id3.add(CTOC(sub_frames=[TYER(encoding=0, text="2006")])) id3.update_to_v24() ctoc = id3.getall("CTOC")[0] self.assertEqual(ctoc.sub_frames.getall("TDRC")[0], u"2006") self.assertFalse(ctoc.sub_frames.getall("TYER")) id3.update_to_v23() self.assertEqual(ctoc.sub_frames.getall("TYER")[0], u"2006")
def musicbrainz_trackid_set(id3, key, value): if len(value) != 1: raise ValueError("only one track ID may be set per song") value = value[0].encode('ascii') try: frame = id3["UFID:http://musicbrainz.org"] except KeyError: frame = mutagen.id3.UFID(owner="http://musicbrainz.org", data=value) id3.add(frame) else: frame.data = value
def write_tags(self): """Write all ID3v2.4 tags by mapping dub2id3_dict dictionnary with the respect of mutagen classes and methods""" from mutagen import id3 id3 = id3.ID3(self.dest) for tag in self.metadata.keys(): if tag in self.dub2id3_dict.keys(): frame_text = self.dub2id3_dict[tag] value = self.metadata[tag] frame = mutagen.id3.Frames[frame_text](3,value) id3.add(frame) id3.save()
def peak_set(id3, key, value): if len(value) != 1: raise ValueError("there must be exactly one peak value, not %r.", value) peak = float(value[0]) if peak >= 2 or peak < 0: raise ValueError("peak must be => 0 and < 2.") try: frame = id3["RVA2:" + key[11:-5]] except KeyError: frame = mutagen.id3.RVA2(desc=key[11:-5], gain=0, peak=0, channel=1) id3.add(frame) frame.peak = peak
def setter(id3, key, value): try: frame = id3[frameid] except KeyError: enc = 0 # Store 8859-1 if we can, per MusicBrainz spec. for v in value: if max(v) > u'\x7f': enc = 3 id3.add(mutagen.id3.TXXX(encoding=enc, text=value, desc=desc)) else: frame.text = value
def peak_set_with_txxx(id3, key, value): frameid = 'TXXX:' + key try: frame = id3[frameid] except KeyError: enc = get_best_txxx_encoding(value) id3.add(mutagen.id3.TXXX(encoding=enc, text=value, desc=key)) else: frame.text = value return peak_set(id3, key, value)
def setter(id3, key, value): try: frame = id3[frameid] except KeyError: enc = 0 # Store 8859-1 if we can, per MusicBrainz spec. for v in value: if v and max(v) > u'\x7f': enc = 3 break id3.add(mutagen.id3.TXXX(encoding=enc, text=value, desc=desc)) else: frame.text = value
def setter(id3, key, value): try: frame = id3[frameid] except KeyError: enc = 0 # Store 8859-1 if we can, per MusicBrainz spec. try: for v in value: v.encode('latin_1') except UnicodeError: enc = 3 id3.add(mutagen.id3.TXXX(encoding=enc, text=value, desc=desc)) else: frame.text = value
def write_metadata(self): """Write all ID3v2.4 tags to file from self.metadata""" from mutagen import id3 id3 = id3.ID3(self.filename) for tag in self.metadata.keys(): value = self.metadata[tag] frame = mutagen.id3.Frames[tag](3,value) try: id3.add(frame) except: raise IOError('EncoderError: cannot tag "'+tag+'"') try: id3.save() except: raise IOError('EncoderError: cannot write tags')
def test_chap_subframes(self): id3 = ID3() id3.version = (2, 3) id3.add( CHAP(element_id="foo", start_time=0, end_time=0, start_offset=0, end_offset=0, sub_frames=[TYER(encoding=0, text="2006")])) id3.update_to_v24() chap = id3.getall("CHAP:foo")[0] self.assertEqual(chap.sub_frames.getall("TDRC")[0], u"2006") self.assertFalse(chap.sub_frames.getall("TYER")) id3.update_to_v23() self.assertEqual(chap.sub_frames.getall("TYER")[0], u"2006")
def write_metadata(self): """Write all ID3v2.4 tags to file from self.metadata""" import mutagen from mutagen import id3 id3 = id3.ID3(self.filename) for tag in self.metadata.keys(): value = self.metadata[tag] frame = mutagen.id3.Frames[tag](3, value) try: id3.add(frame) except: raise IOError('EncoderError: cannot tag "' + tag + '"') try: id3.save() except: raise IOError('EncoderError: cannot write tags')
def test_unknown_chap(self): # add ctoc id3 = ID3(self.filename) id3.add(CTOC(element_id="foo", flags=3, child_element_ids=["ch0"], sub_frames=[TIT2(encoding=3, text=["bla"])])) id3.save() # pretend we don't know ctoc and save id3 = ID3(self.filename, known_frames={"CTOC": CTOC}) ctoc = id3.getall("CTOC")[0] self.assertFalse(ctoc.sub_frames) self.assertTrue(ctoc.sub_frames.unknown_frames) id3.save() # make sure we wrote all sub frames back id3 = ID3(self.filename) self.assertEqual( id3.getall("CTOC")[0].sub_frames.getall("TIT2")[0].text, ["bla"])
def write_tags(self): """Write all ID3v2.4 tags by mapping dub2id3_dict dictionnary with the respect of mutagen classes and methods""" from mutagen import id3 id3 = id3.ID3(self.dest) for tag in self.metadata.keys(): if tag in self.dub2id3_dict.keys(): frame_text = self.dub2id3_dict[tag] value = self.metadata[tag] frame = mutagen.id3.Frames[frame_text](3,value) try: id3.add(frame) except: raise IOError('EncoderError: cannot tag "'+tag+'"') try: id3.save() except: raise IOError('EncoderError: cannot write tags')
def test_merge(self): id3 = ID3(self.filename) id3.delete() id3.add(mutagen.id3.TALB(text=[u"foo"])) id3.save(v2_version=3) target = ID3() target.add(mutagen.id3.TPE1(text=[u"bar", u"quux"])) target.save(self.blank_file, v2_version=4) res, out, err = self.call2( self.filename, self.blank_file, fsn(u"--merge")) assert not any([res, out, err]) result = ID3(self.blank_file) assert result.version == (2, 4, 0) assert result.getall("TALB")[0].text == [u"foo"] assert result.getall("TPE1")[0].text == [u"bar", u"quux"]
def comment_txxx_set_fallback(cls, id3, key, value): frameid = 'TXXX:' if key is None or key == 'comment': frameid = 'COMM' else: frameid = frameid + key try: frame = id3[frameid] except KeyError: enc = get_best_txxx_encoding(value) if key is None: id3.add(mutagen.id3.COMM(encoding=enc, text=value)) else: id3.add(mutagen.id3.TXXX(encoding=enc, text=value, desc=key)) else: frame.text = value
def process(folder): os.chdir(folder) folder = os.getcwd() walk_result = os.walk(folder) for f in walk_result: (dirpath, dirnames, filenames) = f args = dirpath[len(folder) :].split("/") artist = "Unknown" if (len(args) < 2) else args[1] album = "Unknown" if (len(args) < 3) else args[2] print "Artist:", artist, ", album:", album for file in filenames: if file[-4:].lower() != ".mp3": continue title = file[:-4] fullpath = dirpath + "/" + file print title if os.access(fullpath, os.R_OK | os.W_OK) == False: print "Error: bad permissions on", fullpath continue # mutagen.id3.delete(fullpath) id3 = mutagen.id3.ID3() id3.add(mutagen.id3.TPE1(encoding=3, text=artist.decode("utf-8"))) id3.add(mutagen.id3.TALB(encoding=3, text=album.decode("utf-8"))) id3.add(mutagen.id3.TIT2(encoding=3, text=title.decode("utf-8"))) id3.save(fullpath)
def process(folder): os.chdir(folder) folder = os.getcwd() walk_result = os.walk(folder) for f in walk_result: (dirpath, dirnames, filenames) = f args = dirpath[len(folder):].split('/') artist = 'Unknown' if (len(args) < 2) else args[1] album = 'Unknown' if (len(args) < 3) else args[2] print "Artist:", artist, ", album:", album for file in filenames: if file[-4:].lower() != '.mp3': continue title = file[:-4] fullpath = dirpath + "/" + file print title if (os.access(fullpath, os.R_OK | os.W_OK) == False): print 'Error: bad permissions on', fullpath continue #mutagen.id3.delete(fullpath) id3 = mutagen.id3.ID3() id3.add(mutagen.id3.TPE1(encoding = 3, text = artist.decode("utf-8"))) id3.add(mutagen.id3.TALB(encoding = 3, text = album.decode("utf-8"))) id3.add(mutagen.id3.TIT2(encoding = 3, text = title.decode("utf-8"))) id3.save(fullpath)
def test_tyer_tdat_time(self): id3 = ID3() id3.version = (2, 3) id3.add(TYER(encoding=0, text="2006")) id3.add(TDAT(encoding=0, text="0603")) id3.add(TIME(encoding=0, text="1127")) id3.update_to_v24() self.failUnlessEqual(id3["TDRC"], "2006-03-06 11:27:00")
def test_multiple_tyer_tdat_time(self): id3 = ID3() id3.version = (2, 3) id3.add(TYER(text=['2000', '2001', '2002', '19xx', 'foo'])) id3.add(TDAT(text=['0102', '0304', '1111bar'])) id3.add(TIME(text=['1220', '1111quux', '1111'])) id3.update_to_v24() assert [str(t) for t in id3['TDRC']] == \ ['2000-02-01 12:20:00', '2001-04-03', '2002']
def website_set(id3, key, value): id3.delall("WOAR") for v in value: id3.add(mutagen.id3.WOAR(url=v))
def original_date_set(id3, key, value): id3.add(mutagen.id3.TDOR(encoding=3, text=value))
def test_tory(self): id3 = ID3() id3.version = (2, 3) id3.add(TORY(encoding=0, text="2006")) id3.update_to_v24() self.failUnlessEqual(id3["TDOR"], "2006")
def lyrics_set(id3: ID3, key: str, value: List[str]) -> None: assert len(value) == 1 id3.add(mutagen.id3.USLT(text=value[0], lang='eng'))
def picture_set(id3: ID3, key: str, value: List[bytes]) -> None: assert len(value) == 1 id3.add(mutagen.id3.APIC(data=value[0], mime=image_info(value[0])[2]))
def date_set(id3, key, value): id3.add(mutagen.id3.TDRC(encoding=3, text=value))
def test_time_dropped(self): id3 = ID3() id3.version = (2, 3) id3.add(TIME(encoding=0, text=["1155"])) id3.update_to_v24() self.assertFalse(id3.getall("TIME"))
def test_rvad_dropped(self): id3 = ID3() id3.version = (2, 3) id3.add(RVAD()) id3.update_to_v24() self.assertFalse(id3.getall("RVAD"))
def write_files(edits, filenames, escape): # unescape escape sequences and decode values encoded_edits = [] for frame, value in edits: if not value: continue try: frame = frame_from_fsnative(frame) except ValueError as err: print_(text_type(err), file=sys.stderr) assert isinstance(frame, str) # strip "--" frame = frame[2:] try: value = value_from_fsnative(value, escape) except ValueError as err: error(u"%s: %s" % (frame, text_type(err))) assert isinstance(value, text_type) encoded_edits.append((frame, value)) edits = encoded_edits # preprocess: # for all [frame,value] pairs in the edits list # gather values for identical frames into a list tmp = {} for frame, value in edits: if frame in tmp: tmp[frame].append(value) else: tmp[frame] = [value] # edits is now a dictionary of frame -> [list of values] edits = tmp # escape also enables escaping of the split separator if escape: string_split = split_escape else: string_split = lambda s, *args, **kwargs: s.split(*args, **kwargs) for filename in filenames: with _sig.block(): if verbose: print_(u"Writing", filename, file=sys.stderr) try: id3 = mutagen.id3.ID3(filename) except mutagen.id3.ID3NoHeaderError: if verbose: print_(u"No ID3 header found; creating a new tag", file=sys.stderr) id3 = mutagen.id3.ID3() except Exception as err: print_(str(err), file=sys.stderr) continue for (frame, vlist) in edits.items(): if frame == "POPM": for value in vlist: values = string_split(value, ":") if len(values) == 1: email, rating, count = values[0], 0, 0 elif len(values) == 2: email, rating, count = values[0], values[1], 0 else: email, rating, count = values frame = mutagen.id3.POPM(email=email, rating=int(rating), count=int(count)) id3.add(frame) elif frame == "APIC": for value in vlist: values = string_split(value, ":") # FIXME: doesn't support filenames with an invalid # encoding since we have already decoded at that point fn = values[0] if len(values) >= 2: desc = values[1] else: desc = u"cover" if len(values) >= 3: try: picture_type = int(values[2]) except ValueError: error(u"Invalid picture type: %r" % values[1]) else: picture_type = PictureType.COVER_FRONT if len(values) >= 4: mime = values[3] else: mime = mimetypes.guess_type(fn)[0] or "image/jpeg" if len(values) >= 5: error("APIC: Invalid format") encoding = get_frame_encoding(frame, desc) try: with open(fn, "rb") as h: data = h.read() except IOError as e: error(text_type(e)) frame = mutagen.id3.APIC(encoding=encoding, mime=mime, desc=desc, type=picture_type, data=data) id3.add(frame) elif frame == "COMM": for value in vlist: values = string_split(value, ":") if len(values) == 1: value, desc, lang = values[0], "", "eng" elif len(values) == 2: desc, value, lang = values[0], values[1], "eng" else: value = ":".join(values[1:-1]) desc, lang = values[0], values[-1] frame = mutagen.id3.COMM(encoding=3, text=value, lang=lang, desc=desc) id3.add(frame) elif frame == "UFID": for value in vlist: values = string_split(value, ":") if len(values) != 2: error(u"Invalid value: %r" % values) owner = values[0] data = values[1].encode("utf-8") frame = mutagen.id3.UFID(owner=owner, data=data) id3.add(frame) elif frame == "TXXX": for value in vlist: values = string_split(value, ":", 1) if len(values) == 1: desc, value = "", values[0] else: desc, value = values[0], values[1] frame = mutagen.id3.TXXX(encoding=3, text=value, desc=desc) id3.add(frame) elif issubclass(mutagen.id3.Frames[frame], mutagen.id3.UrlFrame): frame = mutagen.id3.Frames[frame](encoding=3, url=vlist) id3.add(frame) else: frame = mutagen.id3.Frames[frame](encoding=3, text=vlist) id3.add(frame) id3.save(filename)
def write_files(edits, filenames, escape): # unescape escape sequences and decode values encoded_edits = [] for frame, value in edits: if not value: continue try: frame = frame_from_fsnative(frame) except ValueError as err: print_(text_type(err), file=sys.stderr) assert isinstance(frame, str) # strip "--" frame = frame[2:] try: value = value_from_fsnative(value, escape) except ValueError as err: error(u"%s: %s" % (frame, text_type(err))) assert isinstance(value, text_type) encoded_edits.append((frame, value)) edits = encoded_edits # preprocess: # for all [frame,value] pairs in the edits list # gather values for identical frames into a list tmp = {} for frame, value in edits: if frame in tmp: tmp[frame].append(value) else: tmp[frame] = [value] # edits is now a dictionary of frame -> [list of values] edits = tmp # escape also enables escaping of the split separator if escape: string_split = split_escape else: string_split = lambda s, *args, **kwargs: s.split(*args, **kwargs) for filename in filenames: with _sig.block(): if verbose: print_(u"Writing", filename, file=sys.stderr) try: id3 = mutagen.id3.ID3(filename) except mutagen.id3.ID3NoHeaderError: if verbose: print_(u"No ID3 header found; creating a new tag", file=sys.stderr) id3 = mutagen.id3.ID3() except Exception as err: print_(str(err), file=sys.stderr) continue for (frame, vlist) in edits.items(): if frame == "POPM": for value in vlist: values = string_split(value, ":") if len(values) == 1: email, rating, count = values[0], 0, 0 elif len(values) == 2: email, rating, count = values[0], values[1], 0 else: email, rating, count = values frame = mutagen.id3.POPM( email=email, rating=int(rating), count=int(count)) id3.add(frame) elif frame == "APIC": for value in vlist: values = string_split(value, ":") # FIXME: doesn't support filenames with an invalid # encoding since we have already decoded at that point fn = values[0] if len(values) >= 2: desc = values[1] else: desc = u"cover" if len(values) >= 3: try: picture_type = int(values[2]) except ValueError: error(u"Invalid picture type: %r" % values[1]) else: picture_type = PictureType.COVER_FRONT if len(values) >= 4: mime = values[3] else: mime = mimetypes.guess_type(fn)[0] or "image/jpeg" if len(values) >= 5: error("APIC: Invalid format") encoding = get_frame_encoding(frame, desc) try: with open(fn, "rb") as h: data = h.read() except IOError as e: error(text_type(e)) frame = mutagen.id3.APIC(encoding=encoding, mime=mime, desc=desc, type=picture_type, data=data) id3.add(frame) elif frame == "COMM": for value in vlist: values = string_split(value, ":") if len(values) == 1: value, desc, lang = values[0], "", "eng" elif len(values) == 2: desc, value, lang = values[0], values[1], "eng" else: value = ":".join(values[1:-1]) desc, lang = values[0], values[-1] frame = mutagen.id3.COMM( encoding=3, text=value, lang=lang, desc=desc) id3.add(frame) elif frame == "USLT": for value in vlist: values = string_split(value, ":") if len(values) == 1: value, desc, lang = values[0], "", "eng" elif len(values) == 2: desc, value, lang = values[0], values[1], "eng" else: value = ":".join(values[1:-1]) desc, lang = values[0], values[-1] frame = mutagen.id3.USLT( encoding=3, text=value, lang=lang, desc=desc) id3.add(frame) elif frame == "UFID": for value in vlist: values = string_split(value, ":") if len(values) != 2: error(u"Invalid value: %r" % values) owner = values[0] data = values[1].encode("utf-8") frame = mutagen.id3.UFID(owner=owner, data=data) id3.add(frame) elif frame == "TXXX": for value in vlist: values = string_split(value, ":", 1) if len(values) == 1: desc, value = "", values[0] else: desc, value = values[0], values[1] frame = mutagen.id3.TXXX( encoding=3, text=value, desc=desc) id3.add(frame) elif frame == "WXXX": for value in vlist: values = string_split(value, ":", 1) if len(values) == 1: desc, value = "", values[0] else: desc, value = values[0], values[1] frame = mutagen.id3.WXXX( encoding=3, url=value, desc=desc) id3.add(frame) elif issubclass(mutagen.id3.Frames[frame], mutagen.id3.UrlFrame): frame = mutagen.id3.Frames[frame]( encoding=3, url=vlist[-1]) id3.add(frame) else: frame = mutagen.id3.Frames[frame](encoding=3, text=vlist) id3.add(frame) id3.save(filename)
def test_ipls(self): id3 = ID3() id3.version = (2, 3) id3.add(IPLS(encoding=0, people=[["a", "b"], ["c", "d"]])) id3.update_to_v24() self.failUnlessEqual(id3["TIPL"], [["a", "b"], ["c", "d"]])
def test_lnk(self): id3 = ID3() id3.version = (2, 2) id3.add(LNK(frameid="PIC", url="http://foo.bar")) id3.update_to_v24() self.assertTrue(id3.getall("LINK"))
def test_pic(self): id3 = ID3() id3.version = (2, 2) id3.add(PIC(encoding=0, mime="PNG", desc="cover", type=3, data=b"")) id3.update_to_v24() self.failUnlessEqual(id3["APIC:cover"].mime, "image/png")