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.
158 lines
2.8 KiB
158 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 |
|
}
|
|
|