mirror of
https://github.com/beetbox/beets.git
synced 2026-02-21 23:03:26 +01:00
changelog/cleanup/fixes for #209
The major functional change here is how files move around when in keep_new mode. Now, files are first moved to the destination directory and then copied/transcoded back into the library. This avoids problems where naming conflicts could occur when transcoding from MP3 to MP3 (and thus not changing the filename).
This commit is contained in:
parent
5a94cfe5d6
commit
87d71abc28
3 changed files with 48 additions and 42 deletions
|
|
@ -22,7 +22,6 @@ from subprocess import Popen
|
|||
from beets.plugins import BeetsPlugin
|
||||
from beets import ui, util
|
||||
from beetsplug.embedart import _embed
|
||||
from beets import library
|
||||
from beets import config
|
||||
|
||||
log = logging.getLogger('beets')
|
||||
|
|
@ -30,25 +29,19 @@ DEVNULL = open(os.devnull, 'wb')
|
|||
_fs_lock = threading.Lock()
|
||||
|
||||
|
||||
def _dest_out(lib, dest_dir, item, keep_new):
|
||||
"""Path to the files outside the directory"""
|
||||
|
||||
def _destination(lib, dest_dir, item, keep_new):
|
||||
"""Return the path under `dest_dir` where the file should be placed
|
||||
(possibly after conversion).
|
||||
"""
|
||||
dest = lib.destination(item, basedir=dest_dir)
|
||||
if keep_new:
|
||||
return os.path.join(dest_dir, lib.destination(item, fragment=True))
|
||||
|
||||
dest = os.path.join(dest_dir, lib.destination(item, fragment=True))
|
||||
return os.path.splitext(dest)[0] + '.mp3'
|
||||
|
||||
|
||||
def _dest_converted(lib, dest_dir, item, keep_new):
|
||||
"""Path to the newly converted files"""
|
||||
|
||||
if keep_new:
|
||||
dest = lib.destination(item)
|
||||
# When we're keeping the converted file, no extension munging
|
||||
# occurs.
|
||||
return dest
|
||||
else:
|
||||
# Otherwise, replace the extension with .mp3.
|
||||
return os.path.splitext(dest)[0] + '.mp3'
|
||||
|
||||
return _dest_out(lib, dest_dir, item, keep_new)
|
||||
|
||||
|
||||
def encode(source, dest):
|
||||
log.info(u'Started encoding {0}'.format(util.displayable_path(source)))
|
||||
|
|
@ -71,11 +64,9 @@ def encode(source, dest):
|
|||
def convert_item(lib, dest_dir, keep_new):
|
||||
while True:
|
||||
item = yield
|
||||
dest = _destination(lib, dest_dir, item, keep_new)
|
||||
|
||||
dest_converted = _dest_converted(lib, dest_dir, item, keep_new)
|
||||
dest_out = _dest_out(lib, dest_dir, item, keep_new)
|
||||
|
||||
if os.path.exists(util.syspath(dest_out)):
|
||||
if os.path.exists(util.syspath(dest)):
|
||||
log.info(u'Skipping {0} (target file exists)'.format(
|
||||
util.displayable_path(item.path)
|
||||
))
|
||||
|
|
@ -85,21 +76,36 @@ def convert_item(lib, dest_dir, keep_new):
|
|||
# time. (The existence check is not atomic with the directory
|
||||
# creation inside this function.)
|
||||
with _fs_lock:
|
||||
util.mkdirall(dest_out)
|
||||
util.mkdirall(dest)
|
||||
|
||||
# When keeping the new file in the library, we first move the
|
||||
# current (pristine) file to the destination. We'll then copy it
|
||||
# back to its old path or transcode it to a new path.
|
||||
if keep_new:
|
||||
log.info(u'Moving to {0}'.
|
||||
format(util.displayable_path(dest)))
|
||||
util.move(item.path, dest)
|
||||
|
||||
maxbr = config['convert']['max_bitrate'].get(int)
|
||||
if item.format == 'MP3' and item.bitrate < 1000 * maxbr:
|
||||
# No transcoding necessary.
|
||||
log.info(u'Copying {0}'.format(util.displayable_path(item.path)))
|
||||
util.copy(item.path, dest_out)
|
||||
else:
|
||||
encode(item.path, dest_converted)
|
||||
|
||||
if keep_new:
|
||||
log.info(u'Moving to destination {0}'.
|
||||
format(util.displayable_path(dest_out)))
|
||||
util.move(item.path, dest_out)
|
||||
util.copy(dest, item.path)
|
||||
else:
|
||||
util.copy(item.path, dest)
|
||||
|
||||
item.path = dest_converted
|
||||
else:
|
||||
if keep_new:
|
||||
item.path = os.path.splitext(item.path)[0] + '.mp3'
|
||||
encode(dest, item.path)
|
||||
lib.store(item)
|
||||
else:
|
||||
encode(item.path, dest)
|
||||
|
||||
# Write tags from the database to the converted file.
|
||||
if not keep_new:
|
||||
item.path = dest
|
||||
item.write()
|
||||
|
||||
if config['convert']['embed']:
|
||||
|
|
@ -109,21 +115,14 @@ def convert_item(lib, dest_dir, keep_new):
|
|||
if artpath:
|
||||
_embed(artpath, [item])
|
||||
|
||||
if keep_new:
|
||||
item.read()
|
||||
log.info(u'Updating new format {0}'.format(item.format))
|
||||
item.write()
|
||||
lib.store(item)
|
||||
|
||||
|
||||
def convert_func(lib, opts, args):
|
||||
dest = opts.dest if opts.dest is not None else \
|
||||
config['convert']['dest'].get()
|
||||
config['convert']['dest'].get()
|
||||
if not dest:
|
||||
raise ui.UserError('no convert destination set')
|
||||
threads = opts.threads if opts.threads is not None else \
|
||||
config['convert']['threads'].get(int)
|
||||
|
||||
config['convert']['threads'].get(int)
|
||||
keep_new = opts.keep_new
|
||||
|
||||
ui.commands.list_items(lib, ui.decargs(args), opts.album, None)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ Other stuff:
|
|||
track in MusicBrainz and updates your library to reflect it. This can help
|
||||
you easily correct errors that have been fixed in the MB database. Thanks to
|
||||
Jakob Schnitzer.
|
||||
* :doc:`/plugins/convert`: A new ``--keep-new`` option lets you store
|
||||
transcoded files in your library while backing up the originals (instead of
|
||||
vice-versa). Thanks to Lucas Duailibe.
|
||||
* :doc:`/plugins/echonest_tempo`: API errors now issue a warning instead of
|
||||
exiting with an exception. We also avoid an error when track metadata
|
||||
contains newlines.
|
||||
|
|
|
|||
|
|
@ -26,13 +26,17 @@ Usage
|
|||
To convert a part of your collection, run ``beet convert QUERY``. This
|
||||
will display all items matching ``QUERY`` and ask you for confirmation before
|
||||
starting the conversion. The ``-a`` (or ``--album``) option causes the command
|
||||
to match albums instead of tracks. The ``-k`` (or ``--keep-new``) allows you to
|
||||
keep the new, converted, files in your library and move the origin files to the
|
||||
destination directory.
|
||||
to match albums instead of tracks.
|
||||
|
||||
The ``-t`` (``--threads``) and ``-d`` (``--dest``) options allow you to specify
|
||||
or overwrite the respective configuration options.
|
||||
|
||||
By default, the command places converted files into the destination directory
|
||||
and leaves your library pristine. To instead back up your original files into
|
||||
the destination directory and keep converted files in your library, use the
|
||||
``-k`` (or ``--keep-new``) option.
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue