-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
166 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ import ( | |
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"math/big" | ||
"os" | ||
"sync" | ||
|
||
|
@@ -268,3 +269,30 @@ func ExampleUnsynchronisedLyricsFrame_add() { | |
} | ||
tag.AddUnsynchronisedLyricsFrame(uslt) | ||
} | ||
|
||
func ExamplePopularimeterFrame_add() { | ||
tag := id3v2.NewEmptyTag() | ||
|
||
popmFrame := id3v2.PopularimeterFrame{ | ||
Email: "[email protected]", | ||
Rating: 128, | ||
Counter: big.NewInt(10000000000000000), | ||
} | ||
tag.AddFrame(tag.CommonID("Popularimeter"), popmFrame) | ||
} | ||
|
||
func ExamplePopularimeterFrame_get() { | ||
tag, err := id3v2.Open("file.mp3", id3v2.Options{Parse: true}) | ||
if tag == nil || err != nil { | ||
log.Fatal("Error while opening mp3 file: ", err) | ||
} | ||
|
||
f := tag.GetLastFrame(tag.CommonID("Popularimeter")) | ||
popm, ok := f.(id3v2.PopularimeterFrame) | ||
if !ok { | ||
log.Fatal("Couldn't assert POPM frame") | ||
} | ||
|
||
// do something with POPM Frame | ||
fmt.Printf("Email: %s, Rating: %d, Counter: %d", popm.Email, popm.Rating, popm.Counter) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package id3v2 | ||
|
||
import ( | ||
"io" | ||
"math/big" | ||
) | ||
|
||
// PopularimeterFrame structure is used for Popularimeter (POPM). | ||
// https://id3.org/id3v2.3.0#Popularimeter | ||
type PopularimeterFrame struct { | ||
// Email is the identifier for a POPM frame. | ||
Email string | ||
|
||
// The rating is 1-255 where 1 is worst and 255 is best. 0 is unknown. | ||
Rating uint8 | ||
|
||
// Counter is the number of times this file has been played by this email. | ||
Counter *big.Int | ||
} | ||
|
||
func (pf PopularimeterFrame) UniqueIdentifier() string { | ||
return pf.Email | ||
} | ||
|
||
func (pf PopularimeterFrame) Size() int { | ||
ratingSize := 1 | ||
return len(pf.Email) + 1 + ratingSize + len(pf.counterBytes()) | ||
} | ||
|
||
// counterBytes returns a byte slice that represents the counter. | ||
func (pf PopularimeterFrame) counterBytes() []byte { | ||
bytes := pf.Counter.Bytes() | ||
|
||
// Specification requires at least 4 bytes for counter, pad if necessary. | ||
bytesNeeded := 4 - len(bytes) | ||
if bytesNeeded > 0 { | ||
padding := make([]byte, bytesNeeded) | ||
bytes = append(padding, bytes...) | ||
} | ||
|
||
return bytes | ||
} | ||
|
||
func (pf PopularimeterFrame) WriteTo(w io.Writer) (n int64, err error) { | ||
return useBufWriter(w, func(bw *bufWriter) { | ||
bw.WriteString(pf.Email) | ||
bw.WriteByte(0) | ||
bw.WriteByte(pf.Rating) | ||
bw.Write(pf.counterBytes()) | ||
}) | ||
} | ||
|
||
func parsePopularimeterFrame(br *bufReader) (Framer, error) { | ||
email := br.ReadText(EncodingISO) | ||
rating := br.ReadByte() | ||
|
||
counter := big.NewInt(0) | ||
remainingBytes := br.ReadAll() | ||
counter = counter.SetBytes(remainingBytes) | ||
|
||
pf := PopularimeterFrame{ | ||
Email: string(email), | ||
Rating: rating, | ||
Counter: counter, | ||
} | ||
|
||
return pf, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package id3v2 | ||
|
||
import ( | ||
"bytes" | ||
"math/big" | ||
"testing" | ||
) | ||
|
||
// Make sure that counter of popularimeter is at least 4 bytes even if it's small number. | ||
func TestPopularimeterFrameSmallCounter(t *testing.T) { | ||
popmFrame := PopularimeterFrame{ | ||
Email: "[email protected]", | ||
Rating: 1, | ||
Counter: big.NewInt(1), | ||
} | ||
|
||
expectedBodyLength := len(popmFrame.Email) + 1 + 1 + 4 | ||
|
||
buf := new(bytes.Buffer) | ||
written, err := popmFrame.WriteTo(buf) | ||
if err != nil { | ||
t.Fatalf("Error by writing: %v", err) | ||
} | ||
|
||
if written != int64(expectedBodyLength) { | ||
t.Fatalf("Expected popularimeter frame body length: %v, got: %v", expectedBodyLength, written) | ||
} | ||
|
||
expectedCounter := []byte{0, 0, 0, 1} | ||
gotCounter := buf.Bytes()[expectedBodyLength-4:] | ||
if !bytes.Equal(expectedCounter, gotCounter) { | ||
t.Fatalf("Expected popularimeter counter: %v, got: %v", expectedCounter, gotCounter) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ import ( | |
"bytes" | ||
"fmt" | ||
"io/ioutil" | ||
"math/big" | ||
"os" | ||
"strings" | ||
"sync" | ||
|
@@ -20,10 +21,10 @@ const ( | |
frontCoverPath = "testdata/front_cover.jpg" | ||
backCoverPath = "testdata/back_cover.jpg" | ||
|
||
framesSize = 211948 | ||
framesSize = 211978 | ||
tagSize = tagHeaderSize + framesSize | ||
musicSize = 3840834 | ||
countOfFrames = 14 | ||
countOfFrames = 15 | ||
) | ||
|
||
var ( | ||
|
@@ -79,6 +80,12 @@ var ( | |
Text: "Der eigentliche Text", | ||
} | ||
|
||
popmFrame = PopularimeterFrame{ | ||
Email: "[email protected]", | ||
Rating: 128, | ||
Counter: big.NewInt(10000000000000000), | ||
} | ||
|
||
unknownFrameID = "WPUB" | ||
unknownFrame = UnknownFrame{ | ||
Body: []byte("https://soundcloud.com/suicidepart2"), | ||
|
@@ -117,6 +124,8 @@ func resetMP3Tag() error { | |
tag.AddUserDefinedTextFrame(musicBrainzUDTF) | ||
tag.AddUFIDFrame(musicBrainzUF) | ||
|
||
tag.AddFrame(tag.CommonID("Popularimeter"), popmFrame) | ||
|
||
tag.AddCommentFrame(engComm) | ||
tag.AddCommentFrame(gerComm) | ||
|
||
|
@@ -146,7 +155,7 @@ func TestCountLenSize(t *testing.T) { | |
} | ||
|
||
// Check len of tag.AllFrames(). | ||
if len(tag.AllFrames()) != 11 { | ||
if len(tag.AllFrames()) != 12 { | ||
t.Errorf("Expected: %v, got: %v", 11, len(tag.AllFrames())) | ||
} | ||
|
||
|