diff --git a/beets/library.py b/beets/library.py index f13ac9e2a..e0a0aa840 100644 --- a/beets/library.py +++ b/beets/library.py @@ -1243,7 +1243,7 @@ class Library(BaseLibrary): return Transaction(self) def destination(self, item, pathmod=None, fragment=False, - basedir=None, platform=None): + basedir=None, platform=None, path_formats=None): """Returns the path in the library directory designated for item item (i.e., where the file ought to be). fragment makes this method return just the path fragment underneath the root library @@ -1254,10 +1254,11 @@ class Library(BaseLibrary): pathmod = pathmod or os.path platform = platform or sys.platform basedir = basedir or self.directory + path_formats = path_formats or self.path_formats # Use a path format based on a query, falling back on the # default. - for query, path_format in self.path_formats: + for query, path_format in path_formats: if query == PF_KEY_DEFAULT: continue query = AndQuery.from_string(query) @@ -1267,7 +1268,7 @@ class Library(BaseLibrary): break else: # No query matched; fall back to default. - for query, path_format in self.path_formats: + for query, path_format in path_formats: if query == PF_KEY_DEFAULT: break else: diff --git a/beets/ui/__init__.py b/beets/ui/__init__.py index 9dd568689..658a997e5 100644 --- a/beets/ui/__init__.py +++ b/beets/ui/__init__.py @@ -437,12 +437,13 @@ def color_diff_suffix(a, b, highlight='red'): return a[:first_diff] + colorize(highlight, a[first_diff:]), \ b[:first_diff] + colorize(highlight, b[first_diff:]) -def get_path_formats(): +def get_path_formats(subview=None): """Get the configuration's path formats as a list of query/template pairs. """ path_formats = [] - for query, view in config['paths'].items(): + subview = subview or config['paths'] + for query, view in subview.items(): query = PF_KEY_QUERIES.get(query, query) # Expand common queries. path_formats.append((query, Template(view.get(unicode)))) return path_formats diff --git a/beetsplug/convert.py b/beetsplug/convert.py index f6aa4a993..4f1544600 100644 --- a/beetsplug/convert.py +++ b/beetsplug/convert.py @@ -31,11 +31,11 @@ _fs_lock = threading.Lock() _temp_files = [] # Keep track of temporary transcoded files for deletion. -def _destination(lib, dest_dir, item, keep_new): +def _destination(lib, dest_dir, item, keep_new, path_formats): """Return the path under `dest_dir` where the file should be placed (possibly after conversion). """ - dest = lib.destination(item, basedir=dest_dir) + dest = lib.destination(item, basedir=dest_dir, path_formats=path_formats) if keep_new: # When we're keeping the converted file, no extension munging # occurs. @@ -71,10 +71,10 @@ def should_transcode(item): return item.format != 'MP3' or item.bitrate >= 1000 * maxbr -def convert_item(lib, dest_dir, keep_new): +def convert_item(lib, dest_dir, keep_new, path_formats): while True: item = yield - dest = _destination(lib, dest_dir, item, keep_new) + dest = _destination(lib, dest_dir, item, keep_new, path_formats) if os.path.exists(util.syspath(dest)): log.info(u'Skipping {0} (target file exists)'.format( @@ -155,6 +155,11 @@ def convert_func(lib, opts, args): config['convert']['threads'].get(int) keep_new = opts.keep_new + if not config['convert']['paths']: + path_formats = ui.get_path_formats() + else: + path_formats = ui.get_path_formats(config['convert']['paths']) + ui.commands.list_items(lib, ui.decargs(args), opts.album, None) if not ui.input_yn("Convert? (Y/n)"): @@ -164,7 +169,7 @@ def convert_func(lib, opts, args): items = (i for a in lib.albums(ui.decargs(args)) for i in a.items()) else: items = lib.items(ui.decargs(args)) - convert = [convert_item(lib, dest, keep_new) for i in range(threads)] + convert = [convert_item(lib, dest, keep_new, path_formats) for i in range(threads)] pipe = util.pipeline.Pipeline([items, convert]) pipe.run_parallel() @@ -179,7 +184,8 @@ class ConvertPlugin(BeetsPlugin): u'opts': u'-aq 2', u'max_bitrate': 500, u'embed': True, - u'auto': False + u'auto': False, + u'paths': dict(), }) self.import_stages = [self.auto_convert] diff --git a/docs/plugins/convert.rst b/docs/plugins/convert.rst index 7486f38dc..48ee778d0 100644 --- a/docs/plugins/convert.rst +++ b/docs/plugins/convert.rst @@ -61,6 +61,9 @@ The plugin offers several configuration options, all of which live under the automatically during the ``import`` command. With this option enabled, the importer will transcode all non-MP3 files over the maximum bitrate before adding them to your library. +* ``paths`` lets you specify the directory structure and naming scheme for the + converted files (and only them), i.e. it does not affect the path formats of + imported files. (see :doc:`/reference/pathformat`) * Finally, ``threads`` determines the number of threads to use for parallel encoding. By default, the plugin will detect the number of processors available and use them all.