def setUp(self): self.filename_1 = get_temp_copy(self.has_tags) self.filename_2 = get_temp_copy(self.no_tags) self.aiff_tmp_id3 = AIFF(self.filename_1) self.aiff_tmp_no_id3 = AIFF(self.filename_2) self.aiff_1 = AIFF(self.silence_1) self.aiff_2 = AIFF(self.silence_2) self.aiff_3 = AIFF(self.silence_3) self.aiff_4 = AIFF(self.silence_4) self.aiff_5 = AIFF(self.silence_5)
def rename(directory, filename, artist, title, extension, namingConvention): if namingConvention == "Artist - Title" or (namingConvention == 'Dynamic' and ' - ' in filename): try: os.rename( directory + '/' + filename, directory + '/' + str(artist) + ' - ' + str(title) + extension) filename = str(artist) + ' - ' + str(title) + extension except PermissionError: messagebox.showinfo( "Permission Error", "File cannot be renamed, it may still be open") return False, False elif namingConvention == "Title" or (namingConvention == 'Dynamic' and ' - ' not in filename): try: os.rename(directory + '/' + filename, str(directory) + '/' + str(title) + extension) filename = str(title) + extension except PermissionError: messagebox.showinfo( "Permission Error", "File cannot be renamed, it may still be open") return False, False if extension == ".wav": audio = WAVE(str(directory) + '/' + filename) audio["TPE1"] = TPE1(encoding=3, text=artist) audio["TIT2"] = TIT2(encoding=3, text=title) audio.save() return audio, filename elif extension == ".flac": audio = FLAC(str(directory) + '/' + filename) audio['artist'] = artist audio['title'] = title audio.save() return audio, filename elif extension == ".aiff": audio = AIFF(str(directory) + '/' + filename) audio["TPE1"] = TPE1(encoding=3, text=artist) audio["TIT2"] = TIT2(encoding=3, text=title) audio.save() return audio, filename elif extension == ".m4a": audio = MP4(str(directory) + '/' + filename) audio["\xa9ART"] = artist audio["\xa9nam"] = title audio.save() return audio, filename elif extension == ".mp3": audio = MP3(str(directory) + '/' + filename) audio["TPE1"] = TPE1(encoding=3, text=artist) audio["TIT2"] = TIT2(encoding=3, text=title) audio.save() return audio, filename elif extension == ".ogg": audio = OggVorbis(str(directory) + '/' + filename) audio['artist'] = artist audio['title'] = title audio.save() return audio, filename
def test_save_tags(self): from mutagen.id3 import TIT1 tags = self.aiff_tmp_id3.tags tags.add(TIT1(encoding=3, text="foobar")) tags.save() new = AIFF(self.aiff_tmp_id3.filename) self.failUnlessEqual(new["TIT1"], ["foobar"])
def setUp(self): fd, self.filename_1 = mkstemp(suffix='.aif') os.close(fd) shutil.copy(self.has_tags, self.filename_1) fd, self.filename_2 = mkstemp(suffix='.aif') os.close(fd) shutil.copy(self.no_tags, self.filename_2) self.aiff_tmp_id3 = AIFF(self.filename_1) self.aiff_tmp_no_id3 = AIFF(self.filename_2) self.aiff_1 = AIFF(self.silence_1) self.aiff_2 = AIFF(self.silence_2) self.aiff_3 = AIFF(self.silence_3) self.aiff_4 = AIFF(self.silence_4) self.aiff_5 = AIFF(self.silence_5)
def info_id3(self, path: str) -> (str, list): #AIFF if path.endswith('.aiff') or path.endswith('.aif'): f = AIFF(path).tags else: f = ID3(path) title = str(f['TIT2']) artists = self._parse_artists(str(f['TPE1'])) return title, artists
def loadAIFF(self, filepath): """Loads a audio file""" #TODO: raise exeption try: self.data = AIFF(filepath) if self.args.debug: self.prettyPrint(self.data.tags) except (FileNotFoundError, IOError): print("Wrong file or file path") return 0 except MutagenError: print("Loading file", filepath, "failed") return 0 return 1
def audioFile(audio): aud_str = str(audio) if aud_str.endswith(".mp3"): aud1 = MP3(audio) len1 = aud1.info.length return int(len1) elif aud_str.endswith('.wav'): aud2 = WAVE(audio) len2 = aud2.info.length return int(len2) elif aud_str.endswith('.flac'): aud3 = FLAC(audio) len3 = aud3.info.length return int(len3) elif aud_str.endswith('.aac'): aud4 = AAC(audio) len4 = aud4.info.length return int(len4) elif aud_str.endswith('.ac3'): aud5 = AC3(audio) len5 = aud5.info.length return int(len5) elif aud_str.endswith('.aiff'): aud6 = AIFF(audio) len6 = aud6.info.length return int(len6) elif aud_str.endswith('.asf'): aud7 = ASF(audio) len7 = aud7.info.length return int(len7) elif aud_str.endswith('.dsf'): aud8 = DSF(audio) len8 = aud8.info.length return int(len8) elif aud_str.endswith('.mp4'): aud9 = MP4(audio) len9 = aud9.info.length return int(len9) elif aud_str.endswith('.smf'): aud10 = SMF(audio) len10 = aud10.info.length return int(len10) elif aud_str.endswith('.ogg'): aud12 = OggFileType(audio) len12 = aud12.info.length return int(len12) else: return str("File type not supported.")
def test_padding(self): AIFF(self.filename_1).save() self.assertEqual(AIFF(self.filename_1).tags._padding, 1002) AIFF(self.filename_1).save() self.assertEqual(AIFF(self.filename_1).tags._padding, 1002) tags = AIFF(self.filename_1) tags.save(padding=lambda x: 1) self.assertEqual(AIFF(self.filename_1).tags._padding, 1) tags = AIFF(self.filename_1) tags.save(padding=lambda x: 100) self.assertEqual(AIFF(self.filename_1).tags._padding, 100) tags = AIFF(self.filename_1) self.assertRaises(AIFFError, tags.save, padding=lambda x: -1)
def checkFileValidity(filename, directory, format): audio = "" if format == "FLAC": try: audio = FLAC(str(directory) + "/" + str(filename)) except: messagebox.showinfo("Error", "Invalid or Corrupt File") return "Invalid or corrupt file\n" elif format == "AIFF": try: audio = AIFF(str(directory) + "/" + str(filename)) except: messagebox.showinfo("Error", "Invalid or Corrupt File") return "Invalid or corrupt file\n" elif format == "MP3": try: audio = MP3(str(directory) + "/" + str(filename)) except: messagebox.showinfo("Error", "Invalid or Corrupt File") return "Invalid or corrupt file\n" elif format == "OGG": try: audio = OggVorbis(str(directory) + "/" + str(filename)) except: messagebox.showinfo("Error", "Invalid or Corrupt File") return "Invalid or corrupt file\n" elif format == "WAV": try: audio = WAVE(str(directory) + "/" + str(filename)) except: messagebox.showinfo("Error", "Invalid or Corrupt File") return "Invalid or corrupt file\n" elif format == "M4A": # M4A is deprecated in mutagen, MP4 is suggested instead try: audio = MP4(str(directory) + "/" + str(filename)) except: messagebox.showinfo("Error", "Invalid or Corrupt File") return "Invalid or corrupt file\n" return audio
class TAIFF(TestCase): silence_1 = os.path.join(DATA_DIR, '11k-1ch-2s-silence.aif') silence_2 = os.path.join(DATA_DIR, '48k-2ch-s16-silence.aif') silence_3 = os.path.join(DATA_DIR, '8k-1ch-1s-silence.aif') silence_4 = os.path.join(DATA_DIR, '8k-1ch-3.5s-silence.aif') silence_5 = os.path.join(DATA_DIR, '8k-4ch-1s-silence.aif') has_tags = os.path.join(DATA_DIR, 'with-id3.aif') no_tags = os.path.join(DATA_DIR, '8k-1ch-1s-silence.aif') def setUp(self): self.filename_1 = get_temp_copy(self.has_tags) self.filename_2 = get_temp_copy(self.no_tags) self.aiff_tmp_id3 = AIFF(self.filename_1) self.aiff_tmp_no_id3 = AIFF(self.filename_2) self.aiff_1 = AIFF(self.silence_1) self.aiff_2 = AIFF(self.silence_2) self.aiff_3 = AIFF(self.silence_3) self.aiff_4 = AIFF(self.silence_4) self.aiff_5 = AIFF(self.silence_5) def test_channels(self): self.failUnlessEqual(self.aiff_1.info.channels, 1) self.failUnlessEqual(self.aiff_2.info.channels, 2) self.failUnlessEqual(self.aiff_3.info.channels, 1) self.failUnlessEqual(self.aiff_4.info.channels, 1) self.failUnlessEqual(self.aiff_5.info.channels, 4) def test_length(self): self.failUnlessEqual(self.aiff_1.info.length, 2) self.failUnlessEqual(self.aiff_2.info.length, 0.1) self.failUnlessEqual(self.aiff_3.info.length, 1) self.failUnlessEqual(self.aiff_4.info.length, 3.5) self.failUnlessEqual(self.aiff_5.info.length, 1) def test_bitrate(self): self.failUnlessEqual(self.aiff_1.info.bitrate, 176400) self.failUnlessEqual(self.aiff_2.info.bitrate, 1536000) self.failUnlessEqual(self.aiff_3.info.bitrate, 128000) self.failUnlessEqual(self.aiff_4.info.bitrate, 128000) self.failUnlessEqual(self.aiff_5.info.bitrate, 512000) def test_sample_rate(self): self.failUnlessEqual(self.aiff_1.info.sample_rate, 11025) self.failUnlessEqual(self.aiff_2.info.sample_rate, 48000) self.failUnlessEqual(self.aiff_3.info.sample_rate, 8000) self.failUnlessEqual(self.aiff_4.info.sample_rate, 8000) self.failUnlessEqual(self.aiff_5.info.sample_rate, 8000) def test_sample_size(self): self.failUnlessEqual(self.aiff_1.info.sample_size, 16) self.failUnlessEqual(self.aiff_2.info.sample_size, 16) self.failUnlessEqual(self.aiff_3.info.sample_size, 16) self.failUnlessEqual(self.aiff_4.info.sample_size, 16) self.failUnlessEqual(self.aiff_5.info.sample_size, 16) def test_notaiff(self): self.failUnlessRaises( AIFFError, AIFF, os.path.join(DATA_DIR, 'empty.ofr')) def test_pprint(self): self.failUnless(self.aiff_1.pprint()) self.failUnless(self.aiff_tmp_id3.pprint()) def test_delete(self): self.aiff_tmp_id3.delete() self.failIf(self.aiff_tmp_id3.tags) self.failUnless(AIFF(self.filename_1).tags is None) def test_module_delete(self): delete(self.filename_1) self.failUnless(AIFF(self.filename_1).tags is None) def test_module_double_delete(self): delete(self.filename_1) delete(self.filename_1) def test_pprint_no_tags(self): self.aiff_tmp_id3.tags = None self.failUnless(self.aiff_tmp_id3.pprint()) def test_save_no_tags(self): self.aiff_tmp_id3.tags = None self.aiff_tmp_id3.save() self.assertTrue(self.aiff_tmp_id3.tags is None) def test_add_tags_already_there(self): self.failUnless(self.aiff_tmp_id3.tags) self.failUnlessRaises(Exception, self.aiff_tmp_id3.add_tags) def test_mime(self): self.failUnless("audio/aiff" in self.aiff_1.mime) self.failUnless("audio/x-aiff" in self.aiff_1.mime) def test_loaded_tags(self): self.failUnless(self.aiff_tmp_id3["TIT2"] == "AIFF title") def test_roundtrip(self): self.failUnlessEqual(self.aiff_tmp_id3["TIT2"], ["AIFF title"]) self.aiff_tmp_id3.save() new = AIFF(self.aiff_tmp_id3.filename) self.failUnlessEqual(new["TIT2"], ["AIFF title"]) def test_save_tags(self): from mutagen.id3 import TIT1 tags = self.aiff_tmp_id3.tags tags.add(TIT1(encoding=3, text="foobar")) tags.save() new = AIFF(self.aiff_tmp_id3.filename) self.failUnlessEqual(new["TIT1"], ["foobar"]) def test_save_with_ID3_chunk(self): from mutagen.id3 import TIT1 self.aiff_tmp_id3["TIT1"] = TIT1(encoding=3, text="foobar") self.aiff_tmp_id3.save() self.failUnless(AIFF(self.filename_1)["TIT1"] == "foobar") self.failUnless(self.aiff_tmp_id3["TIT2"] == "AIFF title") def test_save_without_ID3_chunk(self): from mutagen.id3 import TIT1 self.aiff_tmp_no_id3["TIT1"] = TIT1(encoding=3, text="foobar") self.aiff_tmp_no_id3.save() self.failUnless(AIFF(self.filename_2)["TIT1"] == "foobar") def test_corrupt_tag(self): with open(self.filename_1, "r+b") as h: chunk = IFFFile(h)[u'ID3'] h.seek(chunk.data_offset) h.seek(4, 1) h.write(b"\xff\xff") self.assertRaises(AIFFError, AIFF, self.filename_1) def test_padding(self): AIFF(self.filename_1).save() self.assertEqual(AIFF(self.filename_1).tags._padding, 1002) AIFF(self.filename_1).save() self.assertEqual(AIFF(self.filename_1).tags._padding, 1002) tags = AIFF(self.filename_1) tags.save(padding=lambda x: 1) self.assertEqual(AIFF(self.filename_1).tags._padding, 1) tags = AIFF(self.filename_1) tags.save(padding=lambda x: 100) self.assertEqual(AIFF(self.filename_1).tags._padding, 100) tags = AIFF(self.filename_1) self.assertRaises(AIFFError, tags.save, padding=lambda x: -1) def tearDown(self): os.unlink(self.filename_1) os.unlink(self.filename_2)
def test_save_with_ID3_chunk(self): from mutagen._id3frames import TIT1 self.aiff_tmp_id3["TIT1"] = TIT1(encoding=3, text="foobar") self.aiff_tmp_id3.save() self.failUnless(AIFF(self.filename_1)["TIT1"] == "foobar") self.failUnless(self.aiff_tmp_id3["TIT2"] == "AIFF title")
def test_delete(self): self.aiff_tmp_id3.delete() self.failIf(self.aiff_tmp_id3.tags) self.failUnless(AIFF(self.filename_1).tags is None)
def load(self, filename, **kwargs): return AIFF.load(self, filename, **kwargs)
from mutagen.flac import FLAC from mutagen.aac import AAC from mutagen.aiff import AIFF from mutagen.asf import ASF except ImportError as e: print("Mutagen library is not intalled...") sys.exit(1) audio_ext = { "mp3": lambda x: MP3(x).info.length, "aac": lambda x: AAC(x).info.length, "wmv": lambda x: ASF(x).info.length, "wma": lambda x: ASF(x).info.length, "asf": lambda x: ASF(x).info.length, "flac": lambda x: FLAC(x).info.length, "aiff": lambda x: AIFF(x).info.length } json_list = [] def scan_lib(path): playtime = 0 audio_files = 0 folder_audio = 0 audio_subfolders = 0 for entry in os.listdir(path): entry = os.path.join(path, entry) if os.path.isdir(entry): dir_playtime, dir_audios, dir_faudio, dir_subfolders = scan_lib( entry) playtime += dir_playtime
class TAIFF(TestCase): silence_1 = os.path.join(DATA_DIR, '11k-1ch-2s-silence.aif') silence_2 = os.path.join(DATA_DIR, '48k-2ch-s16-silence.aif') silence_3 = os.path.join(DATA_DIR, '8k-1ch-1s-silence.aif') silence_4 = os.path.join(DATA_DIR, '8k-1ch-3.5s-silence.aif') silence_5 = os.path.join(DATA_DIR, '8k-4ch-1s-silence.aif') has_tags = os.path.join(DATA_DIR, 'with-id3.aif') no_tags = os.path.join(DATA_DIR, '8k-1ch-1s-silence.aif') def setUp(self): self.filename_1 = get_temp_copy(self.has_tags) self.filename_2 = get_temp_copy(self.no_tags) self.aiff_tmp_id3 = AIFF(self.filename_1) self.aiff_tmp_no_id3 = AIFF(self.filename_2) self.aiff_1 = AIFF(self.silence_1) self.aiff_2 = AIFF(self.silence_2) self.aiff_3 = AIFF(self.silence_3) self.aiff_4 = AIFF(self.silence_4) self.aiff_5 = AIFF(self.silence_5) def test_channels(self): self.failUnlessEqual(self.aiff_1.info.channels, 1) self.failUnlessEqual(self.aiff_2.info.channels, 2) self.failUnlessEqual(self.aiff_3.info.channels, 1) self.failUnlessEqual(self.aiff_4.info.channels, 1) self.failUnlessEqual(self.aiff_5.info.channels, 4) def test_length(self): self.failUnlessEqual(self.aiff_1.info.length, 2) self.failUnlessEqual(self.aiff_2.info.length, 0.1) self.failUnlessEqual(self.aiff_3.info.length, 1) self.failUnlessEqual(self.aiff_4.info.length, 3.5) self.failUnlessEqual(self.aiff_5.info.length, 1) def test_bitrate(self): self.failUnlessEqual(self.aiff_1.info.bitrate, 176400) self.failUnlessEqual(self.aiff_2.info.bitrate, 1536000) self.failUnlessEqual(self.aiff_3.info.bitrate, 128000) self.failUnlessEqual(self.aiff_4.info.bitrate, 128000) self.failUnlessEqual(self.aiff_5.info.bitrate, 512000) def test_sample_rate(self): self.failUnlessEqual(self.aiff_1.info.sample_rate, 11025) self.failUnlessEqual(self.aiff_2.info.sample_rate, 48000) self.failUnlessEqual(self.aiff_3.info.sample_rate, 8000) self.failUnlessEqual(self.aiff_4.info.sample_rate, 8000) self.failUnlessEqual(self.aiff_5.info.sample_rate, 8000) def test_bits_per_sample(self): self.failUnlessEqual(self.aiff_1.info.bits_per_sample, 16) self.failUnlessEqual(self.aiff_2.info.bits_per_sample, 16) self.failUnlessEqual(self.aiff_3.info.bits_per_sample, 16) self.failUnlessEqual(self.aiff_4.info.bits_per_sample, 16) self.failUnlessEqual(self.aiff_5.info.bits_per_sample, 16) def test_sample_size(self): for test in [ self.aiff_1, self.aiff_2, self.aiff_3, self.aiff_4, self.aiff_5 ]: info = test.info self.failUnlessEqual(info.sample_size, info.bits_per_sample) def test_notaiff(self): self.failUnlessRaises(AIFFError, AIFF, os.path.join(DATA_DIR, 'empty.ofr')) def test_pprint(self): self.failUnless(self.aiff_1.pprint()) self.failUnless(self.aiff_tmp_id3.pprint()) def test_delete(self): self.aiff_tmp_id3.delete() self.failIf(self.aiff_tmp_id3.tags) self.failUnless(AIFF(self.filename_1).tags is None) def test_module_delete(self): delete(self.filename_1) self.failUnless(AIFF(self.filename_1).tags is None) def test_module_double_delete(self): delete(self.filename_1) delete(self.filename_1) def test_pprint_no_tags(self): self.aiff_tmp_id3.tags = None self.failUnless(self.aiff_tmp_id3.pprint()) def test_save_no_tags(self): self.aiff_tmp_id3.tags = None self.aiff_tmp_id3.save() self.assertTrue(self.aiff_tmp_id3.tags is None) def test_add_tags_already_there(self): self.failUnless(self.aiff_tmp_id3.tags) self.failUnlessRaises(Exception, self.aiff_tmp_id3.add_tags) def test_mime(self): self.failUnless("audio/aiff" in self.aiff_1.mime) self.failUnless("audio/x-aiff" in self.aiff_1.mime) def test_loaded_tags(self): self.failUnless(self.aiff_tmp_id3["TIT2"] == "AIFF title") def test_roundtrip(self): self.failUnlessEqual(self.aiff_tmp_id3["TIT2"], ["AIFF title"]) self.aiff_tmp_id3.save() new = AIFF(self.aiff_tmp_id3.filename) self.failUnlessEqual(new["TIT2"], ["AIFF title"]) def test_save_tags(self): from mutagen.id3 import TIT1 tags = self.aiff_tmp_id3.tags tags.add(TIT1(encoding=3, text="foobar")) tags.save() new = AIFF(self.aiff_tmp_id3.filename) self.failUnlessEqual(new["TIT1"], ["foobar"]) def test_save_with_ID3_chunk(self): from mutagen.id3 import TIT1 self.aiff_tmp_id3["TIT1"] = TIT1(encoding=3, text="foobar") self.aiff_tmp_id3.save() self.failUnless(AIFF(self.filename_1)["TIT1"] == "foobar") self.failUnless(self.aiff_tmp_id3["TIT2"] == "AIFF title") def test_save_without_ID3_chunk(self): from mutagen.id3 import TIT1 self.aiff_tmp_no_id3["TIT1"] = TIT1(encoding=3, text="foobar") self.aiff_tmp_no_id3.save() self.failUnless(AIFF(self.filename_2)["TIT1"] == "foobar") def test_corrupt_tag(self): with open(self.filename_1, "r+b") as h: chunk = IFFFile(h)[u'ID3'] h.seek(chunk.data_offset) h.seek(4, 1) h.write(b"\xff\xff") self.assertRaises(AIFFError, AIFF, self.filename_1) def test_padding(self): AIFF(self.filename_1).save() self.assertEqual(AIFF(self.filename_1).tags._padding, 1002) AIFF(self.filename_1).save() self.assertEqual(AIFF(self.filename_1).tags._padding, 1002) tags = AIFF(self.filename_1) tags.save(padding=lambda x: 1) self.assertEqual(AIFF(self.filename_1).tags._padding, 1) tags = AIFF(self.filename_1) tags.save(padding=lambda x: 100) self.assertEqual(AIFF(self.filename_1).tags._padding, 100) tags = AIFF(self.filename_1) self.assertRaises(AIFFError, tags.save, padding=lambda x: -1) def tearDown(self): os.unlink(self.filename_1) os.unlink(self.filename_2)
def update_id3(self, path: str, track: beatport.Track): #AIFF Check aiff = None if path.endswith('.aiff') or path.endswith('.aif'): aiff = AIFF(path) f = aiff.tags else: f = ID3() f.load(path, v2_version=3, translate=True) #Update tags if UpdatableTags.title in self.config.update_tags and self.config.overwrite: f.setall('TIT2', [TIT2(text=track.title)]) if UpdatableTags.artist in self.config.update_tags and self.config.overwrite: f.setall('TPE1', [ TPE1(text=self.config.artist_separator.join( [a.name for a in track.artists])) ]) if UpdatableTags.album in self.config.update_tags and ( self.config.overwrite or len(f.getall('TALB')) == 0): f.setall('TALB', [TALB(text=track.album.name)]) if UpdatableTags.label in self.config.update_tags and ( self.config.overwrite or len(f.getall('TPUB')) == 0): f.setall('TPUB', [TPUB(text=track.label.name)]) if UpdatableTags.bpm in self.config.update_tags and ( self.config.overwrite or len(f.getall('TBPM')) == 0): f.setall('TBPM', [TBPM(text=str(track.bpm))]) if UpdatableTags.genre in self.config.update_tags and ( self.config.overwrite or len(f.getall('TCON')) == 0): f.setall('TCON', [TCON(text=', '.join([g.name for g in track.genres]))]) #Dates if UpdatableTags.date in self.config.update_tags: #ID3 v2.3 if self.config.id3v23 and (self.config.overwrite or (len(f.getall('TYER')) == 0 and len(f.getall('TDAT')) == 0)): date = track.release_date.strftime('%d%m') f.setall('TDRC', []) f.setall('TDAT', [TDAT(text=date)]) f.setall('TYER', [TYER(text=str(track.release_date.year))]) #ID3 v2.4 if not self.config.id3v23 and (self.config.overwrite or len(f.getall('TDRC')) == 0): date = track.release_date.strftime('%Y-%m-%d') f.setall('TDAT', []) f.setall('TYER', []) f.setall('TDRC', [TDRC(text=date)]) if UpdatableTags.key in self.config.update_tags and ( self.config.overwrite or len(f.getall('TKEY')) == 0): f.setall('TKEY', [TKEY(text=track.id3key())]) if UpdatableTags.publishdate in self.config.update_tags and ( self.config.overwrite or len(f.getall('TDRL')) == 0): # f.setall('TORY', [TORY(text=str(track.publish_date.year))]) if not self.config.id3v23: date = track.publish_date.strftime('%Y-%m-%d') f.setall('TDRL', [TDRL(text=date)]) #Other keys if UpdatableTags.other in self.config.update_tags: f.add(TXXX(desc='WWWAUDIOFILE', text=track.url())) f.add(TXXX(desc='WWWPUBLISHER', text=track.label.url('label'))) #Redownlaod cover if self.config.replace_art: try: url = track.art(self.config.art_resolution) r = requests.get(url) data = APIC(encoding=3, mime='image/jpeg', type=3, desc=u'Cover', data=r.content) f.delall('APIC') f['APIC:cover.jpg'] = data except Exception: logging.warning('Error downloading cover for file: ' + path) if aiff == None: if self.config.id3v23: f.save(path, v2_version=3, v1=0) else: f.save(path, v2_version=4, v1=0) else: aiff.save()
def initiateAIFF(filename, directory, thumbnails, options): audio = AIFF(str(directory) + "/" + str(filename)) # verify artist information is present before preceeding if ' - ' not in filename and str(audio['TCON']) == '': messagebox.showinfo("No artist information found, aborting procedure") return False, False, False # transcribe formal tagnames into informal counterpart formalTagDict = { 'TPE1': 'Artist', 'TALB': 'Album', 'TPE2': 'Album_Artist', 'TBPM': 'BPM', 'COMM::eng': 'Comment', 'TCMP': 'Compilation', 'TCOP': 'Copyright', 'TPOS': 'Discnumber', 'TCON': 'Genre', 'APIC:': 'Image', 'TKEY': 'Key', 'TDRC': 'Release_Date', 'TIT2': 'Title', 'TXXX:replaygain_track_gain': 'ReplayGain', } # transcribe informal tagnames into formal counterpart informalTagDict = {v: k for k, v in formalTagDict.items()} ID3Frames = { 'TPE1': TPE1, 'TALB': TALB, 'TPE2': TPE2, 'TBPM': TBPM, 'COMM': COMM, 'TCMP': TCMP, 'TCOP': TCOP, 'TPOS': TPOS, 'TCON': TCON, 'APIC:': APIC, 'TKEY': TKEY, 'TDRC': TDRC, 'TIT2': TIT2, 'TXXX': TXXX, } fileParameters = [] tagList = list(audio.keys()) for tag in tagList: # delete extraneous tags if the tag is not in the list of selected tags and the delete unselected tags option is activated if (tag not in formalTagDict or formalTagDict[tag] not in options["Selected Tags (L)"] ) and options["Delete Unselected Tags (B)"].get() == True: audio.pop(tag) audio.save() else: fileParameters.append(tag) for tag in options["Selected Tags (L)"]: if tag in informalTagDict: tag = informalTagDict[tag] # add tags of interest if missing if tag not in fileParameters: try: if "COMM" in tag: audio[tag] = COMM(encoding=3, lang="eng", text="") elif "TXXX" in tag: audio[tag] = TXXX(encoding=3, desc="replaygain_track_gain", text="") else: audio[tag] = ID3Frames[tag](encoding=3, text="") audio.save() except: messagebox.showinfo( "Permission Error", "Unable to save tags, file may be open somewhere") return False, False, False # check for discrepancies between tags and filename # check both artist and title tags if ' - ' in filename: artist = filename.split(' - ')[0] title = filename[filename.index(filename.split(' - ')[1]):filename. rfind('.')] if artist != str(audio["TPE1"]) or title != str(audio["TIT2"]): # save artist and title to tag if both are empty if str(audio["TPE1"]) == '' and str(audio["TIT2"]) == '': audio["TPE1"] = TPE1(encoding=3, text=artist) audio["TIT2"] = TIT2(encoding=3, text=title) audio.save() else: audio, filename = compareArtistAndTitle( audio, artist, title, filename, directory, options) # only check title tag else: title = filename[:filename.rfind('.')] if title != str(audio["TIT2"]): # save title to tag if tag is empty if str(audio["TIT2"]) == '': audio["TIT2"] = TIT2(encoding=3, text=title) audio.save() else: audio, filename = compareTitle(audio, title, filename, directory, options) # handle naming format and typo check if options["Audio naming format (S)"].get() == "Artist - Title" or options[ 'Audio naming format (S)'].get() == 'Title': namingConvention = options['Audio naming format (S)'].get() artist = str(audio["TPE1"]) audio, filename = handleStaticNamingConvention(audio, filename, artist, title, directory, namingConvention) if options["Scan Filename and Tags (B)"].get( ) == True and type(audio) != bool: audio, filename, options = extractArtistAndTitle( audio, filename, directory, options, namingConvention) if type(audio) != bool: # save thumbnail to list image = audio["APIC:"] if image.data != b'': stream = BytesIO(image.data) image = Image.open(stream).convert("RGBA") thumbnails = saveThumbnail(image, thumbnails) stream.close() else: thumbnails = saveThumbnail("NA", thumbnails) return audio, filename, informalTagDict, thumbnails, options
class TAIFF(TestCase): silence_1 = os.path.join('tests', 'data', '11k-1ch-2s-silence.aif') silence_2 = os.path.join('tests', 'data', '48k-2ch-s16-silence.aif') silence_3 = os.path.join('tests', 'data', '8k-1ch-1s-silence.aif') silence_4 = os.path.join('tests', 'data', '8k-1ch-3.5s-silence.aif') silence_5 = os.path.join('tests', 'data', '8k-4ch-1s-silence.aif') has_tags = os.path.join('tests', 'data', 'with-id3.aif') no_tags = os.path.join('tests', 'data', '8k-1ch-1s-silence.aif') def setUp(self): fd, self.filename_1 = mkstemp(suffix='.aif') os.close(fd) shutil.copy(self.has_tags, self.filename_1) fd, self.filename_2 = mkstemp(suffix='.aif') os.close(fd) shutil.copy(self.no_tags, self.filename_2) self.aiff_tmp_id3 = AIFF(self.filename_1) self.aiff_tmp_no_id3 = AIFF(self.filename_2) self.aiff_1 = AIFF(self.silence_1) self.aiff_2 = AIFF(self.silence_2) self.aiff_3 = AIFF(self.silence_3) self.aiff_4 = AIFF(self.silence_4) self.aiff_5 = AIFF(self.silence_5) def test_channels(self): self.failUnlessEqual(self.aiff_1.info.channels, 1) self.failUnlessEqual(self.aiff_2.info.channels, 2) self.failUnlessEqual(self.aiff_3.info.channels, 1) self.failUnlessEqual(self.aiff_4.info.channels, 1) self.failUnlessEqual(self.aiff_5.info.channels, 4) def test_length(self): self.failUnlessEqual(self.aiff_1.info.length, 2) self.failUnlessEqual(self.aiff_2.info.length, 0.1) self.failUnlessEqual(self.aiff_3.info.length, 1) self.failUnlessEqual(self.aiff_4.info.length, 3.5) self.failUnlessEqual(self.aiff_5.info.length, 1) def test_bitrate(self): self.failUnlessEqual(self.aiff_1.info.bitrate, 176400) self.failUnlessEqual(self.aiff_2.info.bitrate, 1536000) self.failUnlessEqual(self.aiff_3.info.bitrate, 128000) self.failUnlessEqual(self.aiff_4.info.bitrate, 128000) self.failUnlessEqual(self.aiff_5.info.bitrate, 512000) def test_sample_rate(self): self.failUnlessEqual(self.aiff_1.info.sample_rate, 11025) self.failUnlessEqual(self.aiff_2.info.sample_rate, 48000) self.failUnlessEqual(self.aiff_3.info.sample_rate, 8000) self.failUnlessEqual(self.aiff_4.info.sample_rate, 8000) self.failUnlessEqual(self.aiff_5.info.sample_rate, 8000) def test_sample_size(self): self.failUnlessEqual(self.aiff_1.info.sample_size, 16) self.failUnlessEqual(self.aiff_2.info.sample_size, 16) self.failUnlessEqual(self.aiff_3.info.sample_size, 16) self.failUnlessEqual(self.aiff_4.info.sample_size, 16) self.failUnlessEqual(self.aiff_5.info.sample_size, 16) def test_notaiff(self): self.failUnlessRaises(AIFFError, AIFF, os.path.join('tests', 'data', 'empty.ofr')) def test_pprint(self): self.failUnless(self.aiff_1.pprint()) self.failUnless(self.aiff_tmp_id3.pprint()) def test_delete(self): self.aiff_tmp_id3.delete() self.failIf(self.aiff_tmp_id3.tags) self.failUnless(AIFF(self.filename_1).tags is None) def test_module_delete(self): delete(self.filename_1) self.failUnless(AIFF(self.filename_1).tags is None) def test_module_double_delete(self): delete(self.filename_1) delete(self.filename_1) def test_pprint_no_tags(self): self.aiff_tmp_id3.tags = None self.failUnless(self.aiff_tmp_id3.pprint()) def test_save_no_tags(self): self.aiff_tmp_id3.tags = None self.failUnlessRaises(ValueError, self.aiff_tmp_id3.save) def test_add_tags_already_there(self): self.failUnless(self.aiff_tmp_id3.tags) self.failUnlessRaises(Exception, self.aiff_tmp_id3.add_tags) def test_mime(self): self.failUnless("audio/aiff" in self.aiff_1.mime) self.failUnless("audio/x-aiff" in self.aiff_1.mime) def test_loaded_tags(self): self.failUnless(self.aiff_tmp_id3["TIT2"] == "AIFF title") def test_roundtrip(self): self.failUnlessEqual(self.aiff_tmp_id3["TIT2"], ["AIFF title"]) self.aiff_tmp_id3.save() new = AIFF(self.aiff_tmp_id3.filename) self.failUnlessEqual(new["TIT2"], ["AIFF title"]) def test_save_tags(self): from mutagen.id3 import TIT1 tags = self.aiff_tmp_id3.tags tags.add(TIT1(encoding=3, text="foobar")) tags.save() new = AIFF(self.aiff_tmp_id3.filename) self.failUnlessEqual(new["TIT1"], ["foobar"]) def test_save_with_ID3_chunk(self): from mutagen.id3 import TIT1 self.aiff_tmp_id3["TIT1"] = TIT1(encoding=3, text="foobar") self.aiff_tmp_id3.save() self.failUnless(AIFF(self.filename_1)["TIT1"] == "foobar") self.failUnless(self.aiff_tmp_id3["TIT2"] == "AIFF title") def test_save_without_ID3_chunk(self): from mutagen.id3 import TIT1 self.aiff_tmp_no_id3["TIT1"] = TIT1(encoding=3, text="foobar") self.aiff_tmp_no_id3.save() self.failUnless(AIFF(self.filename_2)["TIT1"] == "foobar") def tearDown(self): os.unlink(self.filename_1) os.unlink(self.filename_2)
def add_tags(self, ID3=_IFFID3): AIFF.add_tags(self)
def test_roundtrip(self): self.failUnlessEqual(self.aiff_tmp_id3["TIT2"], ["AIFF title"]) self.aiff_tmp_id3.save() new = AIFF(self.aiff_tmp_id3.filename) self.failUnlessEqual(new["TIT2"], ["AIFF title"])
def name_change(self): for path in self.filelist: os.chdir(os.path.dirname(path)) file = os.path.basename(path) # tagsにタグのディクショナリを読み込む if file.endswith("flac"): try: tags = FLAC(file) name = ','.join(tags['title']) end = ".flac" except: print("タグエラー: " + path) continue elif file.endswith("mp3"): try: tags = EasyID3(file) name = ','.join(tags['title']) end = ".mp3" except: print("タグエラー: " + path) continue elif file.endswith("aiff") or file.endswith("aif"): try: tags = AIFF(file) name = ','.join(tags['TIT2'].text) end = ".aif" except: print("タグエラー: " + path) continue else: continue # {'TIT2': TIT2(encoding=<Encoding.UTF16: 1>, text=['幻惑SILHOUETTE']), # 'TALB': TALB(encoding=<Encoding.UTF16: 1>, text=['THE IDOLM@STER SHINY COLORS BRILLI@NT WING 03 バベルシティ・グレイス']), # 'TCOP': TCOP(encoding=<Encoding.UTF16: 1>, text=['(P)Lantis']), # 'TSOT': TSOT(encoding=<Encoding.UTF16: 1>, text=['ゲンワクSILHOUETTE']), # 'TSOA': TSOA(encoding=<Encoding.UTF16: 1>, text=['IDOLM@STER SHINY COLORS BRILLI@NT WING 03 バベルシティ・グレイス']), # 'TCON': TCON(encoding=<Encoding.UTF16: 1>, text=['ゲーム']), # 'TRCK': TRCK(encoding=<Encoding.LATIN1: 0>, text=['2/3']), # 'TPOS': TPOS(encoding=<Encoding.LATIN1: 0>, text=['1/1']), # 'TPE1': TPE1(encoding=<Encoding.UTF16: 1>, text=['アンティーカ']), # 'TPE2': TPE2(encoding=<Encoding.UTF16: 1>, text=['アンティーカ']), # 'TCOM': TCOM(encoding=<Encoding.UTF16: 1>, text=['no_my']), # 'COMM::eng': COMM(encoding=<Encoding.UTF16: 1>, lang='eng', desc=''... # ここから拡張子の対応を増やせる # replace()で禁止文字を削除 original = name.replace("\"", " ").replace("\\", " ").replace( "/", " ").replace("*", " ").replace(":", " ").replace( "|", " ").replace("<", " ").replace(">", " ").replace("?", " ") name = original + end i = 1 if name != file: while os.path.exists(name): i += 1 name = original + " " + str(i) + end os.rename(path, os.getcwd() + os.sep + name)
def test_save_without_ID3_chunk(self): from mutagen.id3 import TIT1 self.aiff_tmp_no_id3["TIT1"] = TIT1(encoding=3, text="foobar") self.aiff_tmp_no_id3.save() self.failUnless(AIFF(self.filename_2)["TIT1"] == "foobar")
class TAIFF(TestCase): silence_1 = os.path.join('tests', 'data', '11k-1ch-2s-silence.aif') silence_2 = os.path.join('tests', 'data', '48k-2ch-s16-silence.aif') silence_3 = os.path.join('tests', 'data', '8k-1ch-1s-silence.aif') silence_4 = os.path.join('tests', 'data', '8k-1ch-3.5s-silence.aif') silence_5 = os.path.join('tests', 'data', '8k-4ch-1s-silence.aif') has_tags = os.path.join('tests', 'data', 'with-id3.aif') no_tags = os.path.join('tests', 'data', '8k-1ch-1s-silence.aif') def setUp(self): fd, self.filename_1 = mkstemp(suffix='.aif') os.close(fd) shutil.copy(self.has_tags, self.filename_1) fd, self.filename_2 = mkstemp(suffix='.aif') os.close(fd) shutil.copy(self.no_tags, self.filename_2) self.aiff_tmp_id3 = AIFF(self.filename_1) self.aiff_tmp_no_id3 = AIFF(self.filename_2) self.aiff_1 = AIFF(self.silence_1) self.aiff_2 = AIFF(self.silence_2) self.aiff_3 = AIFF(self.silence_3) self.aiff_4 = AIFF(self.silence_4) self.aiff_5 = AIFF(self.silence_5) def test_channels(self): self.failUnlessEqual(self.aiff_1.info.channels, 1) self.failUnlessEqual(self.aiff_2.info.channels, 2) self.failUnlessEqual(self.aiff_3.info.channels, 1) self.failUnlessEqual(self.aiff_4.info.channels, 1) self.failUnlessEqual(self.aiff_5.info.channels, 4) def test_length(self): self.failUnlessEqual(self.aiff_1.info.length, 2) self.failUnlessEqual(self.aiff_2.info.length, 0.1) self.failUnlessEqual(self.aiff_3.info.length, 1) self.failUnlessEqual(self.aiff_4.info.length, 3.5) self.failUnlessEqual(self.aiff_5.info.length, 1) def test_bitrate(self): self.failUnlessEqual(self.aiff_1.info.bitrate, 176400) self.failUnlessEqual(self.aiff_2.info.bitrate, 1536000) self.failUnlessEqual(self.aiff_3.info.bitrate, 128000) self.failUnlessEqual(self.aiff_4.info.bitrate, 128000) self.failUnlessEqual(self.aiff_5.info.bitrate, 512000) def test_sample_rate(self): self.failUnlessEqual(self.aiff_1.info.sample_rate, 11025) self.failUnlessEqual(self.aiff_2.info.sample_rate, 48000) self.failUnlessEqual(self.aiff_3.info.sample_rate, 8000) self.failUnlessEqual(self.aiff_4.info.sample_rate, 8000) self.failUnlessEqual(self.aiff_5.info.sample_rate, 8000) def test_sample_size(self): self.failUnlessEqual(self.aiff_1.info.sample_size, 16) self.failUnlessEqual(self.aiff_2.info.sample_size, 16) self.failUnlessEqual(self.aiff_3.info.sample_size, 16) self.failUnlessEqual(self.aiff_4.info.sample_size, 16) self.failUnlessEqual(self.aiff_5.info.sample_size, 16) def test_notaiff(self): self.failUnlessRaises( AIFFError, AIFF, os.path.join('tests', 'data', 'empty.ofr')) def test_pprint(self): self.failUnless(self.aiff_1.pprint()) self.failUnless(self.aiff_tmp_id3.pprint()) def test_delete(self): self.aiff_tmp_id3.delete() self.failIf(self.aiff_tmp_id3.tags) self.failUnless(AIFF(self.filename_1).tags is None) def test_module_delete(self): delete(self.filename_1) self.failUnless(AIFF(self.filename_1).tags is None) def test_module_double_delete(self): delete(self.filename_1) delete(self.filename_1) def test_pprint_no_tags(self): self.aiff_tmp_id3.tags = None self.failUnless(self.aiff_tmp_id3.pprint()) def test_save_no_tags(self): self.aiff_tmp_id3.tags = None self.failUnlessRaises(ValueError, self.aiff_tmp_id3.save) def test_add_tags_already_there(self): self.failUnless(self.aiff_tmp_id3.tags) self.failUnlessRaises(Exception, self.aiff_tmp_id3.add_tags) def test_mime(self): self.failUnless("audio/aiff" in self.aiff_1.mime) self.failUnless("audio/x-aiff" in self.aiff_1.mime) def test_loaded_tags(self): self.failUnless(self.aiff_tmp_id3["TIT2"] == "AIFF title") def test_roundtrip(self): self.failUnlessEqual(self.aiff_tmp_id3["TIT2"], ["AIFF title"]) self.aiff_tmp_id3.save() new = AIFF(self.aiff_tmp_id3.filename) self.failUnlessEqual(new["TIT2"], ["AIFF title"]) def test_save_tags(self): from mutagen.id3 import TIT1 tags = self.aiff_tmp_id3.tags tags.add(TIT1(encoding=3, text="foobar")) tags.save() new = AIFF(self.aiff_tmp_id3.filename) self.failUnlessEqual(new["TIT1"], ["foobar"]) def test_save_with_ID3_chunk(self): from mutagen.id3 import TIT1 self.aiff_tmp_id3["TIT1"] = TIT1(encoding=3, text="foobar") self.aiff_tmp_id3.save() self.failUnless(AIFF(self.filename_1)["TIT1"] == "foobar") self.failUnless(self.aiff_tmp_id3["TIT2"] == "AIFF title") def test_save_without_ID3_chunk(self): from mutagen.id3 import TIT1 self.aiff_tmp_no_id3["TIT1"] = TIT1(encoding=3, text="foobar") self.aiff_tmp_no_id3.save() self.failUnless(AIFF(self.filename_2)["TIT1"] == "foobar") def tearDown(self): os.unlink(self.filename_1) os.unlink(self.filename_2)
def test_module_delete(self): delete(self.filename_1) self.failUnless(AIFF(self.filename_1).tags is None)
def detect_file_codec(path): """ Try to detect codec for file """ if not os.path.isfile(path): return None name, extension = os.path.splitext(path) if extension in ('.m4a', 'caf'): from mutagen.mp4 import MP4 try: codec = MP4(path).info.codec if codec == 'alac': return codec elif codec[:4] == 'mp4a': return 'aac' except Exception as e: raise ValueError('Error detecting file {} codec: {}'.format( path, e)) if extension == '.aif': from mutagen.aiff import AIFF try: AIFF(path).info return 'aif' except Exception as e: raise ValueError('Error opening {} as aif: {}'.format(path, e)) if extension == '.flac': from mutagen.flac import FLAC try: FLAC(path).info return 'flac' except Exception as e: raise ValueError('Error opening {} as flac: {}'.format(path, e)) if extension == '.mp3': from mutagen.mp3 import MP3 try: MP3(path).info return 'mp3' except Exception as e: raise ValueError('Error opening {} as mp3: {}'.format(path, e)) if extension == '.opus': from mutagen.oggopus import OggOpus try: OggOpus(path).info return 'opus' except Exception as e: raise ValueError('Error opening {} as mp3: {}'.format(path, e)) if extension == '.ogg': from mutagen.oggvorbis import OggVorbis try: OggVorbis(path).info return 'vorbis' except Exception as e: raise ValueError('Error opening {} as ogg vorbis: {}'.format( path, e)) if extension == '.wv': from mutagen.wavpack import WavPack try: WavPack(path).info return 'wavpack' except Exception as e: raise ValueError('Error opening {} as wavpack: {}'.format(path, e)) return None