Browse Source

❖ Improved utils, continued to work on v2 frames ❖

main
Unbewohnte 3 years ago
parent
commit
2b197fa0c1
  1. BIN
      testData/testwritev1.mp3
  2. 22
      util/etc.go
  3. 13
      util/read.go
  4. 10
      v1/id3v10.go
  5. 10
      v1/id3v11.go
  6. 2
      v2/constants.go
  7. 41
      v2/frame.go
  8. 35
      v2/frame_test.go
  9. 15
      v2/header.go

BIN
testData/testwritev1.mp3

Binary file not shown.

22
util/etc.go

@ -4,6 +4,7 @@ import (
"bytes"
"encoding/binary"
"fmt"
"strconv"
)
// Returns found key (int) in provided map by value (string);
@ -27,3 +28,24 @@ func BytesToInt(gBytes []byte) (int64, error) {
buff = nil
return integer, nil
}
// Decodes given integer bytes into integer, ignores the first bit
// of every given byte in binary form
func BytesToIntIgnoreFirstBit(gBytes []byte) (int64, error) {
// represent each byte in size as binary and get rid from the first bit,
// then concatenate filtered parts
var filteredBits string
for _, b := range gBytes {
// ignore the first bit
filteredPart := fmt.Sprintf("%08b", b)[1:] // byte is 8 bits
filteredBits += filteredPart
}
// convert filtered binary into usable int64
integer, err := strconv.ParseInt(filteredBits, 2, 64)
if err != nil {
return -1, err
}
return integer, nil
}

13
util/read.go

@ -18,7 +18,7 @@ func Read(rs io.Reader, n uint64) ([]byte, error) {
// Shortcut function to read n bytes and convert them into string.
// If encountered zero-byte - converts to string only previously read bytes
func ReadToString(rs io.Reader, n int) (string, error) {
func ReadToStringIgnoreNullB(rs io.Reader, n uint64) (string, error) {
read := make([]byte, n)
_, err := rs.Read(read)
if err != nil {
@ -35,3 +35,14 @@ func ReadToString(rs io.Reader, n int) (string, error) {
return readString, nil
}
// Reads from rs and conversts read []byte into string
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
}

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.ReadToString(rs, 30)
songname, err := util.ReadToStringIgnoreNullB(rs, 30)
if err != nil {
return nil, err
}
artist, err := util.ReadToString(rs, 30)
artist, err := util.ReadToStringIgnoreNullB(rs, 30)
if err != nil {
return nil, err
}
album, err := util.ReadToString(rs, 30)
album, err := util.ReadToStringIgnoreNullB(rs, 30)
if err != nil {
return nil, err
}
yearStr, err := util.ReadToString(rs, 4)
yearStr, err := util.ReadToStringIgnoreNullB(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.ReadToString(rs, 30)
comment, err := util.ReadToStringIgnoreNullB(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.ReadToString(rs, 30)
songname, err := util.ReadToStringIgnoreNullB(rs, 30)
if err != nil {
return nil, err
}
artist, err := util.ReadToString(rs, 30)
artist, err := util.ReadToStringIgnoreNullB(rs, 30)
if err != nil {
return nil, err
}
album, err := util.ReadToString(rs, 30)
album, err := util.ReadToStringIgnoreNullB(rs, 30)
if err != nil {
return nil, err
}
yearStr, err := util.ReadToString(rs, 4)
yearStr, err := util.ReadToStringIgnoreNullB(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.ReadToString(rs, 28)
comment, err := util.ReadToStringIgnoreNullB(rs, 28)
if err != nil {
return nil, err
}

2
v2/constants.go

@ -4,3 +4,5 @@ package v2
const HEADERIDENTIFIER string = "ID3"
const HEADERSIZE int = 10 // bytes
const HEADERMAXSIZE int = 268435456 // bytes (256 MB)
// Version specific constants

41
v2/frame.go

@ -11,49 +11,58 @@ import (
////////////////////////////////////////////////////////////////////////////
type FrameHeader struct {
Identifier string
FrameSize int64
ID string
FrameSize int64
Flags int
}
type Frame struct {
Header *FrameHeader
Header FrameHeader
Contents string
}
// NOT TESTED !
func Readv2Frame(rs io.Reader) (*Frame, error) {
var frameHeader *FrameHeader
// NOT TESTED ! Reads v2.3 | v2.4 frame
func ReadFrame(rs io.Reader) (*Frame, error) {
var frameHeader FrameHeader
var frame Frame
identifier, err := util.ReadToString(rs, 3)
identifier, err := util.ReadToString(rs, 4)
if err != nil {
return nil, err
}
frameHeader.Identifier = identifier
frameHeader.ID = identifier
framesizeBytes, err := util.Read(rs, 3)
framesizeBytes, err := util.Read(rs, 4)
if err != nil {
return nil, err
}
framesize, err := util.BytesToInt(framesizeBytes)
framesize, err := util.BytesToIntIgnoreFirstBit(framesizeBytes)
if err != nil {
return nil, err
}
frameHeader.FrameSize = framesize
frameContents, err := util.ReadToString(rs, int(framesize))
frameFlagsBytes, err := util.Read(rs, 2)
if err != nil {
return nil, err
}
// STILL NOT IMPLEMENTED FLAG HANDLING !
frameFlags, err := util.BytesToInt(frameFlagsBytes)
if err != nil {
return nil, err
}
frameHeader.Flags = int(frameFlags)
frameContents, err := util.Read(rs, uint64(framesize))
if err != nil {
return nil, err
}
frame.Header = frameHeader
frame.Contents = frameContents
frame.Contents = string(frameContents)
return &frame, nil
}
// func ReadFrame(rs io.Reader, version string) error {
// return nil
// }

35
v2/frame_test.go

@ -1,16 +1,27 @@
package v2
// func TestReadFrame(t *testing.T) {
// f, err := os.Open(filepath.Join(TESTDATAPATH, "testreadv2.mp3"))
// if err != nil {
// t.Errorf("%s", err)
// }
import (
"io"
"os"
"path/filepath"
"testing"
)
// // read right after header`s bytes
// f.Seek(int64(HEADERSIZE), io.SeekStart)
func TestReadFrame(t *testing.T) {
f, err := os.Open(filepath.Join(TESTDATAPATH, "testreadv2.mp3"))
if err != nil {
t.Errorf("%s", err)
}
// _, err = Readv2Frame(f)
// if err != nil {
// t.Errorf("ReadFrame failed: %s", err)
// }
// }
// read right after header`s bytes
f.Seek(int64(HEADERSIZE), io.SeekStart)
firstFrame, err := ReadFrame(f)
if err != nil {
t.Errorf("ReadFrame failed: %s", err)
}
if firstFrame.Header.ID != "TRCK" {
t.Errorf("ReadFrame failed: expected ID %s; got %s", "TRCK", firstFrame.Header.ID)
}
}

15
v2/header.go

@ -4,7 +4,6 @@ import (
"bytes"
"fmt"
"io"
"strconv"
"github.com/Unbewohnte/id3ed/util"
)
@ -77,22 +76,12 @@ func GetHeader(rs io.ReadSeeker) (*Header, error) {
return nil, err
}
// represent each byte in size as binary and get rid from the first useless bit,
// then concatenate filtered parts
var filteredSizeStr string
for _, b := range sizeBytes {
// the first bit is always 0, so filter it out
filteredPart := fmt.Sprintf("%08b", b)[1:] // byte is 8 bits
filteredSizeStr += filteredPart
}
// converting filtered binary size into usable int64
size, err := strconv.ParseInt(filteredSizeStr, 2, 64)
size, err := util.BytesToIntIgnoreFirstBit(sizeBytes)
if err != nil {
return nil, err
}
header.Size = int64(size)
header.Size = size
return &header, nil
}

Loading…
Cancel
Save