import subprocess
import uuid
import webbrowser
from beets.plugins import BeetsPlugin
from beets.ui import Subcommand, UserError
MUSICBRAINZ_LOOKUP='https://musicbrainz.org/otherlookup/mbid?other-lookup.mbid='
FIELD_NAMES = ['albumartist', 'album', 'artist', 'releasegroup', 'releasetrack', 'track', 'work']
class BrowsePlugin(BeetsPlugin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def commands(self):
return [BrowseCommand(self.config)]
class BrowseCommand(Subcommand):
explorer = 'thunar'
def __init__(self, config):
super().__init__('browse', parser=None,
help='browse items on MusicBrainz or the file system')
self.parser.add_option('-f', '--field', type='string',
help='which field to look up on MusicBrainz, '
'e.g. album, artist, track, work, ...')
self.parser.add_option('-o', '--open', action='store_true',
help='open in the file browser instead of MusicBrainz')
self.parser.add_album_option()
if 'explorer' in config:
self.explorer = config['explorer'].get()
# pylint: disable=no-self-use
def browse_musicbrainz(self, item, field):
mbid = item.get(f'mb_{field}id')
if not mbid:
raise UserError(f'\'mb_{field}id\' not available for: {item}')
try:
uuid.UUID(mbid)
except ValueError:
raise UserError(f'invalid UUID "{mbid}" for: {item}') from None
webbrowser.open(MUSICBRAINZ_LOOKUP + mbid)
def browse_filesystem(self, item, _):
try:
subprocess.Popen(self.explorer.split(' ') + [item.get('path')]) # pylint: disable=consider-using-with
except OSError as err:
raise UserError(err) from err
def func(self, lib, opts, args):
queryfun = lib.albums if opts.album else lib.items
browsefun = self.browse_filesystem if opts.open else self.browse_musicbrainz
field = opts.field or ('album' if opts.album else 'track')
if field not in FIELD_NAMES:
raise UserError(f'invalid field "{field}", try one of: {", ".join(FIELD_NAMES)}')
if not args:
raise UserError('empty query, refusing')
items = queryfun(args)
if not items:
return
if len(items) == 1:
browsefun(items[0], field)
return
print('Query returned multiple matches, please disambiguate:')
for index, item in enumerate(items):
if index < 5:
print(item)
else:
print(f'[{len(items) - index} more]')
return