From 22c13255a511609ea52d639d53c7a3219b9da346 Mon Sep 17 00:00:00 2001 From: Unbewohnte Date: Sat, 10 Jul 2021 15:12:09 +0300 Subject: [PATCH] =?UTF-8?q?=E2=97=8E=20Improved=20handling=20of=20frames?= =?UTF-8?q?=20in=20v2tag!=20=E2=97=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 15 ++++---- testData/testwritev1.mp3 | Bin 1825 -> 2081 bytes v2/frame_identifiers.go | 29 +++++++++++++++- v2/frame_identifiers_test.go | 24 +++++++++++++ v2/read.go | 10 ++---- v2/read_test.go | 10 ++++-- v2/v2tag.go | 65 ++++++++++++++++++++++++++++++++++- 7 files changed, 132 insertions(+), 21 deletions(-) create mode 100644 v2/frame_identifiers_test.go diff --git a/README.md b/README.md index b89187d..c39fb3d 100644 --- a/README.md +++ b/README.md @@ -119,15 +119,12 @@ func main() { panic(err) } - if mp3tag.Header.Version == id3v2.V2_3 { - // get certain frame by identifier. - // Contents is []byte. CAN AND PROBABLY WILL - // CONTAIN NULL OR OTHER NON-PRINTABLE BYTES !!! - // Text encoding support is still not implemented. - title := mp3tag.Frames["TIT2"].Contents - artist := mp3tag.Frames["TPE1"].Contents - } - + // you can get some essential frames` contents from getters + title := tag.Title() // string + + // or get direct frame by id + commentFrame := tag.GetFrame("COMM") // *Frame + // commentFrame.(Header.(...)|Contents) // etc. } diff --git a/testData/testwritev1.mp3 b/testData/testwritev1.mp3 index 69dfb02b143326261b393e5fa2ae28a7621269d2..35853da0b8a1ebb849fc255b945540ea860141b1 100644 GIT binary patch delta 11 ScmZ3;w@_e%BKzWn%!~jR+5>?A delta 7 OcmZ1|u#j(qB0B&IgaSDL diff --git a/v2/frame_identifiers.go b/v2/frame_identifiers.go index 204b6ed..3a02fbc 100644 --- a/v2/frame_identifiers.go +++ b/v2/frame_identifiers.go @@ -2,7 +2,7 @@ package v2 // from [https://id3.org/] -var V2_2FrameIdentifiers = map[string]string{ +var V2_2FrameIdentifiers = map[string]string{ "BUF": "Recommended buffer size", "CNT": "Play counter", "COM": "Comments", @@ -232,3 +232,30 @@ var V2_4FrameIdentifiers = map[string]string{ "WPUB": "Publishers official webpage", "WXXX": "User defined URL link frame", } + +// Searches for given ID3v2 frame identifier and returns its +// description if found, else returns a "" +func GetFIdentifierDescription(id string) string { + if len(id) == 3 { + // ID3v2.2.0 identifier + description, ok := V2_2FrameIdentifiers[id] + if !ok { + return "" + } + return description + + } else if len(id) == 4 { + // ID3v2.(3|4).0 identifier + description, ok := V2_3FrameIdentifiers[id] + if !ok { + // not in v3, search in v4 + description, ok = V2_4FrameIdentifiers[id] + if !ok { + return "" + } + } + return description + } + + return "" +} diff --git a/v2/frame_identifiers_test.go b/v2/frame_identifiers_test.go new file mode 100644 index 0000000..e2a0a3e --- /dev/null +++ b/v2/frame_identifiers_test.go @@ -0,0 +1,24 @@ +package v2 + +import "testing" + +func Test_GetFIdentifierDescription(t *testing.T) { + description := GetFIdentifierDescription("TIT2") + + if description != "Title/songname/content description" { + t.Errorf("GetFIdentifierDescription failed: expected description for TIT2 to be %s, got %s", + "Title/songname/content description", description) + } + + description = GetFIdentifierDescription("TBP") + if description != "BPM (Beats Per Minute)" { + t.Errorf("GetFIdentifierDescription failed: expected description for TBP to be %s, got %s", + "BPM (Beats Per Minute)", description) + } + + description = GetFIdentifierDescription("SomeInvalidFrameIDName") + if description != "" { + t.Errorf("GetFIdentifierDescription failed: expected description for SomeInvalidFrameIDName to be \"\", got %s", + description) + } +} diff --git a/v2/read.go b/v2/read.go index 5673d1f..37583d4 100644 --- a/v2/read.go +++ b/v2/read.go @@ -34,14 +34,8 @@ func ReadV2Tag(rs io.ReadSeeker) (*ID3v2Tag, error) { frames = append(frames, frame) } - // create a map from collected frames - framesMp := make(map[string]Frame) - for _, frame := range frames { - framesMp[frame.Header.ID] = frame - } - return &ID3v2Tag{ Header: header, - Frames: framesMp, + Frames: frames, }, nil -} +} \ No newline at end of file diff --git a/v2/read_test.go b/v2/read_test.go index 14f385d..a331446 100644 --- a/v2/read_test.go +++ b/v2/read_test.go @@ -19,10 +19,16 @@ func TestReadV2Tag(t *testing.T) { t.Errorf("GetV2Tag failed: %s", err) } - titleFrame := tag.Frames["TIT2"] + titleFrame := tag.GetFrame("TIT2") if util.ToStringLossy(titleFrame.Contents) != "title" { - t.Errorf("ReadV2Tag failed: expected contents to be %s; got %s", + t.Errorf("ReadV2Tag failed: expected contents of the title frame to be %s; got %s", "title", util.ToStringLossy(titleFrame.Contents)) } + + album := tag.Album() + if album != "album" { + t.Errorf("ReadV2Tag failed: expected contents of the album to be %s; got %s", + "album", album) + } } diff --git a/v2/v2tag.go b/v2/v2tag.go index c859d7d..4ca76d1 100644 --- a/v2/v2tag.go +++ b/v2/v2tag.go @@ -1,6 +1,69 @@ package v2 +import "github.com/Unbewohnte/id3ed/util" + type ID3v2Tag struct { Header Header - Frames map[string]Frame + Frames []Frame +} + +// Searches for frame with the same identifier as id in tag, +// returns &it if found +func (tag *ID3v2Tag) GetFrame(id string) *Frame { + for _, frame := range tag.Frames { + if frame.Header.ID == id { + return &frame + } + } + return nil +} + +// Returns the contents for the title frame +func (tag *ID3v2Tag) Title() string { + switch tag.Header.Version { + case V2_2: + return util.ToStringLossy(tag.GetFrame("TT2").Contents) + default: + return util.ToStringLossy(tag.GetFrame("TIT2").Contents) + } +} + +// Returns the contents for the album frame +func (tag *ID3v2Tag) Album() string { + switch tag.Header.Version { + case V2_2: + return util.ToStringLossy(tag.GetFrame("TAL").Contents) + default: + return util.ToStringLossy(tag.GetFrame("TALB").Contents) + } +} + +// Returns the contents for the artist frame +func (tag *ID3v2Tag) Artist() string { + switch tag.Header.Version { + case V2_2: + return util.ToStringLossy(tag.GetFrame("TP1").Contents) + default: + return util.ToStringLossy(tag.GetFrame("TPE1").Contents) + } +} + +// Returns the contents for the year frame +func (tag *ID3v2Tag) Year() string { + switch tag.Header.Version { + case V2_2: + return util.ToStringLossy(tag.GetFrame("TYE").Contents) + default: + return util.ToStringLossy(tag.GetFrame("TYER").Contents) + } +} + +// Returns the contents for the comment frame +func (tag *ID3v2Tag) Comment() string { + switch tag.Header.Version { + case V2_2: + return util.ToStringLossy(tag.GetFrame("COM").Contents) + default: + return util.ToStringLossy(tag.GetFrame("COMM").Contents) + } }