diff --git a/README.md b/README.md index 810ab49..36ef5ea 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# ID3ED (ID3- Encoder - Decoder) +# ID3ED (ID3 - Encoder - Decoder) ## Library for encoding/decoding ID3 tags -# Under construction ! \ No newline at end of file +# Under construction ! +## Bugs are a possibility rn in this state \ No newline at end of file diff --git a/id3v1.1.go b/id3v1.1.go new file mode 100644 index 0000000..72b5d41 --- /dev/null +++ b/id3v1.1.go @@ -0,0 +1,125 @@ +package id3ed + +import ( + "bytes" + "fmt" + "io" + "strconv" +) + +type ID3v11Tags struct { + SongName string + Artist string + Album string + Year int + Comment string + Track int + Genre int +} + +// Retrieves ID3v1.1 field values of provided io.ReadSeeker (usually a file) +func GetID3v11Tags(rs io.ReadSeeker) (*ID3v11Tags, error) { + // set reader to the last 128 bytes + _, err := rs.Seek(-int64(ID3V1SIZE), io.SeekEnd) + if err != nil { + return nil, fmt.Errorf("could not seek: %s", err) + } + + tag, err := read(rs, 3) + if err != nil { + return nil, err + } + + if !bytes.Equal(tag, []byte("TAG")) { + // no TAG, given file does not use ID3v1 + return nil, fmt.Errorf("does not use ID3v1") + } + + songname, err := read(rs, 30) + if err != nil { + return nil, err + } + + artist, err := read(rs, 30) + if err != nil { + return nil, err + } + + album, err := read(rs, 30) + if err != nil { + return nil, err + } + + yearBytes, err := read(rs, 4) + if err != nil { + return nil, err + } + year, err := strconv.Atoi(string(yearBytes)) + if err != nil { + return nil, fmt.Errorf("could not convert yearbytes into int: %s", err) + } + + comment, err := read(rs, 28) + if err != nil { + return nil, err + } + + // skip 1 null byte + _, err = read(rs, 1) + if err != nil { + return nil, err + } + + trackByte, err := read(rs, 1) + if err != nil { + return nil, err + } + + // track is one byte by specification + track := int(trackByte[0]) + + genreByte, err := read(rs, 1) + if err != nil { + return nil, err + } + // genre is one byte by specification + genre := int(genreByte[0]) + + return &ID3v11Tags{ + SongName: string(songname), + Artist: string(artist), + Album: string(album), + Year: year, + Comment: string(comment), + Track: track, + Genre: genre, + }, nil +} + +func (t *ID3v11Tags) GetSongName() string { + return t.SongName +} + +func (t *ID3v11Tags) GetArtist() string { + return t.Artist +} + +func (t *ID3v11Tags) GetAlbum() string { + return t.Album +} + +func (t *ID3v11Tags) GetYear() int { + return t.Year +} + +func (t *ID3v11Tags) GetComment() string { + return t.Comment +} + +func (t *ID3v11Tags) GetTrack() int { + return t.Track +} + +func (t *ID3v11Tags) GetGenre() int { + return t.Genre +} diff --git a/id3v1_test.go b/id3v1_test.go new file mode 100644 index 0000000..962ad32 --- /dev/null +++ b/id3v1_test.go @@ -0,0 +1,17 @@ +package id3ed + +import ( + "os" + "testing" +) + +func TestGetID3v1Tags(t *testing.T) { + testfile, err := os.Open("./testData/id3v1.txt") + if err != nil { + t.Errorf("could not open file for testing: %s", err) + } + _, err = GetID3v1Tags(testfile) + if err != nil { + t.Errorf("GetID3v1Tags failed: %s", err) + } +} diff --git a/testData/id3v1.txt b/testData/id3v1.txt new file mode 100644 index 0000000..c70ca64 Binary files /dev/null and b/testData/id3v1.txt differ