From 534377c8d22f3ef916b0b034b5331072973a0f40 Mon Sep 17 00:00:00 2001 From: kB01 Date: Mon, 10 Feb 2025 01:46:54 +0100 Subject: [PATCH] Restructured Numen Service --- modules/home/services/numen/default.nix | 78 ------------- modules/nixos/services/numen/default.nix | 105 ++++++++++++++++++ .../services/numen/phrases/character.phrases | 71 ++++++++++++ .../services/numen/phrases/control.phrases | 85 ++++++++++++++ .../numen/phrases/environment.phrases | 36 ++++++ .../services/numen/phrases/voice.phrases | 67 +++++++++++ 6 files changed, 364 insertions(+), 78 deletions(-) delete mode 100644 modules/home/services/numen/default.nix create mode 100644 modules/nixos/services/numen/default.nix create mode 100644 modules/nixos/services/numen/phrases/character.phrases create mode 100644 modules/nixos/services/numen/phrases/control.phrases create mode 100644 modules/nixos/services/numen/phrases/environment.phrases create mode 100644 modules/nixos/services/numen/phrases/voice.phrases diff --git a/modules/home/services/numen/default.nix b/modules/home/services/numen/default.nix deleted file mode 100644 index 8a1da0d..0000000 --- a/modules/home/services/numen/default.nix +++ /dev/null @@ -1,78 +0,0 @@ -{ config, lib, pkgs, ... }: -# Source: https://github.com/Lykos153/numen-nix -with lib; - -let - cfg = config.services.numen; -in -{ - options.services.numen = { - enable = mkOption { - type = types.bool; - default = false; - }; - - numenPkg = mkOption { - type = types.package; - default = pkgs.kb-one.numen; - }; - - # models = mkOption { - # type = types.uniq types.listOf types.package; - # default = [vosk-model-small-en-us]; - # example = "[vosk-model-small-en-us]"; - # description = '' - # List of vosk models to be loaded by numen. They can be referred to using the index, eg. model0 or model1. - # ''; - # }; - - model = mkOption { - type = types.pathInStore; - default = "${pkgs.kb-one.vosk-model-small-en-us}/usr/share/vosk-models/small-en-us/"; - example = "vosk-model-small-en-us"; - description = '' - Vosk model to be loaded by numen. - ''; - }; - - phrases = mkOption { - type = types.listOf types.path; - default = [ ]; - description = '' - Phrases to be loaded by numen. If empty, the default phrases are used. - ''; - }; - - extraArgs = mkOption { - type = types.singleLineStr; - default = ""; - description = '' - Additional arguments to be passed to numen. - ''; - }; - - dotoolXkbLayout = mkOption { - type = types.singleLineStr; - default = "en"; - description = '' - The XKB keyboard layout that should be used by dotool. - ''; - }; - }; - - config = mkIf cfg.enable { - systemd.user.services.numen = { - Unit = { - Description = "Numen voice control"; - After = [ "graphical-session-pre.target" ]; - PartOf = [ "graphical-session.target" ]; - }; - Install.WantedBy = [ "graphical-session.target" ]; - Service.Environment = [ - "DOTOOL_XKB_LAYOUT=${cfg.dotoolXkbLayout}" - "NUMEN_MODEL=${cfg.model}" - ]; - Service.ExecStart = "${cfg.numenPkg}/bin/numen ${cfg.extraArgs} ${lib.strings.concatStringsSep " " cfg.phrases}"; - }; - }; -} diff --git a/modules/nixos/services/numen/default.nix b/modules/nixos/services/numen/default.nix new file mode 100644 index 0000000..9841dd5 --- /dev/null +++ b/modules/nixos/services/numen/default.nix @@ -0,0 +1,105 @@ +{ config, lib, pkgs, ... }: +# Source: https://github.com/Lykos153/numen-nix +with lib; + +let + cfg = config.services.numen; +in +{ + options.services.numen = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enables Numen Voice Control. Only available to Users in Group "input". + ''; + }; + + numenPkg = mkOption { + type = types.package; + default = pkgs.kb-one.numen; + }; + + modelPkg = mkOption { + type = types.package; + default = pkgs.kb-one.vosk-model-small-en-us; + description = '' + Vosk model to be loaded by numen. Overrides modelPkg! + ''; + }; + + # models = mkOption { + # type = types.uniq types.listOf types.package; + # default = [vosk-model-small-en-us]; + # example = "[vosk-model-small-en-us]"; + # description = '' + # List of vosk models to be loaded by numen. They can be referred to using the index, eg. model0 or model1. + # ''; + # }; + + dotoolPkg = mkOption { + type = types.package; + default = pkgs.kb-one.dotool; + }; + + autoStart = mkOption { + type = types.bool; + default = true; + }; + + phrases = mkOption { + type = types.listOf types.path; + default = [ + ./phrases/character.phrases + ./phrases/control.phrases + ./phrases/environment.phrases + ./phrases/voice.phrases + ]; + description = '' + Phrases to be loaded by numen. If empty, the default phrases are used. + ''; + }; + + extraArgs = mkOption { + type = types.singleLineStr; + default = ""; + description = '' + Additional arguments to be passed to numen. + ''; + }; + + dotoolXkbLayout = mkOption { + type = types.singleLineStr; + default = "de"; + description = '' + The XKB keyboard layout that should be used by dotool. + ''; + }; + }; + + config = mkIf cfg.enable { + + # System Configuration + environment.systemPackages = [ + cfg.numenPkg + cfg.dotoolPkg + cfg.modelPkg + ]; + services.udev.extraRules = '' + KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput" + ''; + + # Enable AutoStart Service + systemd.user.services.numen = mkIf cfg.autoStart { + description = "Numen voice control"; + after = [ "graphical-session-pre.target" ]; + partOf = [ "graphical-session.target" ]; + wantedBy = [ "graphical-session.target" ]; + environment = { + DOTOOL_XKB_LAYOUT = "${cfg.dotoolXkbLayout}"; + NUMEN_MODEL = "${cfg.modelPkg}/usr/share/vosk-models/small-en-us/"; + }; + serviceConfig.ExecStart = "${cfg.numenPkg}/bin/numen ${cfg.extraArgs} ${lib.strings.concatStringsSep " " cfg.phrases}"; + }; + }; +} diff --git a/modules/nixos/services/numen/phrases/character.phrases b/modules/nixos/services/numen/phrases/character.phrases new file mode 100644 index 0000000..72198e8 --- /dev/null +++ b/modules/nixos/services/numen/phrases/character.phrases @@ -0,0 +1,71 @@ +air: press a +bat: press b +cap: press c +drum: press d +each: press e +fig: press f +gust: press g +hoof: press h +ice: press i +jive: press j +kid: press k +link: press l +made: press m +nerd: press n +odd: press o +pit: press p +quench: press q +red: press r +sun: press s +trap: press t +urge: press u +void: press v +whiz: press w +plex: press x +yank: press y +zip: press z + +newt: press 0 +one: press 1 +two: press 2 +three: press 3 +four: press 4 +five: press 5 +six: press 6 +sept: press 7 +eight: press 8 +nine: press 9 + +ask: press question +plus: press plus +mine: press minus +tide: press asciitilde +yell: press exclam +quid: press dollar +score: press underscore +clause: press colon +same: press semicolon +wax: press parenleft +wane: press parenright +curl: press braceleft +crimp: press braceright +bric: press bracketleft +brac: press bracketright +small: press less +big: press greater +star: press asterisk +hash: press numbersign +mood: press percent +blunt: press asciicircum +snail: press at +gain: press ampersand +vert: press bar +spoke: press quotedbl +mark: press apostrophe +tick: press grave +slash: press slash +slope: press backslash +list: press comma +point: press period +match: press equal + diff --git a/modules/nixos/services/numen/phrases/control.phrases b/modules/nixos/services/numen/phrases/control.phrases new file mode 100644 index 0000000..4168142 --- /dev/null +++ b/modules/nixos/services/numen/phrases/control.phrases @@ -0,0 +1,85 @@ +space: press space +yes: press Return +tab: press Tab +scape: stick off \ + press Escape + +# Enable a modifier for the next press +# (The Super modifier is also known as the "Windows key") +shy: mod shift +troy: mod ctrl +hype: mod alt +shock: mod super \ + stick off +# Clear modifiers +cleanse: mod clear \ + caps off \ + stick off + +# Enable Caps Lock until the end of the sentence or you say "cleanse" +shout: caps on +: caps off + +# Start holding down each pressed key, and stop by saying "cleanse" +squeeze: run notify-send STICKING & \ + stick off \ + stick on + +hack: press BackSpace +mince: press BackSpace BackSpace +toss: press Delete +smite: press Delete Delete +raze: press BackSpace BackSpace BackSpace BackSpace +# Delete a word (depending on the program) +swipe: press ctrl+BackSpace + +left: press Left +right: press Right +up: press Up +down: press Down +lunge: press Left Left +rush: press Right Right +leave: press Left Left Left Left +charge: press Right Right Right Right + +# I use these to navigate words and to complete bits of shell autosuggestions +stretch: press ctrl+Right +wrench: press ctrl+Left + +# PageDown, PageUp, Home, End +page: press Next +reel: press Prior +home: press Home +end: press End + +# Paste the clipboard (depending on the program) +gluten: stick off \ + press XF86Paste + +# Repeat the previous press etc. +more: repeat 1 +bunch: repeat 2 +handful: repeat 4 +fistful: repeat 8 +plateful: repeat 12 + +frank one: press F1 +frank two: press F2 +frank three: press F3 +frank four: press F4 +frank five: press F5 +frank six: press F6 +frank sept: press F7 +frank eight: press F8 +frank nine: press F9 +frank one newt: press F10 +frank one one: press F11 +frank one two: press F12 + +# This saves your changes in vi-style programs +save: caps off \ + press Escape colon w Return +# This cycles round splits in Vim +switch: caps off \ + press Escape ctrl+w w + diff --git a/modules/nixos/services/numen/phrases/environment.phrases b/modules/nixos/services/numen/phrases/environment.phrases new file mode 100644 index 0000000..53f563e --- /dev/null +++ b/modules/nixos/services/numen/phrases/environment.phrases @@ -0,0 +1,36 @@ +# I use these for managing application windows but they just simulate keys, +# so you'll need to configure your desktop environment, or you can use my +# preconfigured desktop environment: https://git.sr.ht/~geb/tiles + +# Navigate to the window in the given direction +west: stick off \ + press super+Left +east: stick off \ + press super+Right +north: stick off \ + press super+Up +south: stick off \ + press super+Down + +# Cycle round the windows +cycle: stick off \ + press super+c +recycle: stick off \ + press super+C + +# Close window +exterminate: stick off \ + press super+q + +# Toggle fullscreen +screen: stick off \ + press super+f + + + +# These two are just for --gadget mode. + +# Switch to controlling the gadget +@gadget shock gadget: handler uinput +# Switch to controlling the host machine +@gadget shock host: handler gadget diff --git a/modules/nixos/services/numen/phrases/voice.phrases b/modules/nixos/services/numen/phrases/voice.phrases new file mode 100644 index 0000000..c773dda --- /dev/null +++ b/modules/nixos/services/numen/phrases/voice.phrases @@ -0,0 +1,67 @@ +# Cancel sentence +# For example, "four down no five down" would just do "five down". +@cancel no: + +# Transcribe a sentence +# For example, "scribe please type this". +@transcribe scribe: set numen_fmt echo normal \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 + +# Transcribe a sentence formatted... + +# With the first letter uppercase +@transcribe scrub: set numen_fmt echo sentence \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 +# With Each First Letter Uppercase +@transcribe tight scribe: set numen_fmt echo title \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 +# with_underscrores_inbetween +@transcribe snake: set numen_fmt echo snake \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 +# with-dashes-inbetween +@transcribe dash: set numen_fmt echo dash \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 +# with.dots.inbetween +@transcribe dot scribe: set numen_fmt echo dot \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 +# with, commas, inbetween +@transcribe roh scribe: set numen_fmt echo list \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 +# with/slashes/inbetween +@transcribe path scribe: set numen_fmt echo path \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 +# allsmashedtogether +@transcribe kludge: set numen_fmt echo smash \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 +# camelCase +@transcribe camel: set numen_fmt echo camel \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 +# PascalCase +@transcribe pascal: set numen_fmt echo pascal \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 +# dot.camelCase +@transcribe dot camel: set numen_fmt echo dotcamel \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 +# dot.PascalCase +@transcribe dot pascal: set numen_fmt echo dotpascal \ + pen /etc/numen/scripts/tweak; /etc/numen/scripts/transcripts | head -n 1 +# (You can also do "shout scribe" etc.) + +# Erase the transcription +ditch: eval /etc/numen/scripts/transcripts | sed 's/./ BackSpace/g; s/^/press/; q' + +# Go to the start of the transcription +trudge: eval /etc/numen/scripts/transcripts | sed 's/./ Left/g; s/^/press/; q' + +# Menus to type or choose another transcription result +# They use the dmenu command (only works in X11) or the command specified +# by $NUMEN_DMENU or $DMENU (you could use wmenu if you're on Wayland). +transcripts: run /etc/numen/scripts/menu | numenc & \ + run sleep 0.1 +change: run /etc/numen/scripts/menu change | numenc & \ + run sleep 0.1 + + +# Ignore this, vosk-model-small-en-us-0.15 can output huh after a long silence. +huh: +