mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-19 00:04:04 +01:00
Allow .txtp matching base files in !tags.m3u
This commit is contained in:
parent
709b897754
commit
c0f5a48aff
70
README.md
70
README.md
@ -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"
|
||||
```
|
||||
|
||||
|
||||
|
@ -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 == '#');
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user