Using CPG¶
CPG is a command line application and can be run by executing command cpg
.
Passing option -h
or --help
to CPG prints basic usage information:
$ cpg --help
Usage: cpg [OPTIONS] AUDIO_DIR PLAYLIST_FILE
[...]
Options:
-a, --absolute Output playlist with absolute paths.
-c, --config FILENAME Configuration file path.
-f, --format [m3u8|pls] Playlist format.
-r, --relative Output playlist with relative paths.
-h, --help Show this message and exit.
CPG expects two arguments. The first argument AUDIO_DIR
is a path to a
directory which will be recursively scanned for audio files. The second
argument PLAYLIST_FILE
will be used as the path of the generated playlist.
The command line interface supports specifying the output playlist’s file
format via options -f
and --format
. Whether the playlist should use
absolute or relative paths can be specified with options --absolute
or
--relative
and their respective short options. By default CPG generates
M3U8 playlists with relative paths.
Configuration File¶
CPG’s advanced features can only be configured through a configuration file.
Its path can be specified with options -c
and --config
. CPG supports
reading TOML configuration files. Details about the TOML file format’s syntax
can be found in its README.
# Example TOML configuration file for CPG.
[playlist]
format = "m3u8"
paths = "relative"
[tracks]
sort = [
["tracknumber", "discnumber"],
["tracknumber"],
]
[[tracks.blacklist."Album 1"]]
discnumber = "1"
tracknumber = "4"
[[tracks.blacklist."Album 2"]]
tracknumber = "5"
[groups]
tags = [
# ["album", "catalognumber"],
["album"],
]
fallback_name = "fallback"
[groups.split_tags]
"Album 1" = ["discnumber"]
"Album 2" = ["artist", "title"]
fallback = ["title"]
[[groups.separate."Album 3"]]
title = "Track title"
[[groups.separate."Album 3"]]
discnumber = "1"
tracknumber = "11"
[[groups.separate."Album 4"]]
discnumber = "2"
tracknumber = "9"
Table playlist
¶
[playlist]
format = "m3u8"
paths = "relative"
In the configuration file, table playlist
can contain keys format
and
paths
to specify the playlist format and paths, respectively. Valid values
for format
are m3u8
and pls
, valid values for paths
are
absolute
and relative
. CPG interprets the values of these keys in a
case insensitive manner.
Table groups
¶
When CPG finishes searching for audio files, it categorizes the found tracks
into groups. Groups are created based on the audio files’ tag information.
Categorizing tracks into groups is controled by keys in table groups
.
Tracks are first grouped together according to tags specified in key tags
.
tags
is a list of lists of tags.
[groups]
tags = [
["album", "catalognumber"],
["album"],
]
The above configuration snippet would cause CPG to first attempt to categorize
each track based on tags album
and catalognumber
. If a track has any
of these tags empty or unspecified, CPG attempts to categorize it with the next
list of tags – in this case only tag album
. The name of the resulting
group is a concatenation of each of the matched tags (in the same order as in
the configuration file). CPG supports an arbitrarily long list of arbitrarily
long lists of tags.
[groups]
fallback_name = "fallback"
If a track can’t be categorized by any of the tag lists described in the
previous paragraph (all lists get skipped because of a missing tag), the track
is assigned to a fallback group. The default fallback group name is
fallback
. The desired name can be assigned to key fallback_name
.
[groups.split_tags]
"Album 1" = ["discnumber"]
"Album 2" = ["artist", "title"]
fallback = ["title"]
CPG can be configured to further split the created groups of tracks in table
groups.split_tags
. The above configuration snippet would split Group
Album 1
based on the value of tag discnumber
. This means that if
Album 1
consisted of two discs, it would be split into two separate groups.
Group splitting can be performed using an arbitrary amount of tags, as shown in
the example with Album 2
. Tracks from group Album 2
would be split
into groups with unique combinations of artist
and title
tags. It’s
even possible to match the fallback group mentioned in the previous paragraph.
[[groups.separate."Album 3"]]
title = "Track title"
[[groups.separate."Album 3"]]
discnumber = "1"
tracknumber = "11"
[[groups.separate."Album 4"]]
discnumber = "2"
tracknumber = "9"
After spliting groups, CPG can separate specific tracks into a new group. This
can be configured by creating arrays of tables nested in table
groups.separate
. The table array names – in the above example Album 3
and Album 4
– are the names of the groups which should be matched. The
above example will first move tracks from Album 3
into a single new group.
Only tracks which match the tag criteria in the first or second table of the
array will be moved, though. A track matches a tag criteria when all keys and
values specified in a table match the track’s respective tags and tag values.
Then tracks from Album 4
will be moved into a different new group.
Again, only tracks which match the tag criteria will be moved.
After creating all groups CPG shuffles the groups so that they’re randomly ordered in the resulting playlist. This shuffling only affects the relative order of groups and doesn’t affect the order of tracks within each group.
Table track
¶
[tracks]
sort = [
["tracknumber", "discnumber"],
["tracknumber"],
]
Table tracks
controls track sorting and blacklisting. The value of key
sort
is a list of lists of tags for sorting groups of tracks. Track
sorting is performed after creating all groups, as described in section
Table groups. A group of tracks can be sorted according to a list of
tags when each track has all tags from the list non-empty. CPG sorts each
group of tracks according to the first such list of tags. In other words, a
group of tracks where all of them have tags tracknumber
and discnumber
non-empty would be sorted according to the first tag list of the above
configuration snippet. On the contrary, a group of tracks where some are
missing the discnumber
tag would be sorted according to the second list.
An arbitrarily long list of arbitrarily long lists of tags is supported. If no
tag list can be chosen for sorting, the group is left unsorted.
[[tracks.blacklist."Album 1"]]
discnumber = "1"
tracknumber = "4"
[[tracks.blacklist."Album 2"]]
tracknumber = "5"
Blacklisted tracks are removed from their groups immediately after assigning
tracks to groups but before any group splitting. Blacklists can be configured
by creating arrays of tables nested in table groups.blacklist
. The table
array names specify which group to blacklist tracks from, in the above example
from groups Album 1
and Album 2
. Narrowing down the choice of
blacklisted tracks is performed by specifying key value pairs in the tables.
Key value pairs correspond to track tag name and value pairs. A table without any
key value pair will blacklist the entire group.