1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
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()
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")])
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
|