mirror of
https://github.com/beetbox/beets.git
synced 2026-02-14 03:17:59 +01:00
Merge branch 'master' into r128-targetlevel-config
This commit is contained in:
commit
e3645dfd59
10 changed files with 64 additions and 12 deletions
|
|
@ -223,6 +223,13 @@ def sorted_walk(path, ignore=(), ignore_hidden=False, logger=None):
|
|||
yield res
|
||||
|
||||
|
||||
def path_as_posix(path):
|
||||
"""Return the string representation of the path with forward (/)
|
||||
slashes.
|
||||
"""
|
||||
return path.replace(b'\\', b'/')
|
||||
|
||||
|
||||
def mkdirall(path):
|
||||
"""Make all the enclosing directories of path (like mkdir -p on the
|
||||
parent).
|
||||
|
|
|
|||
|
|
@ -74,6 +74,9 @@ ABSCHEME = {
|
|||
'sad': 'mood_sad'
|
||||
}
|
||||
},
|
||||
'moods_mirex': {
|
||||
'value': 'moods_mirex'
|
||||
},
|
||||
'ismir04_rhythm': {
|
||||
'value': 'rhythm'
|
||||
},
|
||||
|
|
@ -82,6 +85,9 @@ ABSCHEME = {
|
|||
'tonal': 'tonal'
|
||||
}
|
||||
},
|
||||
'timbre': {
|
||||
'value': 'timbre'
|
||||
},
|
||||
'voice_instrumental': {
|
||||
'value': 'voice_instrumental'
|
||||
},
|
||||
|
|
@ -124,7 +130,9 @@ class AcousticPlugin(plugins.BeetsPlugin):
|
|||
'mood_party': types.Float(6),
|
||||
'mood_relaxed': types.Float(6),
|
||||
'mood_sad': types.Float(6),
|
||||
'moods_mirex': types.STRING,
|
||||
'rhythm': types.Float(6),
|
||||
'timbre': types.STRING,
|
||||
'tonal': types.Float(6),
|
||||
'voice_instrumental': types.STRING,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import os
|
|||
import fnmatch
|
||||
import tempfile
|
||||
import beets
|
||||
from beets.util import path_as_posix
|
||||
|
||||
|
||||
class PlaylistQuery(beets.dbcore.Query):
|
||||
|
|
@ -86,6 +87,7 @@ class PlaylistPlugin(beets.plugins.BeetsPlugin):
|
|||
'auto': False,
|
||||
'playlist_dir': '.',
|
||||
'relative_to': 'library',
|
||||
'forward_slash': False,
|
||||
})
|
||||
|
||||
self.playlist_dir = self.config['playlist_dir'].as_filename()
|
||||
|
|
@ -160,6 +162,8 @@ class PlaylistPlugin(beets.plugins.BeetsPlugin):
|
|||
try:
|
||||
new_path = self.changes[beets.util.normpath(lookup)]
|
||||
except KeyError:
|
||||
if self.config['forward_slash']:
|
||||
line = path_as_posix(line)
|
||||
tempfp.write(line)
|
||||
else:
|
||||
if new_path is None:
|
||||
|
|
@ -170,8 +174,10 @@ class PlaylistPlugin(beets.plugins.BeetsPlugin):
|
|||
changes += 1
|
||||
if is_relative:
|
||||
new_path = os.path.relpath(new_path, base_dir)
|
||||
|
||||
tempfp.write(line.replace(original_path, new_path))
|
||||
line = line.replace(original_path, new_path)
|
||||
if self.config['forward_slash']:
|
||||
line = path_as_posix(line)
|
||||
tempfp.write(line)
|
||||
|
||||
if changes or deletions:
|
||||
self._log.info(
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ from __future__ import division, absolute_import, print_function
|
|||
from beets.plugins import BeetsPlugin
|
||||
from beets import ui
|
||||
from beets.util import (mkdirall, normpath, sanitize_path, syspath,
|
||||
bytestring_path)
|
||||
bytestring_path, path_as_posix)
|
||||
from beets.library import Item, Album, parse_query_string
|
||||
from beets.dbcore import OrQuery
|
||||
from beets.dbcore.query import MultipleSort, ParsingError
|
||||
|
|
@ -37,7 +37,8 @@ class SmartPlaylistPlugin(BeetsPlugin):
|
|||
'relative_to': None,
|
||||
'playlist_dir': u'.',
|
||||
'auto': True,
|
||||
'playlists': []
|
||||
'playlists': [],
|
||||
'forward_slash': False,
|
||||
})
|
||||
|
||||
self._matched_playlists = None
|
||||
|
|
@ -206,6 +207,8 @@ class SmartPlaylistPlugin(BeetsPlugin):
|
|||
mkdirall(m3u_path)
|
||||
with open(syspath(m3u_path), 'wb') as f:
|
||||
for path in m3us[m3u]:
|
||||
if self.config['forward_slash'].get():
|
||||
path = path_as_posix(path)
|
||||
f.write(path + b'\n')
|
||||
|
||||
self._log.info(u"{0} playlists updated", len(self._matched_playlists))
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@ New features:
|
|||
* :doc:`/plugins/replaygain`: The new ``ffmpeg`` ReplayGain backend supports
|
||||
``R128_`` tags, just like the ``bs1770gain`` backend.
|
||||
:bug:`3056`
|
||||
* :doc:`plugins/replaygain`: ``r128_targetlevel`` is a new configuration option
|
||||
for the ReplayGain plugin: It defines the reference volume for files using
|
||||
``R128_`` tags. ``targetlevel`` only configures the reference volume for
|
||||
``REPLAYGAIN_`` files.
|
||||
This also deprecates the ``bs1770gain`` ReplayGain backend's ``method``
|
||||
option. Use ``targetlevel`` and ``r128_targetlevel`` instead.
|
||||
:bug:`3065`
|
||||
* A new :doc:`/plugins/parentwork` gets information about the original work,
|
||||
which is useful for classical music.
|
||||
Thanks to :user:`dosoe`.
|
||||
|
|
@ -42,13 +49,15 @@ New features:
|
|||
new ``discogs_albumid`` field from the Discogs API.
|
||||
Thanks to :user:`thedevilisinthedetails`.
|
||||
:bug:`465` :bug:`3322`
|
||||
* :doc:`plugins/replaygain`: ``r128_targetlevel`` is a new configuration option
|
||||
for the ReplayGain plugin: It defines the reference volume for files using
|
||||
``R128_`` tags. ``targetlevel`` only configures the reference volume for
|
||||
``REPLAYGAIN_`` files.
|
||||
This also deprecates the ``bs1770gain`` ReplayGain backend's ``method``
|
||||
option. Use ``targetlevel`` and ``r128_targetlevel`` instead.
|
||||
:bug:`3065`
|
||||
* :doc:`/plugins/acousticbrainz`: The plugin now fetches two more additional
|
||||
fields: ``moods_mirex`` and ``timbre``.
|
||||
Thanks to :user:`malcops`.
|
||||
:bug:`2860`
|
||||
* :doc:`/plugins/playlist` and :doc:`/plugins/smartplaylist`: A new
|
||||
``forward_slash`` config option facilitates compatibility with MPD on
|
||||
Windows.
|
||||
Thanks to :user:`MartyLake`.
|
||||
:bug:`3331` :bug:`3334`
|
||||
|
||||
Fixes:
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,9 @@ these fields:
|
|||
* ``mood_party``
|
||||
* ``mood_relaxed``
|
||||
* ``mood_sad``
|
||||
* ``moods_mirex``
|
||||
* ``rhythm``
|
||||
* ``timbre``
|
||||
* ``tonal``
|
||||
* ``voice_instrumental``
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ Then configure your playlists like this::
|
|||
auto: no
|
||||
relative_to: ~/Music
|
||||
playlist_dir: ~/.mpd/playlists
|
||||
forward_slash: no
|
||||
|
||||
It is possible to query the library based on a playlist by speicifying its
|
||||
absolute path::
|
||||
|
|
@ -45,3 +46,7 @@ other configuration options are:
|
|||
set it to ``playlist`` to use the playlist's parent directory or to
|
||||
``library`` to use the library directory.
|
||||
Default: ``library``
|
||||
- **forward_slash**: Forces forward slashes in the generated playlist files.
|
||||
If you intend to use this plugin to generate playlists for MPD on
|
||||
Windows, set this to yes.
|
||||
Default: Use system separator.
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ Then configure your smart playlists like the following example::
|
|||
smartplaylist:
|
||||
relative_to: ~/Music
|
||||
playlist_dir: ~/.mpd/playlists
|
||||
forward_slash: no
|
||||
playlists:
|
||||
- name: all.m3u
|
||||
query: ''
|
||||
|
|
@ -96,3 +97,7 @@ other configuration options are:
|
|||
directory. If you intend to use this plugin to generate playlists for MPD,
|
||||
point this to your MPD music directory.
|
||||
Default: Use absolute paths.
|
||||
- **forward_slash**: Forces forward slashes in the generated playlist files.
|
||||
If you intend to use this plugin to generate playlists for MPD on
|
||||
Windows, set this to yes.
|
||||
Default: Use system separator.
|
||||
|
|
|
|||
|
|
@ -95,7 +95,9 @@ class MapDataToSchemeTest(unittest.TestCase):
|
|||
('danceable', 0.143928021193),
|
||||
('rhythm', 'VienneseWaltz'),
|
||||
('mood_electronic', 0.339881360531),
|
||||
('mood_happy', 0.0894767045975)
|
||||
('mood_happy', 0.0894767045975),
|
||||
('moods_mirex', "Cluster3"),
|
||||
('timbre', "bright")
|
||||
}
|
||||
self.assertEqual(mapping, expected)
|
||||
|
||||
|
|
|
|||
|
|
@ -195,6 +195,11 @@ class HelperTest(_common.TestCase):
|
|||
a = ['a', 'b', 'c']
|
||||
self.assertEqual(util.components(p), a)
|
||||
|
||||
def test_forward_slash(self):
|
||||
p = br'C:\a\b\c'
|
||||
a = br'C:/a/b/c'
|
||||
self.assertEqual(util.path_as_posix(p), a)
|
||||
|
||||
|
||||
class AlbumFileTest(_common.TestCase):
|
||||
def setUp(self):
|
||||
|
|
|
|||
Loading…
Reference in a new issue