2015-04-14 16:09:58 +02: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 (
|
|
|
|
"errors"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
)
|
|
|
|
|
|
|
|
// BlockType is a type which represents an enumeration of valid FLAC blocks
|
|
|
|
type BlockType byte
|
|
|
|
|
|
|
|
const (
|
|
|
|
StreamInfoBlock BlockType = 0
|
|
|
|
PaddingBlock = 1
|
|
|
|
ApplicationBlock = 2
|
|
|
|
SeektableBlock = 3
|
|
|
|
VorbisCommentBlock = 4 // Supported
|
|
|
|
CueSheetBlock = 5
|
|
|
|
PictureBlock = 6 // Supported
|
|
|
|
)
|
|
|
|
|
|
|
|
// ReadFLACTags reads FLAC metadata from the io.ReadSeeker, returning the resulting
|
|
|
|
// metadata in a Metadata implementation, or non-nil error if there was a problem.
|
|
|
|
func ReadFLACTags(r io.ReadSeeker) (Metadata, error) {
|
|
|
|
_, err := r.Seek(0, os.SEEK_SET)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
flac, err := readString(r, 4)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if flac != "fLaC" {
|
|
|
|
return nil, errors.New("expected 'fLaC'")
|
|
|
|
}
|
|
|
|
|
|
|
|
m := &metadataFLAC{
|
2015-05-24 02:44:45 +02:00
|
|
|
newMetadataVorbis(),
|
2015-04-14 16:09:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for {
|
|
|
|
last, err := m.readFLACMetadataBlock(r)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if last {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return m, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type metadataFLAC struct {
|
2015-05-24 02:44:45 +02:00
|
|
|
*metadataVorbis
|
2015-04-14 16:09:58 +02:00
|
|
|
}
|
|
|
|
|
2015-04-15 14:20:10 +02:00
|
|
|
func (m *metadataFLAC) readFLACMetadataBlock(r io.ReadSeeker) (last bool, err error) {
|
|
|
|
blockHeader, err := readBytes(r, 1)
|
2015-04-14 16:09:58 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if getBit(blockHeader[0], 7) {
|
|
|
|
blockHeader[0] ^= (1 << 7)
|
|
|
|
last = true
|
|
|
|
}
|
|
|
|
|
2015-04-15 14:20:10 +02:00
|
|
|
blockLen, err := readInt(r, 3)
|
2015-04-14 16:09:58 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-04-15 14:20:10 +02:00
|
|
|
switch BlockType(blockHeader[0]) {
|
|
|
|
case VorbisCommentBlock:
|
|
|
|
err = m.readVorbisComment(r)
|
2015-04-14 16:09:58 +02:00
|
|
|
|
2015-04-15 14:20:10 +02:00
|
|
|
case PictureBlock:
|
|
|
|
err = m.readPictureBlock(r)
|
2015-04-14 16:09:58 +02:00
|
|
|
|
2015-04-15 14:20:10 +02:00
|
|
|
default:
|
|
|
|
_, err = r.Seek(int64(blockLen), os.SEEK_CUR)
|
|
|
|
}
|
2015-04-14 16:09:58 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-05-24 02:44:45 +02:00
|
|
|
func (m *metadataFLAC) FileType() FileType {
|
2015-04-14 16:09:58 +02:00
|
|
|
return FLAC
|
|
|
|
}
|