Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mbsubmit: cleanup and completion #1779

Merged
merged 8 commits into from
Jan 2, 2016
32 changes: 19 additions & 13 deletions beetsplug/mbsubmit.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,17 @@
"""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,
unicode_literals)


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
Expand All @@ -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())
3 changes: 3 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions docs/plugins/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
54 changes: 54 additions & 0 deletions docs/plugins/mbsubmit.rst
Original file line number Diff line number Diff line change
@@ -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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any particular reason for the extra backticks here? It seems like quotes might be enough. (This is officially the tiniest style issue ever!)


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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just format would be OK? Since this is an mbsubmit plugin, the mb_ prefix could be seen as redundant.

same template syntax as beets’ :doc:`path formats </reference/pathformat>`.
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`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"on" -> "at" or "in"

72 changes: 72 additions & 0 deletions test/test_mbsubmit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
# This file is part of beets.
# 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
# "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_print_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_print_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')