tolerate per-medium track numbering (#283)

This commit is contained in:
Adrian Sampson 2012-01-25 20:12:04 -08:00
parent 53e5bb05b7
commit 47891b00f7
6 changed files with 81 additions and 9 deletions

View file

@ -69,12 +69,13 @@ class TrackInfo(object):
may be None.
"""
def __init__(self, title, track_id, artist=None, artist_id=None,
length=None):
length=None, medium_index=None):
self.title = title
self.track_id = track_id
self.artist = artist
self.artist_id = artist_id
self.length = length
self.medium_index = medium_index
# Aggregation of sources.

View file

@ -234,7 +234,7 @@ def track_distance(item, track_info, track_index=None, incl_artist=False):
# Track index.
if track_index and item.track:
if track_index != item.track:
if item.track not in (track_index, track_info.medium_index):
dist += TRACK_INDEX_WEIGHT
dist_max += TRACK_INDEX_WEIGHT

View file

@ -45,12 +45,14 @@ else:
_mb_release_search = musicbrainzngs.search_releases
_mb_recording_search = musicbrainzngs.search_recordings
def track_info(recording):
def track_info(recording, medium_index=None):
"""Translates a MusicBrainz recording result dictionary into a beets
``TrackInfo`` object.
``TrackInfo`` object. ``medium_index``, if provided, is the track's
index (1-based) on its medium.
"""
info = beets.autotag.hooks.TrackInfo(recording['title'],
recording['id'])
recording['id'],
medium_index=medium_index)
# Get the name of the track artist.
if recording.get('artist-credit-phrase'):
@ -93,7 +95,7 @@ def album_info(release):
track_infos = []
for medium in release['medium-list']:
for track in medium['track-list']:
ti = track_info(track['recording'])
ti = track_info(track['recording'], int(track['position']))
if track.get('title'):
# Track title may be distinct from underling recording
# title.

View file

@ -6,6 +6,10 @@ Changelog
* The :doc:`/plugins/lyrics`, originally by `Peter Brunner`_, is revamped and
included with beets, making it easy to fetch **song lyrics**.
* The autotagger now tolerates tracks on multi-disc albums that are numbered
per-disc. For example, if track 24 on a release is the first track on the
second disc, then it is not penalized for having its track number set to 1
instead of 24.
* Fix a bug in the ``rewrite`` plugin that broke the use of multiple rules for
a single field.

View file

@ -173,6 +173,57 @@ class AlbumDistanceTest(unittest.TestCase):
)
self.assertNotEqual(match.distance(items, info), 0)
def test_tracks_out_of_order(self):
items = []
items.append(self.item('one', 1))
items.append(self.item('three', 2))
items.append(self.item('two', 3))
info = AlbumInfo(
artist = 'some artist',
album = 'some album',
tracks = self.trackinfo(),
va = False,
album_id = None, artist_id = None,
)
dist = match.distance(items, info)
self.assertTrue(0 < dist < 0.2)
def test_two_medium_release(self):
items = []
items.append(self.item('one', 1))
items.append(self.item('two', 2))
items.append(self.item('three', 3))
info = AlbumInfo(
artist = 'some artist',
album = 'some album',
tracks = self.trackinfo(),
va = False,
album_id = None, artist_id = None,
)
info.tracks[0].medium_index = 1
info.tracks[1].medium_index = 2
info.tracks[2].medium_index = 1
dist = match.distance(items, info)
self.assertEqual(dist, 0)
def test_per_medium_track_numbers(self):
items = []
items.append(self.item('one', 1))
items.append(self.item('two', 2))
items.append(self.item('three', 1))
info = AlbumInfo(
artist = 'some artist',
album = 'some album',
tracks = self.trackinfo(),
va = False,
album_id = None, artist_id = None,
)
info.tracks[0].medium_index = 1
info.tracks[1].medium_index = 2
info.tracks[2].medium_index = 1
dist = match.distance(items, info)
self.assertEqual(dist, 0)
def _mkmp3(path):
shutil.copyfile(os.path.join(_common.RSRC, 'min.mp3'), path)
class AlbumsInDirTest(unittest.TestCase):

View file

@ -35,9 +35,13 @@ class MBAlbumInfoTest(unittest.TestCase):
'medium-list': [],
}
if tracks:
release['medium-list'].append({
'track-list': [{'recording': track} for track in tracks]
})
track_list = []
for i, track in enumerate(tracks):
track_list.append({
'recording': track,
'position': str(i+1),
})
release['medium-list'].append({ 'track-list': track_list })
return release
def _make_track(self, title, tr_id, duration):
@ -85,6 +89,16 @@ class MBAlbumInfoTest(unittest.TestCase):
self.assertEqual(t[1].track_id, 'ID TWO')
self.assertEqual(t[1].length, 200.0)
def test_parse_track_indices(self):
tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)]
release = self._make_release(tracks=tracks)
d = mb.album_info(release)
t = d.tracks
self.assertEqual(t[0].medium_index, 1)
self.assertEqual(t[1].medium_index, 2)
def test_parse_release_year_month_only(self):
release = self._make_release('1987-03')
d = mb.album_info(release)