-
Notifications
You must be signed in to change notification settings - Fork 0
/
syncSlotMap.go
130 lines (121 loc) · 3.03 KB
/
syncSlotMap.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
130
package main
import (
"sync"
)
type syncSlotMap struct {
mtx sync.Mutex
m map[uint]*player
onPlayerChange func(slot uint, play *player) //this gets called whenever one of the players in the set is changed
}
func newSyncSlotMap() syncSlotMap {
return syncSlotMap{
m: make(map[uint]*player),
}
}
//setFileForSlot creates a new player for the given slot and uses the given filename for populating it.
//If the file does not exist or another problem occurs, an error will be returned
func (s *syncSlotMap) setFileForSlot(slot uint, filename string) error {
//check if file exists, othwerise nothing happens (nothing gets deleted)
if err := checkFilename(filename); err != nil {
return err
}
s.clearSlot(slot) //clear the slot.
s.mtx.Lock()
defer s.mtx.Unlock()
tmpPlay, err := newPlayer(filename)
if err != nil {
return err
}
tmpPlay.onChange = func(play *player) {
if s.onPlayerChange != nil {
s.onPlayerChange(slot, tmpPlay)
}
}
s.m[slot] = tmpPlay
go writeConfig()
return nil
}
//clearSlot clears the slot from a player. If no player exists, nothing happens.
func (s *syncSlotMap) clearSlot(slot uint) {
s.mtx.Lock()
defer s.mtx.Unlock()
if s.m[slot] != nil {
s.m[slot].drain()
delete(s.m, slot)
}
}
//getPlayer returns the player for the given slot. Can be nil, if no player was set.
func (s *syncSlotMap) getPlayer(slot uint) (play *player) {
s.mtx.Lock()
defer s.mtx.Unlock()
play = s.m[slot]
return
}
//getSlotItems returns a list with all items on the syncSlotMap
func (s *syncSlotMap) getSlotItems() (items []slotItem) {
s.mtx.Lock()
items = make([]slotItem, 0, len(s.m))
for slot := range s.m {
s.mtx.Unlock()
/*//getPoolItem is using implicit the mutex of this map too, so we temporarily unlock the mutex
s.mtx.Unlock()
poolItem, err := getPoolItem(player.filename)
if err != nil {
//if an error occured when reading the poolItem skip it
continue
}
item := slotItem{
Slot: slot,
Item: poolItem,
Player: playerItem{
Playing: !player.isPaused(),
Volume: player.volume(),
Loop: player.loop,
},
}
items = append(items, item)
s.mtx.Lock()*/
item, err := s.getSlotItem(slot)
if err != nil {
continue //when error, skip the slot
}
items = append(items, item)
s.mtx.Lock()
}
s.mtx.Unlock()
return
}
func (s *syncSlotMap) getSlotItem(slot uint) (item slotItem, err error) {
player := s.getPlayer(slot)
if player == nil {
return
}
poolItem, err := getPoolItem(player.filename)
if err != nil {
return
}
item = slotItem{
Slot: slot,
Item: poolItem,
Player: playerItem{
Playing: !player.isPaused(),
Volume: player.volume(),
Loop: player.loop,
Current: player.currentSample(),
Length: player.maxSample(),
Rate: player.sampleRate,
},
}
return
}
//checkIfUsed returns true if the file is used in the syncSlotMap
func (s *syncSlotMap) checkIfUsed(filename string) bool {
s.mtx.Lock()
defer s.mtx.Unlock()
for _, player := range s.m {
if player.filename == filename {
return true
}
}
return false
}