diff --git a/README.md b/README.md index c7c2cf0..2f6e942 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,12 @@ To download package source: ``` -go get github.com/Unbewohnte/id3ed +go get github.com/Unbewohnte/id3ed/... ``` To compile package: ``` -go install github.com/Unbewohnte/id3ed +go install github.com/Unbewohnte/id3ed/... ``` --- diff --git a/testData/testwritev1.mp3 b/testData/testwritev1.mp3 index 3402b04..8c78a56 100644 Binary files a/testData/testwritev1.mp3 and b/testData/testwritev1.mp3 differ diff --git a/v2/frame.go b/v2/frame.go index 687b539..5f31f63 100644 --- a/v2/frame.go +++ b/v2/frame.go @@ -21,17 +21,19 @@ type Frame struct { Contents string } -// NOT TESTED ! Reads v2.3 | v2.4 frame -func ReadFrame(rs io.Reader) (*Frame, error) { +// 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 identifier, err := util.ReadToString(rs, 4) if err != nil { return nil, err } frameHeader.ID = identifier + // Size framesizeBytes, err := util.Read(rs, 4) if err != nil { return nil, err @@ -44,18 +46,20 @@ func ReadFrame(rs io.Reader) (*Frame, error) { frameHeader.FrameSize = framesize + // Flags 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) + // Body frameContents, err := util.Read(rs, uint64(framesize)) if err != nil { return nil, err diff --git a/v2/frame_test.go b/v2/frame_test.go index d2c28e6..25d9167 100644 --- a/v2/frame_test.go +++ b/v2/frame_test.go @@ -16,7 +16,7 @@ func TestReadFrame(t *testing.T) { // read right after header`s bytes f.Seek(int64(HEADERSIZE), io.SeekStart) - firstFrame, err := ReadFrame(f) + firstFrame, err := ReadFrame(f, 24) if err != nil { t.Errorf("ReadFrame failed: %s", err) } diff --git a/v2/header.go b/v2/header.go index c46f479..ee14b6f 100644 --- a/v2/header.go +++ b/v2/header.go @@ -4,20 +4,28 @@ import ( "bytes" "fmt" "io" + "strconv" "github.com/Unbewohnte/id3ed/util" ) +type HeaderFlags struct { + Unsynchronisated bool + HasExtendedHeader bool + Experimental bool + FooterPresent bool +} + // ID3v2.x header structure type Header struct { - Identifier string - Version string - Unsynchronisated bool - Compressed bool - Size int64 // size of the whole tag - 10 header bytes + Identifier string + Flags HeaderFlags + Version uint + + Size int64 // size of the whole tag - 10 header bytes } -// Reads and structuralises ID3v2 header +// Reads and structuralises ID3v2.3.0 or ID3v2.4.0 header func GetHeader(rs io.ReadSeeker) (*Header, error) { var header Header @@ -51,23 +59,63 @@ func GetHeader(rs io.ReadSeeker) (*Header, error) { if err != nil { return nil, err } - header.Version = fmt.Sprintf("%d%d", -majorVersion, revisionNumber) + + version, err := strconv.Atoi(fmt.Sprintf("%d%d", majorVersion, revisionNumber)) + if err != nil { + return nil, err + } + header.Version = uint(version) // flags flags, err := util.Read(rs, 1) if err != nil { return nil, err } - bits := fmt.Sprintf("%08b", flags) // 1 byte is 8 bits - if bits[0] == 1 { - header.Unsynchronisated = true - } else { - header.Unsynchronisated = false - } - if bits[1] == 1 { - header.Compressed = true - } else { - header.Compressed = false + + flagBits := fmt.Sprintf("%08b", flags) // 1 byte is 8 bits + + // v3.0 and v4.0 have different amount of flags + switch version { + case 30: + if flagBits[0] == 1 { + header.Flags.Unsynchronisated = true + } else { + header.Flags.Unsynchronisated = false + } + if flagBits[1] == 1 { + header.Flags.HasExtendedHeader = true + } else { + header.Flags.HasExtendedHeader = false + } + if flagBits[2] == 1 { + header.Flags.Experimental = true + } else { + header.Flags.Experimental = false + } + // always false, because ID3v2.3.0 does not support footers + header.Flags.FooterPresent = false + + case 40: + if flagBits[0] == 1 { + header.Flags.Unsynchronisated = true + } else { + header.Flags.Unsynchronisated = false + } + if flagBits[1] == 1 { + header.Flags.HasExtendedHeader = true + } else { + header.Flags.HasExtendedHeader = false + } + if flagBits[2] == 1 { + header.Flags.Experimental = true + } else { + header.Flags.Experimental = false + } + if flagBits[3] == 1 { + header.Flags.FooterPresent = true + } else { + header.Flags.FooterPresent = false + } } // size diff --git a/v2/header_test.go b/v2/header_test.go index 650d63a..4aa788c 100644 --- a/v2/header_test.go +++ b/v2/header_test.go @@ -23,12 +23,12 @@ func TestGetHeader(t *testing.T) { t.Errorf("GetHeader failed: expected identifier %s; got %s", "ID3", header.Identifier) } - if header.Compressed != false { - t.Errorf("GetHeader failed: expected flag %v; got %v", false, header.Compressed) + if header.Flags.HasExtendedHeader != false { + t.Errorf("GetHeader failed: expected flag %v; got %v", false, header.Flags.HasExtendedHeader) } - if header.Unsynchronisated != false { - t.Errorf("GetHeader failed: expected flag %v; got %v", false, header.Unsynchronisated) + if header.Flags.Unsynchronisated != false { + t.Errorf("GetHeader failed: expected flag %v; got %v", false, header.Flags.Unsynchronisated) } if header.Size != 1138 {