Merge pull request #2211 from heylookltsme/better-genre

Proposal: Add specificity option to lastgenre plugin
This commit is contained in:
Adrian Sampson 2016-09-27 09:07:39 -04:00 committed by GitHub
commit 4ae02e0d27
2 changed files with 42 additions and 1 deletions

View file

@ -109,6 +109,7 @@ class LastGenrePlugin(plugins.BeetsPlugin):
'force': True,
'auto': True,
'separator': u', ',
'prefer_specific': False,
})
self.setup()
@ -158,6 +159,24 @@ class LastGenrePlugin(plugins.BeetsPlugin):
elif source == 'artist':
return 'artist',
def _get_depth(self, tag):
"""Find the depth of a tag in the genres tree.
"""
depth = None
for key, value in enumerate(self.c14n_branches):
if tag in value:
depth = value.index(tag)
break
return depth
def _sort_by_depth(self, tags):
"""Given a list of tags, sort the tags by their depths in the
genre tree.
"""
depth_tag_pairs = [(self._get_depth(t), t) for t in tags]
depth_tag_pairs.sort(reverse=True)
return [p[1] for p in depth_tag_pairs]
def _resolve_genres(self, tags):
"""Given a list of strings, return a genre by joining them into a
single string and (optionally) canonicalizing each.
@ -179,12 +198,19 @@ class LastGenrePlugin(plugins.BeetsPlugin):
parents = [find_parents(tag, self.c14n_branches)[-1]]
tags_all += parents
if len(tags_all) >= count:
# Stop if we have enough tags already, unless we need to find
# the most specific tag (instead of the most popular).
if (not self.config['prefer_specific'] and
len(tags_all) >= count):
break
tags = tags_all
tags = deduplicate(tags)
# Sort the tags by specificity.
if self.config['prefer_specific']:
tags = self._sort_by_depth(tags)
# c14n only adds allowed genres but we may have had forbidden genres in
# the original tags list
tags = [x.title() for x in tags if self._is_allowed(x)]

View file

@ -103,6 +103,19 @@ The plugin uses this weight to discard unpopular tags. The default is to
ignore tags with a weight less then 10. You can change this by setting
the ``min_weight`` config option.
Specific vs. Popular Genres
^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default, the plugin sorts genres by popularity. However, you can use the
``prefer_specific`` option to override this behavior and instead sort genres
by specificity, as determined by your whitelist and canonicalization tree.
For instance, say you have both ``folk`` and ``americana`` in your whitelist
and canonicalization tree and ``americana`` is a leaf within ``folk``. If
Last.fm returns both of those tags, lastgenre is going to use the most
popular, which is often the most generic (in this case ``folk``). By setting
``prefer_specific`` to true, lastgenre would use ``americana`` instead.
Configuration
-------------
@ -126,6 +139,8 @@ configuration file. The available options are:
Default: ``yes``.
- **min_weight**: Minimum popularity factor below which genres are discarded.
Default: 10.
- **prefer_specific**: Sort genres by the most to least specific, rather than
most to least popular. Default: ``no``.
- **source**: Which entity to look up in Last.fm. Can be
either ``artist``, ``album`` or ``track``.
Default: ``album``.