-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add musicbrainz id option to importer #1808
Changes from 4 commits
1c95b7c
48c92fb
865be11
c12e974
4e5ddac
39cf465
b526227
4eedd2b
79d84c0
4f51302
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -370,7 +370,7 @@ def _add_candidate(items, results, info): | |
|
||
|
||
def tag_album(items, search_artist=None, search_album=None, | ||
search_id=None): | ||
search_ids=[]): | ||
"""Return a tuple of a artist name, an album name, a list of | ||
`AlbumMatch` candidates from the metadata backend, and a | ||
`Recommendation`. | ||
|
@@ -397,9 +397,11 @@ def tag_album(items, search_artist=None, search_album=None, | |
candidates = {} | ||
|
||
# Search by explicit ID. | ||
if search_id is not None: | ||
log.debug(u'Searching for album ID: {0}', search_id) | ||
search_cands = hooks.albums_for_id(search_id) | ||
if search_ids: | ||
search_cands = [] | ||
for search_id in search_ids: | ||
log.debug(u'Searching for album ID: {0}', search_id) | ||
search_cands.extend(hooks.albums_for_id(search_id)) | ||
|
||
# Use existing metadata or text search. | ||
else: | ||
|
@@ -444,33 +446,35 @@ def tag_album(items, search_artist=None, search_album=None, | |
|
||
|
||
def tag_item(item, search_artist=None, search_title=None, | ||
search_id=None): | ||
search_ids=[]): | ||
"""Attempts to find metadata for a single track. Returns a | ||
`(candidates, recommendation)` pair where `candidates` is a list of | ||
TrackMatch objects. `search_artist` and `search_title` may be used | ||
to override the current metadata for the purposes of the MusicBrainz | ||
title; likewise `search_id`. | ||
title; likewise `search_ids`. | ||
""" | ||
# Holds candidates found so far: keys are MBIDs; values are | ||
# (distance, TrackInfo) pairs. | ||
candidates = {} | ||
|
||
# First, try matching by MusicBrainz ID. | ||
trackid = search_id or item.mb_trackid | ||
if trackid: | ||
log.debug(u'Searching for track ID: {0}', trackid) | ||
for track_info in hooks.tracks_for_id(trackid): | ||
dist = track_distance(item, track_info, incl_artist=True) | ||
candidates[track_info.track_id] = \ | ||
hooks.TrackMatch(dist, track_info) | ||
# If this is a good match, then don't keep searching. | ||
rec = _recommendation(candidates.values()) | ||
if rec == Recommendation.strong and not config['import']['timid']: | ||
log.debug(u'Track ID match.') | ||
return candidates.values(), rec | ||
trackids = search_ids or filter(None, [item.mb_trackid]) | ||
if trackids: | ||
for trackid in trackids: | ||
log.debug(u'Searching for track ID: {0}', trackid) | ||
for track_info in hooks.tracks_for_id(trackid): | ||
dist = track_distance(item, track_info, incl_artist=True) | ||
candidates[track_info.track_id] = \ | ||
hooks.TrackMatch(dist, track_info) | ||
# If this is a good match, then don't keep searching. | ||
rec = _recommendation(candidates.values()) | ||
if rec == Recommendation.strong and \ | ||
not config['import']['timid']: | ||
log.debug(u'Track ID match.') | ||
return candidates.values(), rec | ||
|
||
# If we're searching by ID, don't proceed. | ||
if search_id is not None: | ||
if search_ids != []: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can probably just be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 |
||
if candidates: | ||
return candidates.values(), rec | ||
else: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -581,8 +581,13 @@ def handle_created(self, session): | |
def lookup_candidates(self): | ||
"""Retrieve and store candidates for this album. | ||
""" | ||
# Use a MusicBrainz id directly if provided by the importer -m option. | ||
mb_ids = [] | ||
if config['import']['musicbrainz_ids'].exists(): | ||
mb_ids = config['import']['musicbrainz_ids'].get() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The usual way to provide a default is to put it in Also, you might consider using a type check with |
||
|
||
artist, album, candidates, recommendation = \ | ||
autotag.tag_album(self.items) | ||
autotag.tag_album(self.items, search_ids=mb_ids) | ||
self.cur_artist = artist | ||
self.cur_album = album | ||
self.candidates = candidates | ||
|
@@ -821,7 +826,13 @@ def _emit_imported(self, lib): | |
plugins.send('item_imported', lib=lib, item=item) | ||
|
||
def lookup_candidates(self): | ||
candidates, recommendation = autotag.tag_item(self.item) | ||
# Use a MusicBrainz id directly if provided by the importer -m option. | ||
mb_ids = [] | ||
if config['import']['musicbrainz_ids'].exists(): | ||
mb_ids = config['import']['musicbrainz_ids'].get() | ||
|
||
candidates, recommendation = autotag.tag_item(self.item, | ||
search_ids=mb_ids) | ||
self.candidates = candidates | ||
self.rec = recommendation | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -734,7 +734,7 @@ def choose_match(self, task): | |
search_id = manual_id(False) | ||
if search_id: | ||
_, _, candidates, rec = autotag.tag_album( | ||
task.items, search_id=search_id | ||
task.items, search_ids=[search_id] | ||
) | ||
elif choice in extra_ops.keys(): | ||
# Allow extra ops to automatically set the post-choice. | ||
|
@@ -787,7 +787,7 @@ def choose_item(self, task): | |
search_id = manual_id(True) | ||
if search_id: | ||
candidates, rec = autotag.tag_item(task.item, | ||
search_id=search_id) | ||
search_ids=[search_id]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A related side effect (provided the current implementation of multiple IDs stays more or less the same) is that it would take almost no effort (mainly a matter of splitting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm for it! Edit: But, I should add, I don't think it's critical—we could come back around to this later, of course. |
||
elif choice in extra_ops.keys(): | ||
# Allow extra ops to automatically set the post-choice. | ||
post_choice = extra_ops[choice](self, task) | ||
|
@@ -1022,6 +1022,10 @@ def import_func(lib, opts, args): | |
'--pretend', dest='pretend', action='store_true', | ||
help='just print the files to import' | ||
) | ||
import_cmd.parser.add_option( | ||
'-m', '--musicbrainzid', dest='musicbrainz_ids', action='append', | ||
help='restrict the matching to a single MusicBrainz id' | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a tiny nitpick, but these technically don't need to be MBIDs. Other backends can also interpret these IDs (for now, just the Discogs plugin). Alas, I don't have a great idea for another option name since |
||
import_cmd.func = import_func | ||
default_commands.append(import_cmd) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably describe
search_ids
in the docstring. (Although I note we didn't documentsearch_id
before—bad @sampsyo!)