refactor: decouple tag writers from deezer models
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
package tag
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-flac/flacpicture/v2"
|
||||
"github.com/go-flac/flacvorbis/v2"
|
||||
"github.com/go-flac/go-flac/v2"
|
||||
)
|
||||
|
||||
type flacTagger struct {
|
||||
file *flac.File
|
||||
cmts *flacvorbis.MetaDataBlockVorbisComment
|
||||
index int
|
||||
path string
|
||||
}
|
||||
|
||||
func (t *flacTagger) write(m Metadata) error {
|
||||
if m.Album != nil {
|
||||
date := m.Album.ReleaseDate
|
||||
if parts := strings.Split(date, "-"); len(parts) == 3 {
|
||||
date = parts[0]
|
||||
}
|
||||
|
||||
t.addTag("TRACKNUMBER", m.TrackNumber)
|
||||
t.addTag("ALBUMARTIST", m.Album.Artist)
|
||||
t.addTag("ALBUM", m.Album.Title)
|
||||
t.addTag("PUBLISHER", m.Album.Label)
|
||||
t.addTag("ORIGINALDATE", m.Album.OriginalReleaseDate)
|
||||
t.addTag("DATE", date)
|
||||
t.addTag("COMMENT", m.Album.ProducerLine)
|
||||
t.addTag("COPYRIGHT", m.Album.Copyright)
|
||||
}
|
||||
|
||||
t.addTag("ARTIST", m.Artists)
|
||||
t.addTag("TITLE", m.Title)
|
||||
t.addTag("COMPOSER", m.Composers)
|
||||
t.addTag("LYRICIST", m.Lyricists)
|
||||
t.addTag("GENRE", m.Genre)
|
||||
t.addTag("REPLAYGAIN_TRACK_GAIN", m.Gain)
|
||||
t.addTag("ISRC", m.ISRC)
|
||||
t.addTag("BPM", m.BPM)
|
||||
t.addTag("KEY", m.Key)
|
||||
t.addTag("INITIALKEY", m.Key)
|
||||
|
||||
cmtsMeta := t.cmts.Marshal()
|
||||
if t.index > 0 {
|
||||
t.file.Meta[t.index] = &cmtsMeta
|
||||
} else {
|
||||
t.file.Meta = append(t.file.Meta, &cmtsMeta)
|
||||
}
|
||||
|
||||
picture, err := flacpicture.NewFromImageData(flacpicture.PictureTypeFrontCover, "Front cover", m.Cover, "image/jpeg")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pictureMeta := picture.Marshal()
|
||||
t.file.Meta = append(t.file.Meta, &pictureMeta)
|
||||
|
||||
tmpPath := t.path + ".tmp"
|
||||
if err := t.file.Save(tmpPath); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmpPath, t.path)
|
||||
}
|
||||
|
||||
func (t *flacTagger) addTag(name, value string) {
|
||||
if value != "" {
|
||||
t.cmts.Add(name, value)
|
||||
}
|
||||
}
|
||||
|
||||
func extractFLACComment(file *flac.File) (*flacvorbis.MetaDataBlockVorbisComment, int) {
|
||||
for idx, meta := range file.Meta {
|
||||
if meta.Type == flac.VorbisComment {
|
||||
cmt, err := flacvorbis.ParseFromMetaDataBlock(*meta)
|
||||
if err == nil {
|
||||
return cmt, idx
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, 0
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package tag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/bogem/id3v2/v2"
|
||||
)
|
||||
|
||||
type id3v2Tagger struct {
|
||||
tag *id3v2.Tag
|
||||
}
|
||||
|
||||
func (t *id3v2Tagger) write(m Metadata) error {
|
||||
defer t.tag.Close()
|
||||
|
||||
duration, err := strconv.Atoi(m.Duration)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
length := fmt.Sprintf("%d", duration*1000)
|
||||
|
||||
if m.Album != nil {
|
||||
t.addTag("TRCK", m.TrackNumber)
|
||||
t.addTag("TPE2", m.Album.Artist)
|
||||
t.addTag("TALB", m.Album.Title)
|
||||
t.addTag("TPUB", m.Album.Label)
|
||||
t.addTag("TDOR", m.Album.OriginalReleaseDate)
|
||||
t.addTag("TYER", m.Album.ReleaseDate)
|
||||
t.addTag("COMM", m.Album.ProducerLine)
|
||||
t.addTag("TCOP", m.Album.Copyright)
|
||||
}
|
||||
|
||||
t.addTag("TPE1", m.Artists)
|
||||
t.addTag("TIT2", m.Title)
|
||||
t.addTag("TCOM", m.Composers)
|
||||
t.addTag("TEXT", m.Lyricists)
|
||||
t.addTag("TCON", m.Genre)
|
||||
t.addTag("TLEN", length)
|
||||
t.addTag("TBPM", m.BPM)
|
||||
t.addTag("TKEY", m.Key)
|
||||
t.addTXXX("GAIN", m.Gain)
|
||||
t.addTXXX("ISRC", m.ISRC)
|
||||
|
||||
t.tag.AddAttachedPicture(id3v2.PictureFrame{
|
||||
Encoding: t.tag.DefaultEncoding(),
|
||||
MimeType: "image/jpeg",
|
||||
PictureType: id3v2.PTFrontCover,
|
||||
Description: "Cover",
|
||||
Picture: m.Cover,
|
||||
})
|
||||
|
||||
return t.tag.Save()
|
||||
}
|
||||
|
||||
func (t *id3v2Tagger) addTag(name, value string) {
|
||||
if value != "" {
|
||||
t.tag.AddTextFrame(name, t.tag.DefaultEncoding(), value)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *id3v2Tagger) addTXXX(description, value string) {
|
||||
if value != "" {
|
||||
t.tag.AddUserDefinedTextFrame(id3v2.UserDefinedTextFrame{
|
||||
Encoding: t.tag.DefaultEncoding(),
|
||||
Description: description,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package tag
|
||||
|
||||
import (
|
||||
"path"
|
||||
|
||||
"github.com/bogem/id3v2/v2"
|
||||
"github.com/go-flac/flacvorbis/v2"
|
||||
"github.com/go-flac/go-flac/v2"
|
||||
)
|
||||
|
||||
type AlbumMetadata struct {
|
||||
Artist string
|
||||
Title string
|
||||
Label string
|
||||
OriginalReleaseDate string
|
||||
ReleaseDate string
|
||||
ProducerLine string
|
||||
Copyright string
|
||||
}
|
||||
|
||||
type Metadata struct {
|
||||
Title string
|
||||
Artists string
|
||||
Composers string
|
||||
Lyricists string
|
||||
Genre string
|
||||
BPM string
|
||||
Key string
|
||||
TrackNumber string
|
||||
Duration string
|
||||
Gain string
|
||||
ISRC string
|
||||
Cover []byte
|
||||
Album *AlbumMetadata
|
||||
}
|
||||
|
||||
type tagger interface {
|
||||
write(m Metadata) error
|
||||
}
|
||||
|
||||
func newTagger(filePath string) (tagger, error) {
|
||||
if path.Ext(filePath) == ".mp3" {
|
||||
tag, err := id3v2.Open(filePath, id3v2.Options{Parse: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &id3v2Tagger{tag: tag}, nil
|
||||
}
|
||||
|
||||
file, err := flac.ParseFile(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmts, idx := extractFLACComment(file)
|
||||
if cmts == nil {
|
||||
cmts = flacvorbis.New()
|
||||
}
|
||||
|
||||
return &flacTagger{file: file, cmts: cmts, index: idx, path: filePath}, nil
|
||||
}
|
||||
|
||||
func Write(filePath string, m Metadata) error {
|
||||
t, err := newTagger(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return t.write(m)
|
||||
}
|
||||
Reference in New Issue
Block a user