Skip to content

Commit 4ce85b3

Browse files
committed
refactor(tag): split into tag/normtag
1 parent d759d9b commit 4ce85b3

File tree

11 files changed

+327
-284
lines changed

11 files changed

+327
-284
lines changed

addon/lyrics/lyrics.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"go.senan.xyz/wrtag/addon"
1212
"go.senan.xyz/wrtag/lyrics"
1313
"go.senan.xyz/wrtag/tags"
14+
"go.senan.xyz/wrtag/tags/normtag"
1415
)
1516

1617
func init() {
@@ -52,14 +53,18 @@ func (l LyricsAddon) ProcessRelease(ctx context.Context, paths []string) error {
5253
if err != nil {
5354
return fmt.Errorf("read first: %w", err)
5455
}
55-
if t.Get(tags.Lyrics) != "" {
56+
if normtag.Get(t, normtag.Lyrics) != "" {
5657
return nil
5758
}
58-
lyricData, err := l.source.Search(ctx, t.Get(tags.ArtistCredit), t.Get(tags.Title))
59+
lyricData, err := l.source.Search(ctx, normtag.Get(t, normtag.ArtistCredit), normtag.Get(t, normtag.Title))
5960
if err != nil && !errors.Is(err, lyrics.ErrLyricsNotFound) {
6061
return err
6162
}
62-
if err := tags.WriteTags(path, tags.NewTags(tags.Lyrics, lyricData), 0); err != nil {
63+
64+
lt := map[string][]string{}
65+
normtag.Set(lt, normtag.Lyrics, lyricData)
66+
67+
if err := tags.WriteTags(path, lt, 0); err != nil {
6368
return fmt.Errorf("write new lyrics: %w", err)
6469
}
6570
return nil

addon/musicdesc/musicdesc.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"go.senan.xyz/wrtag/addon"
1414
"go.senan.xyz/wrtag/essentia"
1515
"go.senan.xyz/wrtag/tags"
16+
"go.senan.xyz/wrtag/tags/normtag"
1617
)
1718

1819
func init() {
@@ -53,7 +54,7 @@ func (a MusicDescAddon) ProcessRelease(ctx context.Context, paths []string) erro
5354
if err != nil {
5455
return fmt.Errorf("read first file: %w", err)
5556
}
56-
if first.Get(tags.BPM) != "" && first.Get(tags.Key) != "" {
57+
if normtag.Get(first, normtag.BPM) != "" && normtag.Get(first, normtag.Key) != "" {
5758
return nil
5859
}
5960
}
@@ -73,10 +74,10 @@ func (a MusicDescAddon) ProcessRelease(ctx context.Context, paths []string) erro
7374
return fmt.Errorf("read essentia: %w", err)
7475
}
7576

76-
t := tags.NewTags(
77-
tags.BPM, fmtBPM(info.Rhythm.BPM),
78-
tags.Key, fmtKey(info.Tonal.KeyKey, info.Tonal.KeyScale),
79-
)
77+
t := map[string][]string{}
78+
normtag.Set(t, normtag.BPM, fmtBPM(info.Rhythm.BPM))
79+
normtag.Set(t, normtag.Key, fmtKey(info.Tonal.KeyKey, info.Tonal.KeyScale))
80+
8081
if err := tags.WriteTags(path, t, 0); err != nil {
8182
return fmt.Errorf("write new tags: %w", err)
8283
}

addon/replaygain/replaygain.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"go.senan.xyz/wrtag/addon"
1212
"go.senan.xyz/wrtag/rsgain"
1313
"go.senan.xyz/wrtag/tags"
14+
"go.senan.xyz/wrtag/tags/normtag"
1415
)
1516

1617
func init() {
@@ -54,7 +55,7 @@ func (a ReplayGainAddon) ProcessRelease(ctx context.Context, paths []string) err
5455
if err != nil {
5556
return fmt.Errorf("read first file: %w", err)
5657
}
57-
if first.Get(tags.ReplayGainTrackGain) != "" {
58+
if normtag.Get(first, normtag.ReplayGainTrackGain) != "" {
5859
return nil
5960
}
6061
}
@@ -68,12 +69,12 @@ func (a ReplayGainAddon) ProcessRelease(ctx context.Context, paths []string) err
6869
for i := range paths {
6970
pathL, path := pathLevs[i], paths[i]
7071

71-
t := tags.NewTags(
72-
tags.ReplayGainTrackGain, fmtdB(pathL.GaindB),
73-
tags.ReplayGainTrackPeak, fmtFloat(pathL.Peak, 6),
74-
tags.ReplayGainAlbumGain, fmtdB(albumLev.GaindB),
75-
tags.ReplayGainAlbumPeak, fmtFloat(albumLev.Peak, 6),
76-
)
72+
t := map[string][]string{}
73+
normtag.Set(t, normtag.ReplayGainTrackGain, fmtdB(pathL.GaindB))
74+
normtag.Set(t, normtag.ReplayGainTrackPeak, fmtFloat(pathL.Peak, 6))
75+
normtag.Set(t, normtag.ReplayGainAlbumGain, fmtdB(albumLev.GaindB))
76+
normtag.Set(t, normtag.ReplayGainAlbumPeak, fmtFloat(albumLev.Peak, 6))
77+
7778
if err := tags.WriteTags(path, t, 0); err != nil {
7879
pathErrs = append(pathErrs, err)
7980
continue

cmd/metadata/main.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
"go.senan.xyz/wrtag/cmd/internal/wrtaglog"
1818
"go.senan.xyz/wrtag/tags"
19+
"go.senan.xyz/wrtag/tags/normtag"
1920
)
2021

2122
func init() {
@@ -110,8 +111,8 @@ func cmdRead(to io.Writer, path string, withProperties bool, keys []string) erro
110111
}
111112
} else {
112113
for _, k := range keys {
113-
for _, v := range t.Values(k) {
114-
fmt.Fprintf(to, "%s\t%s\t%s\n", path, tags.NormKey(k), v)
114+
for _, v := range normtag.Values(t, k) {
115+
fmt.Fprintf(to, "%s\t%s\t%s\n", path, normtag.NormKey(k), v)
115116
}
116117
}
117118
}
@@ -152,9 +153,9 @@ func cmdRead(to io.Writer, path string, withProperties bool, keys []string) erro
152153
}
153154

154155
func cmdWrite(path string, keyValues map[string][]string) error {
155-
var t = tags.Tags{}
156+
var t = map[string][]string{}
156157
for k, vs := range keyValues {
157-
t.Set(k, vs...)
158+
normtag.Set(t, k, vs...)
158159
}
159160
if err := tags.WriteTags(path, t, 0); err != nil {
160161
return fmt.Errorf("save: %w", err)
@@ -164,14 +165,14 @@ func cmdWrite(path string, keyValues map[string][]string) error {
164165

165166
func cmdClear(path string, keys []string) error {
166167
if len(keys) == 0 {
167-
if err := tags.WriteTags(path, tags.Tags{}, tags.Clear); err != nil {
168+
if err := tags.WriteTags(path, map[string][]string{}, tags.Clear); err != nil {
168169
return err
169170
}
170171
return nil
171172
}
172-
var t = tags.Tags{}
173+
var t = map[string][]string{}
173174
for _, k := range keys {
174-
t.Set(k)
175+
normtag.Set(t, k)
175176
}
176177
if err := tags.WriteTags(path, t, 0); err != nil {
177178
return err

cmd/wrtag/main_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/rogpeppe/go-internal/testscript"
2121
"go.senan.xyz/wrtag/fileutil"
2222
"go.senan.xyz/wrtag/tags"
23+
"go.senan.xyz/wrtag/tags/normtag"
2324
)
2425

2526
//go:embed testdata/responses
@@ -81,9 +82,9 @@ func mainTag() {
8182
if err := ensureAudioFile(p); err != nil {
8283
log.Fatalf("ensure flac: %v", err)
8384
}
84-
var t = tags.Tags{}
85+
var t = map[string][]string{}
8586
for k, vs := range pairs {
86-
t.Set(k, vs...)
87+
normtag.Set(t, k, vs...)
8788
}
8889
if err := tags.WriteTags(p, t, 0); err != nil {
8990
log.Fatalf("write tag file: %v", err)
@@ -94,7 +95,7 @@ func mainTag() {
9495
log.Fatalf("read tags: %v", err)
9596
}
9697
for k, vs := range pairs {
97-
if got := t.Values(k); !slices.Equal(vs, got) {
98+
if got := normtag.Values(t, k); !slices.Equal(vs, got) {
9899
log.Printf("%s exp %q got %q", p, vs, got)
99100
exit = 1
100101
}
Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ import (
1616

1717
func main() {
1818
flag.Parse()
19-
inPath, outPath := flag.Arg(0), flag.Arg(1)
19+
outPath := flag.Arg(0)
20+
21+
inPath := mustEnv("GOFILE")
22+
pkg := mustEnv("GOPACKAGE")
2023

2124
inFile, err := os.Open(inPath)
2225
cerr(err)
@@ -74,7 +77,7 @@ L:
7477
defer outFile.Close()
7578

7679
fmt.Fprintf(outFile, "// Code generated by %s. DO NOT EDIT.\n", filepath.Base(os.Args[0]))
77-
fmt.Fprintf(outFile, "package tags\n")
80+
fmt.Fprintf(outFile, "package %s\n", pkg)
7881
fmt.Fprintf(outFile, "var knownTags = map[string]struct{}{\n")
7982
for _, key := range tagKeys {
8083
fmt.Fprintf(outFile, "\t%q: {},\n", key)
@@ -95,6 +98,14 @@ L:
9598
fmt.Fprintf(outFile, "}\n")
9699
}
97100

101+
func mustEnv(k string) string {
102+
if v := os.Getenv(k); v != "" {
103+
return v
104+
}
105+
cerr(fmt.Errorf("please provde a %s", k))
106+
return ""
107+
}
108+
98109
func cerr(err error) {
99110
if err != nil {
100111
panic(err)

tags/normtag/normtag.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package normtag
2+
3+
import (
4+
"maps"
5+
"strings"
6+
)
7+
8+
// https://taglib.org/api/p_propertymapping.html
9+
// https://picard-docs.musicbrainz.org/downloads/MusicBrainz_Picard_Tag_Map.html
10+
11+
//go:generate go run gen_taglist.go -- taglist.go
12+
//nolint:gosec
13+
const (
14+
Album = "ALBUM"
15+
AlbumArtist = "ALBUMARTIST" //tag: alts "ALBUM_ARTIST"
16+
AlbumArtists = "ALBUMARTISTS" //tag: alts "ALBUM_ARTISTS"
17+
AlbumArtistCredit = "ALBUMARTIST_CREDIT" //tag: alts "ALBUM_ARTIST_CREDIT"
18+
AlbumArtistsCredit = "ALBUMARTISTS_CREDIT" //tag: alts "ALBUM_ARTISTS_CREDIT"
19+
Date = "DATE" //tag: alts "YEAR" "RELEASEDATE"
20+
OriginalDate = "ORIGINALDATE" //tag: alts "ORIGINAL_YEAR"
21+
MediaFormat = "MEDIA"
22+
Label = "LABEL"
23+
CatalogueNum = "CATALOGNUMBER" //tag: alts "CATALOGNUM" "CAT#" "CATALOGID" "CATNUM"
24+
Barcode = "BARCODE" //tag: alts "UPC" "MCN"
25+
Compilation = "COMPILATION"
26+
ReleaseType = "RELEASETYPE"
27+
28+
MusicBrainzReleaseID = "MUSICBRAINZ_ALBUMID"
29+
MusicBrainzReleaseGroupID = "MUSICBRAINZ_RELEASEGROUPID"
30+
MusicBrainzAlbumArtistID = "MUSICBRAINZ_ALBUMARTISTID"
31+
MusicBrainzAlbumComment = "MUSICBRAINZ_ALBUMCOMMENT"
32+
33+
Title = "TITLE"
34+
Artist = "ARTIST"
35+
Artists = "ARTISTS"
36+
ArtistCredit = "ARTIST_CREDIT" //tag: alts "ARTISTCREDIT"
37+
ArtistsCredit = "ARTISTS_CREDIT" //tag: alts "ARTISTSCREDIT"
38+
Genre = "GENRE"
39+
Genres = "GENRES"
40+
TrackNumber = "TRACKNUMBER" //tag: alts "TRACK" "TRACKNUM"
41+
DiscNumber = "DISCNUMBER"
42+
43+
ISRC = "ISRC"
44+
45+
Remixer = "REMIXER"
46+
Remixers = "REMIXERS"
47+
RemixerCredit = "REMIXER_CREDIT"
48+
RemixersCredit = "REMIXERS_CREDIT"
49+
50+
Composer = "COMPOSER"
51+
Composers = "COMPOSERS"
52+
ComposerCredit = "COMPOSER_CREDIT"
53+
ComposersCredit = "COMPOSERS_CREDIT"
54+
55+
MusicBrainzRecordingID = "MUSICBRAINZ_TRACKID"
56+
MusicBrainzTrackID = "MUSICBRAINZ_RELEASETRACKID"
57+
MusicBrainzArtistID = "MUSICBRAINZ_ARTISTID"
58+
59+
ReplayGainTrackGain = "REPLAYGAIN_TRACK_GAIN"
60+
ReplayGainTrackPeak = "REPLAYGAIN_TRACK_PEAK"
61+
ReplayGainAlbumGain = "REPLAYGAIN_ALBUM_GAIN"
62+
ReplayGainAlbumPeak = "REPLAYGAIN_ALBUM_PEAK"
63+
ReplayGainTrackRange = "REPLAYGAIN_TRACK_RANGE"
64+
ReplayGainAlbumRange = "REPLAYGAIN_ALBUM_RANGE"
65+
ReplayGainReferenceLoudness = "REPLAYGAIN_REFERENCE_LOUDNESS"
66+
67+
BPM = "BPM"
68+
Key = "INITIALKEY" //tag: alts "INITIAL_KEY"
69+
70+
Lyrics = "LYRICS" //tag: alts "LYRICS:DESCRIPTION" "USLT:DESCRIPTION" "©LYR"
71+
72+
AcoustIDFingerprint = "ACOUSTID_FINGERPRINT"
73+
AcoustIDID = "ACOUSTID_ID"
74+
75+
Encoder = "ENCODER"
76+
EncodedBy = "ENCODEDBY"
77+
78+
Comment = "COMMENT"
79+
)
80+
81+
func Set(t map[string][]string, key string, values ...string) {
82+
normKey := NormKey(key)
83+
84+
// remove any existing alternative keys that would normalize to the same key
85+
for k := range t {
86+
if k != normKey && NormKey(k) == normKey {
87+
delete(t, k)
88+
}
89+
}
90+
91+
t[normKey] = values
92+
}
93+
94+
func Get(t map[string][]string, key string) string {
95+
normKey := NormKey(key)
96+
if vs := t[normKey]; len(vs) > 0 {
97+
return vs[0]
98+
}
99+
if altKey := altKey(t, normKey); altKey != "" {
100+
if vs := t[altKey]; len(vs) > 0 {
101+
return vs[0]
102+
}
103+
}
104+
return ""
105+
}
106+
107+
func Values(t map[string][]string, key string) []string {
108+
normKey := NormKey(key)
109+
110+
if vs := t[normKey]; vs != nil {
111+
return vs
112+
}
113+
if altKey := altKey(t, normKey); altKey != "" {
114+
return t[altKey]
115+
}
116+
return nil
117+
}
118+
119+
func NormKey(k string) string {
120+
k = strings.ToUpper(k)
121+
if nk, ok := alternatives[k]; ok {
122+
return nk
123+
}
124+
return k
125+
}
126+
127+
func KnownTags() map[string]struct{} {
128+
return maps.Clone(knownTags)
129+
}
130+
131+
func altKey(t map[string][]string, key string) string {
132+
for rawKey := range t {
133+
if NormKey(rawKey) == key {
134+
return rawKey
135+
}
136+
}
137+
return ""
138+
}
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)