Browse Source

Added checks for already existing ID3v1.x tags

main
Unbewohnte 3 years ago
parent
commit
42c071a5da
  1. 25
      README.md
  2. 47
      id3v10.go
  3. 39
      id3v10_test.go
  4. 47
      id3v11.go
  5. 40
      id3v11_test.go
  6. 0
      testData/testreadv1.mp3
  7. 0
      testData/testwritev1.mp3

25
README.md

@ -1,12 +1,20 @@
# ID3ED (ID3 - Encoder - Decoder) # ID3ED (ID3 - Encoder - Decoder)
## Library for encoding/decoding ID3 tags ## Library for encoding/decoding ID3 tags
---
# Under construction !
---
# Installation # Installation
``` ```
go get github.com/Unbewohnte/id3ed go get github.com/Unbewohnte/id3ed
``` ```
---
# Usage # Usage
## Decoding ID3v1.1 ## Decoding ID3v1.1
@ -33,10 +41,8 @@ func main() {
// print all tags // print all tags
fmt.Printf("%+v",mp3tags) fmt.Printf("%+v",mp3tags)
// get a certain tag from "getter" function songname := mp3tags.SongName
songname := mp3tags.GetSongName()
// get a certain tag from struct field
genre := mp3tags.Genre genre := mp3tags.Genre
// etc. // etc.
@ -52,7 +58,7 @@ func main() {
defer f.Close() defer f.Close()
// create your tags struct // create your tags struct
tags := ID3v11Tags{ tags := &ID3v11Tags{
SongName: "mysong", SongName: "mysong",
Artist: "me", Artist: "me",
Album: "my album", Album: "my album",
@ -62,13 +68,15 @@ func main() {
Genre: "Christian Gangsta Rap", // list of genres see "id3v1genres.go" Genre: "Christian Gangsta Rap", // list of genres see "id3v1genres.go"
} }
// write given tags in file // write given tags to file
err = WriteID3v11Tags(f, tags) err = WriteID3v11ToFile(f, tags)
if err != nil { if err != nil {
panic(err) panic(err)
} }
``` ```
---
# Testing # Testing
``` ```
@ -80,5 +88,4 @@ go test -v
``` ```
to get a verbose output to get a verbose output
# Under construction ! ---
## Bugs are a possibility rn in this state, the package is still not tested properly

47
id3v10.go

@ -5,6 +5,7 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
"os"
"strconv" "strconv"
) )
@ -91,8 +92,8 @@ func GetID3v1Tags(rs io.ReadSeeker) (*ID3v1Tags, error) {
}, nil }, nil
} }
// Writes given ID3v1.0 tags to dst // Writes given ID3v1.0 tags to given io.ReadWriteSeeker.
func WriteID3v1Tags(dst io.WriteSeeker, tags ID3v1Tags) error { func WriteID3v1Tags(dst io.WriteSeeker, tags *ID3v1Tags) error {
dst.Seek(0, io.SeekEnd) dst.Seek(0, io.SeekEnd)
// TAG // TAG
@ -147,3 +148,45 @@ func WriteID3v1Tags(dst io.WriteSeeker, tags ID3v1Tags) error {
return nil return nil
} }
// Checks for existing ID3v1 tag in file, if present - removes it and replaces with provided tags
func WriteID3v1ToFile(f *os.File, tags *ID3v1Tags) error {
defer f.Close()
// check for existing ID3v1 tag
f.Seek(-int64(ID3V1SIZE), io.SeekEnd)
tag, err := read(f, 3)
if err != nil {
return err
}
if !bytes.Equal(tag, []byte("TAG")) {
// no existing tag, just write given tags
err = WriteID3v1Tags(f, tags)
if err != nil {
return err
}
return nil
}
// does contain ID3v1 tag. Removing it
fStats, err := f.Stat()
if err != nil {
return err
}
err = f.Truncate(fStats.Size() - int64(ID3V1SIZE))
if err != nil {
return nil
}
// writing new tags
err = WriteID3v1Tags(f, tags)
if err != nil {
return err
}
return nil
}

39
id3v10_test.go

@ -5,8 +5,17 @@ import (
"testing" "testing"
) )
var TESTv1TAGS = &ID3v1Tags{
SongName: "testsong",
Artist: "testartist",
Album: "testalbum",
Year: 727,
Comment: "testcomment",
Genre: "Blues",
}
func TestGetID3v1Tags(t *testing.T) { func TestGetID3v1Tags(t *testing.T) {
testfile, err := os.Open("./testData/testread.mp3") testfile, err := os.Open("./testData/testreadv1.mp3")
if err != nil { if err != nil {
t.Errorf("could not open file for testing: %s", err) t.Errorf("could not open file for testing: %s", err)
} }
@ -21,22 +30,15 @@ func TestGetID3v1Tags(t *testing.T) {
} }
func TestWriteID3v1Tags(t *testing.T) { func TestWriteID3v1Tags(t *testing.T) {
os.Remove("./testData/testwrite.mp3") os.Remove("./testData/testwritev1.mp3")
f, err := os.Create("./testData/testwrite.mp3") f, err := os.Create("./testData/testwritev1.mp3")
if err != nil { if err != nil {
t.Errorf("%s", err) t.Errorf("%s", err)
} }
defer f.Close() defer f.Close()
tags := ID3v1Tags{ tags := TESTv1TAGS
SongName: "testsong",
Artist: "testartist",
Album: "testalbum",
Year: 727,
Comment: "testcomment",
Genre: "Blues",
}
err = WriteID3v1Tags(f, tags) err = WriteID3v1Tags(f, tags)
if err != nil { if err != nil {
@ -56,3 +58,18 @@ func TestWriteID3v1Tags(t *testing.T) {
t.Errorf("WriteID3v1Tags failed: expected %d; got %d", 727, readTags.Year) t.Errorf("WriteID3v1Tags failed: expected %d; got %d", 727, readTags.Year)
} }
} }
func TestWriteID3v1ToFile(t *testing.T) {
f, err := os.Open("./testData/testwritev1.mp3")
if err != nil {
t.Errorf("%s", err)
}
tags := TESTv1TAGS
err = WriteID3v1ToFile(f, tags)
if err != nil {
t.Errorf("WriteID3v1ToFile failed: %s", err)
}
}

47
id3v11.go

@ -5,6 +5,7 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
"os"
"strconv" "strconv"
) )
@ -18,7 +19,7 @@ type ID3v11Tags struct {
Genre string Genre string
} }
// Retrieves ID3v1.1 field values of provided io.ReadSeeker (usually a file) // Retrieves ID3v1.1 field values of provided io.ReadSeeker
func GetID3v11Tags(rs io.ReadSeeker) (*ID3v11Tags, error) { func GetID3v11Tags(rs io.ReadSeeker) (*ID3v11Tags, error) {
// set reader to the last 128 bytes // set reader to the last 128 bytes
_, err := rs.Seek(-int64(ID3V1SIZE), io.SeekEnd) _, err := rs.Seek(-int64(ID3V1SIZE), io.SeekEnd)
@ -106,7 +107,7 @@ func GetID3v11Tags(rs io.ReadSeeker) (*ID3v11Tags, error) {
} }
// Writes given ID3v1.1 tags to dst // Writes given ID3v1.1 tags to dst
func WriteID3v11Tags(dst io.WriteSeeker, tags ID3v11Tags) error { func WriteID3v11Tags(dst io.WriteSeeker, tags *ID3v11Tags) error {
dst.Seek(0, io.SeekEnd) dst.Seek(0, io.SeekEnd)
// TAG // TAG
@ -175,3 +176,45 @@ func WriteID3v11Tags(dst io.WriteSeeker, tags ID3v11Tags) error {
return nil return nil
} }
// Checks for existing ID3v1.1 tag in file, if present - removes it and replaces with provided tags
func WriteID3v11ToFile(f *os.File, tags *ID3v11Tags) error {
defer f.Close()
// check for existing ID3v1.1 tag
f.Seek(-int64(ID3V1SIZE), io.SeekEnd)
tag, err := read(f, 3)
if err != nil {
return err
}
if !bytes.Equal(tag, []byte("TAG")) {
// no existing tag, just write given tags
err = WriteID3v11Tags(f, tags)
if err != nil {
return err
}
return nil
}
// does contain ID3v1.1 tag. Removing it
fStats, err := f.Stat()
if err != nil {
return err
}
err = f.Truncate(fStats.Size() - int64(ID3V1SIZE))
if err != nil {
return nil
}
// writing new tags
err = WriteID3v11Tags(f, tags)
if err != nil {
return err
}
return nil
}

40
id3v11_test.go

@ -6,8 +6,18 @@ import (
"testing" "testing"
) )
var TESTV11TAGS = &ID3v11Tags{
SongName: "testsong",
Artist: "testartist",
Album: "testalbum",
Year: 727,
Comment: "testcomment",
Track: 5,
Genre: "Blues",
}
func TestGetID3v11Tags(t *testing.T) { func TestGetID3v11Tags(t *testing.T) {
testfile, err := os.Open("./testData/testread.mp3") testfile, err := os.Open("./testData/testreadv1.mp3")
if err != nil { if err != nil {
t.Errorf("could not open file for testing: %s", err) t.Errorf("could not open file for testing: %s", err)
} }
@ -27,23 +37,15 @@ func TestGetID3v11Tags(t *testing.T) {
} }
func TestWriteID3v11Tags(t *testing.T) { func TestWriteID3v11Tags(t *testing.T) {
os.Remove("./testData/testwrite.mp3") os.Remove("./testData/testwritev1.mp3")
f, err := os.Create("./testData/testwrite.mp3") f, err := os.Create("./testData/testwritev1.mp3")
if err != nil { if err != nil {
t.Errorf("%s", err) t.Errorf("%s", err)
} }
defer f.Close() defer f.Close()
tags := ID3v11Tags{ tags := TESTV11TAGS
SongName: "testsong",
Artist: "testartist",
Album: "testalbum",
Year: 727,
Comment: "testcomment",
Track: 5,
Genre: "Blues",
}
err = WriteID3v11Tags(f, tags) err = WriteID3v11Tags(f, tags)
if err != nil { if err != nil {
@ -67,3 +69,17 @@ func TestWriteID3v11Tags(t *testing.T) {
t.Errorf("WriteID3v11Tags failed: expected %d; got %d", 5, readTags.Track) t.Errorf("WriteID3v11Tags failed: expected %d; got %d", 5, readTags.Track)
} }
} }
func TestWriteID3v11ToFile(t *testing.T) {
f, err := os.Open("./testData/testwritev1.mp3")
if err != nil {
t.Errorf("%s", err)
}
tags := TESTV11TAGS
err = WriteID3v11ToFile(f, tags)
if err != nil {
t.Errorf("WriteID3v1ToFile failed: %s", err)
}
}

0
testData/testread.mp3 → testData/testreadv1.mp3

0
testData/testwrite.mp3 → testData/testwritev1.mp3

Loading…
Cancel
Save