From 6817ecd90bfe388c853b823506892deab4440bbf Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Sun, 6 Sep 2026 17:55:21 -0400 Subject: [PATCH] Touch ups and additional capabilities added to fifo functionality. Sample Fenrir scripts in extra --- README.md | 7 ++++- extras/barnard__-__key_b.sh | 9 ++++++ extras/barnard__-__key_d.sh | 9 ++++++ extras/barnard_status__-__key_t.sh | 9 ++++++ ui.go | 47 +++++++++--------------------- uiterm/ui.go | 13 +++++++-- uiterm/ui_regression_test.go | 18 ++++++++++++ 7 files changed, 75 insertions(+), 37 deletions(-) create mode 100755 extras/barnard__-__key_b.sh create mode 100755 extras/barnard__-__key_d.sh create mode 100755 extras/barnard_status__-__key_t.sh diff --git a/README.md b/README.md index ef29ac8..0264d0e 100644 --- a/README.md +++ b/README.md @@ -62,14 +62,19 @@ Each command must end with a \n (0x0a) character. Commands may be added at any time. Per the robustness principle, be liberal in what you receive. Current Commands: -* error: An error has occured to prevent transmitting audio, or taking another action. * micup: Start transmitting, just as when you hold down the talk key. Does nothing if you are already transmiting. * micdown: Stop transmitting, just like when you release your talk key. Does nothing if you are not already transmitting. * toggle: Toggle your transmission state. * talk: Synonym for toggle. +* mute: Toggle self-mute, just like Alt+M by default. +* deafen: Toggle self-deafen, just like Alt+D by default. Self-deafening also mutes your microphone. * noise: Toggle noise suppression on/off for microphone input. * agc: Toggle automatic gain control on/off for microphone input. * record: Toggle recording. You may also use `record start` or `record stop`. +* file: Play an audio file or URL. The path or URL follows the command. +* stop: Stop file playback. +* status: Announce whether you are transmitting. +* admin: Run an admin command. See the admin command section below. * exit: Exit Barnard, just like when you press your quit key. ## Recording diff --git a/extras/barnard__-__key_b.sh b/extras/barnard__-__key_b.sh new file mode 100755 index 0000000..cabed58 --- /dev/null +++ b/extras/barnard__-__key_b.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# Script for fenrir +# Replace USER with your user name + +fifoPath=/home/USER/.config/barnard/cmd + +[[ -p $fifoPath ]] || exit 0 +printf '%s\n' talk | timeout 1s sudo -u USER tee "$fifoPath" &> /dev/null diff --git a/extras/barnard__-__key_d.sh b/extras/barnard__-__key_d.sh new file mode 100755 index 0000000..ffe0ead --- /dev/null +++ b/extras/barnard__-__key_d.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# Script for fenrir +# Replace USER with your user name + +fifoPath=/home/USER/.config/barnard/cmd + +[[ -p $fifoPath ]] || exit 0 +printf '%s\n' deafen | timeout 1s sudo -u USER tee "$fifoPath" &> /dev/null diff --git a/extras/barnard_status__-__key_t.sh b/extras/barnard_status__-__key_t.sh new file mode 100755 index 0000000..c74189d --- /dev/null +++ b/extras/barnard_status__-__key_t.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# Script for fenrir +# Replace USER with your user name + +fifoPath=/home/USER/.config/barnard/cmd + +[[ -p $fifoPath ]] || exit 0 +printf '%s\n' status | timeout 1s sudo -u USER tee "$fifoPath" &> /dev/null diff --git a/ui.go b/ui.go index a382b8b..e7753e4 100644 --- a/ui.go +++ b/ui.go @@ -327,6 +327,14 @@ func (b *Barnard) CommandTalk(ui *uiterm.Ui, cmd string) { b.setTransmit(ui, 2) } +func (b *Barnard) CommandSelfMute(ui *uiterm.Ui, cmd string) { + b.toggleSelfMute() +} + +func (b *Barnard) CommandSelfDeafen(ui *uiterm.Ui, cmd string) { + b.toggleSelfDeafen() +} + func (b *Barnard) CommandMicUp(ui *uiterm.Ui, cmd string) { b.setTransmit(ui, 1) } @@ -649,40 +657,11 @@ func (b *Barnard) OnTextInput(ui *uiterm.Ui, textbox *uiterm.Textbox, text strin // Check if this is a command (starts with /) if strings.HasPrefix(text, "/") { - // Remove the leading slash and process as command + // Remove the leading slash and process it through the same command + // registry used by FIFO control. cmdText := strings.TrimPrefix(text, "/") - parts := strings.SplitN(cmdText, " ", 2) - cmdName := parts[0] - cmdArgs := "" - if len(parts) > 1 { - cmdArgs = parts[1] - } - - // Handle built-in commands - switch cmdName { - case "file": - b.CommandPlayFile(ui, cmdArgs) - case "stop": - b.CommandStopFile(ui, cmdArgs) - case "exit": - b.CommandExit(ui, cmdArgs) - case "status": - b.CommandStatus(ui, cmdArgs) - case "noise": - b.CommandNoiseSuppressionToggle(ui, cmdArgs) - case "agc": - b.CommandAGCToggle(ui, cmdArgs) - case "record": - b.CommandRecord(ui, cmdArgs) - case "admin": - b.CommandAdmin(ui, cmdArgs) - case "micup": - b.CommandMicUp(ui, cmdArgs) - case "micdown": - b.CommandMicDown(ui, cmdArgs) - case "toggle", "talk": - b.CommandTalk(ui, cmdArgs) - default: + if !ui.DispatchCommand(cmdText) { + cmdName, _, _ := strings.Cut(cmdText, " ") b.AddOutputLine(fmt.Sprintf("Unknown command: /%s", cmdName)) } return @@ -766,6 +745,8 @@ func (b *Barnard) OnUiInitialize(ui *uiterm.Ui) { b.Ui.AddCommandListener(b.CommandMicDown, "micdown") b.Ui.AddCommandListener(b.CommandTalk, "toggle") b.Ui.AddCommandListener(b.CommandTalk, "talk") + b.Ui.AddCommandListener(b.CommandSelfMute, "mute") + b.Ui.AddCommandListener(b.CommandSelfDeafen, "deafen") b.Ui.AddCommandListener(b.CommandExit, "exit") b.Ui.AddCommandListener(b.CommandStatus, "status") b.Ui.AddCommandListener(b.CommandNoiseSuppressionToggle, "noise") diff --git a/uiterm/ui.go b/uiterm/ui.go index c6041b9..1871489 100644 --- a/uiterm/ui.go +++ b/uiterm/ui.go @@ -210,25 +210,32 @@ func (ui *Ui) onKeyEvent(key Key) { } func (ui *Ui) onCommandEvent(cmd string) { + ui.DispatchCommand(cmd) +} + +// DispatchCommand sends a command to its registered listeners and reports +// whether any listener accepted it. +func (ui *Ui) DispatchCommand(cmd string) bool { ta := strings.SplitN(cmd, " ", 2) t := ta[0] rest := "" if len(ta) == 2 { rest = ta[1] } + handled := false if ui.commandListeners[t] != nil { + handled = true for _, listener := range ui.commandListeners[t] { listener(ui, rest) } } if ui.commandListeners["*"] != nil { + handled = true for _, listener := range ui.commandListeners["*"] { listener(ui, cmd) } } - // if ui.activeElement != nil { - // ui.activeElement.View.uiKeyEvent(key) - // } + return handled } func (ui *Ui) Add(name string, view View) error { diff --git a/uiterm/ui_regression_test.go b/uiterm/ui_regression_test.go index 4598959..a309de3 100644 --- a/uiterm/ui_regression_test.go +++ b/uiterm/ui_regression_test.go @@ -43,3 +43,21 @@ func TestSafeRuneRemovesTerminalControlCharacters(t *testing.T) { t.Fatalf("safeRune altered printable text: %U", got) } } + +func TestDispatchCommandReportsMatchesAndPreservesArguments(t *testing.T) { + ui := New(nil) + got := "" + ui.AddCommandListener(func(_ *Ui, command string) { + got = command + }, "record") + + if !ui.DispatchCommand("record start") { + t.Fatal("registered command was not handled") + } + if got != "start" { + t.Fatalf("command argument = %q, want start", got) + } + if ui.DispatchCommand("unknown") { + t.Fatal("unknown command was reported as handled") + } +}