From 8746869f7c8198b01e9306150abc1fcd47ed1892 Mon Sep 17 00:00:00 2001 From: Diego Moreda Date: Tue, 29 Dec 2015 17:26:42 +0100 Subject: [PATCH 1/6] mbsubmit: cleanup, revise logic, config options * Cleanup the "mbsubmit" plugin to remove a choice ("print tracks and skip") and make the logic depend on the strength of the Recommendation. * Add configuration options for the Recommendation threshold that triggers the addition of the "Print tracks" choice and for the formatting string to be used for printing the items. * Include link to the official-ish MusicBrainz format page on the docstring. --- beetsplug/mbsubmit.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/beetsplug/mbsubmit.py b/beetsplug/mbsubmit.py index e86ca1ab7..546656cee 100644 --- a/beetsplug/mbsubmit.py +++ b/beetsplug/mbsubmit.py @@ -16,8 +16,10 @@ """Aid in submitting information to MusicBrainz. This plugin allows the user to print track information in a format that is -parseable by the MusicBrainz track parser. Programmatic submitting is not +parseable by the MusicBrainz track parser [1]. Programmatic submitting is not implemented by MusicBrainz yet. + +[1] http://wiki.musicbrainz.org/History:How_To_Parse_Track_Listings """ from __future__ import (division, absolute_import, print_function, @@ -25,7 +27,6 @@ from __future__ import (division, absolute_import, print_function, from beets.autotag import Recommendation -from beets.importer import action from beets.plugins import BeetsPlugin from beets.ui.commands import PromptChoice from beetsplug.info import print_data @@ -35,21 +36,26 @@ class MBSubmitPlugin(BeetsPlugin): def __init__(self): super(MBSubmitPlugin, self).__init__() + self.config.add({ + 'mb_format': '$track. $title - $artist ($length)', + 'threshold': 'medium', + }) + + # validate and store threshold + self.threshold = self.config['threshold'].as_choice({ + 'none': Recommendation.none, + 'low': Recommendation.low, + 'medium': Recommendation.medium, + 'strong': Recommendation.strong + }) + self.register_listener('before_choose_candidate', self.before_choose_candidate_event) def before_choose_candidate_event(self, session, task): - if not task.candidates or task.rec == Recommendation.none: - return [PromptChoice('p', 'Print tracks', self.print_tracks), - PromptChoice('k', 'print tracks and sKip', - self.print_tracks_and_skip)] + if task.rec <= self.threshold: + return [PromptChoice('p', 'Print tracks', self.print_tracks)] - # Callbacks for choices. def print_tracks(self, session, task): for i in task.items: - print_data(None, i, '$track. $artist - $title ($length)') - - def print_tracks_and_skip(self, session, task): - for i in task.items: - print_data(None, i, '$track. $artist - $title ($length)') - return action.SKIP + print_data(None, i, self.config['mb_format'].get()) From 966746fd553ded4f61f87a97dacaa638d9a81522 Mon Sep 17 00:00:00 2001 From: Diego Moreda Date: Tue, 29 Dec 2015 17:41:49 +0100 Subject: [PATCH 2/6] mbsubmit: add basic tests * Add basic unit tests for the mbsubmit plugin, covering the output of the "Print tracks" option on albums and singletons. --- test/test_mbsubmit.py | 72 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 test/test_mbsubmit.py diff --git a/test/test_mbsubmit.py b/test/test_mbsubmit.py new file mode 100644 index 000000000..37d1a9c80 --- /dev/null +++ b/test/test_mbsubmit.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# This file is part of beets. +# Copyright 2015, Adrian Sampson and Diego Moreda. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +from __future__ import (division, absolute_import, print_function, + unicode_literals) + +from test._common import unittest +from test.helper import capture_stdout, control_stdin, TestHelper +from test.test_importer import ImportHelper, AutotagStub +from test.test_ui_importer import TerminalImportSessionSetup + + +class MBSubmitPluginTest(TerminalImportSessionSetup, unittest.TestCase, + ImportHelper, TestHelper): + def setUp(self): + self.setup_beets() + self.load_plugins('mbsubmit') + self._create_import_dir(2) + self._setup_import_session() + self.matcher = AutotagStub().install() + + def tearDown(self): + self.unload_plugins() + self.teardown_beets() + + def test_xxxxprint_tracks_output(self): + """Test the output of the "print tracks" choice.""" + self.matcher.matching = AutotagStub.BAD + + with capture_stdout() as output: + with control_stdin('\n'.join(['p', 's'])): + # Print tracks; Skip + self.importer.run() + + # manually build the string for comparing the output + tracklist = ('Print tracks? ' + '01. Tag Title 1 - Tag Artist (0:01)\n' + '02. Tag Title 2 - Tag Artist (0:01)') + self.assertIn(tracklist, output.getvalue()) + + def test_xxprint_tracks_output_as_tracks(self): + """Test the output of the "print tracks" choice, as singletons.""" + self.matcher.matching = AutotagStub.BAD + + with capture_stdout() as output: + with control_stdin('\n'.join(['t', 's', 'p', 's'])): + # as Tracks; Skip; Print tracks; Skip + self.importer.run() + + # manually build the string for comparing the output + tracklist = ('Print tracks? ' + '02. Tag Title 2 - Tag Artist (0:01)') + self.assertIn(tracklist, output.getvalue()) + + +def suite(): + return unittest.TestLoader().loadTestsFromName(__name__) + +if __name__ == b'__main__': + unittest.main(defaultTest='suite') From 798dd72bb6ae4e6b529901594de0a53a5ea55294 Mon Sep 17 00:00:00 2001 From: Diego Moreda Date: Wed, 30 Dec 2015 20:19:03 +0100 Subject: [PATCH 3/6] mbsubmit: style fixes --- beetsplug/mbsubmit.py | 2 +- test/test_mbsubmit.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/beetsplug/mbsubmit.py b/beetsplug/mbsubmit.py index 546656cee..4306cc798 100644 --- a/beetsplug/mbsubmit.py +++ b/beetsplug/mbsubmit.py @@ -41,7 +41,7 @@ class MBSubmitPlugin(BeetsPlugin): 'threshold': 'medium', }) - # validate and store threshold + # Validate and store threshold. self.threshold = self.config['threshold'].as_choice({ 'none': Recommendation.none, 'low': Recommendation.low, diff --git a/test/test_mbsubmit.py b/test/test_mbsubmit.py index 37d1a9c80..7256a6296 100644 --- a/test/test_mbsubmit.py +++ b/test/test_mbsubmit.py @@ -35,7 +35,7 @@ class MBSubmitPluginTest(TerminalImportSessionSetup, unittest.TestCase, self.unload_plugins() self.teardown_beets() - def test_xxxxprint_tracks_output(self): + def test_print_tracks_output(self): """Test the output of the "print tracks" choice.""" self.matcher.matching = AutotagStub.BAD @@ -44,13 +44,13 @@ class MBSubmitPluginTest(TerminalImportSessionSetup, unittest.TestCase, # Print tracks; Skip self.importer.run() - # manually build the string for comparing the output + # Manually build the string for comparing the output. tracklist = ('Print tracks? ' '01. Tag Title 1 - Tag Artist (0:01)\n' '02. Tag Title 2 - Tag Artist (0:01)') self.assertIn(tracklist, output.getvalue()) - def test_xxprint_tracks_output_as_tracks(self): + def test_print_tracks_output_as_tracks(self): """Test the output of the "print tracks" choice, as singletons.""" self.matcher.matching = AutotagStub.BAD @@ -59,7 +59,7 @@ class MBSubmitPluginTest(TerminalImportSessionSetup, unittest.TestCase, # as Tracks; Skip; Print tracks; Skip self.importer.run() - # manually build the string for comparing the output + # Manually build the string for comparing the output. tracklist = ('Print tracks? ' '02. Tag Title 2 - Tag Artist (0:01)') self.assertIn(tracklist, output.getvalue()) From 85ad17d43103e912e65cacd15e27e48adbfff3bc Mon Sep 17 00:00:00 2001 From: Diego Moreda Date: Wed, 30 Dec 2015 20:29:58 +0100 Subject: [PATCH 4/6] mbsubmit: add documentation, changelog --- docs/changelog.rst | 3 +++ docs/plugins/index.rst | 2 ++ docs/plugins/mbsubmit.rst | 54 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 docs/plugins/mbsubmit.rst diff --git a/docs/changelog.rst b/docs/changelog.rst index dbcd7e399..b69288170 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,6 +9,9 @@ New: * :doc:`/plugins/fetchart`: The Google Images backend has been restored. It now requires an API key from Google. Thanks to :user:`lcharlick`. :bug:`1778` +* A new :doc:`/plugins/mbsubmit` lets you print the tracks of an album in a + format parseable by MusicBrainz track parser during an interactive import + session. :bug:`1779` 1.3.16 (December 28, 2015) diff --git a/docs/plugins/index.rst b/docs/plugins/index.rst index 5da5ee0be..d1cc41015 100644 --- a/docs/plugins/index.rst +++ b/docs/plugins/index.rst @@ -59,6 +59,7 @@ Each plugin has its own set of options that can be defined in a section bearing lastimport lyrics mbcollection + mbsubmit mbsync metasync missing @@ -162,6 +163,7 @@ Miscellaneous * :doc:`ihate`: Automatically skip albums and tracks during the import process. * :doc:`info`: Print music files' tags to the console. * :doc:`mbcollection`: Maintain your MusicBrainz collection list. +* :doc:`mbsubmit`: Print an album's tracks in a MusicBrainz-friendly format. * :doc:`missing`: List missing tracks. * :doc:`random`: Randomly choose albums and tracks from your library. * :doc:`filefilter`: Automatically skip files during the import process based diff --git a/docs/plugins/mbsubmit.rst b/docs/plugins/mbsubmit.rst new file mode 100644 index 000000000..9312eb785 --- /dev/null +++ b/docs/plugins/mbsubmit.rst @@ -0,0 +1,54 @@ +MusicBrainz Submit Plugin +========================= + +The ``mbsubmit`` plugin provides an extra prompt choice during an import +session that prints the tracks of the current album in a format that is +parseable by MusicBrainz's `track parser`_. + +.. _track parser: http://wiki.musicbrainz.org/History:How_To_Parse_Track_Listings + +Usage +----- + +Enable the ``mbsubmit`` plugin in your configuration (see :ref:`using-plugins`) +and select the ``Print tracks`` choice which is by default displayed when no +strong recommendations are found for the album:: + + No matching release found for 3 tracks. + For help, see: http://beets.readthedocs.org/en/latest/faq.html#nomatch + [U]se as-is, as Tracks, Group albums, Skip, Enter search, enter Id, aBort, + Print tracks? p + 01. An Obscure Track - An Obscure Artist (3:37) + 02. Another Obscure Track - An Obscure Artist (2:05) + 03. The Third Track - Another Obscure Artist (3:02) + + No matching release found for 3 tracks. + For help, see: http://beets.readthedocs.org/en/latest/faq.html#nomatch + [U]se as-is, as Tracks, Group albums, Skip, Enter search, enter Id, aBort, + Print tracks? + +As MusicBrainz currently does not support submitting albums programmatically, +the recommended workflow is to copy the output of the ``Print tracks`` choice +and paste it into the parser that can be found by clicking on the +"`Track Parser`" button on MusicBrainz "`Tracklist`" tab. + +Configuration +------------- + +To configure the plugin, make a ``mbsubmit:`` section in your configuration +file. The following options are available: + +- **mb_format**: The format used for printing the tracks, defined using the + same template syntax as beets’ :doc:`path formats `. + Default: ``$track. $title - $artist ($length)``. +- **threshold**: The minimum strength of the autotagger recommendation that + will cause the ``Print tracks`` choice to be displayed on the prompt. + Default: ``medium`` (causing the choice to be displayed for all albums that + have a recommendation of medium strength or lower). Valid values: ``none``, + ``low``, ``medium``, ``strong``. + +Please note that some values of the ``threshold`` configuration option might +require other ``beets`` command line switches to be enabled in order to work as +intended. In particular, setting a threshold of ``strong`` will only display +the prompt if ``timid`` mode is enabled. You can find more information about +how the recommendation system works on :ref:`match-config`. From 53ecec11e02131e42ce655a9da0c148d862ce960 Mon Sep 17 00:00:00 2001 From: Diego Moreda Date: Wed, 30 Dec 2015 20:32:14 +0100 Subject: [PATCH 5/6] mbsubmit: bump copyright year --- test/test_mbsubmit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_mbsubmit.py b/test/test_mbsubmit.py index 7256a6296..5047fd3d0 100644 --- a/test/test_mbsubmit.py +++ b/test/test_mbsubmit.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # This file is part of beets. -# Copyright 2015, Adrian Sampson and Diego Moreda. +# Copyright 2016, Adrian Sampson and Diego Moreda. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the From 9bba782e9ceb30e844b42f75698468487cbcb643 Mon Sep 17 00:00:00 2001 From: Diego Moreda Date: Sat, 2 Jan 2016 13:32:52 +0100 Subject: [PATCH 6/6] mbsubmit: final style fixes (closes #1779) --- beetsplug/mbsubmit.py | 4 ++-- docs/plugins/mbsubmit.rst | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/beetsplug/mbsubmit.py b/beetsplug/mbsubmit.py index 7faedff44..947e4cfc6 100644 --- a/beetsplug/mbsubmit.py +++ b/beetsplug/mbsubmit.py @@ -37,7 +37,7 @@ class MBSubmitPlugin(BeetsPlugin): super(MBSubmitPlugin, self).__init__() self.config.add({ - 'mb_format': '$track. $title - $artist ($length)', + 'format': '$track. $title - $artist ($length)', 'threshold': 'medium', }) @@ -58,4 +58,4 @@ class MBSubmitPlugin(BeetsPlugin): def print_tracks(self, session, task): for i in task.items: - print_data(None, i, self.config['mb_format'].get()) + print_data(None, i, self.config['format'].get()) diff --git a/docs/plugins/mbsubmit.rst b/docs/plugins/mbsubmit.rst index 9312eb785..5c13375ba 100644 --- a/docs/plugins/mbsubmit.rst +++ b/docs/plugins/mbsubmit.rst @@ -30,7 +30,7 @@ strong recommendations are found for the album:: As MusicBrainz currently does not support submitting albums programmatically, the recommended workflow is to copy the output of the ``Print tracks`` choice and paste it into the parser that can be found by clicking on the -"`Track Parser`" button on MusicBrainz "`Tracklist`" tab. +"Track Parser" button on MusicBrainz "Tracklist" tab. Configuration ------------- @@ -38,7 +38,7 @@ Configuration To configure the plugin, make a ``mbsubmit:`` section in your configuration file. The following options are available: -- **mb_format**: The format used for printing the tracks, defined using the +- **format**: The format used for printing the tracks, defined using the same template syntax as beets’ :doc:`path formats `. Default: ``$track. $title - $artist ($length)``. - **threshold**: The minimum strength of the autotagger recommendation that @@ -51,4 +51,4 @@ Please note that some values of the ``threshold`` configuration option might require other ``beets`` command line switches to be enabled in order to work as intended. In particular, setting a threshold of ``strong`` will only display the prompt if ``timid`` mode is enabled. You can find more information about -how the recommendation system works on :ref:`match-config`. +how the recommendation system works at :ref:`match-config`.