19
19
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
from collections import deque
22
23
from PyQt4 import QtCore
23
from picard.metadata import Metadata, run_album_metadata_processors
24
from picard.metadata import Metadata, run_album_metadata_processors, run_track_metadata_processors
24
25
from picard.dataobj import DataObject
25
26
from picard.file import File
26
27
from picard.track import Track
28
29
from picard.ui.item import Item
29
30
from picard.util import format_time, partial, translate_artist, queue, mbid_validate
30
31
from picard.cluster import Cluster
31
from picard.mbxml import release_to_metadata, track_to_metadata
32
from picard.const import RELEASE_FORMATS, VARIOUS_ARTISTS_ID
32
from picard.mbxml import release_to_metadata, track_to_metadata, media_formats_from_node
33
from picard.const import VARIOUS_ARTISTS_ID
35
36
class Album(DataObject, Item):
38
39
DataObject.__init__(self, id)
39
40
self.metadata = Metadata()
41
44
self.loaded = False
42
45
self.rgloaded = False
45
49
self._discid = discid
46
50
self._after_load_callbacks = queue.Queue()
51
self._metadata_plugins = deque()
47
52
self.other_versions = []
48
53
self.unmatched_files = Cluster(_("Unmatched Files"), special=True, related_album=self, hide_if_empty=True)
79
84
release_to_metadata(release_node, m, config=self.config, album=self)
86
self.format_str = media_formats_from_node(release_node.medium_list[0])
87
self.rgid = release_node.release_group[0].id
82
89
m['musicbrainz_discid'] = self._discid
85
releasegroupid = release_node.release_group[0].id
86
self.tagger.xmlws.get_release_group_by_id(releasegroupid, self._release_group_request_finished)
88
91
# 'Translate' artist name
89
92
if self.config.setting['translate_artist_names']:
90
93
m['albumartist'] = m['artist'] = translate_artist(m['artist'], m['artistsort'])
93
96
if m['musicbrainz_artistid'] == VARIOUS_ARTISTS_ID:
94
97
m['albumartistsort'] = m['artistsort'] = m['albumartist'] = m['artist'] = self.config.setting['va_name']
96
# Album metadata plugins
98
run_album_metadata_processors(self, m, release_node)
100
self.log.error(traceback.format_exc())
102
# Prepare parser for user's script
103
if self.config.setting["enable_tagger_script"]:
104
script = self.config.setting["tagger_script"]
105
parser = ScriptParser()
107
script = parser = None
109
99
# Strip leading/trailing whitespace
110
100
m.strip_whitespace()
112
102
ignore_tags = [s.strip() for s in self.config.setting['ignore_tags'].split(',')]
115
107
m['totaldiscs'] = release_node.medium_list[0].count
109
plugins = partial(run_album_metadata_processors, self, m, release_node)
110
self._metadata_plugins.append(plugins)
117
112
for medium in release_node.medium_list[0].medium:
118
113
discnumber = medium.position[0].text
119
114
track_list = medium.track_list[0]
120
115
totaltracks = track_list.count
116
track_counts.append(totaltracks)
121
117
discsubtitle = medium.title[0].text if "title" in medium.children else ""
122
118
format = medium.format[0].text if "format" in medium.children else ""
134
130
if format: tm['media'] = format
136
132
track_to_metadata(node, config=self.config, track=t)
137
t._customize_metadata(node, release_node, script, parser, ignore_tags)
139
artists.add(tm['musicbrainz_artistid'])
140
133
m.length += tm.length
143
for t in self._new_tracks:
144
t.metadata['compilation'] = '1'
147
# Run tagger script for the album itself
149
parser.eval(script, m)
151
self.log.error(traceback.format_exc())
135
artist_id = tm['musicbrainz_artistid']
136
if compilation is False:
137
if first_artist is None:
138
first_artist = artist_id
139
if first_artist != artist_id:
141
for track in self._new_tracks:
142
track.metadata['compilation'] = '1'
144
tm['compilation'] = '1'
146
t._customize_metadata(ignore_tags)
147
plugins = partial(run_track_metadata_processors, self, tm, release_node, node)
148
self._metadata_plugins.append(plugins)
150
self.tracks_str = " + ".join(track_counts)
155
def _parse_release_group(self, document):
156
releases = document.metadata[0].release_group[0].release_list[0].release
157
for release in releases:
159
version["mbid"] = release.id
160
if "date" in release.children:
161
version["date"] = release.date[0].text
162
if "country" in release.children:
163
version["country"] = release.country[0].text
164
version["totaltracks"] = [int(m.track_list[0].count) for m in release.medium_list[0].medium]
166
for medium in release.medium_list[0].medium:
167
if "format" in medium.children:
168
f = medium.format[0].text
169
if f in formats: formats[f] += 1
172
version["media"] = " + ".join(["%s%s" % (str(j)+u"×" if j>1 else "", RELEASE_FORMATS[i])
173
for i, j in formats.items()])
174
self.other_versions.append(version)
175
self.other_versions.sort(key=lambda x: x["date"])
177
154
def _release_request_finished(self, document, http, error):
200
177
if parsed or error:
201
178
self._finalize_loading(error)
180
def _parse_release_group(self, document):
181
releases = document.metadata[0].release_group[0].release_list[0].release
182
for release in releases:
184
version["mbid"] = release.id
185
if "date" in release.children:
186
version["date"] = release.date[0].text
187
if "country" in release.children:
188
version["country"] = release.country[0].text
189
version["tracks"] = " + ".join([m.track_list[0].count for m in release.medium_list[0].medium])
190
version["format"] = media_formats_from_node(release.medium_list[0])
191
self.other_versions.append(version)
192
self.other_versions.sort(key=lambda x: x["date"])
203
194
def _release_group_request_finished(self, document, http, error):
220
212
del self._new_metadata
221
213
del self._new_tracks
224
if not self._requests:
225
for track in self.tracks:
226
for file in list(track.linked_files):
227
file.move(self.unmatched_files)
228
self.metadata = self._new_metadata
229
self.tracks = self._new_tracks
230
del self._new_metadata
233
self.match_files(self.unmatched_files.files)
235
self.tagger.window.set_statusbar_message('Album %s loaded', self.id, timeout=3000)
236
while self._after_load_callbacks.qsize() > 0:
237
func = self._after_load_callbacks.get()
217
# Run metadata plugins
218
while self._metadata_plugins:
220
self._metadata_plugins.pop()()
222
self.log.error(traceback.format_exc())
224
if not self._requests:
225
# Prepare parser for user's script
226
if self.config.setting["enable_tagger_script"]:
227
script = self.config.setting["tagger_script"]
229
parser = ScriptParser()
230
# Run tagger script for each track
231
for track in self._new_tracks:
233
parser.eval(script, track.metadata)
235
self.log.error(traceback.format_exc())
236
# Strip leading/trailing whitespace
237
track.metadata.strip_whitespace()
238
# Run tagger script for the album itself
240
parser.eval(script, self._new_metadata)
242
self.log.error(traceback.format_exc())
244
for track in self.tracks:
245
for file in list(track.linked_files):
246
file.move(self.unmatched_files)
247
self.metadata = self._new_metadata
248
self.tracks = self._new_tracks
249
del self._new_metadata
252
self.match_files(self.unmatched_files.files)
254
self.tagger.window.set_statusbar_message('Album %s loaded', self.id, timeout=3000)
255
while self._after_load_callbacks.qsize() > 0:
256
func = self._after_load_callbacks.get()
241
260
if self._requests:
421
440
for file in track.linked_files:
422
441
track.update_file_metadata(file)
423
442
super(NatAlbum, self).update(update_tracks)
444
def _finalize_loading(self, error):