mirror of
https://github.com/beetbox/beets.git
synced 2026-01-30 03:54:21 +01:00
tolerate per-medium track numbering (#283)
This commit is contained in:
parent
53e5bb05b7
commit
47891b00f7
6 changed files with 81 additions and 9 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue