forked from go-flac/flacvorbis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvorbis.go
129 lines (116 loc) · 3.09 KB
/
vorbis.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package flacvorbis
import (
"bytes"
"strings"
flac "github.com/go-flac/go-flac"
)
type MetaDataBlockVorbisComment struct {
Vendor string
Comments map[string][]string
}
// New creates a new MetaDataBlockVorbisComment
// vendor is set to flacvorbis <version> by default
func New() *MetaDataBlockVorbisComment {
return &MetaDataBlockVorbisComment{
"flacvorbis " + APP_VERSION,
make(map[string][]string),
}
}
// Gets the values of a tag if it exists, or an
// empty list if the tag is not present. If there
// is no tag, error would still be nil
func (c *MetaDataBlockVorbisComment) Get(key string) ([]string, error) {
if value, exists := c.Comments[strings.ToUpper(key)]; exists {
return value, nil
}
return []string{}, nil
}
// Add adds a value to an existing tag, or sets the tag if not present
func (c *MetaDataBlockVorbisComment) Add(key string, val string) error {
stdKey := strings.ToUpper(key)
for _, char := range stdKey {
if char < 0x20 || char > 0x7d || char == '=' {
return ErrorInvalidFieldName
}
}
if xval, exists := c.Comments[stdKey]; exists {
c.Comments[stdKey] = append(xval, val)
} else {
c.Comments[stdKey] = []string{val}
}
return nil
}
// Sets sets a new tag or replaces replaces the value of a existing tag
func (c *MetaDataBlockVorbisComment) Set(key string, val []string) error {
stdKey := strings.ToUpper(key)
for _, char := range stdKey {
if char < 0x20 || char > 0x7d || char == '=' {
return ErrorInvalidFieldName
}
}
c.Comments[stdKey] = val
return nil
}
// Marshal marshals this block back into a flac.MetaDataBlock
func (c MetaDataBlockVorbisComment) Marshal() flac.MetaDataBlock {
data := bytes.NewBuffer([]byte{})
packStr(data, c.Vendor)
data.Write(encodeUint32(uint32(len(c.Comments))))
for key, values := range c.Comments {
for _, value := range values {
packStr(data, key+"="+value)
}
}
return flac.MetaDataBlock{
Type: flac.VorbisComment,
Data: data.Bytes(),
}
}
// ParseFromMetaDataBlock parses an existing picture MetaDataBlock
func ParseFromMetaDataBlock(meta flac.MetaDataBlock) (*MetaDataBlockVorbisComment, error) {
if meta.Type != flac.VorbisComment {
return nil, ErrorNotVorbisComment
}
reader := bytes.NewReader(meta.Data)
res := new(MetaDataBlockVorbisComment)
vendorlen, err := readUint32(reader)
if err != nil {
return nil, err
}
vendorbytes := make([]byte, vendorlen)
nn, err := reader.Read(vendorbytes)
if err != nil {
return nil, err
}
if nn != int(vendorlen) {
return nil, ErrorUnexpEof
}
res.Vendor = string(vendorbytes)
cmtcount, err := readUint32(reader)
if err != nil {
return nil, err
}
res.Comments = make(map[string][]string, cmtcount)
var i uint32
for i = 0; i < cmtcount; i++ {
cmtlen, err := readUint32(reader)
if err != nil {
return nil, err
}
cmtbytes := make([]byte, cmtlen)
nn, err := reader.Read(cmtbytes)
if err != nil {
return nil, err
}
if nn != int(cmtlen) {
return nil, ErrorUnexpEof
}
p := strings.SplitN(string(cmtbytes), "=", 2)
if len(p) != 2 {
return nil, ErrorMalformedComment
}
key, val := p[0], p[1]
res.Add(key, val)
}
return res, nil
}