summaryrefslogtreecommitdiff
path: root/cmd/dolmetschctld/statemachine.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/dolmetschctld/statemachine.go')
-rw-r--r--cmd/dolmetschctld/statemachine.go68
1 files changed, 62 insertions, 6 deletions
diff --git a/cmd/dolmetschctld/statemachine.go b/cmd/dolmetschctld/statemachine.go
index 99416a5..2d8013f 100644
--- a/cmd/dolmetschctld/statemachine.go
+++ b/cmd/dolmetschctld/statemachine.go
@@ -23,6 +23,7 @@
package main
import (
+ "container/list"
"fmt"
"log"
"time"
@@ -70,6 +71,12 @@ func (s Language) MarshalText() (data []byte, err error) {
return
}
+type FullState struct {
+ state State
+ ratio float32
+ language Language
+}
+
type MixerChannelState struct {
level mixer.FaderLevel
mute mixer.Mute
@@ -109,15 +116,18 @@ type getOriginal2InterpreterRatioReq struct {
}
type getStateRes struct {
- state State
- ratio float32
- language Language
+ FullState
}
type getStateReq struct {
resCh chan getStateRes
}
+type subscribeStateReq struct {
+ ch chan<- FullState
+ resCh chan error
+}
+
type StateMachine struct {
mixer *mixer.Mixer
@@ -127,6 +137,7 @@ type StateMachine struct {
setOriginal2InterpreterRatioCh chan setOriginal2InterpreterRatioReq
getOriginal2InterpreterRatioCh chan getOriginal2InterpreterRatioReq
getStateCh chan getStateReq
+ subscribeStateCh chan subscribeStateReq
quitCh chan bool
exitedCh chan struct{}
mixerEventCh chan mixer.Event
@@ -134,10 +145,38 @@ type StateMachine struct {
languages map[Language]*MixerChannels
channel2lang map[mixer.Channel]Language
+ state State
original2InterpreterRatio float32
+ language Language
- state State
- language Language
+ stateSubscribers list.List
+}
+
+func (sm *StateMachine) publishState() {
+ var next *list.Element
+ for sub := sm.stateSubscribers.Front(); sub != nil; sub = next {
+ next = sub.Next()
+
+ ch, ok := (sub.Value).(chan<- FullState)
+ if !ok {
+ panic(fmt.Sprintf("statemachine: subscriber list element value has wrong type: %T", sub.Value))
+ }
+
+ select {
+ case ch <- FullState{sm.state, sm.original2InterpreterRatio, sm.language}:
+ default:
+ // subscriber is not responding...
+ // log.Printf("statemachine: removing subscriber '%v', because it is not responding", ch)
+ close(ch)
+ sm.stateSubscribers.Remove(sub)
+ }
+ }
+}
+
+func (sm *StateMachine) subscribeState(out chan<- FullState) error {
+ // log.Printf("statemachine: %v subscribed to state changes", out)
+ sm.stateSubscribers.PushBack(out)
+ return nil
}
func (sm *StateMachine) handleMixerEvent(ev mixer.Event) {
@@ -266,6 +305,10 @@ func (sm *StateMachine) run() {
sm.initMixer()
t := time.NewTicker(10 * time.Millisecond)
for {
+ oldState := sm.state
+ oldOriginal2InterpreterRadio := sm.original2InterpreterRatio
+ oldLanguage := sm.language
+
select {
case <-t.C:
if sm.state == StateSettling {
@@ -284,13 +327,19 @@ func (sm *StateMachine) run() {
case req := <-sm.getOriginal2InterpreterRatioCh:
req.resCh <- sm.original2InterpreterRatio
case req := <-sm.getStateCh:
- req.resCh <- getStateRes{sm.state, sm.original2InterpreterRatio, sm.language}
+ req.resCh <- getStateRes{FullState{sm.state, sm.original2InterpreterRatio, sm.language}}
+ case req := <-sm.subscribeStateCh:
+ req.resCh <- sm.subscribeState(req.ch)
case ev := <-sm.mixerEventCh:
sm.handleMixerEvent(ev)
sm.reconcile(false)
case <-sm.quitCh:
return
}
+
+ if oldState != sm.state || oldOriginal2InterpreterRadio != sm.original2InterpreterRatio || oldLanguage != sm.language {
+ sm.publishState()
+ }
}
}
@@ -302,6 +351,7 @@ func NewStateMachine(m *mixer.Mixer) (*StateMachine, error) {
sm.setOriginal2InterpreterRatioCh = make(chan setOriginal2InterpreterRatioReq, 10)
sm.getOriginal2InterpreterRatioCh = make(chan getOriginal2InterpreterRatioReq, 10)
sm.getStateCh = make(chan getStateReq, 10)
+ sm.subscribeStateCh = make(chan subscribeStateReq, 10)
sm.quitCh = make(chan bool, 1)
sm.exitedCh = make(chan struct{})
sm.mixerEventCh = make(chan mixer.Event, 1000)
@@ -387,6 +437,12 @@ func (sm *StateMachine) GetState() (State, float32, Language) {
return res.state, res.ratio, res.language
}
+func (sm *StateMachine) SubscribeState(out chan<- FullState) error {
+ resCh := make(chan error)
+ sm.subscribeStateCh <- subscribeStateReq{out, resCh}
+ return <-resCh
+}
+
func (sm *StateMachine) Shutdown() {
select {
case sm.quitCh <- true: