feat(nix): NixOS integration — ALSA_PLUGIN_DIR, nixosModule, home-manager module (#1025)

- Set ALSA_PLUGIN_DIR to PipeWire's alsa-lib path in package wrapper
  (NixOS store paths aren't in ALSA's default plugin search)
- Add nixosModules.default: udev rule for /dev/uinput, systemPackages
- Add homeManagerModules.default: systemd user service for autostart

Co-authored-by: zitongcharliedeng <zitongcharliedeng@users.noreply.github.com>
This commit is contained in:
COGnITO (mode: carbon) 2026-03-16 12:47:32 +00:00 committed by GitHub
parent cafc2b7208
commit cf284b1700
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 105 additions and 0 deletions

View file

@ -174,6 +174,7 @@
preFixup = ''
gappsWrapperArgs+=(
--set WEBKIT_DISABLE_DMABUF_RENDERER 1
--set ALSA_PLUGIN_DIR "${pkgs.pipewire}/lib/alsa-lib:${pkgs.alsa-plugins}/lib/alsa-lib"
--prefix LD_LIBRARY_PATH : "${
lib.makeLibraryPath [
pkgs.vulkan-loader
@ -196,6 +197,22 @@
}
);
# NixOS module for system-level integration (udev, input group)
nixosModules.default =
{ lib, pkgs, ... }:
{
imports = [ ./nix/module.nix ];
programs.handy.package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.handy;
};
# Home-manager module for per-user service
homeManagerModules.default =
{ lib, pkgs, ... }:
{
imports = [ ./nix/hm-module.nix ];
services.handy.package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.handy;
};
# Development shell for building from source
devShells = forAllSystems (
system:

41
nix/hm-module.nix Normal file
View file

@ -0,0 +1,41 @@
# Home-manager module for Handy speech-to-text
#
# Provides a systemd user service for autostart.
# Usage: imports = [ handy.homeManagerModules.default ];
# services.handy.enable = true;
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.handy;
in
{
options.services.handy = {
enable = lib.mkEnableOption "Handy speech-to-text user service";
package = lib.mkOption {
type = lib.types.package;
defaultText = lib.literalExpression "handy.packages.\${system}.handy";
description = "The Handy package to use.";
};
};
config = lib.mkIf cfg.enable {
systemd.user.services.handy = {
Unit = {
Description = "Handy speech-to-text";
After = [ "graphical-session.target" ];
PartOf = [ "graphical-session.target" ];
};
Service = {
ExecStart = "${cfg.package}/bin/handy";
Restart = "on-failure";
RestartSec = 5;
};
Install.WantedBy = [ "graphical-session.target" ];
};
};
}

47
nix/module.nix Normal file
View file

@ -0,0 +1,47 @@
# NixOS module for Handy speech-to-text
#
# Handles system-level configuration that the package wrapper cannot:
# - udev rule for /dev/uinput (rdev grab() needs it for virtual input)
#
# Note: users must add themselves to the "input" group for evdev hotkey access.
#
# Usage in your flake:
#
# inputs.handy.url = "github:cjpais/Handy";
#
# nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
# modules = [
# handy.nixosModules.default
# { programs.handy.enable = true; }
# ];
# };
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.handy;
in
{
options.programs.handy = {
enable = lib.mkEnableOption "Handy offline speech-to-text";
package = lib.mkOption {
type = lib.types.package;
defaultText = lib.literalExpression "handy.packages.\${system}.handy";
description = "The Handy package to use.";
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
# rdev grab() creates virtual input devices via /dev/uinput.
# Default permissions are crw------- root root — open it to the input group.
services.udev.extraRules = ''
KERNEL=="uinput", GROUP="input", MODE="0660"
'';
};
}