diff --git a/README.md b/README.md index bdaf32b..810f55f 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ package main import( "fmt" - "github.com/Unbewohnte/id3ed" + id3v1 "github.com/Unbewohnte/id3ed/v1" ) func main() { @@ -40,7 +40,7 @@ func main() { } // extract ID3v1.1 tags - mp3tags, err := id3ed.GetID3v11Tags(mp3file) + mp3tags, err := id3v1.GetID3v11Tags(mp3file) if err != nil { panic(err) } @@ -62,7 +62,7 @@ package main import( "fmt" - "github.com/Unbewohnte/id3ed" + "github.com/Unbewohnte/id3ed/v1" ) func main() { @@ -73,7 +73,7 @@ func main() { defer f.Close() // create your tags struct - tags := &id3ed.ID3v11Tags{ + tags := &id3v1.ID3v11Tags{ SongName: "mysong", Artist: "me", Album: "my album", @@ -95,15 +95,23 @@ func main() { # ∙ Testing +To test everything ``` -go test +go test ./... ``` or ``` -go test -v +go test -v ./... ``` to get a verbose output +OR + +``` +go test ./package_name_here +``` +to test a specific package + --- # ∙ License diff --git a/testData/testwritev1.mp3 b/testData/testwritev1.mp3 index 7058049..f4f78e5 100644 Binary files a/testData/testwritev1.mp3 and b/testData/testwritev1.mp3 differ diff --git a/util.go b/util/util.go similarity index 85% rename from util.go rename to util/util.go index bb1bf06..8cc1c9d 100644 --- a/util.go +++ b/util/util.go @@ -1,4 +1,4 @@ -package id3ed +package util import ( "bytes" @@ -8,7 +8,7 @@ import ( ) // Shortcut function to read n bytes from reader. Peeked from here: https://github.com/dhowden/tag/blob/master/util.go -func read(rs io.Reader, n int) ([]byte, error) { +func Read(rs io.Reader, n int) ([]byte, error) { read := make([]byte, n) _, err := rs.Read(read) if err != nil { @@ -20,7 +20,7 @@ func read(rs io.Reader, n int) ([]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 ReadToString(rs io.Reader, n int) (string, error) { read := make([]byte, n) _, err := rs.Read(read) if err != nil { @@ -39,7 +39,7 @@ func readToString(rs io.Reader, n int) (string, error) { } // Writes data to wr, if len(data) is less than lenNeeded - adds null bytes until written lenNeeded bytes -func writeToExtent(wr io.Writer, data []byte, lenNeeded int) error { +func WriteToExtent(wr io.Writer, data []byte, lenNeeded int) error { if len(data) > lenNeeded { return fmt.Errorf("length of given data bytes is bigger than length needed") } @@ -69,7 +69,7 @@ func writeToExtent(wr io.Writer, data []byte, lenNeeded int) error { // 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 { +func GetKey(mp map[int]string, givenValue string) int { for key, value := range mp { if value == givenValue { return key @@ -79,7 +79,7 @@ func getKey(mp map[int]string, givenValue string) int { } // Decodes given integer bytes into integer -func bytesToInt(gBytes []byte) (int64, error) { +func BytesToInt(gBytes []byte) (int64, error) { buff := bytes.NewBuffer(gBytes) integer, err := binary.ReadVarint(buff) if err != nil { diff --git a/v1/constants.go b/v1/constants.go new file mode 100644 index 0000000..3fdcf0f --- /dev/null +++ b/v1/constants.go @@ -0,0 +1,5 @@ +package v1 + +const ID3v1IDENTIFIER string = "TAG" +const ID3v1SIZE int = 128 // bytes +const ID3v1INVALIDGENRE int = 255 diff --git a/id3v1genres.go b/v1/genres.go similarity index 99% rename from id3v1genres.go rename to v1/genres.go index f6684b3..1e652d4 100644 --- a/id3v1genres.go +++ b/v1/genres.go @@ -1,4 +1,4 @@ -package id3ed +package v1 // https://en.wikipedia.org/wiki/List_of_ID3v1_Genres diff --git a/id3v10.go b/v1/id3v10.go similarity index 80% rename from id3v10.go rename to v1/id3v10.go index 588ca7b..6d27bd1 100644 --- a/id3v10.go +++ b/v1/id3v10.go @@ -1,4 +1,4 @@ -package id3ed +package v1 import ( "bytes" @@ -7,6 +7,8 @@ import ( "io" "os" "strconv" + + "github.com/Unbewohnte/id3ed/util" ) // https://id3.org/ID3v1 - documentation @@ -28,7 +30,7 @@ func GetID3v1Tags(rs io.ReadSeeker) (*ID3v1Tags, error) { return nil, fmt.Errorf("could not seek: %s", err) } - tag, err := read(rs, 3) + tag, err := util.Read(rs, 3) if err != nil { return nil, err } @@ -38,22 +40,22 @@ func GetID3v1Tags(rs io.ReadSeeker) (*ID3v1Tags, error) { return nil, fmt.Errorf("does not use ID3v1: expected %s; got %s", ID3v1IDENTIFIER, tag) } - songname, err := readToString(rs, 30) + songname, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - artist, err := readToString(rs, 30) + artist, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - album, err := readToString(rs, 30) + album, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - yearStr, err := readToString(rs, 4) + yearStr, err := util.ReadToString(rs, 4) if err != nil { return nil, err } @@ -62,16 +64,16 @@ func GetID3v1Tags(rs io.ReadSeeker) (*ID3v1Tags, error) { return nil, fmt.Errorf("could not convert yearbytes into int: %s", err) } - comment, err := readToString(rs, 30) + comment, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - genreByte, err := read(rs, 1) + genreByte, err := util.Read(rs, 1) if err != nil { return nil, err } - genreInt, err := bytesToInt(genreByte) + genreInt, err := util.BytesToInt(genreByte) if err != nil { return nil, err } @@ -103,37 +105,37 @@ func (tags *ID3v1Tags) Write(dst io.WriteSeeker) error { } // Song name - err = writeToExtent(dst, []byte(tags.SongName), 30) + err = util.WriteToExtent(dst, []byte(tags.SongName), 30) if err != nil { return err } // Artist - err = writeToExtent(dst, []byte(tags.Artist), 30) + err = util.WriteToExtent(dst, []byte(tags.Artist), 30) if err != nil { return err } // Album - err = writeToExtent(dst, []byte(tags.Album), 30) + err = util.WriteToExtent(dst, []byte(tags.Album), 30) if err != nil { return err } // Year - err = writeToExtent(dst, []byte(fmt.Sprint(tags.Year)), 4) + err = util.WriteToExtent(dst, []byte(fmt.Sprint(tags.Year)), 4) if err != nil { return err } // Comment - err = writeToExtent(dst, []byte(tags.Comment), 30) + err = util.WriteToExtent(dst, []byte(tags.Comment), 30) if err != nil { return err } // Genre - genreCode := getKey(id3v1genres, tags.Genre) + genreCode := util.GetKey(id3v1genres, tags.Genre) if genreCode == -1 { // if no genre found - encode genre code as 255 genreCode = ID3v1INVALIDGENRE @@ -156,7 +158,7 @@ func (tags *ID3v1Tags) WriteToFile(f *os.File) error { // check for existing ID3v1 tag f.Seek(-int64(ID3v1SIZE), io.SeekEnd) - tag, err := read(f, 3) + tag, err := util.Read(f, 3) if err != nil { return err } diff --git a/id3v10_test.go b/v1/id3v10_test.go similarity index 75% rename from id3v10_test.go rename to v1/id3v10_test.go index 8b42743..83ed33a 100644 --- a/id3v10_test.go +++ b/v1/id3v10_test.go @@ -1,10 +1,13 @@ -package id3ed +package v1 import ( "os" + "path/filepath" "testing" ) +var TESTDATAPATH string = filepath.Join("..", "testData") + var TESTv1TAGS = &ID3v1Tags{ SongName: "testsong", Artist: "testartist", @@ -15,7 +18,7 @@ var TESTv1TAGS = &ID3v1Tags{ } func TestGetID3v1Tags(t *testing.T) { - testfile, err := os.OpenFile("./testData/testreadv1.mp3", os.O_CREATE|os.O_RDONLY, os.ModePerm) + testfile, err := os.OpenFile(filepath.Join(TESTDATAPATH, "testreadv1.mp3"), os.O_CREATE|os.O_RDONLY, os.ModePerm) if err != nil { t.Errorf("could not open file for testing: %s", err) } @@ -30,7 +33,7 @@ func TestGetID3v1Tags(t *testing.T) { } func TestWriteID3v1Tags(t *testing.T) { - f, err := os.OpenFile("./testData/testwritev1.mp3", os.O_CREATE|os.O_RDWR, os.ModePerm) + f, err := os.OpenFile(filepath.Join(TESTDATAPATH, "testwritev1.mp3"), os.O_CREATE|os.O_RDWR, os.ModePerm) if err != nil { t.Errorf("%s", err) } @@ -60,7 +63,7 @@ func TestWriteID3v1Tags(t *testing.T) { } func TestWriteID3v1ToFile(t *testing.T) { - f, err := os.OpenFile("./testData/testwritev1.mp3", os.O_CREATE|os.O_RDWR, os.ModePerm) + f, err := os.OpenFile(filepath.Join(TESTDATAPATH, "testwritev1.mp3"), os.O_CREATE|os.O_RDWR, os.ModePerm) if err != nil { t.Errorf("%s", err) } diff --git a/id3v11.go b/v1/id3v11.go similarity index 80% rename from id3v11.go rename to v1/id3v11.go index 3d348c7..2a10a81 100644 --- a/id3v11.go +++ b/v1/id3v11.go @@ -1,4 +1,4 @@ -package id3ed +package v1 import ( "bytes" @@ -7,6 +7,8 @@ import ( "io" "os" "strconv" + + "github.com/Unbewohnte/id3ed/util" ) type ID3v11Tags struct { @@ -27,7 +29,7 @@ func GetID3v11Tags(rs io.ReadSeeker) (*ID3v11Tags, error) { return nil, fmt.Errorf("could not seek: %s", err) } - tag, err := read(rs, 3) + tag, err := util.Read(rs, 3) if err != nil { return nil, err } @@ -37,22 +39,22 @@ func GetID3v11Tags(rs io.ReadSeeker) (*ID3v11Tags, error) { return nil, fmt.Errorf("does not use ID3v1: expected %s; got %s", ID3v1IDENTIFIER, tag) } - songname, err := readToString(rs, 30) + songname, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - artist, err := readToString(rs, 30) + artist, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - album, err := readToString(rs, 30) + album, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - yearStr, err := readToString(rs, 4) + yearStr, err := util.ReadToString(rs, 4) if err != nil { return nil, err } @@ -61,32 +63,32 @@ func GetID3v11Tags(rs io.ReadSeeker) (*ID3v11Tags, error) { return nil, fmt.Errorf("could not convert yearbytes into int: %s", err) } - comment, err := readToString(rs, 28) + comment, err := util.ReadToString(rs, 28) if err != nil { return nil, err } // skip 1 null byte - _, err = read(rs, 1) + _, err = util.Read(rs, 1) if err != nil { return nil, err } - trackByte, err := read(rs, 1) + trackByte, err := util.Read(rs, 1) if err != nil { return nil, err } - track, err := bytesToInt(trackByte) + track, err := util.BytesToInt(trackByte) if err != nil { return nil, err } - genreByte, err := read(rs, 1) + genreByte, err := util.Read(rs, 1) if err != nil { return nil, err } - genreInt, err := bytesToInt(genreByte) + genreInt, err := util.BytesToInt(genreByte) if err != nil { return nil, err } @@ -119,31 +121,31 @@ func (tags *ID3v11Tags) Write(dst io.WriteSeeker) error { } // Song name - err = writeToExtent(dst, []byte(tags.SongName), 30) + err = util.WriteToExtent(dst, []byte(tags.SongName), 30) if err != nil { return fmt.Errorf("could not write to dst: %s", err) } // Artist - err = writeToExtent(dst, []byte(tags.Artist), 30) + err = util.WriteToExtent(dst, []byte(tags.Artist), 30) if err != nil { return fmt.Errorf("could not write to dst: %s", err) } // Album - err = writeToExtent(dst, []byte(tags.Album), 30) + err = util.WriteToExtent(dst, []byte(tags.Album), 30) if err != nil { return fmt.Errorf("could not write to dst: %s", err) } // Year - err = writeToExtent(dst, []byte(fmt.Sprint(tags.Year)), 4) + err = util.WriteToExtent(dst, []byte(fmt.Sprint(tags.Year)), 4) if err != nil { return fmt.Errorf("could not write to dst: %s", err) } // Comment - err = writeToExtent(dst, []byte(tags.Comment), 28) + err = util.WriteToExtent(dst, []byte(tags.Comment), 28) if err != nil { return fmt.Errorf("could not write to dst: %s", err) } @@ -156,14 +158,13 @@ func (tags *ID3v11Tags) Write(dst io.WriteSeeker) error { // Track trackBytes := make([]byte, 1) binary.PutVarint(trackBytes, int64(tags.Track)) - // binary.BigEndian.PutUint16(trackBytes, uint16(tags.Track)) _, err = dst.Write(trackBytes) if err != nil { return fmt.Errorf("could not write to dst: %s", err) } //Genre - genreCode := getKey(id3v1genres, tags.Genre) + genreCode := util.GetKey(id3v1genres, tags.Genre) if genreCode == -1 { // if no genre found - encode genre code as 255 genreCode = ID3v1INVALIDGENRE @@ -171,7 +172,7 @@ func (tags *ID3v11Tags) Write(dst io.WriteSeeker) error { genrebyte := make([]byte, 1) binary.PutVarint(genrebyte, int64(genreCode)) - err = writeToExtent(dst, genrebyte, 1) + err = util.WriteToExtent(dst, genrebyte, 1) if err != nil { return fmt.Errorf("could not write to dst: %s", err) } @@ -186,7 +187,7 @@ func (tags *ID3v11Tags) WriteToFile(f *os.File) error { // check for existing ID3v1.1 tag f.Seek(-int64(ID3v1SIZE), io.SeekEnd) - tag, err := read(f, 3) + tag, err := util.Read(f, 3) if err != nil { return err } diff --git a/id3v11_test.go b/v1/id3v11_test.go similarity index 83% rename from id3v11_test.go rename to v1/id3v11_test.go index bf9f0c8..e1d864a 100644 --- a/id3v11_test.go +++ b/v1/id3v11_test.go @@ -1,8 +1,9 @@ -package id3ed +package v1 import ( "fmt" "os" + "path/filepath" "testing" ) @@ -17,7 +18,7 @@ var TESTV11TAGS = &ID3v11Tags{ } func TestGetID3v11Tags(t *testing.T) { - testfile, err := os.Open("./testData/testreadv1.mp3") + testfile, err := os.Open(filepath.Join(TESTDATAPATH, "testreadv1.mp3")) if err != nil { t.Errorf("could not open file for testing: %s", err) } @@ -38,7 +39,7 @@ func TestGetID3v11Tags(t *testing.T) { // WILL ADD NEW "TAG" WITHOUT REMOVING THE OLD ONE !!! func TestWriteID3v11Tags(t *testing.T) { - f, err := os.OpenFile("./testData/testwritev1.mp3", os.O_CREATE|os.O_RDWR, os.ModePerm) + f, err := os.OpenFile(filepath.Join(TESTDATAPATH, "testwritev1.mp3"), os.O_CREATE|os.O_RDWR, os.ModePerm) if err != nil { t.Errorf("%s", err) } @@ -70,7 +71,7 @@ func TestWriteID3v11Tags(t *testing.T) { } func TestWriteID3v11ToFile(t *testing.T) { - f, err := os.OpenFile("./testData/testwritev1.mp3", os.O_CREATE|os.O_RDWR, os.ModePerm) + f, err := os.OpenFile(filepath.Join(TESTDATAPATH, "testwritev1.mp3"), os.O_CREATE|os.O_RDWR, os.ModePerm) if err != nil { t.Errorf("%s", err) } diff --git a/constants.go b/v2/constants.go similarity index 52% rename from constants.go rename to v2/constants.go index d464fa3..a3ae2e3 100644 --- a/constants.go +++ b/v2/constants.go @@ -1,9 +1,4 @@ -package id3ed - -// ID3v1 -const ID3v1IDENTIFIER string = "TAG" -const ID3v1SIZE int = 128 // bytes -const ID3v1INVALIDGENRE int = 255 +package v2 //ID3v2 const ID3v2IDENTIFIER string = "ID3" diff --git a/id3v20.go b/v2/header.go similarity index 80% rename from id3v20.go rename to v2/header.go index d598aae..6b3a63d 100644 --- a/id3v20.go +++ b/v2/header.go @@ -1,4 +1,4 @@ -package id3ed +package v2 ////////////////////////////////////// //(ᗜˬᗜ)~⭐//Under construction//(ᗜ‸ᗜ)// @@ -9,6 +9,8 @@ import ( "fmt" "io" "strconv" + + "github.com/Unbewohnte/id3ed/util" ) // ID3v2.x header structure @@ -17,7 +19,7 @@ type Header struct { Version string Unsynchronisated bool Compressed bool - Size int64 + Size int64 // size of the whole tag - 10 header bytes } // Reads and structuralises ID3v2 header @@ -26,7 +28,7 @@ func GetHeader(rs io.ReadSeeker) (*Header, error) { rs.Seek(0, io.SeekStart) - identifier, err := read(rs, 3) + identifier, err := util.Read(rs, 3) if err != nil { return nil, err } @@ -37,27 +39,27 @@ func GetHeader(rs io.ReadSeeker) (*Header, error) { header.Identifier = string(identifier) // version - majorVersionByte, err := read(rs, 1) + majorVersionByte, err := util.Read(rs, 1) if err != nil { return nil, err } - revisionNumberByte, err := read(rs, 1) + revisionNumberByte, err := util.Read(rs, 1) if err != nil { return nil, err } - majorVersion, err := bytesToInt(majorVersionByte) + majorVersion, err := util.BytesToInt(majorVersionByte) if err != nil { return nil, err } - revisionNumber, err := bytesToInt(revisionNumberByte) + revisionNumber, err := util.BytesToInt(revisionNumberByte) if err != nil { return nil, err } header.Version = fmt.Sprintf("%d%d", -majorVersion, revisionNumber) // flags - flags, err := read(rs, 1) + flags, err := util.Read(rs, 1) if err != nil { return nil, err } @@ -74,7 +76,7 @@ func GetHeader(rs io.ReadSeeker) (*Header, error) { } // size - sizeBytes, err := read(rs, 4) + sizeBytes, err := util.Read(rs, 4) if err != nil { return nil, err } diff --git a/id3v20_test.go b/v2/header_test.go similarity index 81% rename from id3v20_test.go rename to v2/header_test.go index 8a80781..650d63a 100644 --- a/id3v20_test.go +++ b/v2/header_test.go @@ -1,12 +1,15 @@ -package id3ed +package v2 import ( "os" + "path/filepath" "testing" ) +var TESTDATAPATH string = filepath.Join("..", "testData") + func TestGetHeader(t *testing.T) { - f, err := os.Open("./testData/testreadv2.mp3") + f, err := os.Open(filepath.Join(TESTDATAPATH, "testreadv2.mp3")) if err != nil { t.Errorf("%s", err) }