1# -*- coding: utf-8 -*- 2# This file is part of beets. 3# Copyright 2016, Thomas Scholtes. 4# 5# Permission is hereby granted, free of charge, to any person obtaining 6# a copy of this software and associated documentation files (the 7# "Software"), to deal in the Software without restriction, including 8# without limitation the rights to use, copy, modify, merge, publish, 9# distribute, sublicense, and/or sell copies of the Software, and to 10# permit persons to whom the Software is furnished to do so, subject to 11# the following conditions: 12# 13# The above copyright notice and this permission notice shall be 14# included in all copies or substantial portions of the Software. 15 16"""Uses the `KeyFinder` program to add the `initial_key` field. 17""" 18 19from __future__ import division, absolute_import, print_function 20 21import subprocess 22 23from beets import ui 24from beets import util 25from beets.plugins import BeetsPlugin 26 27 28class KeyFinderPlugin(BeetsPlugin): 29 30 def __init__(self): 31 super(KeyFinderPlugin, self).__init__() 32 self.config.add({ 33 u'bin': u'KeyFinder', 34 u'auto': True, 35 u'overwrite': False, 36 }) 37 38 if self.config['auto'].get(bool): 39 self.import_stages = [self.imported] 40 41 def commands(self): 42 cmd = ui.Subcommand('keyfinder', 43 help=u'detect and add initial key from audio') 44 cmd.func = self.command 45 return [cmd] 46 47 def command(self, lib, opts, args): 48 self.find_key(lib.items(ui.decargs(args)), write=ui.should_write()) 49 50 def imported(self, session, task): 51 self.find_key(task.imported_items()) 52 53 def find_key(self, items, write=False): 54 overwrite = self.config['overwrite'].get(bool) 55 bin = self.config['bin'].as_str() 56 57 for item in items: 58 if item['initial_key'] and not overwrite: 59 continue 60 61 try: 62 output = util.command_output([bin, '-f', 63 util.syspath(item.path)]) 64 except (subprocess.CalledProcessError, OSError) as exc: 65 self._log.error(u'execution failed: {0}', exc) 66 continue 67 except UnicodeEncodeError: 68 # Workaround for Python 2 Windows bug. 69 # http://bugs.python.org/issue1759845 70 self._log.error(u'execution failed for Unicode path: {0!r}', 71 item.path) 72 continue 73 74 key_raw = output.rsplit(None, 1)[-1] 75 try: 76 key = util.text_string(key_raw) 77 except UnicodeDecodeError: 78 self._log.error(u'output is invalid UTF-8') 79 continue 80 81 item['initial_key'] = key 82 self._log.info(u'added computed initial key {0} for {1}', 83 key, util.displayable_path(item.path)) 84 85 if write: 86 item.try_write() 87 item.store() 88