diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/dolmetschctl/dolmetschctl.go | 31 | ||||
-rw-r--r-- | cmd/dolmetschctld/dolmetschctld.go | 3 | ||||
-rw-r--r-- | cmd/dolmetschctld/statemachine.go | 115 | ||||
-rw-r--r-- | cmd/dolmetschctld/telnet.go | 3 | ||||
-rw-r--r-- | cmd/dolmetschctld/web.go | 23 | ||||
-rw-r--r-- | cmd/dolmetschctld/web_socket.go | 58 |
6 files changed, 87 insertions, 146 deletions
diff --git a/cmd/dolmetschctl/dolmetschctl.go b/cmd/dolmetschctl/dolmetschctl.go index a1598bc..1d8c6ad 100644 --- a/cmd/dolmetschctl/dolmetschctl.go +++ b/cmd/dolmetschctl/dolmetschctl.go @@ -25,10 +25,26 @@ package main import ( "log" "os" + "time" + "github.com/gorilla/websocket" "spreadspace.org/dolmetschctl/pkg/controller" + // "spreadspace.org/dolmetschctl/pkg/types" ) +func run(c *controller.Controller, ws *websocket.Conn) error { + ch := make(chan controller.Event, 100) + c.Subscribe(ch) + + for { + select { + case ev := <-ch: + log.Printf("got controller event: %v", ev) + } + } + return nil +} + func main() { log.Println("hello world.") @@ -43,14 +59,19 @@ func main() { log.Printf("Error initializeing the controller: %v", err) os.Exit(1) } - log.Printf("controller successfully initialized!") - ch := make(chan controller.Event, 100) - c.Subscribe(ch) for { - ev := <-ch - log.Printf("got controller event: %v", ev) + ws, _, err := websocket.DefaultDialer.Dial("ws://127.0.0.1:8234/api/v1/socket", nil) + if err != nil { + log.Printf("Error connecting to daemon: %v", err) + } else { + + err := run(c, ws) + log.Printf("run() returned: %v", err) + } + log.Printf("will retry in one second...") + time.Sleep(time.Second) } log.Printf("exiting.") diff --git a/cmd/dolmetschctld/dolmetschctld.go b/cmd/dolmetschctld/dolmetschctld.go index 9fa23fa..0f69b51 100644 --- a/cmd/dolmetschctld/dolmetschctld.go +++ b/cmd/dolmetschctld/dolmetschctld.go @@ -27,9 +27,10 @@ import ( "os" "spreadspace.org/dolmetschctl/pkg/mixer" + "spreadspace.org/dolmetschctl/pkg/types" ) -func addLanguage(sm *StateMachine, name Language, original, interpreter mixer.Channel) { +func addLanguage(sm *StateMachine, name types.Language, original, interpreter mixer.Channel) { if err := sm.AddLanguage(name, original, interpreter); err != nil { log.Printf("adding language '%s' failed: %v", name, err) os.Exit(1) diff --git a/cmd/dolmetschctld/statemachine.go b/cmd/dolmetschctld/statemachine.go index 2d8013f..a779604 100644 --- a/cmd/dolmetschctld/statemachine.go +++ b/cmd/dolmetschctld/statemachine.go @@ -29,54 +29,9 @@ import ( "time" "spreadspace.org/dolmetschctl/pkg/mixer" + "spreadspace.org/dolmetschctl/pkg/types" ) -type State int - -const ( - StateNew = iota - StateSettling - StateSettled -) - -func (s State) String() string { - switch s { - case StateNew: - return "new" - case StateSettling: - return "settling" - case StateSettled: - return "settled" - default: - return "unknown" - } -} - -func (s State) MarshalText() (data []byte, err error) { - data = []byte(s.String()) - return -} - -type Language string - -func (l Language) String() string { - if l == "" { - return "none" - } - return string(l) -} - -func (s Language) MarshalText() (data []byte, err error) { - data = []byte(s.String()) - return -} - -type FullState struct { - state State - ratio float32 - language Language -} - type MixerChannelState struct { level mixer.FaderLevel mute mixer.Mute @@ -94,16 +49,16 @@ type MixerChannels struct { } type setLanguageReq struct { - lang Language + lang types.Language resCh chan error } type getLanguageReq struct { - resCh chan Language + resCh chan types.Language } type getLanguagesReq struct { - resCh chan []Language + resCh chan []types.Language } type setOriginal2InterpreterRatioReq struct { @@ -116,7 +71,7 @@ type getOriginal2InterpreterRatioReq struct { } type getStateRes struct { - FullState + types.FullState } type getStateReq struct { @@ -124,7 +79,7 @@ type getStateReq struct { } type subscribeStateReq struct { - ch chan<- FullState + ch chan<- types.FullState resCh chan error } @@ -142,12 +97,12 @@ type StateMachine struct { exitedCh chan struct{} mixerEventCh chan mixer.Event - languages map[Language]*MixerChannels - channel2lang map[mixer.Channel]Language + languages map[types.Language]*MixerChannels + channel2lang map[mixer.Channel]types.Language - state State + state types.State original2InterpreterRatio float32 - language Language + language types.Language stateSubscribers list.List } @@ -157,13 +112,13 @@ func (sm *StateMachine) publishState() { for sub := sm.stateSubscribers.Front(); sub != nil; sub = next { next = sub.Next() - ch, ok := (sub.Value).(chan<- FullState) + ch, ok := (sub.Value).(chan<- types.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}: + case ch <- types.FullState{sm.state, sm.original2InterpreterRatio, sm.language}: default: // subscriber is not responding... // log.Printf("statemachine: removing subscriber '%v', because it is not responding", ch) @@ -173,7 +128,7 @@ func (sm *StateMachine) publishState() { } } -func (sm *StateMachine) subscribeState(out chan<- FullState) error { +func (sm *StateMachine) subscribeState(out chan<- types.FullState) error { // log.Printf("statemachine: %v subscribed to state changes", out) sm.stateSubscribers.PushBack(out) return nil @@ -222,10 +177,10 @@ func (sm *StateMachine) initMixer() { mcs.interpreter.target.level = mixer.FaderLevelOff } sm.language = "" - sm.state = StateSettled + sm.state = types.StateSettled } -func (sm *StateMachine) getLanguages() (langs []Language) { +func (sm *StateMachine) getLanguages() (langs []types.Language) { langs = append(langs, "none") for lang, _ := range sm.languages { langs = append(langs, lang) @@ -234,7 +189,7 @@ func (sm *StateMachine) getLanguages() (langs []Language) { } // the "current language" is what is currently spoken on stage -func (sm *StateMachine) setLanguage(l Language) error { +func (sm *StateMachine) setLanguage(l types.Language) error { if l == "none" { l = "" } @@ -283,18 +238,18 @@ func (sm *StateMachine) reconcile(ticker bool) { } } - if sm.state != StateSettled && !ticker { + if sm.state != types.StateSettled && !ticker { return } - sm.state = StateSettled + sm.state = types.StateSettled for _, mcs := range sm.languages { if mcs.original.target.level != mcs.original.current.level { sm.mixer.SetLevel(mcs.original.num, calcNextLevel(mcs.original.target.level, mcs.original.current.level)) - sm.state = StateSettling + sm.state = types.StateSettling } if mcs.interpreter.target.level != mcs.interpreter.current.level { sm.mixer.SetLevel(mcs.interpreter.num, calcNextLevel(mcs.interpreter.target.level, mcs.interpreter.current.level)) - sm.state = StateSettling + sm.state = types.StateSettling } } } @@ -311,7 +266,7 @@ func (sm *StateMachine) run() { select { case <-t.C: - if sm.state == StateSettling { + if sm.state == types.StateSettling { sm.reconcile(true) } case req := <-sm.setLanguageCh: @@ -327,7 +282,7 @@ func (sm *StateMachine) run() { case req := <-sm.getOriginal2InterpreterRatioCh: req.resCh <- sm.original2InterpreterRatio case req := <-sm.getStateCh: - req.resCh <- getStateRes{FullState{sm.state, sm.original2InterpreterRatio, sm.language}} + req.resCh <- getStateRes{types.FullState{sm.state, sm.original2InterpreterRatio, sm.language}} case req := <-sm.subscribeStateCh: req.resCh <- sm.subscribeState(req.ch) case ev := <-sm.mixerEventCh: @@ -356,17 +311,17 @@ func NewStateMachine(m *mixer.Mixer) (*StateMachine, error) { sm.exitedCh = make(chan struct{}) sm.mixerEventCh = make(chan mixer.Event, 1000) - sm.languages = make(map[Language]*MixerChannels) - sm.channel2lang = make(map[mixer.Channel]Language) + sm.languages = make(map[types.Language]*MixerChannels) + sm.channel2lang = make(map[mixer.Channel]types.Language) - sm.state = StateNew + sm.state = types.StateNew sm.language = "" return sm, nil } // TODO: currently we can only deal with 2 languages... -func (sm *StateMachine) AddLanguage(name Language, original, interpreter mixer.Channel) error { - if sm.state != StateNew { +func (sm *StateMachine) AddLanguage(name types.Language, original, interpreter mixer.Channel) error { + if sm.state != types.StateNew { return fmt.Errorf("adding languages is only allowed during startup") } if name == "none" { @@ -400,20 +355,20 @@ func (sm *StateMachine) Start() { go sm.run() } -func (sm *StateMachine) SetLanguage(l Language) error { +func (sm *StateMachine) SetLanguage(l types.Language) error { resCh := make(chan error) sm.setLanguageCh <- setLanguageReq{l, resCh} return <-resCh } -func (sm *StateMachine) GetLanguage() Language { - resCh := make(chan Language) +func (sm *StateMachine) GetLanguage() types.Language { + resCh := make(chan types.Language) sm.getLanguageCh <- getLanguageReq{resCh} return <-resCh } -func (sm *StateMachine) GetLanguages() []Language { - resCh := make(chan []Language) +func (sm *StateMachine) GetLanguages() []types.Language { + resCh := make(chan []types.Language) sm.getLanguagesCh <- getLanguagesReq{resCh} return <-resCh } @@ -430,14 +385,14 @@ func (sm *StateMachine) GetOriginal2InterpreterRatio() float32 { return <-resCh } -func (sm *StateMachine) GetState() (State, float32, Language) { +func (sm *StateMachine) GetState() (types.State, float32, types.Language) { resCh := make(chan getStateRes) sm.getStateCh <- getStateReq{resCh} res := <-resCh - return res.state, res.ratio, res.language + return res.State, res.Ratio, res.Language } -func (sm *StateMachine) SubscribeState(out chan<- FullState) error { +func (sm *StateMachine) SubscribeState(out chan<- types.FullState) error { resCh := make(chan error) sm.subscribeStateCh <- subscribeStateReq{out, resCh} return <-resCh diff --git a/cmd/dolmetschctld/telnet.go b/cmd/dolmetschctld/telnet.go index a5a4555..5618ebe 100644 --- a/cmd/dolmetschctld/telnet.go +++ b/cmd/dolmetschctld/telnet.go @@ -26,6 +26,7 @@ import ( "strconv" "github.com/spreadspace/telgo" + "spreadspace.org/dolmetschctl/pkg/types" ) type TelnetInterface struct { @@ -42,7 +43,7 @@ func telnetCmdLang(c *telgo.Client, args []string, sm *StateMachine) bool { return false } - if err := sm.SetLanguage(Language(args[1])); err != nil { + if err := sm.SetLanguage(types.Language(args[1])); err != nil { c.Sayln("selecting language failed: %v", err) } return false diff --git a/cmd/dolmetschctld/web.go b/cmd/dolmetschctld/web.go index 696169f..6ffcfea 100644 --- a/cmd/dolmetschctld/web.go +++ b/cmd/dolmetschctld/web.go @@ -26,6 +26,8 @@ import ( "encoding/json" "net/http" "time" + + "spreadspace.org/dolmetschctl/pkg/types" ) type WebInterface struct { @@ -48,17 +50,8 @@ func webSendResponse(w http.ResponseWriter, status int, respdata interface{}) { encoder.Encode(respdata) } -type webError struct { - ResponseCode int `json:"response-code"` - Error string `json:"error"` -} - func webSendErrorResponse(w http.ResponseWriter, status int, error string) { - webSendResponse(w, status, webError{ResponseCode: status, Error: error}) -} - -type webLanguage struct { - Lang Language `json:"language"` + webSendResponse(w, status, types.WebError{ResponseCode: status, Error: error}) } func webLanguageHandler(sm *StateMachine, w http.ResponseWriter, r *http.Request) { @@ -67,7 +60,7 @@ func webLanguageHandler(sm *StateMachine, w http.ResponseWriter, r *http.Request return } - var result webLanguage + var result types.WebLanguage dec := json.NewDecoder(r.Body) dec.DisallowUnknownFields() if err := dec.Decode(&result); err != nil { @@ -82,19 +75,13 @@ func webLanguageHandler(sm *StateMachine, w http.ResponseWriter, r *http.Request webSendResponse(w, http.StatusOK, result) } -type webState struct { - State State `json:"state"` - Ratio float32 `json:"original-to-interpreter-ratio"` - Lang Language `json:"language"` -} - func webStateHandler(sm *StateMachine, w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { webSendErrorResponse(w, http.StatusMethodNotAllowed, "only GET method is allowed") return } - var result webState + var result types.WebState result.State, result.Ratio, result.Lang = sm.GetState() webSendResponse(w, http.StatusOK, result) } diff --git a/cmd/dolmetschctld/web_socket.go b/cmd/dolmetschctld/web_socket.go index f904a1c..09f2efc 100644 --- a/cmd/dolmetschctld/web_socket.go +++ b/cmd/dolmetschctld/web_socket.go @@ -30,33 +30,9 @@ import ( "net/http" "github.com/gorilla/websocket" + "spreadspace.org/dolmetschctl/pkg/types" ) -type webSocketRequest struct { - Command string `json:"command"` - Args []string `json:"arguments"` -} - -type webSocketResponseBase struct { - ResponseCode int `json:"response-code"` - Type string `json:"type"` -} - -type webSocketResponseError struct { - webSocketResponseBase - ErrorString string `json:"error"` -} - -type webSocketResponseState struct { - webSocketResponseBase - webState -} - -type webSocketResponseLanguages struct { - webSocketResponseBase - Languages []Language `json:"languages"` -} - func sendWebSocketResponse(ws *websocket.Conn, rd interface{}) { if err := ws.WriteJSON(rd); err != nil { log.Println("Web(socket) client", ws.RemoteAddr(), "write error:", err) @@ -64,14 +40,14 @@ func sendWebSocketResponse(ws *websocket.Conn, rd interface{}) { } func sendWebSocketErrorResponse(ws *websocket.Conn, code int, errStr string) { - rd := &webSocketResponseError{} + rd := &types.WebSocketResponseError{} rd.ResponseCode = code rd.Type = "error" rd.ErrorString = errStr sendWebSocketResponse(ws, rd) } -func webSocketHandleRequest(ws *websocket.Conn, sm *StateMachine, req webSocketRequest, subCh chan<- FullState) { +func webSocketHandleRequest(ws *websocket.Conn, sm *StateMachine, req types.WebSocketRequest, subCh chan<- types.FullState) { switch req.Command { case "state": if len(req.Args) != 0 { @@ -79,7 +55,7 @@ func webSocketHandleRequest(ws *websocket.Conn, sm *StateMachine, req webSocketR return } - var result webSocketResponseState + var result types.WebSocketResponseState result.ResponseCode = http.StatusOK result.Type = "state" result.State, result.Ratio, result.Lang = sm.GetState() @@ -95,7 +71,7 @@ func webSocketHandleRequest(ws *websocket.Conn, sm *StateMachine, req webSocketR return } - var result webSocketResponseState + var result types.WebSocketResponseState result.ResponseCode = http.StatusOK result.Type = "state" result.State, result.Ratio, result.Lang = sm.GetState() @@ -106,7 +82,7 @@ func webSocketHandleRequest(ws *websocket.Conn, sm *StateMachine, req webSocketR return } - var result webSocketResponseLanguages + var result types.WebSocketResponseLanguages result.ResponseCode = http.StatusOK result.Type = "languages" result.Languages = sm.GetLanguages() @@ -117,12 +93,12 @@ func webSocketHandleRequest(ws *websocket.Conn, sm *StateMachine, req webSocketR return } - if err := sm.SetLanguage(Language(req.Args[0])); err != nil { + if err := sm.SetLanguage(types.Language(req.Args[0])); err != nil { sendWebSocketErrorResponse(ws, http.StatusBadRequest, err.Error()) return } - var result webSocketResponseState + var result types.WebSocketResponseState result.ResponseCode = http.StatusOK result.Type = "state" result.State, result.Ratio, result.Lang = sm.GetState() @@ -132,22 +108,22 @@ func webSocketHandleRequest(ws *websocket.Conn, sm *StateMachine, req webSocketR } } -func webSocketSessionHandler(ws *websocket.Conn, sm *StateMachine, reqCh <-chan webSocketRequest) { +func webSocketSessionHandler(ws *websocket.Conn, sm *StateMachine, reqCh <-chan types.WebSocketRequest) { defer ws.Close() - subCh := make(chan FullState, 100) + subCh := make(chan types.FullState, 100) for { select { case state, ok := <-subCh: if !ok { return } - var result webSocketResponseState + var result types.WebSocketResponseState result.ResponseCode = http.StatusOK result.Type = "state" - result.State = state.state - result.Ratio = state.ratio - result.Lang = state.language + result.State = state.State + result.Ratio = state.Ratio + result.Lang = state.Language sendWebSocketResponse(ws, result) case req, ok := <-reqCh: if !ok { @@ -168,20 +144,20 @@ func webSocketHandler(sm *StateMachine, w http.ResponseWriter, r *http.Request) return } log.Println("Web(socket) client", ws.RemoteAddr(), "connected") - reqCh := make(chan webSocketRequest) + reqCh := make(chan types.WebSocketRequest) go webSocketSessionHandler(ws, sm, reqCh) defer close(reqCh) for { t, r, err := ws.NextReader() if err != nil { - log.Println("Web(socket) Client", ws.RemoteAddr(), "disconnected:", err) + log.Println("Web(socket) client", ws.RemoteAddr(), "disconnected:", err) return } switch t { case websocket.TextMessage: - var req webSocketRequest + var req types.WebSocketRequest dec := json.NewDecoder(r) dec.DisallowUnknownFields() if err := dec.Decode(&req); err != nil { |