// 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 // FLAC block types. const ( // Stream Info Block 0 // Padding Block 1 // Application Block 2 // Seektable Block 3 // Cue Sheet Block 5 vorbisCommentBlock blockType = 4 pictureBlock blockType = 6 ) // 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) { flac, err := readString(r, 4) if err != nil { return nil, err } if flac != "fLaC" { return nil, errors.New("expected 'fLaC'") } m := &metadataFLAC{ newMetadataVorbis(), } for { last, err := m.readFLACMetadataBlock(r) if err != nil { return nil, err } if last { break } } return m, nil } type metadataFLAC struct { *metadataVorbis } func (m *metadataFLAC) readFLACMetadataBlock(r io.ReadSeeker) (last bool, err error) { blockHeader, err := readBytes(r, 1) if err != nil { return } if getBit(blockHeader[0], 7) { blockHeader[0] ^= (1 << 7) last = true } blockLen, err := readInt(r, 3) if err != nil { return } switch blockType(blockHeader[0]) { case vorbisCommentBlock: err = m.readVorbisComment(r) case pictureBlock: err = m.readPictureBlock(r) default: _, err = r.Seek(int64(blockLen), os.SEEK_CUR) } return } func (m *metadataFLAC) FileType() FileType { return FLAC }