Browse Source

Added checks for already existing ID3v1.x tags

main
Unbewohnte 3 years ago
parent
commit
42c071a5da
  1. 23
      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

23
README.md

@ -1,12 +1,20 @@
# ID3ED (ID3 - Encoder - Decoder)
## Library for encoding/decoding ID3 tags
---
# Under construction !
---
# Installation
```
go get github.com/Unbewohnte/id3ed
```
---
# Usage
## Decoding ID3v1.1
@ -33,10 +41,8 @@ func main() {
// print all tags
fmt.Printf("%+v",mp3tags)
// get a certain tag from "getter" function
songname := mp3tags.GetSongName()
songname := mp3tags.SongName
// get a certain tag from struct field
genre := mp3tags.Genre
// etc.
@ -52,7 +58,7 @@ func main() {
defer f.Close()
// create your tags struct
tags := ID3v11Tags{
tags := &ID3v11Tags{
SongName: "mysong",
Artist: "me",
Album: "my album",
@ -62,13 +68,15 @@ func main() {
Genre: "Christian Gangsta Rap", // list of genres see "id3v1genres.go"
}
// write given tags in file
err = WriteID3v11Tags(f, tags)
// write given tags to file
err = WriteID3v11ToFile(f, tags)
if err != nil {
panic(err)
}
```
---
# Testing
```
@ -80,5 +88,4 @@ go test -v
```
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"
"fmt"
"io"
"os"
"strconv"
)
@ -91,8 +92,8 @@ func GetID3v1Tags(rs io.ReadSeeker) (*ID3v1Tags, error) {
}, nil
}
// Writes given ID3v1.0 tags to dst
func WriteID3v1Tags(dst io.WriteSeeker, tags ID3v1Tags) error {
// Writes given ID3v1.0 tags to given io.ReadWriteSeeker.
func WriteID3v1Tags(dst io.WriteSeeker, tags *ID3v1Tags) error {
dst.Seek(0, io.SeekEnd)
// TAG
@ -147,3 +148,45 @@ func WriteID3v1Tags(dst io.WriteSeeker, tags ID3v1Tags) error {
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"
)
var TESTv1TAGS = &ID3v1Tags{
SongName: "testsong",
Artist: "testartist",
Album: "testalbum",
Year: 727,
Comment: "testcomment",
Genre: "Blues",
}
func TestGetID3v1Tags(t *testing.T) {
testfile, err := os.Open("./testData/testread.mp3")
testfile, err := os.Open("./testData/testreadv1.mp3")
if err != nil {
t.Errorf("could not open file for testing: %s", err)
}
@ -21,22 +30,15 @@ func TestGetID3v1Tags(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 {
t.Errorf("%s", err)
}
defer f.Close()
tags := ID3v1Tags{
SongName: "testsong",
Artist: "testartist",
Album: "testalbum",
Year: 727,
Comment: "testcomment",
Genre: "Blues",
}
tags := TESTv1TAGS
err = WriteID3v1Tags(f, tags)
if err != nil {
@ -56,3 +58,18 @@ func TestWriteID3v1Tags(t *testing.T) {
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"
"fmt"
"io"
"os"
"strconv"
)
@ -18,7 +19,7 @@ type ID3v11Tags struct {
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) {
// set reader to the last 128 bytes
_, 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
func WriteID3v11Tags(dst io.WriteSeeker, tags ID3v11Tags) error {
func WriteID3v11Tags(dst io.WriteSeeker, tags *ID3v11Tags) error {
dst.Seek(0, io.SeekEnd)
// TAG
@ -175,3 +176,45 @@ func WriteID3v11Tags(dst io.WriteSeeker, tags ID3v11Tags) error {
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"
)
var TESTV11TAGS = &ID3v11Tags{
SongName: "testsong",
Artist: "testartist",
Album: "testalbum",
Year: 727,
Comment: "testcomment",
Track: 5,
Genre: "Blues",
}
func TestGetID3v11Tags(t *testing.T) {
testfile, err := os.Open("./testData/testread.mp3")
testfile, err := os.Open("./testData/testreadv1.mp3")
if err != nil {
t.Errorf("could not open file for testing: %s", err)
}
@ -27,23 +37,15 @@ func TestGetID3v11Tags(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 {
t.Errorf("%s", err)
}
defer f.Close()
tags := ID3v11Tags{
SongName: "testsong",
Artist: "testartist",
Album: "testalbum",
Year: 727,
Comment: "testcomment",
Track: 5,
Genre: "Blues",
}
tags := TESTV11TAGS
err = WriteID3v11Tags(f, tags)
if err != nil {
@ -67,3 +69,17 @@ func TestWriteID3v11Tags(t *testing.T) {
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