From 2fda23100409853aebf0a801869e92712d3fbe00 Mon Sep 17 00:00:00 2001 From: Tai Lee Date: Tue, 21 May 2013 23:50:02 +1000 Subject: [PATCH 1/9] Abstract method to determine if track number has changed. This is a little more accurate than the previous method (check if track is in index or medium_index) by looking at the `per_disc_numbering` setting and comparing the index or medium index accordingly. It's also a little more accurate in the display output by diffing the combined `disc-track` to `medium-medium_index` (if using per disc numbering) and intelligently colorizing the either the whole track number or just the suffix. --- beets/autotag/match.py | 14 +++++++++++--- beets/ui/commands.py | 33 +++++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/beets/autotag/match.py b/beets/autotag/match.py index c423e7a56..1f60e59ff 100644 --- a/beets/autotag/match.py +++ b/beets/autotag/match.py @@ -196,6 +196,14 @@ def assign_items(items, tracks): extra_tracks = set(tracks) - set(mapping.values()) return mapping, extra_items, extra_tracks +def track_index_changed(item, track_info): + if config['per_disc_numbering'].get(bool): + if item.track != track_info.medium_index: + return True + elif item.track != track_info.index: + return True + return False + def track_distance(item, track_info, incl_artist=False): """Determines the significance of a track metadata change. Returns a float in [0.0,1.0]. `incl_artist` indicates that a distance @@ -230,7 +238,7 @@ def track_distance(item, track_info, incl_artist=False): # Track index. if track_info.index and item.track: - if item.track not in (track_info.index, track_info.medium_index): + if track_index_changed(item, track_info): dist += TRACK_INDEX_WEIGHT dist_max += TRACK_INDEX_WEIGHT @@ -374,8 +382,8 @@ def _recommendation(results): rec = max_rec['tracklength'] # Track number differs. - elif rec > max_rec['tracknumber'] and item.track not in \ - (track_info.index, track_info.medium_index): + elif rec > max_rec['tracknumber'] and \ + track_index_changed(item, track_info): rec = max_rec['tracknumber'] return rec diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 2cd1ec682..706ca5a95 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -163,14 +163,22 @@ def show_change(cur_artist, cur_album, match): """Return a string representing the track index of the given TrackInfo object. """ - if config['per_disc_numbering'].get(bool): - if match.info.mediums > 1: - return u'{0}-{1}'.format(track_info.medium, - track_info.medium_index) - else: - return unicode(track_info.medium_index) + if isinstance(track_info, autotag.hooks.TrackInfo): + index = track_info.index + medium_index = track_info.medium_index + medium = track_info.medium + mediums = match.info.mediums else: - return unicode(track_info.index) + index = medium_index = track_info.track + medium = track_info.disc + mediums = track_info.disctotal + if config['per_disc_numbering'].get(bool): + if mediums > 1: + return u'{0}-{1}'.format(medium, medium_index) + else: + return unicode(medium_index) + else: + return unicode(index) # Identify the album in question. if cur_artist != match.info.artist or \ @@ -222,9 +230,14 @@ def show_change(cur_artist, cur_album, match): lhs_width = len(cur_title) # Track number change. - if item.track not in (track_info.index, track_info.medium_index): - cur_track, new_track = unicode(item.track), format_index(track_info) - lhs_track, rhs_track = ui.color_diff_suffix(cur_track, new_track) + cur_track, new_track = format_index(item), format_index(track_info) + if cur_track != new_track: + if (cur_track + new_track).count('-') == 1: + lhs_track, rhs_track = ui.colorize('red', cur_track), \ + ui.colorize('red', new_track) + else: + lhs_track, rhs_track = ui.color_diff_suffix(cur_track, + new_track) templ = ui.colorize('red', u' (#') + u'{0}' + \ ui.colorize('red', u')') lhs += templ.format(lhs_track) From 2d04285ebc15e2996f473a5f9dc47fcc2db6f4cb Mon Sep 17 00:00:00 2001 From: Tai Lee Date: Tue, 21 May 2013 23:52:10 +1000 Subject: [PATCH 2/9] Don't colorise the "()" around partial match text. For consistency (and a little easier to read?) --- beets/ui/commands.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 706ca5a95..432aac4f3 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -114,7 +114,7 @@ default_commands.append(fields_cmd) VARIOUS_ARTISTS = u'Various Artists' -PARTIAL_MATCH_MESSAGE = u'(partial match!)' +PARTIAL_MATCH_MESSAGE = u'partial match!' # Importer utilities and support. @@ -155,7 +155,7 @@ def show_change(cur_artist, cur_album, match): # Add a suffix if this is a partial match. if partial: - out += u' ' + ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) + out += u' (%s)' % ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) print_(out) @@ -200,7 +200,7 @@ def show_change(cur_artist, cur_album, match): else: message = u"Tagging: %s - %s" % (match.info.artist, match.info.album) if match.extra_items or match.extra_tracks: - message += u' ' + ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) + message += u' (%s)' % ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) print_(message) # Info line. @@ -440,7 +440,7 @@ def choose_candidate(candidates, singleton, rec, cur_artist=None, if match.extra_items or match.extra_tracks: warning = PARTIAL_MATCH_MESSAGE warning = ui.colorize('yellow', warning) - line += u' %s' % warning + line += u' (%s)' % warning print_(line) From d1548c11785a720124fa141bfbfd4f1a329a7cb0 Mon Sep 17 00:00:00 2001 From: Tai Lee Date: Tue, 21 May 2013 23:52:58 +1000 Subject: [PATCH 3/9] Indent album title and artist when there are no changes for consistency with when there are (and easier to read?) --- beets/ui/commands.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 432aac4f3..bab48da06 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -198,7 +198,8 @@ def show_change(cur_artist, cur_album, match): print_("To:") show_album(artist_r, album_r) else: - message = u"Tagging: %s - %s" % (match.info.artist, match.info.album) + message = u"Tagging:\n %s - %s" % (match.info.artist, + match.info.album) if match.extra_items or match.extra_tracks: message += u' (%s)' % ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) print_(message) From a2942895cc62c3ddb388071fd093057f23e8a789 Mon Sep 17 00:00:00 2001 From: Tai Lee Date: Tue, 21 May 2013 23:55:12 +1000 Subject: [PATCH 4/9] Display album ambiguation on info line (after similarity and source). Colorise disambiguation light grey for subtle distinction from album text. --- beets/ui/commands.py | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/beets/ui/commands.py b/beets/ui/commands.py index bab48da06..ee4ad6a51 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -205,9 +205,10 @@ def show_change(cur_artist, cur_album, match): print_(message) # Info line. - print_('from {0}, similarity: {1}'.format( + print_('from {0}, similarity: {1} [{2}]'.format( source_string(match.info.data_source), dist_string(match.distance), + ui.colorize('lightgray', album_disambig(match.info)), )) # Tracks. @@ -341,6 +342,24 @@ def _summary_judment(rec): print_('Importing as-is.') return action +def album_disambig(info): + # Label, year and media disambiguation, if available. + disambig = [] + if info.label: + disambig.append(info.label) + if info.year: + disambig.append(unicode(info.year)) + if info.media: + if info.mediums > 1: + disambig.append(u'{0}x{1}'.format( + info.mediums, info.media)) + else: + disambig.append(info.media) + if info.albumdisambig: + disambig.append(info.albumdisambig) + if disambig: + return u', '.join(disambig) + def choose_candidate(candidates, singleton, rec, cur_artist=None, cur_album=None, item=None, itemcount=None): """Given a sorted list of candidates, ask the user for a selection @@ -418,22 +437,10 @@ def choose_candidate(candidates, singleton, rec, cur_artist=None, line = '%i. %s - %s' % (i + 1, match.info.artist, match.info.album) - # Label, year and media disambiguation, if available. - disambig = [] - if match.info.label: - disambig.append(match.info.label) - if match.info.year: - disambig.append(unicode(match.info.year)) - if match.info.media: - if match.info.mediums > 1: - disambig.append(u'{0}x{1}'.format( - match.info.mediums, match.info.media)) - else: - disambig.append(match.info.media) - if match.info.albumdisambig: - disambig.append(match.info.albumdisambig) + disambig = album_disambig(match.info) if disambig: - line += u' [{0}]'.format(u', '.join(disambig)) + line += u' [{0}]'.format(ui.colorize('lightgray', + disambig)) line += ' (%s)' % dist_string(match.distance) From 7672fafc7ef8d40cbdf0463479322a86ef7578e1 Mon Sep 17 00:00:00 2001 From: Tai Lee Date: Wed, 22 May 2013 18:38:45 +1000 Subject: [PATCH 5/9] Colorize benign track index changes (to/from per disc numbering) in yellow. --- beets/ui/commands.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/beets/ui/commands.py b/beets/ui/commands.py index ee4ad6a51..35daca373 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -161,7 +161,7 @@ def show_change(cur_artist, cur_album, match): def format_index(track_info): """Return a string representing the track index of the given - TrackInfo object. + TrackInfo or Item object. """ if isinstance(track_info, autotag.hooks.TrackInfo): index = track_info.index @@ -234,14 +234,18 @@ def show_change(cur_artist, cur_album, match): # Track number change. cur_track, new_track = format_index(item), format_index(track_info) if cur_track != new_track: + if item.track in (track_info.index, track_info.medium_index): + color = 'yellow' + else: + color = 'red' if (cur_track + new_track).count('-') == 1: - lhs_track, rhs_track = ui.colorize('red', cur_track), \ - ui.colorize('red', new_track) + lhs_track, rhs_track = ui.colorize(color, cur_track), \ + ui.colorize(color, new_track) else: lhs_track, rhs_track = ui.color_diff_suffix(cur_track, new_track) - templ = ui.colorize('red', u' (#') + u'{0}' + \ - ui.colorize('red', u')') + templ = ui.colorize(color, u' (#') + u'{0}' + \ + ui.colorize(color, u')') lhs += templ.format(lhs_track) rhs += templ.format(rhs_track) lhs_width += len(cur_track) + 4 From 1c02d98e0ec830a5a17b5a7014ee850c7c7621e4 Mon Sep 17 00:00:00 2001 From: Tai Lee Date: Wed, 22 May 2013 18:51:02 +1000 Subject: [PATCH 6/9] No penalty for track index changes to/from per disc numbering. --- beets/autotag/match.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/beets/autotag/match.py b/beets/autotag/match.py index 1f60e59ff..7975b9bf0 100644 --- a/beets/autotag/match.py +++ b/beets/autotag/match.py @@ -197,12 +197,10 @@ def assign_items(items, tracks): return mapping, extra_items, extra_tracks def track_index_changed(item, track_info): - if config['per_disc_numbering'].get(bool): - if item.track != track_info.medium_index: - return True - elif item.track != track_info.index: - return True - return False + """Returns True if the item and track info index is different. Tolerates + per disc and per release numbering. + """ + return item.track not in (track_info.medium_index, track_info.index) def track_distance(item, track_info, incl_artist=False): """Determines the significance of a track metadata change. Returns a From 2420c3de66249ae2e1d480af95e66171a18735cc Mon Sep 17 00:00:00 2001 From: Tai Lee Date: Wed, 22 May 2013 19:02:20 +1000 Subject: [PATCH 7/9] Colorize parenthesis around partial match message. --- beets/ui/commands.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 35daca373..58db14b51 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -114,7 +114,7 @@ default_commands.append(fields_cmd) VARIOUS_ARTISTS = u'Various Artists' -PARTIAL_MATCH_MESSAGE = u'partial match!' +PARTIAL_MATCH_MESSAGE = u'(partial match!)' # Importer utilities and support. @@ -155,7 +155,7 @@ def show_change(cur_artist, cur_album, match): # Add a suffix if this is a partial match. if partial: - out += u' (%s)' % ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) + out += u' %s' % ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) print_(out) @@ -201,7 +201,7 @@ def show_change(cur_artist, cur_album, match): message = u"Tagging:\n %s - %s" % (match.info.artist, match.info.album) if match.extra_items or match.extra_tracks: - message += u' (%s)' % ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) + message += u' %s' % ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) print_(message) # Info line. From e12093e46c3ec5140c0b820baf8f9486cc9e5828 Mon Sep 17 00:00:00 2001 From: Tai Lee Date: Thu, 23 May 2013 17:50:42 +1000 Subject: [PATCH 8/9] Display each part of info line in parenthesis. Source and disambiguation info are conditional. --- beets/ui/commands.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 58db14b51..bdf5bcdb7 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -131,13 +131,6 @@ def dist_string(dist): out = ui.colorize('red', out) return out -def source_string(source): - """Colorize a data_source string. - """ - if source == 'MusicBrainz': - return source - return ui.colorize('yellow', source) - def show_change(cur_artist, cur_album, match): """Print out a representation of the changes that will be made if an album's tags are changed according to `match`, which must be an AlbumMatch @@ -205,11 +198,15 @@ def show_change(cur_artist, cur_album, match): print_(message) # Info line. - print_('from {0}, similarity: {1} [{2}]'.format( - source_string(match.info.data_source), - dist_string(match.distance), - ui.colorize('lightgray', album_disambig(match.info)), - )) + info = [] + info.append('(Similarity: %s)' % dist_string(match.distance)) + if match.info.data_source != 'MusicBrainz': + info.append(ui.colorize('yellow', + '(%s)' % match.info.data_source)) + disambig = album_disambig(match.info) + if disambig: + info.append(ui.colorize('lightgray', '(%s)' % disambig)) + print_(' '.join(info)) # Tracks. pairs = match.mapping.items() From fd20e419d6a202aafbe2c40cf19f488f794ef620 Mon Sep 17 00:00:00 2001 From: Tai Lee Date: Thu, 23 May 2013 17:53:52 +1000 Subject: [PATCH 9/9] Display constant data first (similarity) followed by optional data (partial match, disambiguation). Use consistent and colorized parenthesis for optional data. --- beets/ui/commands.py | 62 +++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/beets/ui/commands.py b/beets/ui/commands.py index bdf5bcdb7..cf097dc80 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -118,6 +118,25 @@ PARTIAL_MATCH_MESSAGE = u'(partial match!)' # Importer utilities and support. +def disambig_string(info): + """Returns label, year and media disambiguation, if available. + """ + disambig = [] + if info.label: + disambig.append(info.label) + if info.year: + disambig.append(unicode(info.year)) + if info.media: + if info.mediums > 1: + disambig.append(u'{0}x{1}'.format( + info.mediums, info.media)) + else: + disambig.append(info.media) + if info.albumdisambig: + disambig.append(info.albumdisambig) + if disambig: + return u', '.join(disambig) + def dist_string(dist): """Formats a distance (a float) as a colorized similarity percentage string. @@ -203,7 +222,7 @@ def show_change(cur_artist, cur_album, match): if match.info.data_source != 'MusicBrainz': info.append(ui.colorize('yellow', '(%s)' % match.info.data_source)) - disambig = album_disambig(match.info) + disambig = disambig_string(match.info) if disambig: info.append(ui.colorize('lightgray', '(%s)' % disambig)) print_(' '.join(info)) @@ -343,24 +362,6 @@ def _summary_judment(rec): print_('Importing as-is.') return action -def album_disambig(info): - # Label, year and media disambiguation, if available. - disambig = [] - if info.label: - disambig.append(info.label) - if info.year: - disambig.append(unicode(info.year)) - if info.media: - if info.mediums > 1: - disambig.append(u'{0}x{1}'.format( - info.mediums, info.media)) - else: - disambig.append(info.media) - if info.albumdisambig: - disambig.append(info.albumdisambig) - if disambig: - return u', '.join(disambig) - def choose_candidate(candidates, singleton, rec, cur_artist=None, cur_album=None, item=None, itemcount=None): """Given a sorted list of candidates, ask the user for a selection @@ -435,23 +436,20 @@ def choose_candidate(candidates, singleton, rec, cur_artist=None, (cur_artist, cur_album)) print_('Candidates:') for i, match in enumerate(candidates): - line = '%i. %s - %s' % (i + 1, match.info.artist, - match.info.album) - - disambig = album_disambig(match.info) - if disambig: - line += u' [{0}]'.format(ui.colorize('lightgray', - disambig)) - - line += ' (%s)' % dist_string(match.distance) + line = ['%i. %s - %s (%s)' % (i + 1, match.info.artist, + match.info.album, + dist_string(match.distance))] # Point out the partial matches. if match.extra_items or match.extra_tracks: - warning = PARTIAL_MATCH_MESSAGE - warning = ui.colorize('yellow', warning) - line += u' (%s)' % warning + line.append(ui.colorize('yellow', + PARTIAL_MATCH_MESSAGE)) - print_(line) + disambig = disambig_string(match.info) + if disambig: + line.append(ui.colorize('lightgray', '(%s)' % disambig)) + + print_(' '.join(line)) # Ask the user for a choice. if singleton: