diff --git a/beetsplug/plexupdate.py b/beetsplug/plexupdate.py index 02ed2324c..340bcdf4d 100644 --- a/beetsplug/plexupdate.py +++ b/beetsplug/plexupdate.py @@ -18,7 +18,7 @@ from beets import config from beets.plugins import BeetsPlugin -def get_music_section(host, port, token): +def get_music_section(host, port, token, library_name): """Getting the section key for the music library in Plex. """ api_endpoint = append_token('library/sections', token) @@ -30,15 +30,15 @@ def get_music_section(host, port, token): # Parse xml tree and extract music section key. tree = ET.fromstring(r.text) for child in tree.findall('Directory'): - if child.get('title') == 'Music': + if child.get('title') == library_name: return child.get('key') -def update_plex(host, port, token): +def update_plex(host, port, token, library_name): """Sends request to the Plex api to start a library refresh. """ # Getting section key and build url. - section_key = get_music_section(host, port, token) + section_key = get_music_section(host, port, token, library_name) api_endpoint = 'library/sections/{0}/refresh'.format(section_key) api_endpoint = append_token(api_endpoint, token) url = urljoin('http://{0}:{1}'.format(host, port), api_endpoint) @@ -64,7 +64,8 @@ class PlexUpdate(BeetsPlugin): config['plex'].add({ u'host': u'localhost', u'port': 32400, - u'token': u''}) + u'token': u'', + u'library_name': u'Music'}) self.register_listener('database_change', self.listen_for_db_change) @@ -82,7 +83,8 @@ class PlexUpdate(BeetsPlugin): update_plex( config['plex']['host'].get(), config['plex']['port'].get(), - config['plex']['token'].get()) + config['plex']['token'].get(), + config['plex']['library_name'].get()) self._log.info('... started.') except requests.exceptions.RequestException: diff --git a/beetsplug/replaygain.py b/beetsplug/replaygain.py index e621e9b21..8186b42f4 100644 --- a/beetsplug/replaygain.py +++ b/beetsplug/replaygain.py @@ -700,6 +700,23 @@ class AudioToolsBackend(Backend): """ return [self._compute_track_gain(item) for item in items] + def _title_gain(self, rg, audiofile): + """Get the gain result pair from PyAudioTools using the `ReplayGain` + instance `rg` for the given `audiofile`. + + Wraps `rg.title_gain(audiofile.to_pcm())` and throws a + `ReplayGainError` when the library fails. + """ + try: + # The method needs an audiotools.PCMReader instance that can + # be obtained from an audiofile instance. + return rg.title_gain(audiofile.to_pcm()) + except ValueError as exc: + # `audiotools.replaygain` can raise a `ValueError` if the sample + # rate is incorrect. + self._log.debug('error in rg.title_gain() call: {}', exc) + raise ReplayGainError('audiotools audio data error') + def _compute_track_gain(self, item): """Compute ReplayGain value for the requested item. @@ -707,17 +724,10 @@ class AudioToolsBackend(Backend): """ audiofile = self.open_audio_file(item) rg = self.init_replaygain(audiofile, item) - # Each call to title_gain on a replaygain object return peak and gain + + # Each call to title_gain on a ReplayGain object returns peak and gain # of the track. - # Note that the method needs an audiotools.PCMReader instance that can - # be obtained from an audiofile instance. - try: - rg_track_gain, rg_track_peak = rg.title_gain(audiofile.to_pcm()) - except ValueError as exc: - # `audiotools.replaygain` can raise a `ValueError` if the sample - # rate is incorrect. - self._log.debug('error in rg.title_gain() call: {}', exc) - raise ReplayGainError('audiotools audio data error') + rg_track_gain, rg_track_peak = rg._title_gain(rg, audiofile) self._log.debug(u'ReplayGain for track {0} - {1}: {2:.2f}, {3:.2f}', item.artist, item.title, rg_track_gain, rg_track_peak) @@ -740,7 +750,7 @@ class AudioToolsBackend(Backend): track_gains = [] for item in album.items(): audiofile = self.open_audio_file(item) - rg_track_gain, rg_track_peak = rg.title_gain(audiofile.to_pcm()) + rg_track_gain, rg_track_peak = self._title_gain(rg, audiofile) track_gains.append( Gain(gain=rg_track_gain, peak=rg_track_peak) ) diff --git a/docs/changelog.rst b/docs/changelog.rst index bee5fe373..020e39379 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -20,6 +20,8 @@ The new features: :bug:`1591` :bug:`733` * :doc:`/plugins/play`: You can now configure the number of tracks that trigger a "lots of music" warning. :bug:`1577` +* :doc:`/plugins/plexupdate`: A new ``library_name`` option allows you to select + which Plex library to update. :bug:`1572` :bug:`1595` Fixes: diff --git a/docs/plugins/plexupdate.rst b/docs/plugins/plexupdate.rst index f99e6de66..4ac047660 100644 --- a/docs/plugins/plexupdate.rst +++ b/docs/plugins/plexupdate.rst @@ -39,3 +39,5 @@ The available options under the ``plex:`` section are: Default: 32400. - **token**: The Plex Home token. Default: Empty. +- **library_name**: The name of the Plex library to update. + Default: ``Music`` diff --git a/test/test_embedart.py b/test/test_embedart.py index 055899a5f..a4c88a429 100644 --- a/test/test_embedart.py +++ b/test/test_embedart.py @@ -82,6 +82,26 @@ class EmbedartCliTest(_common.TestCase, TestHelper): mediafile = MediaFile(syspath(item.path)) self.assertEqual(mediafile.images[0].data, self.image_data) + def test_embed_art_remove_art_file(self): + self._setup_data() + album = self.add_album_fixture() + + logging.getLogger('beets.embedart').setLevel(logging.DEBUG) + + handle, tmp_path = tempfile.mkstemp() + os.write(handle, self.image_data) + os.close(handle) + + album.artpath = tmp_path + album.store() + + config['embedart']['remove_art_file'] = True + self.run_command('embedart') + + if os.path.isfile(tmp_path): + os.remove(tmp_path) + self.fail('Artwork file {0} was not deleted'.format(tmp_path)) + def test_art_file_missing(self): self.add_album_fixture() logging.getLogger('beets.embedart').setLevel(logging.DEBUG) diff --git a/test/test_plexupdate.py b/test/test_plexupdate.py index 9949be933..58388f728 100644 --- a/test/test_plexupdate.py +++ b/test/test_plexupdate.py @@ -8,9 +8,12 @@ import responses class PlexUpdateTest(unittest.TestCase, TestHelper): - def add_response_get_music_section(self): + def add_response_get_music_section(self, section_name='Music'): """Create response for mocking the get_music_section function. """ + + escaped_section_name = section_name.replace('"', '\\"') + body = ( '' '' '