diff --git a/README.md b/README.md index 6546387..276b7ce 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ NixOS configuration for my three main machines (nixbook, nixpad, tuxcomp). | `flake.nix` | Inputs + one nixosConfigurations entry per hostname. | | `hosts//` | Configuration unique to each machine: hardware, wireguard tunnels. `hardware-configuration.nix` should not be edited as these are generated by `nixos-generate-config`. | | `modules/` | Everything shared; one file/folder per feature. | -| `secrets/` | sops-encrypted files + the only place `sops.secrets` are declared. | +| `secrets/` | Sops-encrypted files + the only place `sops.secrets` are declared. | | `patches/` | Custom patches, currently only a gamescope patch. | Each modules feature sets the required system options and packages. @@ -28,8 +28,7 @@ make update # update flake.lock nix fmt # format the Nix files (nixfmt) ``` -Do not run the above commands as root. -nixos-rebuild asks for the sudo password when it activates. +Run the above commmands as normal user. Generations older than 30 days are garbage-collected weekly. ## Secrets diff --git a/hosts/nixbook/default.nix b/hosts/nixbook/default.nix index 155d112..fc43853 100644 --- a/hosts/nixbook/default.nix +++ b/hosts/nixbook/default.nix @@ -1,4 +1,4 @@ -{ config, pkgs, ... }: +{ lib, config, pkgs, ... }: { imports = [ diff --git a/modules/apps.nix b/modules/apps.nix index 053a5a4..da8ac8e 100644 --- a/modules/apps.nix +++ b/modules/apps.nix @@ -40,6 +40,8 @@ # tools fastfetch gparted + killall + tealdeer unrar unzip zip diff --git a/modules/audio.nix b/modules/audio.nix deleted file mode 100644 index d113ee9..0000000 --- a/modules/audio.nix +++ /dev/null @@ -1,39 +0,0 @@ -{ pkgs, ... }: - -{ - services.pulseaudio.enable = false; - security.rtkit.enable = true; - - services.pipewire = { - enable = true; - alsa.enable = true; - alsa.support32Bit = true; - pulse.enable = true; - jack.enable = true; - - # disable automatic gain control for specific apps - extraConfig.pipewire-pulse."10-block-source-volume.conf"."pulse.rules" = [ - { - matches = [ - { "application.name" = "~Chromium.*"; } - { "application.process.binary" = "Discord"; } - { "application.process.binary" = "vesktop"; } - # TODO: add element to this list - ]; - actions.quirks = [ "block-source-volume" ]; - } - ]; - }; - - programs.nix-ld.libraries = [ pkgs.pipewire ]; - - # home-manager.users.djai.home.packages = with pkgs; [ - # pavucontrol - # qpwgraph - # ]; - - users.users.djai.packages = with pkgs; [ - pavucontrol - qpwgraph - ]; -} diff --git a/modules/audio/default.nix b/modules/audio/default.nix new file mode 100644 index 0000000..0889f14 --- /dev/null +++ b/modules/audio/default.nix @@ -0,0 +1,125 @@ +{ pkgs, ... }: + +let + linkSinksScript = pkgs.writeShellApplication { + name = "link-virtual-sinks"; + runtimeInputs = with pkgs; [ + coreutils + gnugrep + pipewire + ]; + runtimeEnv = { + USB_C_SINK = "alsa_output.usb-HP__Inc_HyperX_Cloud_III_Wireless_0000000000000000-00.analog-stereo"; + }; + text = builtins.readFile ./linkSinks.sh; + }; +in +{ + services.pulseaudio.enable = false; + security.rtkit.enable = true; + + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + jack.enable = true; + + # disable automatic gain control for specific apps + extraConfig.pipewire-pulse."10-block-source-volume.conf"."pulse.rules" = [ + { + matches = [ + { "application.name" = "~Chromium.*"; } + { "application.process.binary" = "Discord"; } + { "application.process.binary" = "vesktop"; } + # TODO: add element to this list + ]; + actions.quirks = [ "block-source-volume" ]; + } + ]; + + extraConfig.pipewire."91-virtual-sinks" = { + "context.objects" = [ + { + factory = "adapter"; + args = { + "factory.name" = "support.null-audio-sink"; + "node.name" = "game"; + "node.description" = "game"; + "media.class" = "Audio/Sink"; + "audio.position" = "FL,FR"; + }; + } + { + factory = "adapter"; + args = { + "factory.name" = "support.null-audio-sink"; + "node.name" = "clementine"; + "node.description" = "clementine"; + "media.class" = "Audio/Sink"; + "audio.position" = "FL,FR"; + }; + } + { + factory = "adapter"; + args = { + "factory.name" = "support.null-audio-sink"; + "node.name" = "element"; + "node.description" = "element"; + "media.class" = "Audio/Sink"; + "audio.position" = "FL,FR"; + }; + } + { + factory = "adapter"; + args = { + "factory.name" = "support.null-audio-sink"; + "node.name" = "combine"; + "node.description" = "combine"; + "media.class" = "Audio/Sink"; + "audio.position" = "FL,FR"; + }; + } + ]; + }; + + wireplumber.extraConfig."91-default-sink" = { + "wireplumber.settings" = { + "default.audio.sink" = "combine"; + }; + }; + }; + + programs.nix-ld.libraries = [ pkgs.pipewire ]; + + systemd.user.services.link-virtual-sinks = { + description = "Link virtual PipeWire sinks"; + + wantedBy = [ "graphical-session.target" ]; + wants = [ + "pipewire.service" + "wireplumber.service" + ]; + after = [ + "pipewire.service" + "wireplumber.service" + ]; + + serviceConfig = { + Type = "oneshot"; + ExecStart = "${linkSinksScript}/bin/link-virtual-sinks"; + RemainAfterExit = true; + }; + }; + + # home-manager.users.djai.home.packages = with pkgs; [ + # pavucontrol + # qpwgraph + # ]; + + users.users.djai.packages = with pkgs; [ + pavucontrol + pipewire + qpwgraph + ]; +} diff --git a/modules/audio/linkSinks.sh b/modules/audio/linkSinks.sh new file mode 100755 index 0000000..2426358 --- /dev/null +++ b/modules/audio/linkSinks.sh @@ -0,0 +1,40 @@ +# wait until pw-link port becomes available +# $1: port identifier +wait_for_port() { + for _ in $(seq 1 10); do + if pw-link -io 2>/dev/null | grep -Fq "$1"; then + return 0 + fi + sleep 1 + done + echo "Timed out waiting for PipeWire port: $1" >&2 + return 1 +} + +# link two pipewire ports together. waits for htme to exist first. +# $1: output port +# $2: input port +link_ports() { + wait_for_port "$1" + wait_for_port "$2" + + # pw-link errors if a link already exists, but we don't want that to fail the script + pw-link "$1" "$2" 2>/dev/null || true +} + +# link clementine -> combine +link_ports "clementine:monitor_FL" "combine:playback_FL" +link_ports "clementine:monitor_FR" "combine:playback_FR" + +# link element -> combine +link_ports "element:monitor_FL" "combine:playback_FL" +link_ports "element:monitor_FR" "combine:playback_FR" + +# link game -> combine +link_ports "game:monitor_FL" "combine:playback_FL" +link_ports "game:monitor_FR" "combine:playback_FR" + +# link combine -> usb_c_sink +link_ports "combine:monitor_FL" "$USB_C_SINK:playback_FL" +link_ports "combine:monitor_FR" "$USB_C_SINK:playback_FR" + diff --git a/modules/default.nix b/modules/default.nix index 4c208f5..2644bf8 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -2,7 +2,7 @@ imports = [ # ../secrets # TODO: uncomment ./apps.nix - ./audio.nix + ./audio ./base.nix ./desktop ./dev.nix diff --git a/modules/desktop/default.nix b/modules/desktop/default.nix index 4fc5ec7..a218e43 100644 --- a/modules/desktop/default.nix +++ b/modules/desktop/default.nix @@ -47,6 +47,7 @@ users.users.djai.packages = with pkgs; [ hyprpicker hyprsunset + hyprlandPlugins.hypr-darkwindow kanshi rofi waybar