def commands(self): lastgenre_cmd = ui.Subcommand('lastgenre', help='fetch genres') def lastgenre_func(lib, config, opts, args): # The "write to files" option corresponds to the # import_write config value. write = ui.config_val(config, 'beets', 'import_write', commands.DEFAULT_IMPORT_WRITE, bool) for album in lib.albums(ui.decargs(args)): tags = [] lastfm_obj = LASTFM.get_album(album.albumartist, album.album) if album.genre: tags.append(album.genre) tags.extend(_tags_for(lastfm_obj)) genre = _tags_to_genre(tags) if not genre and fallback_str != None: genre = fallback_str log.debug(u'no last.fm genre found: fallback to %s' % genre) if genre is not None: log.debug(u'adding last.fm album genre: %s' % genre) album.genre = genre if write: for item in album.items(): item.write() lastgenre_cmd.func = lastgenre_func return [lastgenre_cmd]
def commands(self): def queries(lib, opts, args): success = self._parse_opts(opts) if success: results = self._match_library_tracks(lib, ui.decargs(args)) self._output_match_results(results) spotify_cmd = ui.Subcommand('spotify', help=u'build a Spotify playlist') spotify_cmd.parser.add_option( u'-m', u'--mode', action='store', help=u'"open" to open Spotify with playlist, ' u'"list" to print (default)', ) spotify_cmd.parser.add_option( u'-f', u'--show-failures', action='store_true', dest='show_failures', help=u'list tracks that did not match a Spotify ID', ) spotify_cmd.func = queries return [spotify_cmd]
def commands(self): cmd = ui.Subcommand('bpsync', help='update metadata from Beatport') cmd.parser.add_option( '-p', '--pretend', action='store_true', help='show all changes but do nothing', ) cmd.parser.add_option( '-m', '--move', action='store_true', dest='move', help="move files in the library directory", ) cmd.parser.add_option( '-M', '--nomove', action='store_false', dest='move', help="don't move files in library", ) cmd.parser.add_option( '-W', '--nowrite', action='store_false', default=None, dest='write', help="don't write updated metadata to files", ) cmd.parser.add_format_option() cmd.func = self.func return [cmd]
def commands(self): cmd = ui.Subcommand( 'ftintitle', help= 'puts featuring artists in the title instead of the artist field') def func(lib, config, opts, args): for track in lib.items(): artistfield = track.__getattr__("artist") regxRes = re.split( '\s[fF]t\.|\s[fF]eaturing|\s[fF]eat\.|\s[wW]ith', artistfield) if len(regxRes) > 1: titleField = track.__getattr__("title") featInTitle = re.search('[fF]t\.|[fF]eaturing|[fF]eat\.', titleField) if featInTitle == None: print track.__getattr__("path") track.__setattr__("artist", regxRes[0]) track.__setattr__( "title", titleField + " (feat." + regxRes[1] + ")") track.write() else: track.__setattr__("artist", regxRes[0]) track.write() print "A Manual 'beet update' run is recommended. " cmd.func = func return [cmd]
def commands(self): spl_update = ui.Subcommand( 'splupdate', help=u'update the smart playlists. Playlist names may be ' u'passed as arguments.') spl_update.func = self.update_cmd return [spl_update]
def commands(self): cmd = ui.Subcommand('web2', help='start a Web2 interface') cmd.parser.add_option('-d', '--debug', action='store_true', default=False, help='debug mode') def func(lib, opts, args): args = ui.decargs(args) if args: self.config['host'] = args.pop(0) if args: self.config['port'] = int(args.pop(0)) if args: self.config['server'] = args.pop(0) host = self.config['host'].get(str) port = self.config['port'].get(int) server = self.config['server'].get(str) username = self.config['username'].get(str) password = self.config['password'].get(str) app = make_app(lib, username, password) run(app, host=host, port=port, server=server, debug=opts.debug) cmd.func = func return [cmd]
def commands(self): cmd = ui.Subcommand('info', help=u'show file metadata') cmd.func = self.run cmd.parser.add_option( u'-l', u'--library', action='store_true', help=u'show library fields instead of tags', ) cmd.parser.add_option( u'-s', u'--summarize', action='store_true', help=u'summarize the tags of all files', ) cmd.parser.add_option( u'-i', u'--include-keys', default=[], action='append', dest='included_keys', help=u'comma separated list of keys to show', ) cmd.parser.add_option( u'-k', u'--keys-only', action='store_true', help=u'show only the keys', ) cmd.parser.add_format_option(target='item') return [cmd]
def commands(self): def update(lib, opts, args): update_playlists(lib) spl_update = ui.Subcommand('splupdate', help='update the smart playlists') spl_update.func = update return [spl_update]
def commands(self): cmd = ui.Subcommand('mpdstats', help='run a MPD client to gather play statistics') cmd.parser.add_option( '--host', dest='host', type='string', help='set the hostname of the server to connect to') cmd.parser.add_option( '--port', dest='port', type='int', help='set the port of the MPD server to connect to') cmd.parser.add_option( '--password', dest='password', type='string', help='set the password of the MPD server to connect to') def func(lib, opts, args): self.config.set_args(opts) Client(lib).run() cmd.func = func return [cmd]
def commands(self): # TODO: Add option to use albums cmd = ui.Subcommand('export', help=u'export data from beets') cmd.func = self.run cmd.parser.add_option( u'-l', u'--library', action='store_true', help=u'show library fields instead of tags', ) cmd.parser.add_option( u'--append', action='store_true', default=False, help=u'if should append data to the file', ) cmd.parser.add_option( u'-i', u'--include-keys', default=[], action='append', dest='included_keys', help=u'comma separated list of keys to show', ) cmd.parser.add_option( u'-o', u'--output', help=u'path for the output file. If not given, will print the data' ) return [cmd]
def commands(self): def queries(lib, opts, args): success = self._parse_opts(opts) if success: results = self._match_library_tracks(lib, ui.decargs(args)) self._output_match_results(results) spotify_cmd = ui.Subcommand( 'spotify', help=f'build a {self.data_source} playlist') spotify_cmd.parser.add_option( '-m', '--mode', action='store', help='"open" to open {} with playlist, ' '"list" to print (default)'.format(self.data_source), ) spotify_cmd.parser.add_option( '-f', '--show-failures', action='store_true', dest='show_failures', help='list tracks that did not match a {} ID'.format( self.data_source), ) spotify_cmd.func = queries return [spotify_cmd]
def commands(self): """Return the "replaygain" ui subcommand. """ def func(lib, opts, args): try: write = ui.should_write(opts.write) force = opts.force # Bypass self.open_pool() if called with `--threads 0` if opts.threads != 0: threads = opts.threads or self.config['threads'].get(int) self.open_pool(threads) if opts.album: albums = lib.albums(ui.decargs(args)) self._log.info( "Analyzing {} albums ~ {} backend...".format( len(albums), self.backend_name)) for album in albums: self.handle_album(album, write, force) else: items = lib.items(ui.decargs(args)) self._log.info( "Analyzing {} tracks ~ {} backend...".format( len(items), self.backend_name)) for item in items: self.handle_track(item, write, force) self.close_pool() except (SystemExit, KeyboardInterrupt): # Silence interrupt exceptions pass cmd = ui.Subcommand('replaygain', help=u'analyze for ReplayGain') cmd.parser.add_album_option() cmd.parser.add_option("-t", "--threads", dest="threads", type=int, help=u'change the number of threads, \ defaults to maximum available processors') cmd.parser.add_option("-f", "--force", dest="force", action="store_true", default=False, help=u"analyze all files, including those that " "already have ReplayGain metadata") cmd.parser.add_option("-w", "--write", default=None, action="store_true", help=u"write new metadata to files' tags") cmd.parser.add_option("-W", "--nowrite", dest="write", action="store_false", help=u"don't write metadata (opposite of -w)") cmd.func = func return [cmd]
def commands(self): recording_date_command = ui.Subcommand( 'oldestdate', help="Retrieve the date of the oldest known recording or release of a track.", aliases=['olddate']) recording_date_command.func = self._command_func return [recording_date_command]
def commands(self): def func(lib, opts, args): self.config.set_args(opts) force_parent = self.config['force'].get(bool) write = ui.should_write() for item in lib.items(ui.decargs(args)): self.find_work(item, force_parent) item.store() if write: item.try_write() command = ui.Subcommand( 'parentwork', help=u'fetche parent works, composers and dates') command.parser.add_option( u'-f', u'--force', dest='force', action='store_true', default=None, help=u're-fetch when parent work is already present') command.func = func return [command]
def commands(self): """Return the "replaygain" ui subcommand. """ cmd = ui.Subcommand('replaygain', help=u'analyze for ReplayGain') cmd.parser.add_album_option() cmd.parser.add_option("-t", "--threads", dest="threads", type=int, help=u'change the number of threads, \ defaults to maximum available processors') cmd.parser.add_option("-f", "--force", dest="force", action="store_true", default=False, help=u"analyze all files, including those that " "already have ReplayGain metadata") cmd.parser.add_option("-w", "--write", default=None, action="store_true", help=u"write new metadata to files' tags") cmd.parser.add_option("-W", "--nowrite", dest="write", action="store_false", help=u"don't write metadata (opposite of -w)") cmd.func = self.command_func return [cmd]
def commands(self): cmd = ui.Subcommand( 'mpdstats', help=u'run a MPD client to gather play statistics') cmd.parser.add_option( u'--host', dest='host', type='string', help=u'set the hostname of the server to connect to') cmd.parser.add_option( u'--port', dest='port', type='int', help=u'set the port of the MPD server to connect to') cmd.parser.add_option( u'--password', dest='password', type='string', help=u'set the password of the MPD server to connect to') def func(lib, opts, args): mpd_config.set_args(opts) # Overrides for MPD settings. if opts.host: mpd_config['host'] = opts.host.decode('utf-8') if opts.port: mpd_config['host'] = int(opts.port) if opts.password: mpd_config['password'] = opts.password.decode('utf-8') try: MPDStats(lib, self._log).run() except KeyboardInterrupt: pass cmd.func = func return [cmd]
def commands(self): def scrub_func(lib, config, opts, args): # This is a little bit hacky, but we set a global flag to # avoid autoscrubbing when we're also explicitly scrubbing. global scrubbing scrubbing = True # Walk through matching files and remove tags. for item in lib.items(ui.decargs(args)): log.info(u'scrubbing: %s' % util.displayable_path(item.path)) mf = mediafile.MediaFile(item.path) _scrub(mf) mf.save() if opts.write: log.debug(u'writing new tags after scrub') item.write() scrubbing = False scrub_cmd = ui.Subcommand('scrub', help='clean audio tags') scrub_cmd.parser.add_option('-W', '--nowrite', dest='write', action='store_false', default=True, help='leave tags empty') scrub_cmd.func = scrub_func return [scrub_cmd]
def commands(self): cmd = ui.Subcommand('ipfs', help='interact with ipfs') cmd.parser.add_option('-a', '--add', dest='add', action='store_true', help='Add to ipfs') cmd.parser.add_option('-g', '--get', dest='get', action='store_true', help='Get from ipfs') cmd.parser.add_option('-p', '--publish', dest='publish', action='store_true', help='Publish local library to ipfs') cmd.parser.add_option('-i', '--import', dest='_import', action='store_true', help='Import remote library from ipfs') cmd.parser.add_option('-l', '--list', dest='_list', action='store_true', help='Query imported libraries') cmd.parser.add_option('-m', '--play', dest='play', action='store_true', help='Play music from remote libraries') def func(lib, opts, args): if opts.add: for album in lib.albums(ui.decargs(args)): if len(album.items()) == 0: self._log.info('{0} does not contain items, aborting', album) self.ipfs_add(album) album.store() if opts.get: self.ipfs_get(lib, ui.decargs(args)) if opts.publish: self.ipfs_publish(lib) if opts._import: self.ipfs_import(lib, ui.decargs(args)) if opts._list: self.ipfs_list(lib, ui.decargs(args)) if opts.play: self.ipfs_play(lib, opts, ui.decargs(args)) cmd.func = func return [cmd]
def commands(self): lastgenre_cmd = ui.Subcommand('lastgenre', help='fetch genres') lastgenre_cmd.parser.add_option( '-f', '--force', dest='force', action='store_true', default=False, help='re-download genre when already present' ) lastgenre_cmd.parser.add_option( '-s', '--source', dest='source', type='string', help='genre source: artist, album, or track' ) def lastgenre_func(lib, opts, args): write = ui.should_write() self.config.set_args(opts) for album in lib.albums(ui.decargs(args)): album.genre, src = self._get_genre(album) self._log.info(u'genre for album {0} ({1}): {0.genre}', album, src) album.store() for item in album.items(): # If we're using track-level sources, also look up each # track on the album. if 'track' in self.sources: item.genre, src = self._get_genre(item) item.store() self._log.info(u'genre for track {0} ({1}): {0.genre}', item, src) if write: item.try_write() lastgenre_cmd.func = lastgenre_func return [lastgenre_cmd]
def commands(self): cmd = ui.Subcommand( u'inconsistent-album-tracks', help=u'Identify albums whose tracks have inconsistent album fields.' ) cmd.parser.add_option( '-i', '--include-fields', default=[], action='append', metavar='FIELD', dest='included_fields', help='comma separated list of fields to show', ) cmd.parser.add_option( '-x', '--exclude-fields', default=[], action='append', metavar='FIELD', dest='ignored_fields', help='comma separated list of fields to exclude/ignore', ) cmd.func = self.command return [cmd]
def commands(self): """Return the "replaygain" ui subcommand. """ def func(lib, opts, args): write = ui.should_write(opts.write) force = opts.force if opts.album: for album in lib.albums(ui.decargs(args)): self.handle_album(album, write, force) else: for item in lib.items(ui.decargs(args)): self.handle_track(item, write, force) cmd = ui.Subcommand('replaygain', help=u'analyze for ReplayGain') cmd.parser.add_album_option() cmd.parser.add_option( "-f", "--force", dest="force", action="store_true", default=False, help=u"analyze all files, including those that " "already have ReplayGain metadata") cmd.parser.add_option( "-w", "--write", default=None, action="store_true", help=u"write new metadata to files' tags") cmd.parser.add_option( "-W", "--nowrite", dest="write", action="store_false", help=u"don't write metadata (opposite of -w)") cmd.func = func return [cmd]
def commands(self): cmd = ui.Subcommand( 'absubmit', help=u'calculate and submit AcousticBrainz analysis' ) cmd.func = self.command return [cmd]
def commands(self): cmd = ui.Subcommand('convert', help=u'convert to external location') cmd.parser.add_option('-p', '--pretend', action='store_true', help=u'show actions but do nothing') cmd.parser.add_option('-t', '--threads', action='store', type='int', help=u'change the number of threads, \ defaults to maximum available processors') cmd.parser.add_option('-k', '--keep-new', action='store_true', dest='keep_new', help=u'keep only the converted \ and move the old files') cmd.parser.add_option('-d', '--dest', action='store', help=u'set the destination directory') cmd.parser.add_option('-f', '--format', action='store', dest='format', help=u'set the target format of the tracks') cmd.parser.add_option('-y', '--yes', action='store_true', dest='yes', help=u'do not ask for confirmation') cmd.parser.add_album_option() cmd.func = self.convert_func return [cmd]
def commands(self): cmd = ui.Subcommand('web', help=u'start a Web interface') cmd.parser.add_option(u'-d', u'--debug', action='store_true', default=False, help=u'debug mode') def func(lib, opts, args): args = ui.decargs(args) if args: self.config['host'] = args.pop(0) if args: self.config['port'] = int(args.pop(0)) app.config['lib'] = lib # Enable CORS if required. if self.config['cors']: self._log.info(u'Enabling CORS with origin: {0}', self.config['cors']) from flask.ext.cors import CORS app.config['CORS_ALLOW_HEADERS'] = "Content-Type" app.config['CORS_RESOURCES'] = { r"/*": {"origins": self.config['cors'].get(str)} } CORS(app) # Start the web application. app.run(host=self.config['host'].get(unicode), port=self.config['port'].get(int), debug=opts.debug, threaded=True) cmd.func = func return [cmd]
def commands(self): cmd = ui.Subcommand('mbsync', help='update metadata from musicbrainz') 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=config['import']['write'], dest='write', help="don't write updated metadata to files") cmd.parser.add_option('-f', '--format', action='store', default='', help='print with custom format') cmd.func = self.func return [cmd]
def commands(self): for plugin in plugins.find_plugins(): if plugin.name == 'spotify': self.spotify = plugin break else: raise ui.UserError('spotify plugin is required') def explicits(lib, opts, args): args = ui.decargs(args) items = lib.items(args) results = self.spotify._match_library_tracks(lib, args) if results: for item, track in zip(items, results): if track['explicit']: title = track['name'] album = track['album']['name'] artist = track['artists'][0]['name'] tracknum = track['track_number'] url = track['external_urls']['spotify'] plugins.send("spotify_explicit_track", lib=lib, track=track, item=item) print('{} - {} - {} - {} - {}'.format( album, tracknum, artist, title, url)) explicit_cmd = ui.Subcommand('spotify-explicit', help=u'') explicit_cmd.parser.add_all_common_options() explicit_cmd.func = explicits return [explicit_cmd]
def commands(self): cmd = ui.Subcommand('lyrics', help='fetch song lyrics') cmd.parser.add_option('-p', '--print', dest='printlyr', action='store_true', default=False, help='print lyrics to console') cmd.parser.add_option('-f', '--force', dest='force_refetch', action='store_true', default=False, help='always re-download lyrics') def func(lib, opts, args): # The "write to files" option corresponds to the # import_write config value. write = config['import']['write'].get(bool) for item in lib.items(ui.decargs(args)): self.fetch_item_lyrics(lib, logging.INFO, item, write, opts.force_refetch) if opts.printlyr and item.lyrics: ui.print_(item.lyrics) cmd.func = func return [cmd]
def commands(self): cmd = ui.Subcommand( 'structuredcomments', help=u'for when you need beets data outside of beets') cmd.parser.add_option(u'-d', u'--dry-run', dest="dry_run", action="store_true", default=False, help=u'Print changes without writing to files') cmd.parser.add_option( u'-f', u'--force', dest="force", action="store_true", default=False, help=u'Rewrite tags to file even if they are the same') # XXX not sure how to ensure we come back to the next 100 if we do batch of 100, maybe a skip arg # cmd.parser.add_option( # u'-b', u'--batch', dest="batch", # action="store", default=None, # help=u'Write comments in batches instead of all at once' # ) cmd.func = self.command return [cmd]
def commands(self): cmd = ui.Subcommand('tempo', help='fetch song tempo (bpm)') cmd.parser.add_option('-p', '--print', dest='printlyr', action='store_true', default=False, help='print tempo (bpm) to console') def func(lib, config, opts, args): # The "write to files" option corresponds to the # import_write config value. if not _echonest_apikey: raise ui.UserError('no EchoNest user API key provided') write = ui.config_val(config, 'beets', 'import_write', commands.DEFAULT_IMPORT_WRITE, bool) for item in lib.items(ui.decargs(args)): fetch_item_tempo(lib, logging.INFO, item, write) if opts.printlyr and item.bpm: ui.print_(item.bpm) cmd.func = func return [cmd]
def commands(self): """ Return the "userrating" ui subcommand. """ cmd = ui.Subcommand('userrating', help=u'manage user ratings for tracks') cmd.func = lambda lib, opts, args: self.handle_tracks(lib.items(ui.decargs(args)), opts) cmd.parser.add_option( u'-u', u'--update', action='store', help=u'all files will be rated with given value', ) cmd.parser.add_option( u'-i', u'--imported', action='store_true', help=u'all files will be rated if possible with known players value in file', ) cmd.parser.add_option( u'-o', u'--overwrite', action='store_true', help=u'allow overwriting rated file (default is to skip already rated file)', ) cmd.parser.add_option( u'-s',u'--sync', action='store', help=u'write rating for existing players rating (default is to not update any players rating but beets)', ) cmd.parser.add_option( u'-a', u'--all', action='store_true', help=u'write rating for all known players (default is to not update any players rating but beets)', ) return [cmd]