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" "encoding/binary"
"fmt" "fmt"
"strconv" "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 // Decodes given integer bytes into integer
func BytesToInt(gBytes []byte) (int64, error) { func BytesToInt(gBytes []byte) (int64, error) {
buff := bytes.NewBuffer(gBytes) buff := bytes.NewBuffer(gBytes)
@ -49,3 +39,17 @@ func BytesToIntIgnoreFirstBit(gBytes []byte) (int64, error) {
return integer, nil 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 return read, nil
} }
// Shortcut function to read n bytes and convert them into string. // Reads from rs and conversts read []byte into string, ignoring all non-printable or
// If encountered zero-byte - converts to string only previously read bytes // invalid characters.
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
func ReadToString(rs io.Reader, n uint64) (string, error) { func ReadToString(rs io.Reader, n uint64) (string, error) {
read := make([]byte, n) read := make([]byte, n)
_, err := rs.Read(read) _, err := rs.Read(read)
if err != nil { if err != nil {
return "", fmt.Errorf("could not read from reader: %s", err) return "", fmt.Errorf("could not read from reader: %s", err)
} }
return ToString(read), nil
return string(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) 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 { if err != nil {
return nil, err return nil, err
} }
artist, err := util.ReadToStringIgnoreNullB(rs, 30) artist, err := util.ReadToString(rs, 30)
if err != nil { if err != nil {
return nil, err return nil, err
} }
album, err := util.ReadToStringIgnoreNullB(rs, 30) album, err := util.ReadToString(rs, 30)
if err != nil { if err != nil {
return nil, err return nil, err
} }
yearStr, err := util.ReadToStringIgnoreNullB(rs, 4) yearStr, err := util.ReadToString(rs, 4)
if err != nil { if err != nil {
return nil, err 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) 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 { if err != nil {
return nil, err 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) 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 { if err != nil {
return nil, err return nil, err
} }
artist, err := util.ReadToStringIgnoreNullB(rs, 30) artist, err := util.ReadToString(rs, 30)
if err != nil { if err != nil {
return nil, err return nil, err
} }
album, err := util.ReadToStringIgnoreNullB(rs, 30) album, err := util.ReadToString(rs, 30)
if err != nil { if err != nil {
return nil, err return nil, err
} }
yearStr, err := util.ReadToStringIgnoreNullB(rs, 4) yearStr, err := util.ReadToString(rs, 4)
if err != nil { if err != nil {
return nil, err 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) 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 { if err != nil {
return nil, err return nil, err
} }

88
v2/frame.go

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

23
v2/frame_test.go

@ -5,6 +5,8 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/Unbewohnte/id3ed/util"
) )
func TestReadFrame(t *testing.T) { func TestReadFrame(t *testing.T) {
@ -21,7 +23,24 @@ func TestReadFrame(t *testing.T) {
t.Errorf("ReadFrame failed: %s", err) t.Errorf("ReadFrame failed: %s", err)
} }
if firstFrame.Header.ID != "TRCK" { if firstFrame.ID != "TRCK" {
t.Errorf("ReadFrame failed: expected ID %s; got %s", "TRCK", firstFrame.Header.ID) 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