Add support for lyrics.
Not supported in id3v1 and id3v22
This commit is contained in:
parent
3c6f62d3e8
commit
0f62dc116a
4
flac.go
4
flac.go
@ -288,6 +288,10 @@ func (m *metadataFLAC) Disc() (int, int) {
|
||||
return x, n
|
||||
}
|
||||
|
||||
func (m *metadataFLAC) Lyrics() string {
|
||||
return m.c["lyrics"]
|
||||
}
|
||||
|
||||
func (m *metadataFLAC) Picture() *Picture {
|
||||
return m.p
|
||||
}
|
||||
|
1
id3v1.go
1
id3v1.go
@ -134,3 +134,4 @@ func (m metadataID3v1) AlbumArtist() string { return "" }
|
||||
func (m metadataID3v1) Composer() string { return "" }
|
||||
func (metadataID3v1) Disc() (int, int) { return 0, 0 }
|
||||
func (m metadataID3v1) Picture() *Picture { return nil }
|
||||
func (m metadataID3v1) Lyrics() string { return "" }
|
||||
|
7
id3v2.go
7
id3v2.go
@ -218,6 +218,13 @@ func readID3v2Frames(r io.Reader, h *ID3v2Header) (map[string]interface{}, error
|
||||
}
|
||||
result[rawName] = txt
|
||||
|
||||
case name == "COMM" || name == "USLT":
|
||||
t, err := readTextWithDescrFrame(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[rawName] = t
|
||||
|
||||
case name == "APIC":
|
||||
p, err := readAPICFrame(b)
|
||||
if err != nil {
|
||||
|
@ -81,6 +81,21 @@ func decodeUTF16(b []byte, bo binary.ByteOrder) string {
|
||||
return string(utf16.Decode(s))
|
||||
}
|
||||
|
||||
// Comm is a type used in COMM and USLT tag. It's a text with a description and
|
||||
// a specified language
|
||||
|
||||
type Comm struct {
|
||||
Language string
|
||||
Description string
|
||||
Text string
|
||||
}
|
||||
|
||||
// String returns a string representation of the underlying Comm instance.
|
||||
func (t Comm) String() string {
|
||||
return fmt.Sprintf("Text{Lang: '%v', Description: '%v', %v lines}",
|
||||
t.Language, t.Description, strings.Count(t.Text, "\n"))
|
||||
}
|
||||
|
||||
var pictureTypes = map[byte]string{
|
||||
0x00: "Other",
|
||||
0x01: "32x32 pixels 'file icon' (PNG only)",
|
||||
@ -158,6 +173,35 @@ func readPICFrame(b []byte) (*Picture, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// IDv2.{3,4}
|
||||
// -- Header
|
||||
// <Header for 'Unsynchronised lyrics/text transcription', ID: "USLT">
|
||||
// <Header for 'Comment', ID: "COMM">
|
||||
// -- readTextWithDescrFrame
|
||||
// Text encoding $xx
|
||||
// Language $xx xx xx
|
||||
// Content descriptor <text string according to encoding> $00 (00)
|
||||
// Lyrics/text <full text string according to encoding>
|
||||
func readTextWithDescrFrame(b []byte) (*Comm, error) {
|
||||
enc := b[0]
|
||||
descTextSplit := bytes.SplitN(b[4:], []byte{0}, 2)
|
||||
desc, err := decodeText(enc, descTextSplit[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding tag description text: %v", err)
|
||||
}
|
||||
|
||||
text, err := decodeText(enc, descTextSplit[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding tag description text: %v", err)
|
||||
}
|
||||
|
||||
return &Comm{
|
||||
Language: string(b[1:4]),
|
||||
Description: desc,
|
||||
Text: text,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// IDv2.{3,4}
|
||||
// -- Header
|
||||
// <Header for 'Attached picture', ID: "APIC">
|
||||
|
@ -37,6 +37,7 @@ var frames = frameNames(map[string][2]string{
|
||||
"disc": [2]string{"TPA", "TPOS"},
|
||||
"genre": [2]string{"TCO", "TCON"},
|
||||
"picture": [2]string{"PIC", "APIC"},
|
||||
"lyrics": [2]string{"", "USLT"},
|
||||
})
|
||||
|
||||
// metadataID3v2 is the implementation of Metadata used for ID3v2 tags.
|
||||
@ -112,6 +113,14 @@ func (m metadataID3v2) Disc() (int, int) {
|
||||
return parseXofN(m.getString(frames.Name("disc", m.Format())))
|
||||
}
|
||||
|
||||
func (m metadataID3v2) Lyrics() string {
|
||||
t, ok := m.frames[frames.Name("lyrics", m.Format())]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return t.(*Comm).Text
|
||||
}
|
||||
|
||||
func (m metadataID3v2) Picture() *Picture {
|
||||
v, ok := m.frames[frames.Name("picture", m.Format())]
|
||||
if !ok {
|
||||
|
8
mp4.go
8
mp4.go
@ -222,6 +222,14 @@ func (m metadataMP4) Disc() (int, int) {
|
||||
return x, 0
|
||||
}
|
||||
|
||||
func (m metadataMP4) Lyrics() string {
|
||||
t, ok := m["\xa9lyr"]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return t.(string)
|
||||
}
|
||||
|
||||
func (m metadataMP4) Picture() *Picture {
|
||||
v, ok := m["covr"]
|
||||
if !ok {
|
||||
|
5
tag.go
5
tag.go
@ -87,9 +87,12 @@ type Metadata interface {
|
||||
// Disc returns the disc number and total discs, or zero values if unavailable.
|
||||
Disc() (int, int)
|
||||
|
||||
// Picture returns a picture, or nil if not avilable.
|
||||
// Picture returns a picture, or nil if not available.
|
||||
Picture() *Picture
|
||||
|
||||
// Lyrics returns the lyrics, or an empty string if unavailable.
|
||||
Lyrics() string
|
||||
|
||||
// Raw returns the raw mapping of retrieved tag names and associated values.
|
||||
// NB: tag/atom names are not standardised between formats.
|
||||
Raw() map[string]interface{}
|
||||
|
Loading…
Reference in New Issue
Block a user