feat(scripts): analyze Rekordbox My Tags by user (102)
Why?
It's cool to see the distribution of tags by users of my Beatcloud.
What?
Group tracks in an XML by the part of the `Location` path that
corresponds with username, search the `Comments` field for the regex
matching `My Tags` data, counting the frequency of each tag, and then
plot histograms per user.
feat(scripts): move "My Tags" data around
Why?
Users would like the ability to do bulk edits to their "My Tags" data.
What?
An r/rekordbox user asked for a way to move "My Tag" data that encodes genre info into the `Genre` field.
I wanted to be able to sort my `Comments` field to sort by energy level, so I added the ability to move particular tags to the front of the `Comments` field.
feat(rekordbox): deprecate registered_users.yaml
Why?
Users shouldn't have to maintain a list of registered users. The whole
point of this file is to facilitate `Location` field manipulations as
part of `rewrite_xml` but, since the `Location` field has a hardcoded
substring of "DJ Music", we can infer all users' `USB_PATH`.
What?
Remove the usage of `registered_users.yaml`.
feat(sync): parameterize track title/artist order (105)
Why?
Some users may already have a collection stored in the `ARTIST_FIRST`
format. These users should still be able to use the `--check-tracks` and
`--playlist-from-upload` features without having to rename all their
files.
What?
Adds the `sync` package configuration option, `ARTIST_FIRST`, which has
Spotify API calls return tracks as `artist - track` instead of
`track - artist`. Additionally, when using with
`CHECK_TRACKS_LOCAL_DIRS`, Beatcloud tracks will have their filenames
temporarily reversed to be the opposite of however they're stored as in
order to facilitate `ARTIST_FIRST` comparison.
feat(version): add single source package version
Why?
A `__version__` variable and `--version` option should be available.
What?
Add a `version.py` module containing a `__version__` variable which is:
- used to setup the package
- exported from the `__init__` module
- printed with the `--version` option
refactor(configs): improve config print upon execution
Why?
Interpreting the config in the console is difficult.
What?
Override the `__repr__` method of `BaseConfig` to print only the
attributes of the sub-class. Format the representation with new lines
and indentations to improve readability.
feat(playlist_builder): Minimal Deep Tech logic (107)
Why?
The genre "Minimal Deep Tech" straddles "House" and "Techno". Users
should be able to control which tracks appear in that genre playlist
depending on some conditions.
What?
A prefix genre tag of "Techno" followed by "Minimal Deep Tech" controls
which tracks belong in playlists called "Minimal Deep Tech" with a parent
playlist called "Techno".
feat(playlist_builder): automatic pure playlists
Why?
Users should not have to configure the playlist builder to apply "pure"
playlist logic.
What?
Automatically find playlists prefixed with "Pure " and feed those
suffixes into the TagParser.
feat(playlist_builder): print ASCII histograms of tag statistics (109)
Why?
To quickly iterate on the proper Combiner playlist expressions, it would
be helpful if the CLI immediately output useful information to help
guide users in the right direction.
What?
Print simple ASCII tables for each TagParser implementation for each
playlist in the set of Combiner playlists generated in the run. Tables
show the frequency of each tag's apperance in each playlist. Tag
frequencies are scaled to a maximum value to constrain table heights.
TODO: Investigate vertical X-axis labels to constrain histogram width.
Investigate splitting histograms into chunks when there is a large
number of X-axis labels.
feat(collections): create collection abstractions
Why?
The `rekordbox` package offers many modules that are only useful to
Rekordbox users because they make assumptions about the structure of
collections, playlists, and tracks. Abstractions should be created for
these structures so that implementations can be made for different DJ
software platforms. This decouples the database (de)serialization logic
from the modules like the `PlaylistBuilder`.
What?
Rename the `rekordbox` package to `collection`. Create abstract classes
for Collection, Playlist, and Track. Implement these abstractions for the
Rekordbox use-case. Replace all Rekordbox-specific implementation
details in the `collection` package with the methods defined on the
abstractions. Add a configuration option for DJ software.
Renamed a bunch of the CLI args.
fix: More elegant music sync (116)
Why?
The carriage return prints made by `awscli` which contain information
about the amount of data and number of files transferred was getting
lost due to the use of `readline()` which splits on "\n" characters.
What?
Read stdout one character at a time so the carriage return data can be
displayed.
Also remove the usage of `shell=True` from all `Popen` calls.
refactor: CLI sub-commands (117)
Why?
The `--help` menu is verbose and hard to read.
What?
Break down all the CLI args into sub-commands based on the package they
pertain to.
refactor: Filter list args and parse JSON args
Why?
Previously, the `--spotify-playlist-subreddits` arg would accept YAML
strings and parse them into dictionaries. Formatting an arg as YAML is
annoying since whitespace matters. JSON is much easier to use.
Overriding list type args that have a default value was not possible
without editing the config that defines that default value.
What?
Revert `parse_yaml` back to `parse_json` for the
`--spotify-playlists-subreddits` argument.
Iterate parsed args and apply a `list(filter(None, ...` expression to
values that are an instance of `list`.