def _finalize_loading_track(self, track_node, metadata, artists, va, absolutetracknumber, discpregap): track = Track(track_node.recording[0].id, self) self._new_tracks.append(track) # Get track metadata tm = track.metadata tm.copy(metadata) track_to_metadata(track_node, track) track.metadata["~absolutetracknumber"] = absolutetracknumber track._customize_metadata() self._new_metadata.length += tm.length artists.add(tm["artist"]) if va: tm["compilation"] = "1" if discpregap: tm["~discpregap"] = "1" # Run track metadata plugins try: run_track_metadata_processors(self, tm, self._release_node, track_node) except: self.error_append(traceback.format_exc()) return track
def _finalize_loading_track(self, track_node, metadata, artists, extra_metadata=None): # As noted in `_parse_release` above, the release artist nodes # may contain supplementary data that isn't present in track # artist nodes. Similarly, the track artists may contain # information which the recording artists don't. Copy this # information across to wherever the artist IDs match. _copy_artist_nodes(self._release_artist_nodes, track_node) _copy_artist_nodes(self._release_artist_nodes, track_node['recording']) _copy_artist_nodes(_create_artist_node_dict(track_node), track_node['recording']) track = Track(track_node['recording']['id'], self) self._new_tracks.append(track) # Get track metadata tm = track.metadata tm.copy(metadata) track_to_metadata(track_node, track) track._customize_metadata() self._new_metadata.length += tm.length artists.add(tm["artist"]) if extra_metadata: tm.update(extra_metadata) # Run track metadata plugins try: run_track_metadata_processors(self, tm, track_node, self._release_node) except BaseException: self.error_append(traceback.format_exc()) return track
def test_update_album_images(self): album = Album('00000000-0000-0000-0000-000000000000') track1 = Track('00000000-0000-0000-0000-000000000001') track1.linked_files.append(self.test_files[0]) track2 = Track('00000000-0000-0000-0000-000000000002') track2.linked_files.append(self.test_files[1]) album.tracks = [track1, track2] album.unmatched_files.files.append(self.test_files[2]) update_metadata_images(album) self.assertEqual(set(self.test_images), set(album.orig_metadata.images)) self.assertFalse(album.orig_metadata.has_common_images) album.tracks.remove(track2) update_metadata_images(album) self.assertEqual(set(self.test_images), set(album.orig_metadata.images)) self.assertFalse(album.orig_metadata.has_common_images) # album.unmatched_files.files.remove(self.test_files[2]) album.tracks.remove(track1) update_metadata_images(album) self.assertEqual(set(self.test_images[1:]), set(album.orig_metadata.images)) self.assertTrue(album.orig_metadata.has_common_images) album.tracks.append(track2) update_metadata_images(album) self.assertEqual(set(self.test_images[1:]), set(album.orig_metadata.images)) self.assertTrue(album.orig_metadata.has_common_images)
def test_negative_zero(self): genres = Counter(pop=-6, rock=0, blues=-2) ret = Track._genres_to_metadata(genres) self.assertEqual(ret, []) genres = Counter(pop=-6, rock=1, blues=-2) ret = Track._genres_to_metadata(genres) self.assertEqual(ret, ['Rock'])
def test_update_track_images(self): track = Track('00000000-0000-0000-0000-000000000000') track.linked_files = list(self.test_files) update_metadata_images(track) self.assertEqual(set(self.test_images), set(track.orig_metadata.images)) self.assertFalse(track.orig_metadata.has_common_images) track.linked_files.remove(self.test_files[2]) update_metadata_images(track) self.assertEqual(set(self.test_images), set(track.orig_metadata.images)) self.assertFalse(track.orig_metadata.has_common_images) track.linked_files.remove(self.test_files[0]) update_metadata_images(track) self.assertEqual(set(self.test_images[1:]), set(track.orig_metadata.images)) self.assertTrue(track.orig_metadata.has_common_images) track.linked_files.append(self.test_files[2]) update_metadata_images(track) self.assertEqual(set(self.test_images[1:]), set(track.orig_metadata.images)) self.assertTrue(track.orig_metadata.has_common_images)
def _finalize_loading_track(self, track_node, metadata, artists, va, absolutetracknumber, discpregap): track = Track(track_node['recording']['id'], self) self._new_tracks.append(track) # Get track metadata tm = track.metadata tm.copy(metadata) track_to_metadata(track_node, track) track.metadata["~absolutetracknumber"] = absolutetracknumber track._customize_metadata() self._new_metadata.length += tm.length artists.add(tm["artist"]) if va: tm["compilation"] = "1" if discpregap: tm["~discpregap"] = "1" # Run track metadata plugins try: run_track_metadata_processors(self, tm, self._release_node, track_node) except: self.error_append(traceback.format_exc()) return track
def test_remove_from_track_with_common_images(self): track = Track('00000000-0000-0000-0000-000000000000') track.linked_files = list(self.test_files[1:]) update_metadata_images(track) track.linked_files.remove(self.test_files[1]) remove_metadata_images(track, [self.test_files[1]]) self.assertEqual(set(self.test_images[1:]), set(track.orig_metadata.images)) self.assertTrue(track.orig_metadata.has_common_images)
def test_minusage(self): genres = Counter(pop=6, rock=7, blues=2) ret = Track._genres_to_metadata(genres, minusage=10) self.assertEqual(ret, ['Blues', 'Pop', 'Rock']) ret = Track._genres_to_metadata(genres, minusage=50) self.assertEqual(ret, ['Pop', 'Rock']) ret = Track._genres_to_metadata(genres, minusage=90) self.assertEqual(ret, ['Rock'])
def _load_tracks(self, release_node, album): # this happens after the album metadata processor in picard self.tracks = [] for medium_node in release_node['media']: mm = Metadata() mm.copy(album._new_metadata) # noqa medium_to_metadata(medium_node, mm) for track_node in medium_node['tracks']: track = Track(track_node['recording']['id'], album) self.tracks.append(track) # Get track metadata tm = track.metadata tm.copy(mm) track_to_metadata(track_node, track) track._customize_metadata() # noqa
def _load_tracks(self, release_node, album): # this happens after the album metadata processor in picard self.tracks = [] for medium_node in release_node.medium_list[0].medium: mm = Metadata() mm.copy(album._new_metadata) medium_to_metadata(medium_node, mm) for track_node in medium_node.track_list[0].track: track = Track(track_node.recording[0].id, album) self.tracks.append(track) # Get track metadata tm = track.metadata tm.copy(mm) self._track_to_metadata(track_node, track) track._customize_metadata()
def test_recording(self): m = Metadata() t = Track('1') recording_to_metadata(self.json_doc, m, t) self.assertIn('instrumental', m.getall('~performance_attributes')) self.assertEqual(m['language'], 'zxx') self.assertNotIn('lyricist', m)
def test_recording_standardize_artist_credits(self): m = Metadata() t = Track("1") config.setting["standardize_artists"] = True recording_to_metadata(self.json_doc, m, t) self.assertNotIn('performer:solo', m) self.assertEqual(m['performer:solo vocals'], 'Anni-Frid Lyngstad')
def test_translate(self): m = Metadata() t = Track('1') config.setting['translate_artist_names'] = True recording_to_metadata(self.json_doc, m, t) self.assertEqual(m['composer'], 'Pyotr Ilyich Tchaikovsky') self.assertEqual(m['composersort'], 'Tchaikovsky, Pyotr Ilyich')
def test_remove_from_empty_track(self): track = Track('00000000-0000-0000-0000-000000000000') track.linked_files.append(File('test1.flac')) update_metadata_images(track) remove_metadata_images(track, [track.linked_files[0]]) self.assertEqual(set(), set(track.orig_metadata.images)) self.assertTrue(track.orig_metadata.has_common_images)
def test_recording_solo_vocals(self): m = Metadata() t = Track("1") recording_to_metadata(self.json_doc, m, t) config.setting["standardize_artists"] = False self.assertNotIn('performer:solo', m) self.assertEqual(m['performer:solo vocals'], 'Frida')
def test_track(self): t = Track("1") m = t.metadata track_to_metadata(self.json_doc, t) self.assertEqual(m['title'], 'Lady') self.assertEqual(m['tracknumber'], '0') self.assertEqual(m['~musicbrainz_tracknumber'], '0')
def test_recording_instrument_credits(self): m = Metadata() t = Track('1') config.setting['standardize_instruments'] = False recording_to_metadata(self.json_doc, m, t) self.assertEqual(m['performer:vocals'], 'Ed Sheeran') self.assertEqual(m['performer:acoustic guitar'], 'Ed Sheeran')
def test_recording(self): m = Metadata() t = Track('1') recording_to_metadata(self.json_doc, m, t) self.assertEqual(m['director'], 'Edward 209') self.assertEqual(m['producer'], 'Edward 209') self.assertEqual(m['~video'], '1')
def test_compare_to_track(self): track_json = load_test_json('track.json') track = Track(track_json['id']) track_to_metadata(track_json, track) match = track.metadata.compare_to_track(track_json, File.comparison_weights) self.assertEqual(1.0, match.similarity) self.assertEqual(track_json, match.track)
def test_recording(self): m = Metadata() t = Track('1') recording_to_metadata(self.json_doc, m, t) self.assertEqual(m['artist'], 'Ed Sheeran') self.assertEqual(m['artists'], 'Ed Sheeran') self.assertEqual(m['artistsort'], 'Sheeran, Ed') self.assertEqual(m['isrc'], 'GBAHS1400099') self.assertEqual(m['language'], 'eng') self.assertEqual(m['musicbrainz_artistid'], 'b8a7c51f-362c-4dcb-a259-bc6e0095f0a6') self.assertEqual(m['musicbrainz_recordingid'], 'cb2cc207-8125-445c-9ef9-6ea44eee959a') self.assertEqual(m['musicbrainz_workid'], 'dc469dc8-198e-42e5-b5a7-6be2f0a95ac0') self.assertEqual(m['performer:'], 'Ed Sheeran') self.assertEqual(m['performer:lead vocals'], 'Ed Sheeran') self.assertEqual(m['performer:guitar family'], 'Ed Sheeran') self.assertEqual(m['title'], 'Thinking Out Loud') self.assertEqual(m['work'], 'Thinking Out Loud') self.assertEqual(m['writer'], 'Ed Sheeran; Amy Wadge') self.assertEqual(m['~artists_sort'], 'Sheeran, Ed') self.assertEqual(m['~length'], '4:41') self.assertEqual(m['~recordingtitle'], 'Thinking Out Loud') self.assertEqual(t.genres, { 'blue-eyed soul': 1, 'pop': 3}) for artist in t._track_artists: self.assertEqual(artist.genres, { 'dance-pop': 1, 'guitarist': 0})
def test_use_credited_as(self): m = Metadata() t = Track('1') config.setting['translate_artist_names'] = False config.setting['standardize_artists'] = False recording_to_metadata(self.json_doc, m, t) self.assertEqual(m['composer'], 'Tchaikovsky') self.assertEqual(m['composersort'], 'Tchaikovsky, Pyotr Ilyich')
def test_compare_to_track_with_score(self): track_json = load_test_json('track.json') track = Track(track_json['id']) track_to_metadata(track_json, track) for score, sim in ((42, 0.42), ('42', 0.42), ('foo', 1.0), (None, 1.0)): track_json['score'] = score match = track.metadata.compare_to_track(track_json, File.comparison_weights) self.assertEqual(sim, match.similarity)
def test_track(self): t = Track("1") m = t.metadata track_to_metadata(self.json_doc, t) self.assertEqual(m['title'], 'Speak to Me') self.assertEqual(m['musicbrainz_recordingid'], 'bef3fddb-5aca-49f5-b2fd-d56a23268d63') self.assertEqual(m['musicbrainz_trackid'], 'd4156411-b884-368f-a4cb-7c0101a557a2') self.assertEqual(m['~length'], '1:08') self.assertEqual(m['tracknumber'], '1') self.assertEqual(m['~musicbrainz_tracknumber'], 'A1') self.assertEqual(m['~recordingcomment'], 'original stereo mix') self.assertEqual(m['~recordingtitle'], 'Speak to Me')
def _finalize_loading_track(self, track_node, metadata, artists, va, absolutetracknumber, discpregap): # As noted in `_parse_release` above, the release artist nodes # may contain supplementary data that isn't present in track # artist nodes. Similarly, the track artists may contain # information which the recording artists don't. Copy this # information across to wherever the artist IDs match. _copy_artist_nodes(self._release_artist_nodes, track_node) _copy_artist_nodes(self._release_artist_nodes, track_node['recording']) _copy_artist_nodes(_create_artist_node_dict(track_node), track_node['recording']) track = Track(track_node['recording']['id'], self) self._new_tracks.append(track) # Get track metadata tm = track.metadata tm.copy(metadata) track_to_metadata(track_node, track) tm["~absolutetracknumber"] = absolutetracknumber track.orig_metadata.copy(tm) track._customize_metadata() self._new_metadata.length += tm.length artists.add(tm["artist"]) if va: tm["compilation"] = "1" else: del tm["compilation"] if discpregap: tm["~discpregap"] = "1" # Run track metadata plugins try: run_track_metadata_processors(self, tm, self._release_node, track_node) except BaseException: self.error_append(traceback.format_exc()) return track
def test_recording(self): m = Metadata() t = Track("1") recording_to_metadata(self.json_doc, m, t) self.assertEqual(m['artist'], 'Ed Sheeran') self.assertEqual(m['artists'], 'Ed Sheeran') self.assertEqual(m['artistsort'], 'Sheeran, Ed') self.assertEqual(m['isrc'], 'GBAHS1400099') self.assertEqual(m['language'], 'eng') self.assertEqual(m['musicbrainz_artistid'], 'b8a7c51f-362c-4dcb-a259-bc6e0095f0a6') self.assertEqual(m['musicbrainz_recordingid'], 'cb2cc207-8125-445c-9ef9-6ea44eee959a') self.assertEqual(m['musicbrainz_workid'], 'dc469dc8-198e-42e5-b5a7-6be2f0a95ac0') self.assertEqual(m['performer:'], 'Ed Sheeran') self.assertEqual(m['performer:vocals'], 'Ed Sheeran') self.assertEqual(m['title'], 'Thinking Out Loud') self.assertEqual(m['work'], 'Thinking Out Loud') self.assertEqual(m['writer'], 'Ed Sheeran; Amy Wadge') self.assertEqual(m['~artists_sort'], 'Sheeran, Ed') self.assertEqual(m['~length'], '4:41') self.assertEqual(m['~recordingtitle'], 'Thinking Out Loud')
def _finalize_loading(self, error): if error: self.metadata.clear() self.metadata['album'] = _("[could not load album %s]") % self.id del self._new_metadata del self._new_tracks self.update() return if self._requests > 0: return if not self._tracks_loaded: artists = set() totalalbumtracks = 0 djmix_ars = {} if hasattr(self._new_metadata, "_djmix_ars"): djmix_ars = self._new_metadata._djmix_ars for medium_node in self._release_node.medium_list[0].medium: mm = Metadata() mm.copy(self._new_metadata) medium_to_metadata(medium_node, mm) totalalbumtracks += int(mm["totaltracks"]) for dj in djmix_ars.get(mm["discnumber"], []): mm.add("djmixer", dj) for track_node in medium_node.track_list[0].track: track = Track(track_node.recording[0].id, self) self._new_tracks.append(track) # Get track metadata tm = track.metadata tm.copy(mm) track_to_metadata(track_node, track, self.config) track._customize_metadata() self._new_metadata.length += tm.length artists.add(tm["musicbrainz_artistid"]) # Run track metadata plugins try: run_track_metadata_processors(self, tm, self._release_node, track_node) except: self.log.error(traceback.format_exc()) totalalbumtracks = str(totalalbumtracks) for track in self._new_tracks: track.metadata["~totalalbumtracks"] = totalalbumtracks if len(artists) > 1: track.metadata["compilation"] = "1" del self._release_node self._tracks_loaded = True if not self._requests: # Prepare parser for user's script if self.config.setting["enable_tagger_script"]: script = self.config.setting["tagger_script"] if script: parser = ScriptParser() for track in self._new_tracks: # Run tagger script for each track try: parser.eval(script, track.metadata) except: self.log.error(traceback.format_exc()) # Strip leading/trailing whitespace track.metadata.strip_whitespace() # Run tagger script for the album itself try: parser.eval(script, self._new_metadata) except: self.log.error(traceback.format_exc()) self._new_metadata.strip_whitespace() for track in self.tracks: for file in list(track.linked_files): file.move(self.unmatched_files) self.metadata = self._new_metadata self.tracks = self._new_tracks del self._new_metadata del self._new_tracks self.loaded = True self.match_files(self.unmatched_files.files) self.update() self.tagger.window.set_statusbar_message(_('Album %s loaded'), self.id, timeout=3000) while self._after_load_callbacks.qsize() > 0: func = self._after_load_callbacks.get() func()
def test_track(self): t = Track("1") m = t.metadata track_to_metadata(self.json_doc, t) self.assertEqual(m, {})
def test_recording_instrument_decamelcase(self): m = Metadata() t = Track("1") recording_to_metadata(self.json_doc, m, t) self.assertEqual(m['performer:ewi'], 'Michael Brecker')
def test_recording(self): m = Metadata() t = Track("1") recording_to_metadata(self.json_doc, m, t) self.assertEqual(m, {})
def _parse_release(self, document): self.log.debug("Loading release %r", self.id) release_node = document.metadata[0].release[0] if release_node.id != self.id: album = self.tagger.get_album_by_id(release_node.id) self.tagger.albumids[self.id] = release_node.id self.id = release_node.id if album: album.match_files(self.unmatched_files.files) album.update() self.tagger.remove_album(self) self.log.debug("Release %r already loaded", self.id) return False # Get release metadata m = self._new_metadata m.length = 0 release_to_metadata(release_node, m, config=self.config, album=self) self.format_str = media_formats_from_node(release_node.medium_list[0]) self.rgid = release_node.release_group[0].id if self._discid: m['musicbrainz_discid'] = self._discid # 'Translate' artist name if self.config.setting['translate_artist_names']: m['albumartist'] = translate_artist(m['albumartist'], m['albumartistsort']) # Custom VA name if m['musicbrainz_albumartistid'] == VARIOUS_ARTISTS_ID: m['albumartistsort'] = m['albumartist'] = self.config.setting['va_name'] ignore_tags = [s.strip() for s in self.config.setting['ignore_tags'].split(',')] first_artist = None compilation = False track_counts = [] m['totaldiscs'] = release_node.medium_list[0].count self._metadata_processors = [partial(run_album_metadata_processors, self, m, release_node)] for medium_node in release_node.medium_list[0].medium: mm = Metadata() mm.copy(m) medium_to_metadata(medium_node, mm) track_counts.append(mm['totaltracks']) for track_node in medium_node.track_list[0].track: t = Track(track_node.recording[0].id, self) self._new_tracks.append(t) # Get track metadata tm = t.metadata tm.copy(mm) track_to_metadata(track_node, t, self.config) m.length += tm.length artist_id = tm['musicbrainz_artistid'] if compilation is False: if first_artist is None: first_artist = artist_id if first_artist != artist_id: compilation = True for track in self._new_tracks: track.metadata['compilation'] = '1' else: tm['compilation'] = '1' t._customize_metadata(ignore_tags) plugins = partial(run_track_metadata_processors, self, tm, release_node, track_node) self._metadata_processors.append(plugins) m["~totalalbumtracks"] = str(sum(map(int, track_counts))) self.tracks_str = " + ".join(track_counts) return True
def _finalize_loading(self, error): if error: self.metadata.clear() self.metadata['album'] = _("[could not load album %s]") % self.id del self._new_metadata del self._new_tracks self.update() return if self._requests > 0: return if not self._tracks_loaded: artists = set() totalalbumtracks = 0 djmix_ars = {} if hasattr(self._new_metadata, "_djmix_ars"): djmix_ars = self._new_metadata._djmix_ars for medium_node in self._release_node.medium_list[0].medium: mm = Metadata() mm.copy(self._new_metadata) medium_to_metadata(medium_node, mm) totalalbumtracks += int(mm["totaltracks"]) for dj in djmix_ars.get(mm["discnumber"], []): mm.add("djmixer", dj) for track_node in medium_node.track_list[0].track: track = Track(track_node.recording[0].id, self) self._new_tracks.append(track) # Get track metadata tm = track.metadata tm.copy(mm) track_to_metadata(track_node, track, self.config) track._customize_metadata() self._new_metadata.length += tm.length artists.add(tm["musicbrainz_artistid"]) # Run track metadata plugins try: run_track_metadata_processors(self, tm, self._release_node, track_node) except: self.log.error(traceback.format_exc()) totalalbumtracks = str(totalalbumtracks) for track in self._new_tracks: track.metadata["~totalalbumtracks"] = totalalbumtracks if len(artists) > 1: track.metadata["compilation"] = "1" del self._release_node self._tracks_loaded = True if not self._requests: # Prepare parser for user's script if self.config.setting["enable_tagger_script"]: script = self.config.setting["tagger_script"] if script: parser = ScriptParser() for track in self._new_tracks: # Run tagger script for each track try: parser.eval(script, track.metadata) except: self.log.error(traceback.format_exc()) # Strip leading/trailing whitespace track.metadata.strip_whitespace() # Run tagger script for the album itself try: parser.eval(script, self._new_metadata) except: self.log.error(traceback.format_exc()) self._new_metadata.strip_whitespace() for track in self.tracks: for file in list(track.linked_files): file.move(self.unmatched_files) self.metadata = self._new_metadata self.tracks = self._new_tracks del self._new_metadata del self._new_tracks self.loaded = True self.match_files(self.unmatched_files.files) self.update() self.tagger.window.set_statusbar_message('Album %s loaded', self.id, timeout=3000) while self._after_load_callbacks.qsize() > 0: func = self._after_load_callbacks.get() func()
def test_filters(self): genres = Counter(pop=6, rock=7, blues=2) ret = Track._genres_to_metadata(genres, filters="-blues") self.assertEqual(ret, ['Pop', 'Rock'])
def test_join_with(self): genres = Counter(pop=6, rock=7, blues=2) ret = Track._genres_to_metadata(genres, join_with=",") self.assertEqual(ret, ['Blues,Pop,Rock'])