2015-03-19 13:21:53 +01:00
|
|
|
// Copyright 2015, David Howden
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package tag
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
type frameNames map[string][2]string
|
|
|
|
|
|
|
|
func (f frameNames) Name(s string, fm Format) string {
|
|
|
|
l, ok := f[s]
|
|
|
|
if !ok {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
switch fm {
|
|
|
|
case ID3v2_2:
|
|
|
|
return l[0]
|
|
|
|
case ID3v2_3, ID3v2_4:
|
|
|
|
return l[1]
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
var frames = frameNames(map[string][2]string{
|
|
|
|
"title": [2]string{"TT2", "TIT2"},
|
|
|
|
"artist": [2]string{"TP1", "TPE1"},
|
|
|
|
"album": [2]string{"TAL", "TALB"},
|
|
|
|
"album_artist": [2]string{"TP2", "TPE2"},
|
|
|
|
"composer": [2]string{"TCM", "TCOM"},
|
|
|
|
"year": [2]string{"TYE", "TYER"},
|
|
|
|
"track": [2]string{"TRK", "TRCK"},
|
|
|
|
"disc": [2]string{"TPA", "TPOS"},
|
|
|
|
"genre": [2]string{"TCO", "TCON"},
|
|
|
|
"picture": [2]string{"PIC", "APIC"},
|
2015-05-18 09:32:54 +02:00
|
|
|
"lyrics": [2]string{"", "USLT"},
|
2015-03-19 13:21:53 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
// metadataID3v2 is the implementation of Metadata used for ID3v2 tags.
|
|
|
|
type metadataID3v2 struct {
|
|
|
|
header *ID3v2Header
|
|
|
|
frames map[string]interface{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m metadataID3v2) getString(k string) string {
|
|
|
|
v, ok := m.frames[k]
|
|
|
|
if !ok {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return v.(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m metadataID3v2) getInt(k string) int {
|
|
|
|
v, ok := m.frames[k]
|
|
|
|
if !ok {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return v.(int)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m metadataID3v2) Format() Format { return m.header.Version }
|
|
|
|
func (m metadataID3v2) Raw() map[string]interface{} { return m.frames }
|
|
|
|
|
|
|
|
func (m metadataID3v2) Title() string {
|
|
|
|
return m.getString(frames.Name("title", m.Format()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m metadataID3v2) Artist() string {
|
|
|
|
return m.getString(frames.Name("artist", m.Format()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m metadataID3v2) Album() string {
|
|
|
|
return m.getString(frames.Name("album", m.Format()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m metadataID3v2) AlbumArtist() string {
|
|
|
|
return m.getString(frames.Name("album_artist", m.Format()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m metadataID3v2) Composer() string {
|
|
|
|
return m.getString(frames.Name("composer", m.Format()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m metadataID3v2) Genre() string {
|
|
|
|
return m.getString(frames.Name("genre", m.Format()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m metadataID3v2) Year() int {
|
|
|
|
year, _ := strconv.Atoi(m.getString(frames.Name("year", m.Format())))
|
|
|
|
return year
|
|
|
|
}
|
|
|
|
|
|
|
|
func parseXofN(s string) (x, n int) {
|
|
|
|
xn := strings.Split(s, "/")
|
|
|
|
if len(xn) != 2 {
|
|
|
|
x, _ = strconv.Atoi(s)
|
|
|
|
return x, 0
|
|
|
|
}
|
|
|
|
x, _ = strconv.Atoi(strings.TrimSpace(xn[0]))
|
|
|
|
n, _ = strconv.Atoi(strings.TrimSpace(xn[1]))
|
|
|
|
return x, n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m metadataID3v2) Track() (int, int) {
|
|
|
|
return parseXofN(m.getString(frames.Name("track", m.Format())))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m metadataID3v2) Disc() (int, int) {
|
|
|
|
return parseXofN(m.getString(frames.Name("disc", m.Format())))
|
|
|
|
}
|
|
|
|
|
2015-05-18 09:32:54 +02:00
|
|
|
func (m metadataID3v2) Lyrics() string {
|
|
|
|
t, ok := m.frames[frames.Name("lyrics", m.Format())]
|
|
|
|
if !ok {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return t.(*Comm).Text
|
|
|
|
}
|
|
|
|
|
2015-03-19 13:21:53 +01:00
|
|
|
func (m metadataID3v2) Picture() *Picture {
|
|
|
|
v, ok := m.frames[frames.Name("picture", m.Format())]
|
|
|
|
if !ok {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return v.(*Picture)
|
|
|
|
}
|