Discogs (and other individual plugins) should return a penalty between
0.0 and 0.1, which will be multiplied by the general source weight. This
allows individual plugins to be weighted against relative to each other,
and amplified together against other penalty categories (track, title,
etc.)
Some albums have a single disc with positions like I, II, III, IV, etc.
Previously beets thought each track on these albums was a new medium.
Now we assume that if there is no explicit medium index and the ordinal
of an alpha medium does not appear to be sequential (e.g. A, B, C) that
the medium is actually the medium index.
This is a refactor of the plugin developed by `imenem`.
- Pass `artist`, `album` and `va_likely` to `candidates()` so that
plugins don't have to work this out from `items` all over again.
- Pass `artist` and `title` to `item_candidates()`.
- Silence spurious `urllib3` info log lines.
- Use a proper "beets" user agent with `discogs_client`.
- Remove `abstract_search` plugin. It seems unnecessary. How many
music databases are there? How many will beets support? How much
common code might there be between them? We can add some abstraction
if or when more databases are supported.
- Derive more AlbumInfo and TrackInfo properties from discogs Release
objects, especially album ID so that beets doesn't just use the first
release and think all subsequent releases are duplicates.
- Add basic documentation, doc strings and code comments.
- Sanitise search query. Remove non-word characters and medium info that
might filter out good search results.
- Use artist `join` strings from discogs Release object when an album
or track has multiple artists.
- Don't rely on discogs track position, which is unreliable. But tracks
are in order, so we can recalculate medium and medium_index as long as
we can extract a consistent medium across tracks from the position.
- Add "various" as a known signal to indicate various artists.
- Prevent `chroma` plugin from returning a a huge track distance for any
track that is missing an ID (e.g. all discog tracks).
- `TrackInfo.index` should be the release index (calculated by beets),
not the medium index (derived from discogs track position).
- Add `AlbumInfo.data_source`. It's "Unknown" by default which is shown
in red when displaying a suggested or selected match. The built in
auto tagger sets it to "MusicBrainz" which is shown in green. Anything
else (e.g. "Discogs") is shown in yellow.
- Remove double spaces from album titles (bad data from Discogs).
This slight modification to the selection algorithm avoids the situation in
which too many objects are chosen for a given artist and fewer than N objects
are eventually returned. We do this by implementing "selection without
replacement" literally: we choose objects one at a time and pop them from the
population when they are selected.
The main change here, aside from documentation/naming updates, is that we skip
"duplicates" that arise from albums/tracks that are missing their MBIDs.
Add a 'fallback' option to facilitate working around the 100 queries/day google
limit by marking files as 'visited' so they are not considered for lyrics search
on the next beet run.
I've put my own google_engine_ID as default value in the code but could be
reconsidered, this engine contains databases known to be scrappable by the
plugin algorithm though.
The initial idea for this refactor was motivated by the need to make
PluginQuery.match() have the same method signature as the match() methods on
other queries. That is, it needed to take an *item*, not the pattern and
value. (The pattern is supplied when the query is constructed.) So it made
sense to move the value-to-pattern code to a class method.
But then I realized that all the other FieldQuery subclasses needed to do
essentially the same thing. So I eliminated PluginQuery altogether and
refactored FieldQuery to subsume its functionality. I then changed all the
other FieldQuery subclasses to conform to the same pattern.
This has the side effect of allowing different kinds of queries (even
non-field queries) down the road.
This turns on metadata-writing based on the import.write config option, so
those with this option turned off will be spared any surprises. (Affects #217
and #143.)
This avoids naming conflicts in the source directory. In particular, when
encoding MP3 -> MP3, the previous scheme would overwrite the original file
(and hang ffmpeg waiting for input). This should also work in
situations where the source directory is read-only.
I introduced a regression a few commits ago when I started using
lib.destination with the basedir keyword argument as opposed to doing
os.path.join manually.
The major functional change here is how files move around when in keep_new
mode. Now, files are first moved to the destination directory and then
copied/transcoded back into the library.
This avoids problems where naming conflicts could occur when transcoding from
MP3 to MP3 (and thus not changing the filename).