From 04c30355e2743b7f0bd2cbfce89472483a0d5b85 Mon Sep 17 00:00:00 2001 From: Calvin Walton Date: Sun, 22 Sep 2013 08:23:57 -0400 Subject: [PATCH] Rename internal trackid to recordingid, add a new tag for trackids. --- picard/acoustid.py | 4 ++-- picard/acoustidmanager.py | 18 +++++++++--------- picard/album.py | 30 +++++++++++++++--------------- picard/browser/filelookup.py | 4 ++-- picard/file.py | 4 ++-- picard/formats/apev2.py | 2 ++ picard/formats/asf.py | 3 ++- picard/formats/id3.py | 5 +++-- picard/formats/mp4.py | 3 ++- picard/formats/vorbis.py | 10 ++++++++++ picard/mbxml.py | 3 ++- picard/tagger.py | 26 +++++++++++++------------- picard/ui/options/renaming.py | 4 ++-- picard/util/tags.py | 3 ++- picard/webservice.py | 4 ++-- 15 files changed, 70 insertions(+), 53 deletions(-) diff --git a/picard/acoustid.py b/picard/acoustid.py index 4d0858e1c6..2d7b526f17 100644 --- a/picard/acoustid.py +++ b/picard/acoustid.py @@ -133,8 +133,8 @@ def _lookup_fingerprint(self, next, filename, result=None, error=None): params['fingerprint'] = fingerprint params['duration'] = str(length) else: - type, trackid = result - params['trackid'] = trackid + type, recordingid = result + params['recordingid'] = recordingid self.tagger.xmlws.query_acoustid(partial(self._on_lookup_finished, next, file), **params) def _on_fpcalc_finished(self, next, file, exit_code, exit_status): diff --git a/picard/acoustidmanager.py b/picard/acoustidmanager.py index 9bbf7bdcde..67ea1e90a5 100644 --- a/picard/acoustidmanager.py +++ b/picard/acoustidmanager.py @@ -23,12 +23,12 @@ class Submission(object): - def __init__(self, fingerprint, duration, orig_trackid=None, trackid=None, puid=None): + def __init__(self, fingerprint, duration, orig_recordingid=None, recordingid=None, puid=None): self.fingerprint = fingerprint self.duration = duration self.puid = puid - self.orig_trackid = orig_trackid - self.trackid = trackid + self.orig_recordingid = orig_recordingid + self.recordingid = recordingid class AcoustIDManager(QtCore.QObject): @@ -37,20 +37,20 @@ def __init__(self): QtCore.QObject.__init__(self) self._fingerprints = {} - def add(self, file, trackid): + def add(self, file, recordingid): if not hasattr(file, 'acoustid_fingerprint'): return if not hasattr(file, 'acoustid_length'): return puid = file.metadata['musicip_puid'] - self._fingerprints[file] = Submission(file.acoustid_fingerprint, file.acoustid_length, trackid, trackid, puid) + self._fingerprints[file] = Submission(file.acoustid_fingerprint, file.acoustid_length, recordingid, recordingid, puid) self._check_unsubmitted() - def update(self, file, trackid): + def update(self, file, recordingid): submission = self._fingerprints.get(file) if submission is None: return - submission.trackid = trackid + submission.recordingid = recordingid self._check_unsubmitted() def remove(self, file): @@ -60,7 +60,7 @@ def remove(self, file): def _unsubmitted(self): for submission in self._fingerprints.itervalues(): - if submission.trackid and submission.orig_trackid != submission.trackid: + if submission.recordingid and submission.orig_recordingid != submission.recordingid: yield submission def _check_unsubmitted(self): @@ -84,5 +84,5 @@ def __fingerprint_submission_finished(self, fingerprints, document, http, error) else: self.tagger.window.set_statusbar_message(N_('AcoustIDs successfully submitted!'), timeout=3000) for submission in fingerprints: - submission.orig_trackid = submission.trackid + submission.orig_recordingid = submission.recordingid self._check_unsubmitted() diff --git a/picard/album.py b/picard/album.py index d7d77d2e5d..c5db98e160 100644 --- a/picard/album.py +++ b/picard/album.py @@ -152,10 +152,10 @@ def _release_request_finished(self, document, http, error): nat_name = config.setting["nat_name"] files = list(self.unmatched_files.files) for file in files: - trackid = file.metadata["musicbrainz_trackid"] - if mbid_validate(trackid) and file.metadata["album"] == nat_name: + recordingid = file.metadata["musicbrainz_recordingid"] + if mbid_validate(recordingid) and file.metadata["album"] == nat_name: nats = True - self.tagger.move_file_to_nat(file, trackid) + self.tagger.move_file_to_nat(file, recordingid) self.tagger.nats.update() if nats and not self.get_num_unmatched_files(): self.tagger.remove_album(self) @@ -329,15 +329,15 @@ def _remove_file(self, track, file): self._files -= 1 self.update(update_tracks=False) - def match_files(self, files, use_trackid=True): - """Match files to tracks on this album, based on metadata similarity or trackid.""" + def match_files(self, files, use_recordingid=True): + """Match files to tracks on this album, based on metadata similarity or recordingid.""" for file in list(files): if file.state == File.REMOVED: continue matches = [] - trackid = file.metadata['musicbrainz_trackid'] - if use_trackid and mbid_validate(trackid): - matches = self._get_trackid_matches(file, trackid) + recordingid = file.metadata['musicbrainz_recordingid'] + if use_recordingid and mbid_validate(recordingid): + matches = self._get_recordingid_matches(file, recordingid) if not matches: for track in self.tracks: sim = track.metadata.compare(file.orig_metadata) @@ -349,25 +349,25 @@ def match_files(self, files, use_trackid=True): else: file.move(self.unmatched_files) - def match_file(self, file, trackid=None): - """Match the file on a track on this album, based on trackid or metadata similarity.""" + def match_file(self, file, recordingid=None): + """Match the file on a track on this album, based on recordingid or metadata similarity.""" if file.state == File.REMOVED: return - if trackid is not None: - matches = self._get_trackid_matches(file, trackid) + if recordingid is not None: + matches = self._get_recordingid_matches(file, recordingid) if matches: matches.sort(reverse=True) file.move(matches[0][1]) return - self.match_files([file], use_trackid=False) + self.match_files([file], use_recordingid=False) - def _get_trackid_matches(self, file, trackid): + def _get_recordingid_matches(self, file, recordingid): matches = [] tracknumber = file.metadata['tracknumber'] discnumber = file.metadata['discnumber'] for track in self.tracks: tm = track.metadata - if trackid == tm['musicbrainz_trackid']: + if recordingid == tm['musicbrainz_recordingid']: if tracknumber == tm['tracknumber']: if discnumber == tm['discnumber']: matches.append((4.0, track)) diff --git a/picard/browser/filelookup.py b/picard/browser/filelookup.py index e4768b7ee0..1132689f2d 100644 --- a/picard/browser/filelookup.py +++ b/picard/browser/filelookup.py @@ -60,8 +60,8 @@ def discLookup(self, url): def _lookup(self, type_, id_): return self._build_launch("/%s/%s" % (type_, id_)) - def trackLookup(self, track_id): - return self._lookup('recording', track_id) + def recordingLookup(self, recording_id): + return self._lookup('recording', recording_id) def albumLookup(self, album_id): return self._lookup('release', album_id) diff --git a/picard/file.py b/picard/file.py index e12b2ed76d..e9164d89f5 100644 --- a/picard/file.py +++ b/picard/file.py @@ -403,7 +403,7 @@ def move(self, parent): self.parent.remove_file(self) self.parent = parent self.parent.add_file(self) - self.tagger.acoustidmanager.update(self, self.metadata['musicbrainz_trackid']) + self.tagger.acoustidmanager.update(self, self.metadata['musicbrainz_recordingid']) def _move(self, parent): if parent != self.parent: @@ -411,7 +411,7 @@ def _move(self, parent): if self.parent: self.parent.remove_file(self) self.parent = parent - self.tagger.acoustidmanager.update(self, self.metadata['musicbrainz_trackid']) + self.tagger.acoustidmanager.update(self, self.metadata['musicbrainz_recordingid']) def supports_tag(self, name): """Returns whether tag ``name`` can be saved to the file.""" diff --git a/picard/formats/apev2.py b/picard/formats/apev2.py index fdfd8fd624..eadcce5de7 100644 --- a/picard/formats/apev2.py +++ b/picard/formats/apev2.py @@ -48,6 +48,8 @@ class APEv2File(File): "Language": "language", "MUSICBRAINZ_ALBUMSTATUS": "releasestatus", "MUSICBRAINZ_ALBUMTYPE": "releasetype", + "musicbrainz_trackid": "musicbrainz_recordingid", + "musicbrainz_releasetrackid": "musicbrainz_trackid", } __rtranslate = dict([(v, k) for k, v in __translate.iteritems()]) diff --git a/picard/formats/asf.py b/picard/formats/asf.py index d32a126034..4ff5f4a43c 100644 --- a/picard/formats/asf.py +++ b/picard/formats/asf.py @@ -107,7 +107,8 @@ class ASFFile(File): 'albumartistsort': 'WM/AlbumArtistSortOrder', 'artistsort': 'WM/ArtistSortOrder', 'titlesort': 'WM/TitleSortOrder', - 'musicbrainz_trackid': 'MusicBrainz/Track Id', + 'musicbrainz_recordingid': 'MusicBrainz/Track Id', + 'musicbrainz_trackid': 'MusicBrainz/Release Track Id', 'musicbrainz_albumid': 'MusicBrainz/Album Id', 'musicbrainz_artistid': 'MusicBrainz/Artist Id', 'musicbrainz_albumartistid': 'MusicBrainz/Album Artist Id', diff --git a/picard/formats/id3.py b/picard/formats/id3.py index af4976ae2a..20caf21be4 100644 --- a/picard/formats/id3.py +++ b/picard/formats/id3.py @@ -142,6 +142,7 @@ class ID3File(File): 'MusicBrainz Album Type': 'releasetype', 'MusicBrainz Album Status': 'releasestatus', 'MusicBrainz TRM Id': 'musicbrainz_trmid', + 'MusicBrainz Release Track Id': 'musicbrainz_trackid', 'MusicBrainz Disc Id': 'musicbrainz_discid', 'MusicBrainz Work Id': 'musicbrainz_workid', 'MusicBrainz Release Group Id': 'musicbrainz_releasegroupid', @@ -232,7 +233,7 @@ def _load(self, filename): name += ':%s' % frame.desc metadata.add(name, unicode(frame.text)) elif frameid == 'UFID' and frame.owner == 'http://musicbrainz.org': - metadata['musicbrainz_trackid'] = frame.data.decode('ascii', 'ignore') + metadata['musicbrainz_recordingid'] = frame.data.decode('ascii', 'ignore') elif frameid == 'TRCK': value = frame.text[0].split('/') if len(value) > 1: @@ -346,7 +347,7 @@ def _save(self, filename, metadata): elif name in self._rtipl_roles: for value in values: tipl.people.append([self._rtipl_roles[name], value]) - elif name == 'musicbrainz_trackid': + elif name == 'musicbrainz_recordingid': tags.add(id3.UFID(owner='http://musicbrainz.org', data=str(values[0]))) elif name == '~rating': # Search for an existing POPM frame to get the current playcount diff --git a/picard/formats/mp4.py b/picard/formats/mp4.py index 736f5040c5..410eb1b233 100644 --- a/picard/formats/mp4.py +++ b/picard/formats/mp4.py @@ -65,7 +65,7 @@ class MP4File(File): __r_int_tags = dict([(v, k) for k, v in __int_tags.iteritems()]) __freeform_tags = { - "----:com.apple.iTunes:MusicBrainz Track Id": "musicbrainz_trackid", + "----:com.apple.iTunes:MusicBrainz Track Id": "musicbrainz_recordingid", "----:com.apple.iTunes:MusicBrainz Artist Id": "musicbrainz_artistid", "----:com.apple.iTunes:MusicBrainz Album Id": "musicbrainz_albumid", "----:com.apple.iTunes:MusicBrainz Album Artist Id": "musicbrainz_albumartistid", @@ -77,6 +77,7 @@ class MP4File(File): "----:com.apple.iTunes:MusicBrainz TRM Id": "musicbrainz_trmid", "----:com.apple.iTunes:MusicBrainz Work Id": "musicbrainz_workid", "----:com.apple.iTunes:MusicBrainz Release Group Id": "musicbrainz_releasegroupid", + "----:com.apple.iTunes:MusicBrainz Release Track Id": "musicbrainz_trackid", "----:com.apple.iTunes:Acoustid Fingerprint": "acoustid_fingerprint", "----:com.apple.iTunes:Acoustid Id": "acoustid_id", "----:com.apple.iTunes:ASIN": "asin", diff --git a/picard/formats/vorbis.py b/picard/formats/vorbis.py index 2533dc7b8d..c8a2d5fd67 100644 --- a/picard/formats/vorbis.py +++ b/picard/formats/vorbis.py @@ -42,6 +42,12 @@ class VCommentFile(File): """Generic VComment-based file.""" _File = None + __translate = { + "musicbrainz_trackid": "musicbrainz_recordingid", + "musicbrainz_releasetrackid": "musicbrainz_trackid", + } + __rtranslate = dict([(v, k) for k, v in __translate.iteritems()]) + def _load(self, filename): log.debug("Loading file %r", filename) file = self._File(encode_filename(filename)) @@ -96,6 +102,8 @@ def _load(self, filename): } metadata.add_image(image.mime, image.data, extras=extras) continue + elif name in self.__translate: + name = self.__translate[name] metadata.add(name, value) if self._File == mutagen.flac.FLAC: for image in file.pictures: @@ -153,6 +161,8 @@ def _save(self, filename, metadata): elif name == "musicip_fingerprint": name = "fingerprint" value = "MusicMagic Fingerprint%s" % value + elif name in self.__rtranslate: + name = self.__rtranslate[name] tags.setdefault(name.upper().encode('utf-8'), []).append(value) if "totaltracks" in metadata: diff --git a/picard/mbxml.py b/picard/mbxml.py index 46932c12d5..5b12b30001 100644 --- a/picard/mbxml.py +++ b/picard/mbxml.py @@ -204,6 +204,7 @@ def track_to_metadata(node, track): m = track.metadata recording_to_metadata(node.recording[0], track) # overwrite with data we have on the track + m['musicbrainz_trackid'] = node.attribs['id'] for name, nodes in node.children.iteritems(): if not nodes: continue @@ -221,7 +222,7 @@ def track_to_metadata(node, track): def recording_to_metadata(node, track): m = track.metadata m.length = 0 - m['musicbrainz_trackid'] = node.attribs['id'] + m['musicbrainz_recordingid'] = node.attribs['id'] for name, nodes in node.children.iteritems(): if not nodes: continue diff --git a/picard/tagger.py b/picard/tagger.py index 95b6ee49fb..80b83d5951 100644 --- a/picard/tagger.py +++ b/picard/tagger.py @@ -214,11 +214,11 @@ def move_file_to_album(self, file, albumid): """Move `file` to a track on album `albumid`.""" self.move_files_to_album([file], albumid) - def move_file_to_track(self, file, albumid, trackid): - """Move `file` to track `trackid` on album `albumid`.""" + def move_file_to_track(self, file, albumid, recordingid): + """Move `file` to recording `recordingid` on album `albumid`.""" album = self.load_album(albumid) file.move(album.unmatched_files) - album.run_when_loaded(partial(album.match_file, file, trackid)) + album.run_when_loaded(partial(album.match_file, file, recordingid)) def create_nats(self): if self.nats is None: @@ -227,10 +227,10 @@ def create_nats(self): self.album_added.emit(self.nats) return self.nats - def move_file_to_nat(self, file, trackid, node=None): + def move_file_to_nat(self, file, recordingid, node=None): self.create_nats() file.move(self.nats.unmatched_files) - nat = self.load_nat(trackid, node=node) + nat = self.load_nat(recordingid, node=node) nat.run_when_loaded(partial(file.move, nat)) if nat.loaded: self.nats.update() @@ -277,18 +277,18 @@ def event(self, event): def _file_loaded(self, file, target=None): if file is not None and not file.has_error(): - trackid = file.metadata['musicbrainz_trackid'] + recordingid = file.metadata['musicbrainz_recordingid'] if target is not None: self.move_files([file], target) elif not config.setting["ignore_file_mbids"]: albumid = file.metadata['musicbrainz_albumid'] if mbid_validate(albumid): - if mbid_validate(trackid): - self.move_file_to_track(file, albumid, trackid) + if mbid_validate(recordingid): + self.move_file_to_track(file, albumid, recordingid) else: self.move_file_to_album(file, albumid) - elif mbid_validate(trackid): - self.move_file_to_nat(file, trackid) + elif mbid_validate(recordingid): + self.move_file_to_nat(file, recordingid) elif config.setting['analyze_new_files'] and file.can_analyze(): self.analyze([file]) elif config.setting['analyze_new_files'] and file.can_analyze(): @@ -360,10 +360,10 @@ def browser_lookup(self, item): lookup = self.get_file_lookup() metadata = item.metadata albumid = metadata["musicbrainz_albumid"] - trackid = metadata["musicbrainz_trackid"] + recordingid = metadata["musicbrainz_recordingid"] # Only lookup via MB IDs if matched to a DataObject; otherwise ignore and use metadata details - if isinstance(item, Track) and trackid: - lookup.trackLookup(trackid) + if isinstance(item, Track) and recordingid: + lookup.recordingLookup(recordingid) elif isinstance(item, Album) and albumid: lookup.albumLookup(albumid) else: diff --git a/picard/ui/options/renaming.py b/picard/ui/options/renaming.py index 33900fcd9a..9b3cb769c4 100644 --- a/picard/ui/options/renaming.py +++ b/picard/ui/options/renaming.py @@ -225,7 +225,7 @@ def example_1(self): file.metadata['musicbrainz_albumid'] = '2c053984-4645-4699-9474-d2c35c227028' file.metadata['musicbrainz_albumartistid'] = 'b10bbbfc-cf9e-42e0-be17-e2c3e1d2600d' file.metadata['musicbrainz_artistid'] = 'b10bbbfc-cf9e-42e0-be17-e2c3e1d2600d' - file.metadata['musicbrainz_trackid'] = '898a2916-f64d-48d3-ab1a-3446fb450448' + file.metadata['musicbrainz_recordingid'] = '898a2916-f64d-48d3-ab1a-3446fb450448' return file def example_2(self): @@ -250,7 +250,7 @@ def example_2(self): file.metadata['musicbrainz_albumid'] = 'bcc97e8a-2055-400b-a6ed-83288285c6fc' file.metadata['musicbrainz_albumartistid'] = '89ad4ac3-39f7-470e-963a-56509c546377' file.metadata['musicbrainz_artistid'] = '06704773-aafe-4aca-8833-b449e0a6467f' - file.metadata['musicbrainz_trackid'] = 'd92837ee-b1e4-4649-935f-e433c3e5e429' + file.metadata['musicbrainz_recordingid'] = 'd92837ee-b1e4-4649-935f-e433c3e5e429' return file STYLESHEET_ERROR = "QWidget { background-color: #f55; color: white; font-weight:bold }" diff --git a/picard/util/tags.py b/picard/util/tags.py index 46622f417d..e4e4dc775f 100644 --- a/picard/util/tags.py +++ b/picard/util/tags.py @@ -50,7 +50,8 @@ 'subtitle': N_('Subtitle'), 'discsubtitle': N_('Disc Subtitle'), 'remixer': N_('Remixer'), - 'musicbrainz_trackid': N_('MusicBrainz Recording Id'), + 'musicbrainz_recordingid': N_('MusicBrainz Recording Id'), + 'musicbrainz_trackid': N_('MusicBrainz Track Id'), 'musicbrainz_albumid': N_('MusicBrainz Release Id'), 'musicbrainz_artistid': N_('MusicBrainz Artist Id'), 'musicbrainz_albumartistid': N_('MusicBrainz Release Artist Id'), diff --git a/picard/webservice.py b/picard/webservice.py index 9ca22e2cc5..43470ebf05 100644 --- a/picard/webservice.py +++ b/picard/webservice.py @@ -347,8 +347,8 @@ def _get_by_id(self, entitytype, entityid, handler, inc=[], params=[], priority= def get_release_by_id(self, releaseid, handler, inc=[], priority=True, important=False, mblogin=False): return self._get_by_id('release', releaseid, handler, inc, priority=priority, important=important, mblogin=mblogin) - def get_track_by_id(self, trackid, handler, inc=[], priority=True, important=False, mblogin=False): - return self._get_by_id('recording', trackid, handler, inc, priority=priority, important=important, mblogin=mblogin) + def get_track_by_id(self, recordingid, handler, inc=[], priority=True, important=False, mblogin=False): + return self._get_by_id('recording', recordingid, handler, inc, priority=priority, important=important, mblogin=mblogin) def lookup_discid(self, discid, handler, priority=True, important=True): inc = ['artist-credits', 'labels']