Browse Source

❮ Looks like it can read Frames now. Also utils are looking neat! ❯

main
Unbewohnte 3 years ago
parent
commit
d730be2ce4
  1. BIN
      testData/testwritev1.mp3
  2. 26
      util/conversion.go
  3. 13
      util/conversion_test.go
  4. 12
      util/maps.go
  5. 26
      util/read.go
  6. 10
      v1/id3v10.go
  7. 10
      v1/id3v11.go
  8. 88
      v2/frame.go
  9. 23
      v2/frame_test.go

BIN
testData/testwritev1.mp3

Binary file not shown.

26
util/etc.go → util/conversion.go

@ -5,19 +5,9 @@ import (
"encoding/binary"
"fmt"
"strconv"
"strings"
)
// Returns found key (int) in provided map by value (string);
// If key does not exist in map - returns -1
func GetKey(mp map[int]string, givenValue string) int {
for key, value := range mp {
if value == givenValue {
return key
}
}
return -1
}
// Decodes given integer bytes into integer
func BytesToInt(gBytes []byte) (int64, error) {
buff := bytes.NewBuffer(gBytes)
@ -49,3 +39,17 @@ func BytesToIntIgnoreFirstBit(gBytes []byte) (int64, error) {
return integer, nil
}
// Converts given bytes into string, ignoring the first 31 non-printable ASCII characters.
// (LOSSY, if given bytes contain some nasty ones)
func ToString(gBytes []byte) string {
var filteredBytes []byte
for _, b := range gBytes {
if b <= 31 {
continue
}
filteredBytes = append(filteredBytes, b)
}
return strings.ToValidUTF8(string(filteredBytes), "")
}

13
util/conversion_test.go

@ -0,0 +1,13 @@
package util
import "testing"
func TestToString(t *testing.T) {
someVeryNastyBytes := []byte{0, 1, 2, 3, 4, 5, 6, 50, 7, 8, 9, 10, 11, 50, 50}
gString := ToString(someVeryNastyBytes)
if gString != "222" {
t.Errorf("ToString failed: expected output: %s; got %s", "222", gString)
}
}

12
util/maps.go

@ -0,0 +1,12 @@
package util
// Returns found key (int) in provided map by value (string);
// If key does not exist in map - returns -1
func GetKey(mp map[int]string, givenValue string) int {
for key, value := range mp {
if value == givenValue {
return key
}
}
return -1
}

26
util/read.go

@ -16,33 +16,13 @@ func Read(rs io.Reader, n uint64) ([]byte, error) {
return read, nil
}
// Shortcut function to read n bytes and convert them into string.
// If encountered zero-byte - converts to string only previously read bytes
func ReadToStringIgnoreNullB(rs io.Reader, n uint64) (string, error) {
read := make([]byte, n)
_, err := rs.Read(read)
if err != nil {
return "", fmt.Errorf("could not read from reader: %s", err)
}
var readString string
for _, b := range read {
if b == 0 {
break
}
readString += string(b)
}
return readString, nil
}
// Reads from rs and conversts read []byte into string
// Reads from rs and conversts read []byte into string, ignoring all non-printable or
// invalid characters.
func ReadToString(rs io.Reader, n uint64) (string, error) {
read := make([]byte, n)
_, err := rs.Read(read)
if err != nil {
return "", fmt.Errorf("could not read from reader: %s", err)
}
return string(read), nil
return ToString(read), nil
}

10
v1/id3v10.go

@ -40,22 +40,22 @@ func Getv1Tags(rs io.ReadSeeker) (*ID3v1Tags, error) {
return nil, fmt.Errorf("does not use ID3v1: expected %s; got %s", ID3v1IDENTIFIER, tag)
}
songname, err := util.ReadToStringIgnoreNullB(rs, 30)
songname, err := util.ReadToString(rs, 30)
if err != nil {
return nil, err
}
artist, err := util.ReadToStringIgnoreNullB(rs, 30)
artist, err := util.ReadToString(rs, 30)
if err != nil {
return nil, err
}
album, err := util.ReadToStringIgnoreNullB(rs, 30)
album, err := util.ReadToString(rs, 30)
if err != nil {
return nil, err
}
yearStr, err := util.ReadToStringIgnoreNullB(rs, 4)
yearStr, err := util.ReadToString(rs, 4)
if err != nil {
return nil, err
}
@ -64,7 +64,7 @@ func Getv1Tags(rs io.ReadSeeker) (*ID3v1Tags, error) {
return nil, fmt.Errorf("could not convert yearbytes into int: %s", err)
}
comment, err := util.ReadToStringIgnoreNullB(rs, 30)
comment, err := util.ReadToString(rs, 30)
if err != nil {
return nil, err
}

10
v1/id3v11.go

@ -39,22 +39,22 @@ func Getv11Tags(rs io.ReadSeeker) (*ID3v11Tags, error) {
return nil, fmt.Errorf("does not use ID3v1: expected %s; got %s", ID3v1IDENTIFIER, tag)
}
songname, err := util.ReadToStringIgnoreNullB(rs, 30)
songname, err := util.ReadToString(rs, 30)
if err != nil {
return nil, err
}
artist, err := util.ReadToStringIgnoreNullB(rs, 30)
artist, err := util.ReadToString(rs, 30)
if err != nil {
return nil, err
}
album, err := util.ReadToStringIgnoreNullB(rs, 30)
album, err := util.ReadToString(rs, 30)
if err != nil {
return nil, err
}
yearStr, err := util.ReadToStringIgnoreNullB(rs, 4)
yearStr, err := util.ReadToString(rs, 4)
if err != nil {
return nil, err
}
@ -63,7 +63,7 @@ func Getv11Tags(rs io.ReadSeeker) (*ID3v11Tags, error) {
return nil, fmt.Errorf("could not convert yearbytes into int: %s", err)
}
comment, err := util.ReadToStringIgnoreNullB(rs, 28)
comment, err := util.ReadToString(rs, 28)
if err != nil {
return nil, err
}

88
v2/frame.go

@ -1,29 +1,31 @@
package v2
import (
"fmt"
"io"
"github.com/Unbewohnte/id3ed/util"
)
////////////////////////////////////////////////////////////////////////////
//(ᗜˬᗜ)~⭐//Under construction//Please don`t use it in this verison//(ᗜ‸ᗜ)///
////////////////////////////////////////////////////////////////////////////
type FrameHeader struct {
ID string
FrameSize int64
Flags int
type FrameFlags struct {
TagAlterPreservation bool
FileAlterPreservation bool
ReadOnly bool
Compressed bool
Encrypted bool
InGroup bool
}
type Frame struct {
Header FrameHeader
Contents string
ID string
Size int64
Flags FrameFlags
GroupByte byte
Contents []byte
}
// Reads ID3v2.3.0 or ID3v2.4.0 frame
func ReadFrame(rs io.Reader, version uint) (*Frame, error) {
var frameHeader FrameHeader
var frame Frame
// ID
@ -31,7 +33,7 @@ func ReadFrame(rs io.Reader, version uint) (*Frame, error) {
if err != nil {
return nil, err
}
frameHeader.ID = identifier
frame.ID = identifier
// Size
framesizeBytes, err := util.Read(rs, 4)
@ -44,20 +46,67 @@ func ReadFrame(rs io.Reader, version uint) (*Frame, error) {
return nil, err
}
frameHeader.FrameSize = framesize
frame.Size = framesize
// Flags
frameFlagsBytes, err := util.Read(rs, 2)
frameFlagsByte1, err := util.Read(rs, 1)
if err != nil {
return nil, err
}
frameFlags, err := util.BytesToInt(frameFlagsBytes)
frameFlagsByte2, err := util.Read(rs, 1)
if err != nil {
return nil, err
}
frameHeader.Flags = int(frameFlags)
// 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))
@ -65,8 +114,11 @@ func ReadFrame(rs io.Reader, version uint) (*Frame, error) {
return nil, err
}
frame.Header = frameHeader
frame.Contents = string(frameContents)
frame.Contents = frameContents
return &frame, nil
}
func WriteFlag() {
}

23
v2/frame_test.go

@ -5,6 +5,8 @@ import (
"os"
"path/filepath"
"testing"
"github.com/Unbewohnte/id3ed/util"
)
func TestReadFrame(t *testing.T) {
@ -21,7 +23,24 @@ func TestReadFrame(t *testing.T) {
t.Errorf("ReadFrame failed: %s", err)
}
if firstFrame.Header.ID != "TRCK" {
t.Errorf("ReadFrame failed: expected ID %s; got %s", "TRCK", firstFrame.Header.ID)
if firstFrame.ID != "TRCK" {
t.Errorf("ReadFrame failed: expected ID %s; got %s", "TRCK", firstFrame.ID)
}
if firstFrame.Flags.Encrypted != false {
t.Errorf("ReadFrame failed: expected compressed flag to be %v; got %v", false, firstFrame.Flags.Encrypted)
}
secondFrame, err := ReadFrame(f, 24)
if err != nil {
t.Errorf("ReadFrame failed: %s", err)
}
if secondFrame.ID != "TDRC" {
t.Errorf("ReadFrame failed: expected ID %s; got %s", "TDRC", secondFrame.ID)
}
if util.ToString(secondFrame.Contents) != "2006" {
t.Errorf("ReadFrame failed: expected contents to be %s; got %s", "2006", util.ToString(secondFrame.Contents))
}
}

Loading…
Cancel
Save