-
Notifications
You must be signed in to change notification settings - Fork 1
/
sfx.go
159 lines (130 loc) · 3.38 KB
/
sfx.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package mawt
// This module implements a sound effects generator that tracks the state of portal(s)
// based on portal state messages events that are sent to it, it then
// in turn queues up sounds effects to match.
import (
"fmt"
"os"
"strings"
"sync"
"time"
"github.com/TeamNorCal/mawt/model"
"github.com/karlmutch/errors"
)
type SFXState struct {
current *model.Status
last *model.Status
ambientC chan string
sfxC chan []string
sync.Mutex
}
func (sfx *SFXState) process(msg *model.PortalMsg) (err errors.Error) {
if msg == nil {
return nil
}
sfx.Lock()
current := msg.Status.DeepCopy()
lastState := sfx.current
sfx.Unlock()
state := msg.Status.DeepCopy()
// If there is no history add the fresh state as the previous state
//
forceAmbient := false
if lastState == nil {
lastState = current
forceAmbient = true
}
// Sounds effects that are gathered as a result of state
// and played back later
sfxs := []string{}
factionChange := lastState.Faction != state.Faction
if factionChange {
// e-loss, r-loss, n-loss
faction := strings.ToLower(lastState.Faction)
effect := faction + "-loss"
sfxs = append(sfxs, effect)
// e-capture, r-capture, n-capture
faction = strings.ToLower(state.Faction)
effect = faction + "-capture"
sfxs = append(sfxs, effect)
} else {
// If the new state was not a change of faction did the number
// of resonators change
}
if factionChange || forceAmbient {
ambient := ""
faction := strings.ToLower(state.Faction)
ambient = faction + "-ambient"
forceAmbient = false
go func() {
select {
case sfx.ambientC <- ambient:
case <-time.After(time.Second):
}
}()
}
// Check for sound effects that need to be played
if len(sfxs) != 0 {
go func() {
select {
case sfx.sfxC <- sfxs:
case <-time.After(time.Second):
}
}()
}
// Save the new state as the last known state
sfx.Lock()
sfx.last = sfx.current
sfx.current = current
sfx.Unlock()
return nil
}
// StartSFX will add itself to the subscriptions for portal messages
func StartSFX(subscribeC chan chan *model.PortalMsg, errorC chan<- errors.Error, quitC <-chan struct{}) {
sfx := &SFXState{
ambientC: make(chan string, 3),
sfxC: make(chan []string, 3),
}
if err := InitAudio(sfx.ambientC, sfx.sfxC, errorC, quitC); err != nil {
select {
case errorC <- err:
case <-time.After(100 * time.Millisecond):
fmt.Fprintf(os.Stderr, err.Error())
}
}
// Allow a lot of messages to queue up as we will only process the last one anyway
updateC := make(chan *model.PortalMsg, 10)
defer close(updateC)
// Subscribe to portal events
subscribeC <- updateC
// Attempt to set the default audio effects
select {
case sfx.ambientC <- "n-ambient":
case <-time.After(100 * time.Millisecond):
fmt.Fprintf(os.Stderr, "unable to start the neutral ambient SFX")
}
// Now listen to the subscribed portal events
for {
lastMsg := &model.PortalMsg{}
select {
case msg := <-updateC:
// Only process the most recent portal status msg for the Home portal in
// the channel, if we are backed up
if msg.Home {
lastMsg = msg.DeepCopy()
}
if len(updateC) == 0 && lastMsg != nil {
if err := sfx.process(lastMsg); err != nil {
select {
case errorC <- err:
case <-time.After(20 * time.Millisecond):
fmt.Fprintf(os.Stderr, err.Error())
}
}
lastMsg = nil
}
case <-quitC:
return
}
}
}