/
albumartist_website.py
161 lines (137 loc) · 6.56 KB
/
albumartist_website.py
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# -*- coding: utf-8 -*-
PLUGIN_NAME = 'Album Artist Website'
PLUGIN_AUTHOR = 'Sophist, Sambhav Kothari, Philipp Wolfer'
PLUGIN_DESCRIPTION = '''Add's the album artist(s) Official Homepage(s)
(if they are defined in the MusicBrainz database).'''
PLUGIN_VERSION = '1.1'
PLUGIN_API_VERSIONS = ["2.0", "2.1", "2.2"]
PLUGIN_LICENSE = "GPL-2.0"
PLUGIN_LICENSE_URL = "https://www.gnu.org/licenses/gpl-2.0.html"
from picard import config, log
from picard.util import LockableObject
from picard.metadata import register_track_metadata_processor
from functools import partial
class AlbumArtistWebsite:
class ArtistWebsiteQueue(LockableObject):
def __init__(self):
LockableObject.__init__(self)
self.queue = {}
def __contains__(self, name):
return name in self.queue
def __iter__(self):
return self.queue.__iter__()
def __getitem__(self, name):
self.lock_for_read()
value = self.queue[name] if name in self.queue else None
self.unlock()
return value
def __setitem__(self, name, value):
self.lock_for_write()
self.queue[name] = value
self.unlock()
def append(self, name, value):
self.lock_for_write()
if name in self.queue:
self.queue[name].append(value)
value = False
else:
self.queue[name] = [value]
value = True
self.unlock()
return value
def remove(self, name):
self.lock_for_write()
value = None
if name in self.queue:
value = self.queue[name]
del self.queue[name]
self.unlock()
return value
def __init__(self):
self.website_cache = {}
self.website_queue = self.ArtistWebsiteQueue()
def add_artist_website(self, album, track_metadata, track_node, release_node):
albumArtistIds = track_metadata.getall('musicbrainz_albumartistid')
for artistId in albumArtistIds:
# Jump through hoops to get track object!!
track = album._new_tracks[-1]
if artistId in self.website_cache:
if self.website_cache[artistId]:
self.add_websites_to_track(track, self.website_cache[artistId])
else:
self.website_add_track(album, track, artistId)
def website_add_track(self, album, track, artistId):
self.album_add_request(album)
if self.website_queue.append(artistId, (track, album)):
host = config.setting["server_host"]
port = config.setting["server_port"]
path = "/ws/2/%s/%s" % ('artist', artistId)
queryargs = {"inc": "url-rels"}
return album.tagger.webservice.get(host, port, path,
partial(self.website_process, artistId),
parse_response_type="xml", priority=True, important=False,
queryargs=queryargs)
def website_process(self, artistId, response, reply, error):
if error:
log.error("%s: %r: Network error retrieving artist record", PLUGIN_NAME, artistId)
tuples = self.website_queue.remove(artistId)
for track, album in tuples:
self.album_remove_request(album)
return
urls = self.artist_process_metadata(artistId, response)
self.website_cache[artistId] = urls
tuples = self.website_queue.remove(artistId)
for track, album in tuples:
self.add_websites_to_track(track, urls)
self.album_remove_request(album)
def add_websites_to_track(self, track, urls):
tm = track.metadata
websites = tm.getall('website')
websites += urls
websites.sort()
tm['website'] = websites
for file in track.iterfiles(True):
file.metadata['website'] = websites
def album_add_request(self, album):
album._requests += 1
def album_remove_request(self, album):
album._requests -= 1
album._finalize_loading(None)
def artist_process_metadata(self, artistId, response):
log.debug("%s: %r: Processing Artist record for official website urls: %r", PLUGIN_NAME, artistId, response)
relations = self.artist_get_relations(response)
if not relations:
log.info("%s: %r: Artist does have any associated urls.", PLUGIN_NAME, artistId)
return []
urls = []
for relation in relations:
log.debug("%s: %r: Examining: %r", PLUGIN_NAME, artistId, relation)
if 'type' in relation.attribs and relation.type == 'official homepage':
if 'target' in relation.children and len(relation.target) > 0:
log.debug("%s: Adding artist url: %s", PLUGIN_NAME, relation.target[0].text)
urls.append(relation.target[0].text)
else:
log.debug("%s: No url in relation: %r", PLUGIN_NAME, relation)
if urls:
log.info("%s: %r: Artist Official Homepages: %r", PLUGIN_NAME, artistId, urls)
else:
log.info("%s: %r: Artist does not have any official website urls.", PLUGIN_NAME, artistId)
return sorted(urls)
def artist_get_relations(self, response):
log.debug("%s: artist_get_relations called", PLUGIN_NAME)
if 'metadata' in response.children and len(response.metadata) > 0:
if 'artist' in response.metadata[0].children and len(response.metadata[0].artist) > 0:
if 'relation_list' in response.metadata[0].artist[0].children and len(response.metadata[0].artist[0].relation_list) > 0:
if 'relation' in response.metadata[0].artist[0].relation_list[0].children:
log.debug("%s: artist_get_relations returning: %r", PLUGIN_NAME, response.metadata[0].artist[0].relation_list[0].relation)
return response.metadata[0].artist[0].relation_list[0].relation
else:
log.debug("%s: artist_get_relations - no relation in relation_list", PLUGIN_NAME)
else:
log.debug("%s: artist_get_relations - no relation_list in artist", PLUGIN_NAME)
else:
log.debug("%s: artist_get_relations - no artist in metadata", PLUGIN_NAME)
else:
log.debug("%s: artist_get_relations - no metadata in response", PLUGIN_NAME)
return None
register_track_metadata_processor(AlbumArtistWebsite().add_artist_website)