From 2154c5b763188e2ed1bedca911635805ff43b90a Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Wed, 13 Feb 2019 20:12:31 +0100 Subject: added state change subscription to state machine --- cmd/dolmetschctld/statemachine.go | 68 +++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 6 deletions(-) (limited to 'cmd/dolmetschctld/statemachine.go') 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: -- cgit v1.2.3