From 38b00e55b0e3a0a0dd541eab3ae1d3cf0a748a4d Mon Sep 17 00:00:00 2001 From: bel Date: Fri, 24 Mar 2023 19:51:38 -0600 Subject: [PATCH] split src/devices/input into src/devices/input/{raw,wrap} --- src/device/input/input.go | 57 ++---------------- src/device/input/input_exported_test.go | 16 +++--- src/device/input/input_test.go | 33 ----------- src/device/input/{ => raw}/keyboard.go | 19 ++---- src/device/input/{ => raw}/random.go | 24 ++------ src/device/input/{ => raw}/random_test.go | 2 +- src/device/input/raw/raw.go | 26 +++++++++ src/device/input/raw/raw_test.go | 9 +++ src/device/input/{ => raw}/udp.go | 21 +++---- src/device/input/{ => wrap}/buffered.go | 8 +-- src/device/input/wrap/button.go | 6 ++ src/device/input/{ => wrap}/refresh.go | 10 ++-- src/device/input/{ => wrap}/refresh_test.go | 7 ++- src/device/input/{ => wrap}/remap.go | 8 +-- src/device/input/wrap/wrap.go | 64 +++++++++++++++++++++ src/device/input/wrap/wrap_test.go | 10 ++++ 16 files changed, 161 insertions(+), 159 deletions(-) delete mode 100644 src/device/input/input_test.go rename src/device/input/{ => raw}/keyboard.go (75%) rename src/device/input/{ => raw}/random.go (80%) rename src/device/input/{ => raw}/random_test.go (98%) create mode 100644 src/device/input/raw/raw.go create mode 100644 src/device/input/raw/raw_test.go rename src/device/input/{ => raw}/udp.go (61%) rename src/device/input/{ => wrap}/buffered.go (90%) create mode 100644 src/device/input/wrap/button.go rename src/device/input/{ => wrap}/refresh.go (80%) rename src/device/input/{ => wrap}/refresh_test.go (83%) rename src/device/input/{ => wrap}/remap.go (83%) create mode 100644 src/device/input/wrap/wrap.go create mode 100644 src/device/input/wrap/wrap_test.go diff --git a/src/device/input/input.go b/src/device/input/input.go index e088922..b77ebff 100644 --- a/src/device/input/input.go +++ b/src/device/input/input.go @@ -2,63 +2,16 @@ package input import ( "context" - "os" - "strconv" - "syscall" + "mayhem-party/src/device/input/raw" + "mayhem-party/src/device/input/wrap" ) type Input interface { - Read() []Button + Read() []wrap.Button Close() } func New(ctx context.Context) Input { - return newNew(ctx)() -} - -func newNew(ctx context.Context) func() Input { - maker := newSourceFunc() - - if os.Getenv("INPUT_BUFFERED") == "true" { - oldMaker := maker - maker = func() Input { - return NewBuffered(ctx, oldMaker()) - } - } - if p := os.Getenv("INPUT_REMAP_FILE"); p != "" { - oldMaker := maker - maker = func() Input { - return NewRemapFromFile(oldMaker(), p) - } - } - if os.Getenv("INPUT_REFRESH_ON_SIGUSR1") != "" { - oldMaker := maker - c := NewRefreshCh(syscall.SIGUSR1) - maker = func() Input { - return NewRefresh(oldMaker, c) - } - } - return maker -} - -func newSourceFunc() func() Input { - if os.Getenv("INPUT_KEYBOARD") == "true" { - singletonKeyboard := NewKeyboard() - return func() Input { - return singletonKeyboard - } - } - if port, _ := strconv.Atoi(os.Getenv("INPUT_UDP")); port != 0 { - singletonUDP := NewUDP(port) - return func() Input { - return singletonUDP - } - } - return func() Input { - generator := randomCharFromRange('a', 'g') - if p, ok := os.LookupEnv("INPUT_RANDOM_WEIGHT_FILE"); ok && len(p) > 0 { - generator = randomCharFromWeightFile(p) - } - return NewRandom(generator) - } + src := raw.New(ctx) + return wrap.New(ctx, src) } diff --git a/src/device/input/input_exported_test.go b/src/device/input/input_exported_test.go index 27a1fc9..bc9e1b2 100644 --- a/src/device/input/input_exported_test.go +++ b/src/device/input/input_exported_test.go @@ -30,11 +30,11 @@ func TestNewRemapped(t *testing.T) { t.Fatal(err) } - os.Setenv("INPUT_REMAP_FILE", remap) - os.Setenv("INPUT_RANDOM_WEIGHT_FILE", rand) + os.Setenv("WRAP_REMAP_FILE", remap) + os.Setenv("RAW_RANDOM_WEIGHT_FILE", rand) t.Cleanup(func() { - os.Unsetenv("INPUT_REMAP_FILE") - os.Unsetenv("INPUT_RANDOM_WEIGHT_FILE") + os.Unsetenv("WRAP_REMAP_FILE") + os.Unsetenv("RAW_RANDOM_WEIGHT_FILE") }) r := input.New(context.Background()) @@ -50,9 +50,9 @@ func TestNewRemapped(t *testing.T) { } func TestNewBuffered(t *testing.T) { - os.Setenv("INPUT_BUFFERED", "true") + os.Setenv("WRAP_BUFFERED", "true") t.Cleanup(func() { - os.Unsetenv("INPUT_BUFFERED") + os.Unsetenv("WRAP_BUFFERED") }) r := input.New(context.Background()) @@ -71,9 +71,9 @@ func TestNewRandomWeightFile(t *testing.T) { t.Fatal(err) } - os.Setenv("INPUT_RANDOM_WEIGHT_FILE", p) + os.Setenv("RAW_RANDOM_WEIGHT_FILE", p) t.Cleanup(func() { - os.Unsetenv("INPUT_RANDOM_WEIGHT_FILE") + os.Unsetenv("RAW_RANDOM_WEIGHT_FILE") }) r := input.New(context.Background()) diff --git a/src/device/input/input_test.go b/src/device/input/input_test.go deleted file mode 100644 index 4eff7a6..0000000 --- a/src/device/input/input_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package input - -import ( - "context" - "os" - "testing" -) - -func TestInput(t *testing.T) { - var _ Input = &Random{} - var _ Input = Keyboard{} - var _ Input = &Buffered{} - var _ Input = Remap{} - var _ Input = &Refresh{} - var _ Input = UDP{} -} - -func TestNewNew(t *testing.T) { - t.Run("refreshing", func(t *testing.T) { - ctx, can := context.WithCancel(context.Background()) - defer can() - os.Setenv("INPUT_BUFFERED", "true") - os.Setenv("INPUT_REFRESH_ON_SIGUSR1", "true") - foo := New(ctx) - if refresh, ok := foo.(*Refresh); !ok { - t.Errorf("%T", foo) - } else if buffered, ok := refresh.input.(*Buffered); !ok { - t.Errorf("%T", refresh.input) - } else if _, ok := buffered.input.(*Random); !ok { - t.Errorf("%T", buffered.input) - } - }) -} diff --git a/src/device/input/keyboard.go b/src/device/input/raw/keyboard.go similarity index 75% rename from src/device/input/keyboard.go rename to src/device/input/raw/keyboard.go index 3c9cfc2..f9d53ee 100644 --- a/src/device/input/keyboard.go +++ b/src/device/input/raw/keyboard.go @@ -1,4 +1,4 @@ -package input +package raw import ( "io" @@ -44,25 +44,14 @@ func (kb Keyboard) Close() { } } -func (kb Keyboard) Read() []Button { +func (kb Keyboard) Read() []byte { b := make([]byte, 5) n, err := os.Stdin.Read(b) if err != nil && err != io.EOF { panic(err) } - - down := true - result := make([]Button, 0, n) - for i := 0; i < n; i++ { - if b[i] == '!' { - down = false - } else if b[i] != '\n' { - result = append(result, Button{Char: b[i], Down: down}) - down = true - } - } if os.Getenv("DEBUG") == "true" { - log.Printf("input.Keyboard.Read() %s => %+v", b[:n], result) + log.Printf("raw.Keyboard.Read() %s", b[:n]) } - return result + return b[:n] } diff --git a/src/device/input/random.go b/src/device/input/raw/random.go similarity index 80% rename from src/device/input/random.go rename to src/device/input/raw/random.go index 3039054..419041b 100644 --- a/src/device/input/random.go +++ b/src/device/input/raw/random.go @@ -1,4 +1,4 @@ -package input +package raw import ( "bytes" @@ -12,14 +12,9 @@ import ( "github.com/go-yaml/yaml" ) -type Button struct { - Char byte - Down bool -} - type Random struct { generator func() byte - down []Button + down []byte } func NewRandom(generator func() byte) *Random { @@ -30,19 +25,8 @@ func NewRandom(generator func() byte) *Random { func (r *Random) Close() { } -func (r *Random) Read() []Button { - if len(r.down) > 0 && rand.Int()%2 == 0 { - was := r.down - for i := range was { - was[i].Down = false - } - r.down = r.down[:0] - return was - } else { - c := Button{Char: r.generator(), Down: true} - r.down = append(r.down, c) - return []Button{c} - } +func (r *Random) Read() []byte { + return []byte{r.generator()} } func randomCharFromRange(start, stop byte) func() byte { diff --git a/src/device/input/random_test.go b/src/device/input/raw/random_test.go similarity index 98% rename from src/device/input/random_test.go rename to src/device/input/raw/random_test.go index 91feeeb..feeedd2 100644 --- a/src/device/input/random_test.go +++ b/src/device/input/raw/random_test.go @@ -1,4 +1,4 @@ -package input +package raw import ( "strings" diff --git a/src/device/input/raw/raw.go b/src/device/input/raw/raw.go new file mode 100644 index 0000000..e7145b4 --- /dev/null +++ b/src/device/input/raw/raw.go @@ -0,0 +1,26 @@ +package raw + +import ( + "context" + "os" + "strconv" +) + +type Raw interface { + Read() []byte + Close() +} + +func New(ctx context.Context) Raw { + if os.Getenv("RAW_KEYBOARD") == "true" { + return NewKeyboard() + } + if port, _ := strconv.Atoi(os.Getenv("RAW_UDP")); port != 0 { + return NewUDP(port) + } + generator := randomCharFromRange('a', 'g') + if p, ok := os.LookupEnv("RAW_RANDOM_WEIGHT_FILE"); ok && len(p) > 0 { + generator = randomCharFromWeightFile(p) + } + return NewRandom(generator) +} diff --git a/src/device/input/raw/raw_test.go b/src/device/input/raw/raw_test.go new file mode 100644 index 0000000..1e3036d --- /dev/null +++ b/src/device/input/raw/raw_test.go @@ -0,0 +1,9 @@ +package raw + +import "testing" + +func TestRaw(t *testing.T) { + var _ Raw = &Random{} + var _ Raw = UDP{} + var _ Raw = Keyboard{} +} diff --git a/src/device/input/udp.go b/src/device/input/raw/udp.go similarity index 61% rename from src/device/input/udp.go rename to src/device/input/raw/udp.go index 1d21e43..1d2b221 100644 --- a/src/device/input/udp.go +++ b/src/device/input/raw/udp.go @@ -1,7 +1,9 @@ -package input +package raw import ( + "log" "net" + "os" "strconv" ) @@ -19,26 +21,17 @@ func NewUDP(port int) UDP { } } -func (udp UDP) Read() []Button { +func (udp UDP) Read() []byte { panic("NEEDS TO BE IN BG THREAD SO WE CAN SHUT DOWN WITHOUT BLOCKING ON READ OR AT LEAST BE RESPONSIVE") buff := make([]byte, 1024) n, _, err := udp.conn.ReadFrom(buff) if err != nil { panic(err) } - buttons := make([]Button, 0, n) - down := true - for i := range buff[:n] { - if buff[i] == '!' { - down = false - } else { - if buff[i] != '\n' { - buttons = append(buttons, Button{Char: buff[i], Down: down}) - } - down = true - } + if os.Getenv("DEBUG") == "true" { + log.Printf("raw.UDP.Read() => %s", buff[:n]) } - return buttons + return buff[:n] } func (udp UDP) Close() { diff --git a/src/device/input/buffered.go b/src/device/input/wrap/buffered.go similarity index 90% rename from src/device/input/buffered.go rename to src/device/input/wrap/buffered.go index 2f10b8a..8e5331e 100644 --- a/src/device/input/buffered.go +++ b/src/device/input/wrap/buffered.go @@ -1,4 +1,4 @@ -package input +package wrap import ( "context" @@ -12,15 +12,15 @@ type Buffered struct { can context.CancelFunc lock sync.Mutex keys map[byte]int64 - input Input + input Wrap listenInterval time.Duration expirationInterval time.Duration } -func NewBuffered(ctx context.Context, input Input) *Buffered { +func NewBuffered(ctx context.Context, input Wrap) *Buffered { ctx, can := context.WithCancel(ctx) expirationInterval := time.Millisecond * 125 - if d, err := time.ParseDuration(os.Getenv("INPUT_BUFFERED_STICKY_DURATION")); err == nil { + if d, err := time.ParseDuration(os.Getenv("WRAP_BUFFERED_STICKY_DURATION")); err == nil { expirationInterval = d } result := &Buffered{ diff --git a/src/device/input/wrap/button.go b/src/device/input/wrap/button.go new file mode 100644 index 0000000..16ae08c --- /dev/null +++ b/src/device/input/wrap/button.go @@ -0,0 +1,6 @@ +package wrap + +type Button struct { + Char byte + Down bool +} diff --git a/src/device/input/refresh.go b/src/device/input/wrap/refresh.go similarity index 80% rename from src/device/input/refresh.go rename to src/device/input/wrap/refresh.go index 37748a0..d58ad20 100644 --- a/src/device/input/refresh.go +++ b/src/device/input/wrap/refresh.go @@ -1,4 +1,4 @@ -package input +package wrap import ( "context" @@ -9,7 +9,7 @@ import ( type Refresh struct { can context.CancelFunc - input Input + input Wrap } func NewRefreshCh(sig os.Signal) <-chan os.Signal { @@ -18,11 +18,11 @@ func NewRefreshCh(sig os.Signal) <-chan os.Signal { return c } -func NewRefresh(newInput func() Input, ch <-chan os.Signal) *Refresh { +func NewRefresh(newWrap func() Wrap, ch <-chan os.Signal) *Refresh { ctx, can := context.WithCancel(context.Background()) result := &Refresh{ can: can, - input: newInput(), + input: newWrap(), } go func() { defer log.Println("refreshing done") @@ -32,7 +32,7 @@ func NewRefresh(newInput func() Input, ch <-chan os.Signal) *Refresh { return case sig := <-ch: log.Println("refreshing for", sig) - result.input = newInput() + result.input = newWrap() } } }() diff --git a/src/device/input/refresh_test.go b/src/device/input/wrap/refresh_test.go similarity index 83% rename from src/device/input/refresh_test.go rename to src/device/input/wrap/refresh_test.go index 57f7558..a2a6b73 100644 --- a/src/device/input/refresh_test.go +++ b/src/device/input/wrap/refresh_test.go @@ -1,6 +1,7 @@ -package input +package wrap import ( + "mayhem-party/src/device/input/raw" "os" "syscall" "testing" @@ -9,9 +10,9 @@ import ( func TestRefresh(t *testing.T) { b := byte('a') - generator := func() Input { + generator := func() Wrap { b += byte(1) - return NewRandom(func() byte { return b }) + return explicit{src: raw.NewRandom(func() byte { return b })} } ch := make(chan os.Signal, 1) defer close(ch) diff --git a/src/device/input/remap.go b/src/device/input/wrap/remap.go similarity index 83% rename from src/device/input/remap.go rename to src/device/input/wrap/remap.go index 3eb777f..4c2c09c 100644 --- a/src/device/input/remap.go +++ b/src/device/input/wrap/remap.go @@ -1,4 +1,4 @@ -package input +package wrap import ( "os" @@ -7,11 +7,11 @@ import ( ) type Remap struct { - input Input + input Wrap m map[byte]byte } -func NewRemapFromFile(input Input, p string) Remap { +func NewRemapFromFile(input Wrap, p string) Remap { b, err := os.ReadFile(p) if err != nil { panic(err) @@ -30,7 +30,7 @@ func NewRemapFromFile(input Input, p string) Remap { return NewRemap(input, remap) } -func NewRemap(input Input, m map[byte]byte) Remap { +func NewRemap(input Wrap, m map[byte]byte) Remap { return Remap{ input: input, m: m, diff --git a/src/device/input/wrap/wrap.go b/src/device/input/wrap/wrap.go new file mode 100644 index 0000000..3bae9c4 --- /dev/null +++ b/src/device/input/wrap/wrap.go @@ -0,0 +1,64 @@ +package wrap + +import ( + "context" + "mayhem-party/src/device/input/raw" + "os" + "syscall" +) + +type Wrap interface { + Read() []Button + Close() +} + +func New(ctx context.Context, src raw.Raw) Wrap { + maker := func() Wrap { + return explicit{src: src} + } + if os.Getenv("WRAP_BUFFERED") == "true" { + oldMaker := maker + maker = func() Wrap { + return NewBuffered(ctx, oldMaker()) + } + } + if p := os.Getenv("WRAP_REMAP_FILE"); p != "" { + oldMaker := maker + maker = func() Wrap { + return NewRemapFromFile(oldMaker(), p) + } + } + if os.Getenv("WRAP_REFRESH_ON_SIGUSR1") != "" { + oldMaker := maker + c := NewRefreshCh(syscall.SIGUSR1) + maker = func() Wrap { + return NewRefresh(oldMaker, c) + } + } + return maker() +} + +type explicit struct { + src raw.Raw +} + +func (e explicit) Close() { + e.src.Close() +} + +func (e explicit) Read() []Button { + b := e.src.Read() + buttons := make([]Button, 0, len(b)) + down := true + for i := range b { + if b[i] == '!' { + down = false + } else { + if b[i] != '\n' { + buttons = append(buttons, Button{Char: b[i], Down: down}) + } + down = true + } + } + return buttons +} diff --git a/src/device/input/wrap/wrap_test.go b/src/device/input/wrap/wrap_test.go new file mode 100644 index 0000000..e03c574 --- /dev/null +++ b/src/device/input/wrap/wrap_test.go @@ -0,0 +1,10 @@ +package wrap + +import "testing" + +func TestWrap(t *testing.T) { + var _ Wrap = explicit{} + var _ Wrap = &Refresh{} + var _ Wrap = &Buffered{} + var _ Wrap = &Remap{} +}