def setUp(self): # WMA 9.1 64kbps CBR 48khz self.wma1 = ASF(os.path.join("tests", "data", "silence-1.wma")) # WMA 9.1 Professional 192kbps VBR 44khz self.wma2 = ASF(os.path.join("tests", "data", "silence-2.wma")) # WMA 9.1 Lossless 44khz self.wma3 = ASF(os.path.join("tests", "data", "silence-3.wma"))
def test_non_text_type(self): audio = ASF(self.filename) audio["Author"] = [42] audio.save() self.assertFalse(audio.to_content_description) new = ASF(self.filename) self.assertEqual(new["Author"], [42])
def test_issue_29_description(self): self.audio["Description"] = "Hello" self.audio.save() audio = ASF(self.filename) self.failUnless("Description" in audio) self.failUnlessEqual(audio["Description"], ["Hello"]) del(audio["Description"]) self.failIf("Description" in audio) audio.save() audio = ASF(self.filename) self.failIf("Description" in audio)
def test_empty(self): audio = ASF(self.filename) audio["Author"] = [u"", u""] audio["Title"] = [u""] audio["Copyright"] = [] audio.save() new = ASF(self.filename) self.assertEqual(new["Author"], [u"", u""]) self.assertEqual(new["Title"], [u""]) self.assertFalse("Copyright" in new)
def test_author(self): audio = ASF(self.filename) values = [u"Foo", u"Bar", u"Baz"] audio["Author"] = values audio.save() self.assertEqual(list(audio.to_content_description.items()), [(u"Author", u"Foo")]) self.assertEqual(audio.to_metadata_library, [(u"Author", u"Bar"), (u"Author", u"Baz")]) new = ASF(self.filename) self.assertEqual(new["Author"], values)
def test_save_large_bytearray(self): audio = ASF(self.filename) audio["QL/LargeObject"] = [ASFValue(b"." * (0xFFFF + 1), BYTEARRAY)] audio.save() self.failIf("QL/LargeObject" in audio.to_extended_content_description) self.failIf("QL/LargeObject" in audio.to_metadata) self.failIf("QL/LargeObject" not in dict(audio.to_metadata_library))
def setUp(self): fd, self.filename = mkstemp(suffix='wma') os.close(fd) shutil.copy(self.original, self.filename) audio = ASF(self.filename) audio.clear() audio.save()
def test_save_large_string(self): audio = ASF(self.filename) audio["QL/LargeObject"] = [ASFValue("." * 0x7FFF, UNICODE)] audio.save() self.failIf("QL/LargeObject" in audio.to_extended_content_description) self.failIf("QL/LargeObject" in audio.to_metadata) self.failIf("QL/LargeObject" not in dict(audio.to_metadata_library))
def songSort(song, ext): if (ext == "mp3"): metadata = EasyID3(song) album = str(metadata['album']) elif (ext == "m4a"): metadata = MP4(song) album = str(metadata["\xa9alb"]) elif (ext == "wma"): metadata = ASF(song) album = str(metadata["WM/AlbumTitle"]) album = album[22:-3] else: album = album[2:-2] albumList = os.listdir(musicSort / "Albums") #album folder check if (album not in albumList): if (DEBUG): print(song) print(album + " not found") os.mkdir(musicSort / "Albums" / album) return (musicSort / "Albums" / album)
def _save(self, filename, metadata, settings): self.log.debug("Saving file %r", filename) file = ASF(encode_filename(filename)) if settings['clear_existing_tags']: file.tags.clear() if settings['save_images_to_tags']: cover = [] for mime, data in metadata.images: tag_data = pack_image(mime, data, 3) cover.append(ASFByteArrayAttribute(tag_data)) if cover: file.tags['WM/Picture'] = cover for name, values in metadata.rawitems(): if name.startswith('lyrics:'): name = 'lyrics' elif name == '~rating': values[0] = int( values[0]) * 99 / (settings['rating_steps'] - 1) if name not in self.__TRANS: continue name = self.__TRANS[name] file.tags[name] = map(unicode, values) file.save()
def _load(self, filename): self.log.debug("Loading file %r", filename) file = ASF(encode_filename(filename)) metadata = Metadata() for name, values in file.tags.items(): if name == 'WM/Picture': for image in values: (mime, data, type) = unpack_image(image.value) if type == 3: # Only cover images metadata.add_image(mime, data) continue elif name not in self.__RTRANS: continue elif name == 'WM/SharedUserRating': # Rating in WMA ranges from 0 to 99, normalize this to the range 0 to 5 values[0] = int( round( int(unicode(values[0])) / 99.0 * (self.config.setting['rating_steps'] - 1))) name = self.__RTRANS[name] values = filter(bool, map(unicode, values)) if values: metadata[name] = values self._info(metadata, file) return metadata
def _save(self, filename, metadata): log.debug("Saving file %r", filename) file = ASF(encode_filename(filename)) if config.setting['clear_existing_tags']: file.tags.clear() if config.setting['save_images_to_tags']: cover = [] for image in metadata.images: if not save_this_image_to_tags(image): continue tag_data = pack_image(image["mime"], image["data"], image_type_as_id3_num(image['type']), image['desc']) cover.append(ASFByteArrayAttribute(tag_data)) if cover: file.tags['WM/Picture'] = cover for name, values in metadata.rawitems(): if name.startswith('lyrics:'): name = 'lyrics' elif name == '~rating': values[0] = int( values[0]) * 99 / (config.setting['rating_steps'] - 1) if name not in self.__TRANS: continue name = self.__TRANS[name] file.tags[name] = map(unicode, values) file.save()
def setUp(self): fd, self.filename = mkstemp(suffix='wma') os.close(fd) shutil.copy(self.original, self.filename) audio = ASF(self.filename) audio["large_value1"] = "#" * 50000 audio.save()
def _save(self, filename, metadata): log.debug("Saving file %r", filename) file = ASF(encode_filename(filename)) if config.setting['clear_existing_tags']: file.tags.clear() cover = [] for image in metadata.images_to_be_saved_to_tags: tag_data = pack_image(image.mimetype, image.data, image_type_as_id3_num(image.maintype), image.comment) cover.append(ASFByteArrayAttribute(tag_data)) if cover: file.tags['WM/Picture'] = cover for name, values in metadata.rawitems(): if name.startswith('lyrics:'): name = 'lyrics' elif name == '~rating': values[0] = int( values[0]) * 99 / (config.setting['rating_steps'] - 1) elif name == 'discnumber' and 'totaldiscs' in metadata: values[0] = '%s/%s' % (metadata['discnumber'], metadata['totaldiscs']) if name not in self.__TRANS: continue name = self.__TRANS[name] file.tags[name] = map(unicode, values) file.save()
def test_multiple_delete(self): self.audio["large_value1"] = "#" * 50000 self.audio.save() audio = ASF(self.filename) for tag in audio.keys(): del (audio[tag]) audio.save()
def test_save_guid(self): # https://github.com/quodlibet/mutagen/issues/81 audio = ASF(self.filename) audio["QL/GuidObject"] = [ASFValue(b" " * 16, GUID)] audio.save() self.failIf("QL/GuidObject" in audio.to_extended_content_description) self.failIf("QL/GuidObject" in audio.to_metadata) self.failIf("QL/GuidObject" not in dict(audio.to_metadata_library))
def test_save_guid(self): # http://code.google.com/p/mutagen/issues/detail?id=81 audio = ASF(self.filename) audio["QL/GuidObject"] = [ASFValue(b" " * 16, GUID)] audio.save() self.failIf("QL/GuidObject" in audio.to_extended_content_description) self.failIf("QL/GuidObject" in audio.to_metadata) self.failIf("QL/GuidObject" not in dict(audio.to_metadata_library))
def _load(self, filename): log.debug("Loading file %r", filename) config = get_config() self.__casemap = {} file = ASF(encode_filename(filename)) metadata = Metadata() for name, values in file.tags.items(): if name == 'WM/Picture': for image in values: try: (mime, data, image_type, description) = unpack_image(image.value) except ValueError as e: log.warning('Cannot unpack image from %r: %s', filename, e) continue try: coverartimage = TagCoverArtImage( file=filename, tag=name, types=types_from_id3(image_type), comment=description, support_types=True, data=data, id3_type=image_type, ) except CoverArtImageError as e: log.error('Cannot load image from %r: %s' % (filename, e)) else: metadata.images.append(coverartimage) continue elif name == 'WM/SharedUserRating': # Rating in WMA ranges from 0 to 99, normalize this to the range 0 to 5 values[0] = int( round( int(str(values[0])) / 99.0 * (config.setting['rating_steps'] - 1))) elif name == 'WM/PartOfSet': disc = str(values[0]).split("/") if len(disc) > 1: metadata["totaldiscs"] = disc[1] values[0] = disc[0] name_lower = name.lower() if name in self.__RTRANS: name = self.__RTRANS[name] elif name_lower in self.__RTRANS_CI: orig_name = name name = self.__RTRANS_CI[name_lower] self.__casemap[name] = orig_name else: continue values = [str(value) for value in values if value] if values: metadata[name] = values self._info(metadata, file) return metadata
def getTrack(filename): """ Return a Track created from an asf file """ from mutagen.asf import ASF asfFile = ASF(filename) length = int(round(asfFile.info.length)) bitrate = int(asfFile.info.bitrate) samplerate = int(asfFile.info.sample_rate) try: trackNumber = str(asfFile['WM/TrackNumber'][0]) except: trackNumber = None try: discNumber = str(asfFile['WM/PartOfSet'][0]) except: discNumber = None try: date = str(asfFile['WM/Year'][0]) except: date = None try: title = str(asfFile['Title'][0]) except: title = None try: album = str(asfFile['WM/AlbumTitle'][0]) except: album = None try: artist = str(asfFile['Author'][0]) except: artist = None try: albumArtist = str(asfFile['WM/AlbumArtist'][0]) except: albumArtist = None try: genre = str(asfFile['WM/Genre'][0]) except: genre = None try: musicbrainzId = str(asfFile['MusicBrainz/Track Id'][0]) except: musicbrainzId = None return createFileTrack(filename, bitrate, length, samplerate, False, title, album, artist, albumArtist, musicbrainzId, genre, trackNumber, date, discNumber)
def __init__(self, file, threshold=60, duration_distance_threshold=10000): self.file = file self.threshold = threshold self.ddt = duration_distance_threshold self.cleaner = re.compile(r"[^A-Za-z0-9 ]").sub try: self.audio = MP3(file, ID3=EasyID3) except: try: self.audio = FLAC(file) except: try: self.audio = OggVorbis(file) except: try: self.audio = OggFLAC(file) except: try: self.audio = OggTheora(file) except: try: self.audio = APEv2(file) except: try: self.audio = ASF(file) except: try: self.audio = MP4(file) except: try: self.audio = Musepack(file) except: try: self.audio = TrueAudio(file) except: try: self.audio = WavPack(file) except: raise FileTypeException( 'Unknown file type, no metadata, or file not found.' ) try: [title] = self.audio['title'] self.title = self.__clean_literal(str(title)) except: self.title = None try: [artist] = self.audio['artist'] self.artist = self.__clean_literal(str(artist)) except: self.artist = None try: [album] = self.audio['album'] self.album = self.__clean_literal(str(album)) except: self.album = None self.mbzQuery()
def test_invalid_header(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") asf = ASF() fileobj = cBytesIO( b"0&\xb2u\x8ef\xcf\x11\xa6\xd9\x00\xaa\x00b\xcel\x19\xbf\x01\x00" b"\x00\x00\x00\x00\x07\x00\x00\x00\x01\x02") self.assertRaises(ASFHeaderError, HeaderObject.parse_full, asf, fileobj)
def read_asf_tags(song, path): audio = ASF(path) song[Song.artist] = get_str(audio, "WM/AlbumArtist", "unknown artist") song[Song.album] = get_str(audio, "WM/AlbumTitle", "unknown album") song[Song.title] = get_str(audio, "Title", "unknown title") song[Song.genre] = get_str(audio, "WM/Genre", "unknown genre") song[Song.album_index] = get_int(audio, 'WM/TrackNumber') song[Song.year] = get_int(audio, "WM/Year", '-') song[Song.length] = int(audio.info.length)
def set_key(self, key, value, result=None): self.audio[key] = value self.audio.save() self.audio = ASF(self.audio.filename) self.failUnless(key in self.audio) newvalue = self.audio[key] if isinstance(newvalue, list): for a, b in zip(sorted(newvalue), sorted(result or value)): self.failUnlessEqual(a, b) else: self.failUnlessEqual(audio[key], result or value)
def test_author_long(self): audio = ASF(self.filename) # 2 ** 16 - 2 bytes encoded text + 2 bytes termination just_small_enough = u"a" * (((2 ** 16) // 2) - 2) audio["Author"] = [just_small_enough] audio.save() self.assertTrue(audio.to_content_description) self.assertFalse(audio.to_metadata_library) audio["Author"] = [just_small_enough + u"a"] audio.save() self.assertFalse(audio.to_content_description) self.assertTrue(audio.to_metadata_library)
def __init__(self, path): super(Track, self).__init__(path) self.wma = ASF(path) f = self.wma self.title = l(f.get('Title')) self.discnumber = reader.number(l(f.get('WM/PartOfSet'))) self.tracknumber = reader.number(l(f.get('WM/TrackNumber'))) self.length = int(f.info.length) self.bitrate = int(f.info.bitrate) self.musicbrainz_trackid = v(l(f.get('MusicBrainz/Track Id'))) self.genres = f.get('WM/Genre') artist = reader.Artist() artist.name = l(f.get('Author')) artist.sortname = l(f.get('WM/ArtistSortOrder')) artist.musicbrainz_artistid = [ v(i) for i in f.get('MusicBrainz/Artist Id', []) ] self.artist = artist for a, i in zip( f.get('WM/ARTISTS', []), f.get('MusicBrainz/Artist Id', []), ): artist = reader.Artist() artist.name = a artist.musicbrainz_artistid = v(i) self.artists.append(artist) album = reader.Album() album.title = l(f.get('WM/AlbumTitle')) album.date = l(f.get('WM/OriginalReleaseYear') or f.get('WM/Year')) album.country = l(f.get('MusicBrainz/Album Release Country')) album.musicbrainz_albumid = v(l(f.get('MusicBrainz/Album Id'))) album.musicbrainz_releasegroupid = v( l(f.get('MusicBrainz/Release Group Id'))) album.labels = f.get('WM/Publisher') album.albumtypes = f.get('MusicBrainz/Album Type') album.albumstatus = f.get('MusicBrainz/Album Status') albumartist = reader.Artist() albumartist.name = l(f.get('WM/AlbumArtist')) albumartist.sortname = l(f.get('WM/AlbumArtistSortOrder')) albumartist.musicbrainz_artistid = [ v(i) for i in f.get('MusicBrainz/Album Artist Id', []) ] album.artist = albumartist self.album = album
def set_key(self, key, value, result=None, expected=True): self.audio[key] = value self.audio.save() self.audio = ASF(self.audio.filename) self.failUnless(key in self.audio) self.failUnless(key in self.audio.tags) self.failUnless(key in self.audio.tags.keys()) self.failUnless(key in self.audio.tags.as_dict().keys()) newvalue = self.audio[key] if isinstance(newvalue, list): for a, b in zip(sorted(newvalue), sorted(result or value)): self.failUnlessEqual(a, b) else: self.failUnlessEqual(self.audio[key], result or value)
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_lang_and_stream_mix(self): self.audio["QL/Mix"] = [ ASFValue("Whee", UNICODE, stream=1), ASFValue("Whee", UNICODE, language=2), ASFValue("Whee", UNICODE, stream=3, language=4), ASFValue("Whee", UNICODE), ] self.audio.save() self.audio = ASF(self.audio.filename) self.failUnlessEqual(self.audio["QL/Mix"][0].language, None) self.failUnlessEqual(self.audio["QL/Mix"][0].stream, 1) self.failUnlessEqual(self.audio["QL/Mix"][1].language, 2) self.failUnlessEqual(self.audio["QL/Mix"][1].stream, 0) self.failUnlessEqual(self.audio["QL/Mix"][2].language, 4) self.failUnlessEqual(self.audio["QL/Mix"][2].stream, 3) self.failUnlessEqual(self.audio["QL/Mix"][3].language, None) self.failUnlessEqual(self.audio["QL/Mix"][3].stream, None)
def _save(self, filename, metadata): log.debug("Saving file %r", filename) config = get_config() file = ASF(encode_filename(filename)) tags = file.tags if config.setting['clear_existing_tags']: cover = tags['WM/Picture'] if config.setting[ 'preserve_images'] else None tags.clear() if cover: tags['WM/Picture'] = cover cover = [] for image in metadata.images.to_be_saved_to_tags(): tag_data = pack_image(image.mimetype, image.data, image_type_as_id3_num(image.maintype), image.comment) cover.append(ASFByteArrayAttribute(tag_data)) if cover: tags['WM/Picture'] = cover for name, values in metadata.rawitems(): if name.startswith('lyrics:'): name = 'lyrics' elif name == '~rating': values = [ int(values[0]) * 99 // (config.setting['rating_steps'] - 1) ] elif name == 'discnumber' and 'totaldiscs' in metadata: values = [ '%s/%s' % (metadata['discnumber'], metadata['totaldiscs']) ] if name in self.__TRANS: name = self.__TRANS[name] elif name in self.__TRANS_CI: if name in self.__casemap: name = self.__casemap[name] else: name = self.__TRANS_CI[name] delall_ci(tags, name) else: continue tags[name] = values self._remove_deleted_tags(metadata, tags) file.save()
def test_stream(self): self.audio["QL/OneHasStream"] = [ ASFValue("Whee", UNICODE, stream=2), ASFValue("Whee", UNICODE), ] self.audio["QL/AllHaveStream"] = [ ASFValue("Whee", UNICODE, stream=1), ASFValue("Whee", UNICODE, stream=2), ] self.audio["QL/NoStream"] = ASFValue("Whee", UNICODE) self.audio.save() self.audio = ASF(self.audio.filename) self.failUnlessEqual(self.audio["QL/NoStream"][0].stream, None) self.failUnlessEqual(self.audio["QL/OneHasStream"][1].stream, 2) self.failUnlessEqual(self.audio["QL/OneHasStream"][0].stream, None) self.failUnlessEqual(self.audio["QL/AllHaveStream"][0].stream, 1) self.failUnlessEqual(self.audio["QL/AllHaveStream"][1].stream, 2)