⬥ ID3 encoding/decoding library in Go ⬥
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

159 lines
2.8 KiB

package v2
import (
"fmt"
"io"
"github.com/Unbewohnte/id3ed/util"
)
type FrameFlags struct {
TagAlterPreservation bool
FileAlterPreservation bool
ReadOnly bool
Compressed bool
Encrypted bool
InGroup bool
}
type Frame struct {
ID string
Size int64
Flags FrameFlags
GroupByte byte
Contents []byte
}
// Reads ID3v2.3.0 or ID3v2.4.0 frame
func ReadFrame(rs io.Reader) (*Frame, error) {
var frame Frame
// ID
identifier, err := util.ReadToString(rs, 4)
if err != nil {
return nil, err
}
frame.ID = identifier
// Size
framesizeBytes, err := util.Read(rs, 4)
if err != nil {
return nil, err
}
framesize, err := util.BytesToIntIgnoreFirstBit(framesizeBytes)
if err != nil {
return nil, err
}
frame.Size = framesize
// Flags
frameFlagsByte1, err := util.Read(rs, 1)
if err != nil {
return nil, err
}
frameFlagsByte2, err := util.Read(rs, 1)
if err != nil {
return nil, err
}
// I don`t have enough knowledge to handle this more elegantly
// Any pointers ?
flagsByte1Bits := fmt.Sprintf("%08b", frameFlagsByte1)
flagsByte2Bits := fmt.Sprintf("%08b", frameFlagsByte2)
var flags FrameFlags
if flagsByte1Bits[0] == 1 {
flags.TagAlterPreservation = true
} else {
flags.TagAlterPreservation = false
}
if flagsByte1Bits[1] == 1 {
flags.FileAlterPreservation = true
} else {
flags.FileAlterPreservation = false
}
if flagsByte1Bits[2] == 1 {
flags.ReadOnly = true
} else {
flags.ReadOnly = false
}
if flagsByte2Bits[0] == 1 {
flags.Compressed = true
} else {
flags.Compressed = false
}
if flagsByte2Bits[1] == 1 {
flags.Encrypted = true
} else {
flags.Encrypted = false
}
if flagsByte2Bits[2] == 1 {
flags.InGroup = true
} else {
flags.InGroup = false
}
frame.Flags = flags
if flags.InGroup {
groupByte, err := util.Read(rs, 1)
if err != nil {
return nil, err
}
frame.GroupByte = groupByte[0]
}
// Body
frameContents, err := util.Read(rs, uint64(framesize))
if err != nil {
return nil, err
}
frame.Contents = frameContents
return &frame, nil
}
// Reads ID3v2 frames from rs. NOT TESTED !!!!
func GetFrames(rs io.ReadSeeker) ([]*Frame, error) {
header, err := GetHeader(rs)
if err != nil {
return nil, err
}
tagsize := header.Size
fmt.Println("NEED TO READ ", tagsize)
var frames []*Frame
var read uint64 = 0
for {
if read == uint64(tagsize) {
break
}
frame, err := ReadFrame(rs)
if err != nil {
return frames, fmt.Errorf("could not read frame: %s", err)
}
frames = append(frames, frame)
// counting how many bytes has been read
read += 10 // frame header
if frame.Flags.InGroup {
// header has 1 additional byte
read += 1
}
read += uint64(frame.Size) // and the contents itself
fmt.Println("Read: ", read, " ", frame.ID)
}
return frames, nil
}