diff --git a/id.go b/id.go new file mode 100644 index 0000000..d967f17 --- /dev/null +++ b/id.go @@ -0,0 +1,70 @@ +package tag + +import ( + "fmt" + "io" + "os" +) + +// Identify reads from the given ReadSeaker and +func Identify(r io.ReadSeeker) (format Format, fileType FileType, err error) { + b, err := readBytes(r, 11) + if err != nil { + return + } + + _, err = r.Seek(-11, os.SEEK_CUR) + if err != nil { + err = fmt.Errorf("could not seek back to original position: %v", err) + return + } + + switch { + case string(b[0:4]) == "fLaC": + return VORBIS, FLAC, nil + + case string(b[0:4]) == "OggS": + return VORBIS, OGG, nil + + case string(b[4:11]) == "ftypM4A": + return AAC, MP4, nil + + case string(b[0:3]) == "ID3": + b := b[3:] + switch uint(b[0]) { + case 2: + format = ID3v2_2 + case 3: + format = ID3v2_3 + case 4: + format = ID3v2_4 + case 0, 1: + fallthrough + default: + err = fmt.Errorf("ID3 version: %v, expected: 2, 3 or 4", uint(b[0])) + return + } + return format, MP3, nil + } + + n, err := r.Seek(-128, os.SEEK_END) + if err != nil { + return + } + + tag, err := readString(r, 3) + if err != nil { + return + } + + _, err = r.Seek(-n, os.SEEK_CUR) + if err != nil { + return + } + + if tag != "TAG" { + err = ErrNoTagsFound + return + } + return ID3v1, MP3, nil +} diff --git a/tag.go b/tag.go index 1186725..dabfaee 100644 --- a/tag.go +++ b/tag.go @@ -68,12 +68,13 @@ type Format string // Supported tag formats. const ( - ID3v1 Format = "ID3v1" // ID3v1 tag format. - 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. - VORBIS = "VORBIS" // Vorbis Comment tag format. + UnknownFormat Format = "" // Unknown Format. + ID3v1 = "ID3v1" // ID3v1 tag format. + 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. + VORBIS = "VORBIS" // Vorbis Comment tag format. ) // FileType is an enumeration of the audio file types supported by this package, in particular @@ -83,11 +84,12 @@ type FileType string // Supported file types. const ( - MP3 FileType = "MP3" // MP3 file - AAC = "AAC" // M4A file (MP4) - ALAC = "ALAC" // Apple Lossless file FIXME: actually detect this - FLAC = "FLAC" // FLAC file - OGG = "OGG" // OGG file + UnknownFileType FileType = "" // Unknown FileType. + MP3 = "MP3" // MP3 file + AAC = "AAC" // M4A file (MP4) + ALAC = "ALAC" // Apple Lossless file FIXME: actually detect this + FLAC = "FLAC" // FLAC file + OGG = "OGG" // OGG file ) // Metadata is an interface which is used to describe metadata retrieved by this package.