Allow .txtp matching base files in !tags.m3u

This commit is contained in:
bnnm 2020-08-22 13:39:48 +02:00
parent 709b897754
commit c0f5a48aff
2 changed files with 87 additions and 29 deletions

View File

@ -329,9 +329,9 @@ filename2
```
Accepted tags depend on the player (foobar: any; winamp: see ATF config),
typically *ALBUM/ARTIST/TITLE/DISC/TRACK/COMPOSER/etc*, lower or uppercase,
separated by one or multiple spaces. Repeated tags overwrite previous
(ex.- may define *@COMPOSER* for multiple tracks). It only reads up to current
*filename* though, so any *@TAG* below would be ignored.
separated by one or multiple spaces. Repeated tags overwrite previous (ex.-
may define *@COMPOSER* multiple times for "sections"). It only reads up to
current *filename* though, so any *@TAG* below would be ignored.
Playlist title formatting should follow player's config. ASCII or UTF-8 tags work.
@ -339,7 +339,16 @@ Playlist title formatting should follow player's config. ASCII or UTF-8 tags wor
- *AUTOTRACK*: sets *%TRACK* tag automatically (1..N as files are encountered
in the tag file).
- *AUTOALBUM*: sets *%ALBUM* tag automatically using the containing dir as album.
- *EXACTMATCH*: disables matching .txtp with regular files (explained below).
Note that with global tags you don't need to put all files inside. This would be
a perfectly valid *!tags.m3u*:
```
# @ALBUM Game
# @ARTIST Various Artists
```
### Tags with spaces
Some players like foobar accept tags with spaces. To use them surround the tag
with both characters.
```
@ -350,13 +359,7 @@ filename1
```
As a side effect if text has @/% inside you also need them: `# @ALBUMARTIST@ Tom-H@ck`
Note that since you can use global tags don't need to put all files inside.
This would be a perfectly valid *!tags.m3u*:
```
# @ALBUM Game
# @ARTIST Various Artists
```
### ReplayGain
foobar2000/Winamp can apply the following replaygain tags (if ReplayGain is
enabled in preferences):
```
@ -365,7 +368,48 @@ enabled in preferences):
# @replaygain_album_gain N.NN dB
# @replaygain_album_peak N.NNN
```
### TXTP matching
To ease *TXTP* config, tags with plain files will match .txtp with config, and tags
with .txtp config also match plain files:
**!tags.m3u**
```
# @TITLE Title1
BGM01.adx #P 3.0.txtp
# @TITLE Title2
BGM02.wav
```
**config.m3u**
```
# matches "Title1" (1:1)
BGM01.adx #P 3.0.txtp
# matches "Title1" (plain file matches config tag)
BGM01.adx
# matches "Title2" (config file matches plain tag)
BGM02.wav #P 3.0.txtp
# doesn't match anything (different config can't match)
BGM01.adx #P 10.0.txtp
```
Since it matches when a tag is found, some cases that depend on order won't work.
You can disable this feature manually then:
**!tags.m3u**
```
# $EXACTMATCH
#
# %TITLE Title3 (without config)
BGM01.adx
# %TITLE Title3 (with config)
BGM01.adx #I 1.0 90.0 .txtp
```
**config.m3u**
```
# Would match "Title3 (without config)" without "$EXACTMATCH", as it's found first
# Could use "BGM01.adx.txtp" as first entry in !tags.m3u instead (different configs won't match)
BGM01.adx #I 1.0 90.0 .txtp
```
### Issues
If your player isn't picking tags make sure vgmstream is detecting the song
(as other plugins can steal its extensions, see above), .m3u is properly
named and that filenames inside match the song filename. For Winamp you need
@ -378,7 +422,7 @@ Currently there is no tool to aid in the creation of there m3u, but you can crea
a base m3u and edit as a text file.
vgmstream's "m3u tagging" is meant to be simple to make and share (just a text
file), easier to support in multiple players (rather than needed a custom plugin),
file), easier to support in multiple players (rather than needing a custom plugin),
having OST-like ordering in the M3U, and be flexible enough to have commands.
If you are not satisfied with vgmstream's tagging format, foobar2000 has other
plugins (with write support) that may be of use:
@ -420,8 +464,8 @@ boss2_3ningumi_ver6.adx #l 1.0 #F .txtp
You can also use it in CLI for quick access to some txtp-exclusive functions:
```
# force change sample rate to 22050
test.exe btl_koopa1_44k_lp.brstm #h22050.txtp -o btl_koopa1_44k_lp.wav
# force change sample rate to 22050 (don't forget to use " with spaces)
test.exe -o btl_koopa1_44k_lp.wav "btl_koopa1_44k_lp.brstm #h22050.txtp"
```

View File

@ -189,6 +189,7 @@ struct VGMSTREAM_TAGS {
int autotrack_on;
int autotrack_written;
int track_count;
int exact_match;
int autoalbum_on;
int autoalbum_written;
@ -311,22 +312,27 @@ int vgmstream_tags_next_tag(VGMSTREAM_TAGS* tags, STREAMFILE* tagfile) {
if (line[0] == '#') {
/* find possible global command */
ok = sscanf(line, "# $%[^ \t] %[^\r\n]", tags->key,tags->val);
ok = sscanf(line, "# $%n%[^ \t]%n %[^\r\n]", &n1, tags->key, &n2, tags->val);
if (ok == 1 || ok == 2) {
if (strcasecmp(tags->key,"AUTOTRACK") == 0) {
int key_len = n2 - n1;
if (strncasecmp(tags->key, "AUTOTRACK", key_len) == 0) {
tags->autotrack_on = 1;
}
else if (strcasecmp(tags->key,"AUTOALBUM") == 0) {
else if (strncasecmp(tags->key, "AUTOALBUM", key_len) == 0) {
tags->autoalbum_on = 1;
}
else if (strncasecmp(tags->key, "EXACTMATCH", key_len) == 0) {
tags->exact_match = 1;
VGM_LOG("exact\n");
}
continue; /* not an actual tag */
}
/* find possible global tag */
ok = sscanf(line, "# @%[^@]@ %[^\r\n]", tags->key,tags->val); /* key with spaces */
ok = sscanf(line, "# @%[^@]@ %[^\r\n]", tags->key, tags->val); /* key with spaces */
if (ok != 2)
ok = sscanf(line, "# @%[^ \t] %[^\r\n]", tags->key,tags->val); /* key without */
ok = sscanf(line, "# @%[^ \t] %[^\r\n]", tags->key, tags->val); /* key without */
if (ok == 2) {
tags_clean(tags);
return 1;
@ -342,20 +348,28 @@ int vgmstream_tags_next_tag(VGMSTREAM_TAGS* tags, STREAMFILE* tagfile) {
int currentname_len = n2 - n1;
int filename_found = 0;
/* we want to find file with the same name (case insensitive), OR a virtual .txtp with
* the filename inside (so 'file.adx' gets tags from 'file.adx#i.txtp', reading
* tags even if we don't open !tags.m3u with virtual .txtp directly) */
/* we want to match file with the same name (case insensitive), OR a virtual .txtp with
* the filename inside to ease creation of tag files with config, also check end char to
* tell apart the unlikely case of having both 'bgm01.ad.txtp' and 'bgm01.adp.txtp' */
/* strcasecmp works ok even for UTF-8 */
if (currentname_len >= tags->targetname_len && /* starts with targetname */
strncasecmp(currentname, tags->targetname, tags->targetname_len) == 0) {
if (currentname_len == tags->targetname_len) { /* exact match */
filename_found = 1;
/* try exact match (strcasecmp works ok even for UTF-8) */
if (currentname_len == tags->targetname_len &&
strncasecmp(currentname, tags->targetname, currentname_len) == 0) {
filename_found = 1;
}
else if (!tags->exact_match) {
/* try tagfile is "bgm.adx" + target is "bgm.adx #(cfg) .txtp" */
if (currentname_len < tags->targetname_len &&
strncasecmp(currentname, tags->targetname, currentname_len) == 0 &&
vgmstream_is_virtual_filename(tags->targetname)) {
char c = tags->targetname[currentname_len];
filename_found = (c==' ' || c == '.' || c == '#');
}
else if (vgmstream_is_virtual_filename(currentname)) { /* ends with .txth */
/* tagfile has "bgm.adx (...) .txtp" + target has "bgm.adx" */
else if (tags->targetname_len < currentname_len &&
strncasecmp(tags->targetname, currentname, tags->targetname_len) == 0 &&
vgmstream_is_virtual_filename(currentname)) {
char c = currentname[tags->targetname_len];
/* tell apart the unlikely case of having both 'bgm01.ad.txtp' and 'bgm01.adp.txtp' */
filename_found = (c==' ' || c == '.' || c == '#');
}
}