From 9d55179d2d88e586d1051b6e404659e579e640f7 Mon Sep 17 00:00:00 2001 From: Simon Kohlmeyer Date: Sat, 13 Sep 2014 19:07:25 +0200 Subject: [PATCH] Added never_convert_lossy_files option to convert plugin When set to true, this config option chooses copying over converting when the source file is in a lossy format. At the moment, everything except ape, flac, alac and wav is considered lossy. --- beetsplug/convert.py | 5 +++++ docs/plugins/convert.rst | 4 ++++ test/test_convert.py | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/beetsplug/convert.py b/beetsplug/convert.py index b840078af..e60d5fb07 100644 --- a/beetsplug/convert.py +++ b/beetsplug/convert.py @@ -37,6 +37,8 @@ ALIASES = { u'vorbis': u'ogg', } +LOSSLESS_FORMATS = ['ape', 'flac', 'alac', 'wav'] + def replace_ext(path, ext): """Return the path with its extension replaced by `ext`. @@ -128,6 +130,8 @@ def should_transcode(item, format): """Determine whether the item should be transcoded as part of conversion (i.e., its bitrate is high or it has the wrong format). """ + if config['convert']['never_convert_lossy_files'] and not (item.format.lower() in LOSSLESS_FORMATS): + return False maxbr = config['convert']['max_bitrate'].get(int) return format.lower() != item.format.lower() or \ item.bitrate >= 1000 * maxbr @@ -308,6 +312,7 @@ class ConvertPlugin(BeetsPlugin): u'quiet': False, u'embed': True, u'paths': {}, + u'never_convert_lossy_files': False, }) self.import_stages = [self.auto_convert] diff --git a/docs/plugins/convert.rst b/docs/plugins/convert.rst index b94f874d7..3a2485b5e 100644 --- a/docs/plugins/convert.rst +++ b/docs/plugins/convert.rst @@ -67,6 +67,10 @@ The plugin offers several configuration options, all of which live under the adding them to your library. * ``quiet`` mode prevents the plugin from announcing every file it processes. Default: false. +* ``never_convert_lossy_files`` means that lossy codecs, such as mp3, ogg vorbis, + etc, are never converted, as converting lossy files to other lossy codecs will + decrease quality further. If set to true, lossy files are always copied. + Default: false * ``paths`` lets you specify the directory structure and naming scheme for the converted files. Use the same format as the top-level ``paths`` section (see :ref:`path-format-config`). By default, the plugin reuses your top-level diff --git a/test/test_convert.py b/test/test_convert.py index 24ed44748..4a6119884 100644 --- a/test/test_convert.py +++ b/test/test_convert.py @@ -124,6 +124,44 @@ class ConvertCliTest(unittest.TestCase, TestHelper): mediafile = MediaFile(converted) self.assertEqual(mediafile.images[0].data, image_data) +class NeverConvertLossyFilesTest(unittest.TestCase, TestHelper): + + def setUp(self): + self.setup_beets(disk=True) # Converter is threaded + self.album_ogg = self.add_album_fixture(ext='ogg') + self.album_flac = self.add_album_fixture(ext='flac') + self.load_plugins('convert') + + self.convert_dest = os.path.join(self.temp_dir, 'convert_dest') + self.config['convert'] = { + 'dest': self.convert_dest, + 'paths': {'default': 'converted'}, + 'never_convert_lossy_files': False, + 'format': 'mp3', + 'formats': { + 'mp3': 'cp $source $dest', + 'opus': { + 'command': 'cp $source $dest', + 'extension': 'ops', + } + } + } + + def tearDown(self): + self.unload_plugins() + self.teardown_beets() + + def test_convert_flac_to_mp3_works(self): + with control_stdin('y'): + self.run_command('convert', self.album_flac.items()[0].path) + converted = os.path.join(self.convert_dest, 'converted.mp3') + self.assertTrue(os.path.isfile(converted)) + + def test_convert_ogg_to_mp3_prevented(self): + with control_stdin('y'): + self.run_command('convert', self.album_ogg.items()[0].path) + converted = os.path.join(self.convert_dest, 'converted.mp3') + self.assertTrue(os.path.isfile(converted)) def suite(): return unittest.TestLoader().loadTestsFromName(__name__)