def candidates(self, items, artist, album, va_likely): albums = [] for relid in _all_releases(items): album = hooks.album_for_mbid(relid) if album: albums.append(album) log.debug('acoustid album candidates: %i' % len(albums)) return albums
def candidates(self, items, artist, album, va_likely): albums = [] for relid in prefix(_all_releases(items), MAX_RELEASES): album = hooks.album_for_mbid(relid) if album: albums.append(album) self._log.debug(u'acoustid album candidates: {0}', len(albums)) return albums
def candidates(self, items, artist, album, va_likely): albums = [] for relid in prefix(_all_releases(items), MAX_RELEASES): album = hooks.album_for_mbid(relid) if album: albums.append(album) self._log.debug(u'acoustid album candidates: {0}', len(albums)) return albums
def candidates(self, items, artist, album, va_likely): # TODO we already have album infos in _process_items. # we should cache and reuse them. release_ids = _process_items(items) releases = [] for id in release_ids: try: # album_for_mbid may raise a MusicBrainzAPIError albuminfo = hooks.album_for_mbid(id) if albuminfo: releases.append(albuminfo) except: pass return releases
def candidates(self, items, artist, album, va_likely): releases = [] release_ids = _process_items(items) if not release_ids: return releases for id in release_ids: try: # album_for_mbid may raise a MusicBrainzAPIError albuminfo = hooks.album_for_mbid(id) if albuminfo: releases.append(albuminfo) except: pass return releases
def mbsync_albums(lib, query, move, pretend, write): """Retrieve and apply info from the autotagger for albums matched by query and their items. """ # Process matching albums. for a in lib.albums(query): if not a.mb_albumid: log.info(u'Skipping album {0}: has no mb_albumid'.format(a.id)) continue items = list(a.items()) # Get the MusicBrainz album information. album_info = hooks.album_for_mbid(a.mb_albumid) if not album_info: log.info(u'Release ID not found: {0}'.format(a.mb_albumid)) continue # Construct a track mapping according to MBIDs. This should work # for albums that have missing or extra tracks. mapping = {} for item in items: for track_info in album_info.tracks: if item.mb_trackid == track_info.track_id: mapping[item] = track_info break # Apply. with lib.transaction(): autotag.apply_metadata(album_info, mapping) changed = False for item in items: item_changed = ui.show_model_changes(item) changed |= item_changed if item_changed: apply_item_changes(lib, item, move, pretend, write) if not changed: # No change to any item. continue if not pretend: # Update album structure to reflect an item in it. for key in library.Album.item_keys: a[key] = items[0][key] a.store() # Move album art (and any inconsistent items). if move and lib.directory in util.ancestry(items[0].path): log.debug(u'moving album {0}'.format(a.id)) a.move()
def mbsync_albums(lib, query, move, pretend, write): """Retrieve and apply info from the autotagger for albums matched by query and their items. """ # Process matching albums. for a in lib.albums(query): if not a.mb_albumid: log.info(u'Skipping album {0}: has no mb_albumid'.format(a.id)) continue items = list(a.items()) # Get the MusicBrainz album information. album_info = hooks.album_for_mbid(a.mb_albumid) if not album_info: log.info(u'Release ID not found: {0}'.format(a.mb_albumid)) continue # Construct a track mapping according to MBIDs. This should work # for albums that have missing or extra tracks. mapping = {} for item in items: for track_info in album_info.tracks: if item.mb_trackid == track_info.track_id: mapping[item] = track_info break # Apply. with lib.transaction(): autotag.apply_metadata(album_info, mapping) changed = False for item in items: item_changed = ui.show_model_changes(item) changed |= item_changed if item_changed: apply_item_changes(lib, item, move, pretend, write) if not changed: # No change to any item. continue if not pretend: # Update album structure to reflect an item in it. for key in library.Album.item_keys: a[key] = items[0][key] a.store() # Move album art (and any inconsistent items). if move and lib.directory in util.ancestry(items[0].path): log.debug(u'moving album {0}'.format(a.id)) a.move()
def _missing(self, album): """Query MusicBrainz to determine items missing from `album`. """ item_mbids = [x.mb_trackid for x in album.items()] if len([i for i in album.items()]) < album.albumtotal: # fetch missing items # TODO: Implement caching that without breaking other stuff album_info = hooks.album_for_mbid(album.mb_albumid) for track_info in getattr(album_info, 'tracks', []): if track_info.track_id not in item_mbids: item = _item(track_info, album_info, album.id) self._log.debug(u'track {0} in album {1}', track_info.track_id, album_info.album_id) yield item
def _missing(album): """Query MusicBrainz to determine items missing from `album`. """ item_mbids = map(lambda x: x.mb_trackid, album.items()) if len([i for i in album.items()]) < album.tracktotal: # fetch missing items # TODO: Implement caching that without breaking other stuff album_info = hooks.album_for_mbid(album.mb_albumid) for track_info in getattr(album_info, "tracks", []): if track_info.track_id not in item_mbids: item = _item(track_info, album_info, album.id) log.debug("{}: track {} in album {}".format(PLUGIN, track_info.track_id, album_info.album_id)) yield item
def _missing(self, album): """Query MusicBrainz to determine items missing from `album`. """ item_mbids = map(lambda x: x.mb_trackid, album.items()) if len([i for i in album.items()]) < album.albumtotal: # fetch missing items # TODO: Implement caching that without breaking other stuff album_info = hooks.album_for_mbid(album.mb_albumid) for track_info in getattr(album_info, 'tracks', []): if track_info.track_id not in item_mbids: item = _item(track_info, album_info, album.id) self._log.debug(u'track {0} in album {1}', track_info.track_id, album_info.album_id) yield item
def _barcodes_to_albuminfos(barcodes): """Converts a list of barcodes to a list of AlbumInfo objects """ releases = [] for barcode in barcodes: res = musicbrainzngs.search_releases(barcode=barcode, catno=barcode, limit=30) if res['release-list']: for release in res['release-list']: try: releases.append(hooks.album_for_mbid(release['id'])) except: pass return releases
def mbsync_albums(lib, query, move, pretend, write): """Synchronize matching albums. """ # Process matching albums. for a in lib.albums(query): if not a.mb_albumid: log.info(u'Skipping album {0}: has no mb_albumid'.format(a.id)) continue items = list(a.items()) for item in items: item.old_data = dict(item.record) # Get the MusicBrainz album information. album_info = hooks.album_for_mbid(a.mb_albumid) if not album_info: log.info(u'Release ID not found: {0}'.format(a.mb_albumid)) continue # Construct a track mapping according to MBIDs. This should work # for albums that have missing or extra tracks. mapping = {} for item in items: for track_info in album_info.tracks: if item.mb_trackid == track_info.track_id: mapping[item] = track_info break # Apply. with lib.transaction(): autotag.apply_metadata(album_info, mapping) changed = False for item in items: changed = _print_and_apply_changes(lib, item, move, pretend, write) or changed if not changed: # No change to any item. continue if not pretend: # Update album structure to reflect an item in it. for key in library.ALBUM_KEYS_ITEM: setattr(a, key, getattr(items[0], key)) # Move album art (and any inconsistent items). if move and lib.directory in util.ancestry(items[0].path): log.debug(u'moving album {0}'.format(a.id)) a.move()
def mbsync_albums(lib, query, move, pretend, write): """Synchronize matching albums. """ # Process matching albums. for a in lib.albums(query): if not a.mb_albumid: log.info(u'Skipping album {0}: has no mb_albumid'.format(a.id)) continue items = list(a.items()) for item in items: item.old_data = dict(item.record) # Get the MusicBrainz album information. album_info = hooks.album_for_mbid(a.mb_albumid) if not album_info: log.info(u'Release ID not found: {0}'.format(a.mb_albumid)) continue # Construct a track mapping according to MBIDs. This should work # for albums that have missing or extra tracks. mapping = {} for item in items: for track_info in album_info.tracks: if item.mb_trackid == track_info.track_id: mapping[item] = track_info break # Apply. with lib.transaction(): autotag.apply_metadata(album_info, mapping) changed = False for item in items: changed = _print_and_apply_changes(lib, item, move, pretend, write) or changed if not changed: # No change to any item. continue if not pretend: # Update album structure to reflect an item in it. for key in library.ALBUM_KEYS_ITEM: setattr(a, key, getattr(items[0], key)) # Move album art (and any inconsistent items). if move and lib.directory in util.ancestry(items[0].path): log.debug(u'moving album {0}'.format(a.id)) a.move()
def match_by_id(items): """If the items are tagged with a MusicBrainz album ID, returns an AlbumInfo object for the corresponding album. Otherwise, returns None. """ # Is there a consensus on the MB album ID? albumids = [item.mb_albumid for item in items if item.mb_albumid] if not albumids: log.debug(u'No album IDs found.') return None # If all album IDs are equal, look up the album. if bool(reduce(lambda x, y: x if x == y else (), albumids)): albumid = albumids[0] log.debug(u'Searching for discovered album ID: {0}', albumid) return hooks.album_for_mbid(albumid) else: log.debug(u'No album ID consensus.')
def match_by_id(items): """If the items are tagged with a MusicBrainz album ID, returns an AlbumInfo object for the corresponding album. Otherwise, returns None. """ # Is there a consensus on the MB album ID? albumids = [item.mb_albumid for item in items if item.mb_albumid] if not albumids: log.debug('No album IDs found.') return None # If all album IDs are equal, look up the album. if bool(reduce(lambda x,y: x if x==y else (), albumids)): albumid = albumids[0] log.debug('Searching for discovered album ID: ' + albumid) return hooks.album_for_mbid(albumid) else: log.debug('No album ID consensus.')
def match_by_id(items): """If the items are tagged with a MusicBrainz album ID, returns an AlbumInfo object for the corresponding album. Otherwise, returns None. """ albumids = (item.mb_albumid for item in items if item.mb_albumid) # Did any of the items have an MB album ID? try: first = next(albumids) except StopIteration: log.debug(u'No album ID found.') return None # Is there a consensus on the MB album ID? for other in albumids: if other != first: log.debug(u'No album ID consensus.') return None # If all album IDs are equal, look up the album. log.debug(u'Searching for discovered album ID: {0}', first) return hooks.album_for_mbid(first)
def match_by_id(items): """If the items are tagged with a MusicBrainz album ID, returns an AlbumInfo object for the corresponding album. Otherwise, returns None. """ albumids = (item.mb_albumid for item in items if item.mb_albumid) # Did any of the items have an MB album ID? try: first = next(albumids) except StopIteration: log.debug('No album ID found.') return None # Is there a consensus on the MB album ID? for other in albumids: if other != first: log.debug('No album ID consensus.') return None # If all album IDs are equal, look up the album. log.debug('Searching for discovered album ID: {0}', first) return hooks.album_for_mbid(first)
def mbsync_albums(lib, query, move, pretend, write): """Retrieve and apply info from the autotagger for albums matched by query and their items. """ # Process matching albums. for a in lib.albums(query): if not a.mb_albumid: log.info(u'Skipping album {0}: has no mb_albumid', a.id) continue items = list(a.items()) # Get the MusicBrainz album information. album_info = hooks.album_for_mbid(a.mb_albumid) if not album_info: log.info(u'Release ID not found: {0}', a.mb_albumid) continue # Map recording MBIDs to their information. Recordings can appear # multiple times on a release, so each MBID maps to a list of TrackInfo # objects. track_index = defaultdict(list) for track_info in album_info.tracks: track_index[track_info.track_id].append(track_info) # Construct a track mapping according to MBIDs. This should work # for albums that have missing or extra tracks. If there are multiple # copies of a recording, they are disambiguated using their disc and # track number. mapping = {} for item in items: candidates = track_index[item.mb_trackid] if len(candidates) == 1: mapping[item] = candidates[0] else: for c in candidates: if c.medium_index == item.track and c.medium == item.disc: mapping[item] = c break # Apply. with lib.transaction(): autotag.apply_metadata(album_info, mapping) changed = False for item in items: item_changed = ui.show_model_changes(item) changed |= item_changed if item_changed: apply_item_changes(lib, item, move, pretend, write) if not changed: # No change to any item. continue if not pretend: # Update album structure to reflect an item in it. for key in library.Album.item_keys: a[key] = items[0][key] a.store() # Move album art (and any inconsistent items). if move and lib.directory in util.ancestry(items[0].path): log.debug(u'moving album {0}', a.id) a.move()
def albums(self, lib, query, move, pretend, write): """Retrieve and apply info from the autotagger for albums matched by query and their items. """ # Process matching albums. for a in lib.albums(query): album_formatted = format(a) if not a.mb_albumid: self._log.info('Skipping album with no mb_albumid: {0}', album_formatted) continue items = list(a.items()) # Do we have a valid MusicBrainz album ID? if not re.match(MBID_REGEX, a.mb_albumid): self._log.info('Skipping album with invalid mb_albumid: {0}', album_formatted) continue # Get the MusicBrainz album information. album_info = hooks.album_for_mbid(a.mb_albumid) if not album_info: self._log.info('Release ID {0} not found for album {1}', a.mb_albumid, album_formatted) continue # Map release track and recording MBIDs to their information. # Recordings can appear multiple times on a release, so each MBID # maps to a list of TrackInfo objects. releasetrack_index = {} track_index = defaultdict(list) for track_info in album_info.tracks: releasetrack_index[track_info.release_track_id] = track_info track_index[track_info.track_id].append(track_info) # Construct a track mapping according to MBIDs (release track MBIDs # first, if available, and recording MBIDs otherwise). This should # work for albums that have missing or extra tracks. mapping = {} for item in items: if item.mb_releasetrackid and \ item.mb_releasetrackid in releasetrack_index: mapping[item] = releasetrack_index[item.mb_releasetrackid] else: candidates = track_index[item.mb_trackid] if len(candidates) == 1: mapping[item] = candidates[0] else: # If there are multiple copies of a recording, they are # disambiguated using their disc and track number. for c in candidates: if (c.medium_index == item.track and c.medium == item.disc): mapping[item] = c break # Apply. self._log.debug('applying changes to {}', album_formatted) with lib.transaction(): autotag.apply_metadata(album_info, mapping) changed = False # Find any changed item to apply MusicBrainz changes to album. any_changed_item = items[0] for item in items: item_changed = ui.show_model_changes(item) changed |= item_changed if item_changed: any_changed_item = item apply_item_changes(lib, item, move, pretend, write) if not changed: # No change to any item. continue if not pretend: # Update album structure to reflect an item in it. for key in library.Album.item_keys: a[key] = any_changed_item[key] a.store() # Move album art (and any inconsistent items). if move and lib.directory in util.ancestry(items[0].path): self._log.debug('moving album {0}', album_formatted) a.move()
def mbsync_albums(lib, query, move, pretend, write): """Retrieve and apply info from the autotagger for albums matched by query and their items. """ # Process matching albums. for a in lib.albums(query): if not a.mb_albumid: log.info(u'Skipping album {0}: has no mb_albumid'.format(a.id)) continue items = list(a.items()) # Get the MusicBrainz album information. album_info = hooks.album_for_mbid(a.mb_albumid) if not album_info: log.info(u'Release ID not found: {0}'.format(a.mb_albumid)) continue # Map recording MBIDs to their information. Recordings can appear # multiple times on a release, so each MBID maps to a list of TrackInfo # objects. track_index = defaultdict(list) for track_info in album_info.tracks: track_index[track_info.track_id].append(track_info) # Construct a track mapping according to MBIDs. This should work # for albums that have missing or extra tracks. If there are multiple # copies of a recording, they are disambiguated using their disc and # track number. mapping = {} for item in items: candidates = track_index[item.mb_trackid] if len(candidates) == 1: mapping[item] = candidates[0] else: for c in candidates: if c.medium_index == item.track and c.medium == item.disc: mapping[item] = c break # Apply. with lib.transaction(): autotag.apply_metadata(album_info, mapping) changed = False for item in items: item_changed = ui.show_model_changes(item) changed |= item_changed if item_changed: apply_item_changes(lib, item, move, pretend, write) if not changed: # No change to any item. continue if not pretend: # Update album structure to reflect an item in it. for key in library.Album.item_keys: a[key] = items[0][key] a.store() # Move album art (and any inconsistent items). if move and lib.directory in util.ancestry(items[0].path): log.debug(u'moving album {0}'.format(a.id)) a.move()
def albums(self, lib, query, move, pretend, write): """Retrieve and apply info from the autotagger for albums matched by query and their items. """ # Process matching albums. for a in lib.albums(query): album_formatted = format(a) if not a.mb_albumid: self._log.info(u'Skipping album with no mb_albumid: {0}', album_formatted) continue items = list(a.items()) # Get the MusicBrainz album information. album_info = hooks.album_for_mbid(a.mb_albumid) if not album_info: self._log.info(u'Release ID {0} not found for album {1}', a.mb_albumid, album_formatted) continue # Map release track and recording MBIDs to their information. # Recordings can appear multiple times on a release, so each MBID # maps to a list of TrackInfo objects. releasetrack_index = dict() track_index = defaultdict(list) for track_info in album_info.tracks: releasetrack_index[track_info.release_track_id] = track_info track_index[track_info.track_id].append(track_info) # Construct a track mapping according to MBIDs (release track MBIDs # first, if available, and recording MBIDs otherwise). This should # work for albums that have missing or extra tracks. mapping = {} for item in items: if item.mb_releasetrackid and \ item.mb_releasetrackid in releasetrack_index: mapping[item] = releasetrack_index[item.mb_releasetrackid] else: candidates = track_index[item.mb_trackid] if len(candidates) == 1: mapping[item] = candidates[0] else: # If there are multiple copies of a recording, they are # disambiguated using their disc and track number. for c in candidates: if (c.medium_index == item.track and c.medium == item.disc): mapping[item] = c break # Apply. self._log.debug(u'applying changes to {}', album_formatted) with lib.transaction(): autotag.apply_metadata(album_info, mapping) changed = False # Find any changed item to apply MusicBrainz changes to album. any_changed_item = items[0] for item in items: item_changed = ui.show_model_changes(item) changed |= item_changed if item_changed: any_changed_item = item apply_item_changes(lib, item, move, pretend, write) if not changed: # No change to any item. continue if not pretend: # Update album structure to reflect an item in it. for key in library.Album.item_keys: a[key] = any_changed_item[key] a.store() # Move album art (and any inconsistent items). if move and lib.directory in util.ancestry(items[0].path): self._log.debug(u'moving album {0}', album_formatted) a.move()