-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfreedb.go
120 lines (103 loc) · 3.43 KB
/
freedb.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
// package freedb
// Copyright (C) 2019 Lars Lehtonen
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Package freedb can parse freedb.org dumps and insert into PostgreSQL.
package freedb
import (
"fmt"
"strings"
)
// These shard names are meaningless and vestigal, but are needed to
// disambiguate the freedb.org DISCID
var Shards = []string{
"blues",
"classical",
"country",
"data",
"folk",
"jazz",
"misc",
"newage",
"reggae",
"rock",
"soundtrack",
}
// Disc represents the parsed output of a freeDB dump
type Disc struct {
// IDs is a list of non-unique algorithmically-generated hashes identifying
// a compact disc stored in hexadecimal.
IDs [][]uint8
// Shard is an 8 bit unsigned int that represents the position of the shard
// in the Shards slice. These shards look like genre subdirectories, but
// that meaning is vestigal. The subdirectories are used as generic shard
// buckets to work around ID collisions.
Shard uint8
// Title is the combined artist name and release name of a compact disc.
Title string
// Genre is an optional field that represents the genre of music found
// on a compact disc.
Genre *string
// Year is an optional field denoting the release year of a compact disc.
Year *uint16
// Offsets are the positions on a CD where tracks begin.
Offsets []uint32
// Duration of the compact disc, in seconds.
Duration uint16
// Tracks is a slice of strings representing the track titles on a compact
// disc.
Tracks []string
}
// AppendTitle appends to the string that represents the compact disc title,
// ensuring that the string is valid UTF8.
func (d *Disc) AppendTitle(s string) {
d.Title = d.Title + strings.ToValidUTF8(s, "")
}
// AppendTrack appends to the track title in the given slice position,
// ensuring that the string is valid UTF8.
func (d *Disc) AppendTrack(s string, pos int) error {
switch {
case len(d.Tracks) == pos:
d.Tracks = append(d.Tracks, strings.ToValidUTF8(s, ""))
case len(d.Tracks) == pos+1:
d.Tracks[pos] = d.Tracks[pos] + strings.ToValidUTF8(s, "")
default:
return fmt.Errorf("attempted to append position %d to %d length slice",
pos, len(d.Tracks))
}
return nil
}
// ShardErr is the response to an unknown shard name.
type ShardErr struct {
shard string
}
// Error provides an error string for the ShardErr type.
func (e *ShardErr) Error() string {
return fmt.Sprintf("unknown shard name: %s", e.shard)
}
// ShardPos returns the shard position of a named shard as well as a ShardErr
// if the named shard does not exist.
func ShardPos(name string) (uint8, error) {
for i, s := range Shards {
if name == s {
return uint8(i), nil
}
}
return 0, &ShardErr{name}
}
// ComposeUID concatenates the non-unique DISCID with the unique shard number
// to create an actually unique ID.
func ComposeUID(discID []uint8, shard uint8) []uint8 {
return append(discID, uint8(shard))
}