beets/beetsplug/mbsync.py
Jakob Schnitzer 2fd3ad5362 initial version of the mbsync plugin
this plugin provides a faster way to query new metadata from
musicbrainz. (instead of having to 're-import' the files)
Currently it lacks all forms of documentation and will only work for
album queries. not really tested so far so be careful
2013-03-03 23:39:13 +01:00

100 lines
3.9 KiB
Python

# This file is part of beets.
# Copyright 2013, Jakob Schnitzer.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
"""Update local library from MusicBrainz
"""
import logging
from beets.plugins import BeetsPlugin
from beets import autotag, library, ui, util
log = logging.getLogger('beets')
def mbsync_func(lib, opts, args):
#album = opts.album
album = True
move = True
pretend = opts.pretend
with lib.transaction():
# Right now this only works for albums....
_, albums = ui.commands._do_query(lib, ui.decargs(args), album)
for a in albums:
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)
cur_artist, cur_album, candidates, _ = \
autotag.match.tag_album(items, search_id=a.mb_albumid)
match = candidates[0] # There should only be one match!
# ui.commands.show_change(cur_artist, cur_album, match)
autotag.apply_metadata(match.info, match.mapping)
for item in items:
changes = {}
for key in library.ITEM_KEYS_META:
if item.dirty[key]:
changes[key] = item.old_data[key], getattr(item, key)
if changes:
# Something changed.
ui.print_obj(item, lib)
for key, (oldval, newval) in changes.iteritems():
ui.commands._showdiff(key, oldval, newval)
# If we're just pretending, then don't move or save.
if pretend:
continue
# Move the item if it's in the library.
if move and lib.directory in util.ancestry(item.path):
lib.move(item)
lib.store(item)
if pretend or a.id is None: # pretend or Singleton
continue
# 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()
class MBSyncPlugin(BeetsPlugin):
def __init__(self):
super(MBSyncPlugin, self).__init__()
def commands(self):
cmd = ui.Subcommand('mbsync',
help='update metadata from musicbrainz')
#cmd.parser.add_option('-a', '--album', action='store_true',
# help='choose albums instead of tracks')
cmd.parser.add_option('-p', '--pretend', action='store_true',
help='show all changes but do nothing')
cmd.parser.add_option('-M', '--nomove', action='store_false',
default=True, dest='move',
help="don't move files in library")
cmd.parser.add_option('-W', '--nowrite', action='store_false',
default=True, dest='move',
help="don't write updated metadata to files")
cmd.func = mbsync_func
return [cmd]