Distinguish between M4{A,B,P} formats.

Note: Removes tag.AAC.
This commit is contained in:
David Howden 2016-02-22 21:01:12 +11:00
parent 5b94194b29
commit a35ac09042
3 changed files with 37 additions and 17 deletions

16
id.go
View File

@ -26,8 +26,20 @@ func Identify(r io.ReadSeeker) (format Format, fileType FileType, err error) {
case string(b[0:4]) == "OggS":
return VORBIS, OGG, nil
case string(b[4:11]) == "ftypM4A":
return AAC, MP4, nil
case string(b[4:8]) == "ftyp":
b = b[8:11]
fileType = UnknownFileType
switch string(b) {
case "M4A":
fileType = M4A
case "M4B":
fileType = M4B
case "M4P":
fileType = M4P
}
return MP4, fileType, nil
case string(b[0:3]) == "ID3":
b := b[3:]

32
mp4.go
View File

@ -57,12 +57,18 @@ func (f atomNames) Name(n string) []string {
}
// metadataMP4 is the implementation of Metadata for MP4 tag (atom) data.
type metadataMP4 map[string]interface{}
type metadataMP4 struct {
fileType FileType
data map[string]interface{}
}
// ReadAtoms reads MP4 metadata atoms from the io.ReadSeeker into a Metadata, returning
// non-nil error if there was a problem.
func ReadAtoms(r io.ReadSeeker) (Metadata, error) {
m := make(metadataMP4)
m := metadataMP4{
data: make(map[string]interface{}),
fileType: UnknownFileType,
}
err := m.readAtoms(r)
return m, err
}
@ -137,8 +143,8 @@ func (m metadataMP4) readAtomData(r io.ReadSeeker, name string, size uint32) err
b = b[8:]
if name == "trkn" || name == "disk" {
m[name] = int(b[3])
m[name+"_count"] = int(b[5])
m.data[name] = int(b[3])
m.data[name+"_count"] = int(b[5])
return nil
}
@ -157,7 +163,7 @@ func (m metadataMP4) readAtomData(r io.ReadSeeker, name string, size uint32) err
Data: b,
}
}
m[name] = data
m.data[name] = data
return nil
}
@ -220,13 +226,13 @@ func readCustomAtom(r io.ReadSeeker, size uint32) (string, uint32, error) {
}
func (metadataMP4) Format() Format { return MP4 }
func (metadataMP4) FileType() FileType { return AAC }
func (m metadataMP4) FileType() FileType { return m.fileType }
func (m metadataMP4) Raw() map[string]interface{} { return m }
func (m metadataMP4) Raw() map[string]interface{} { return m.data }
func (m metadataMP4) getString(n []string) string {
for _, k := range n {
if x, ok := m[k]; ok {
if x, ok := m.data[k]; ok {
return x.(string)
}
}
@ -235,7 +241,7 @@ func (m metadataMP4) getString(n []string) string {
func (m metadataMP4) getInt(n []string) int {
for _, k := range n {
if x, ok := m[k]; ok {
if x, ok := m.data[k]; ok {
return x.(int)
}
}
@ -277,7 +283,7 @@ func (m metadataMP4) Year() int {
func (m metadataMP4) Track() (int, int) {
x := m.getInt([]string{"trkn"})
if n, ok := m["trkn_count"]; ok {
if n, ok := m.data["trkn_count"]; ok {
return x, n.(int)
}
return x, 0
@ -285,14 +291,14 @@ func (m metadataMP4) Track() (int, int) {
func (m metadataMP4) Disc() (int, int) {
x := m.getInt([]string{"disk"})
if n, ok := m["disk_count"]; ok {
if n, ok := m.data["disk_count"]; ok {
return x, n.(int)
}
return x, 0
}
func (m metadataMP4) Lyrics() string {
t, ok := m["\xa9lyr"]
t, ok := m.data["\xa9lyr"]
if !ok {
return ""
}
@ -300,7 +306,7 @@ func (m metadataMP4) Lyrics() string {
}
func (m metadataMP4) Picture() *Picture {
v, ok := m["covr"]
v, ok := m.data["covr"]
if !ok {
return nil
}

6
tag.go
View File

@ -73,7 +73,7 @@ const (
ID3v2_2 = "ID3v2.2" // ID3v2.2 tag format.
ID3v2_3 = "ID3v2.3" // ID3v2.3 tag format (most common).
ID3v2_4 = "ID3v2.4" // ID3v2.4 tag format.
MP4 = "MP4" // MP4 tag (atom) format.
MP4 = "MP4" // MP4 tag (atom) format (see http://www.ftyps.com/ for a full file type list)
VORBIS = "VORBIS" // Vorbis Comment tag format.
)
@ -86,7 +86,9 @@ type FileType string
const (
UnknownFileType FileType = "" // Unknown FileType.
MP3 = "MP3" // MP3 file
AAC = "AAC" // M4A file (MP4)
M4A = "M4A" // M4A file Apple iTunes (ACC) Audio
M4B = "M4B" // M4A file Apple iTunes (ACC) Audio Book
M4P = "M4P" // M4A file Apple iTunes (ACC) AES Protected Audio
ALAC = "ALAC" // Apple Lossless file FIXME: actually detect this
FLAC = "FLAC" // FLAC file
OGG = "OGG" // OGG file