diff --git a/hosts/vali/mars/programs.nix b/hosts/vali/mars/programs.nix index ab0fbb8..44dfaab 100644 --- a/hosts/vali/mars/programs.nix +++ b/hosts/vali/mars/programs.nix @@ -56,6 +56,7 @@ in { strawberry telegram-desktop texliveFull + thunderbird tor-browser-bundle-bin trash-cli tree diff --git a/modules/gui/vivado2.nix b/modules/gui/vivado2.nix new file mode 100644 index 0000000..c73846f --- /dev/null +++ b/modules/gui/vivado2.nix @@ -0,0 +1,58 @@ +{ config, lib, pkgs, ...}: + +let + vivado-desktop-symbol = pkgs.makeDesktopItem { + name = "vivado-2022_2"; + desktopName = "Vivado"; + exec = "${pkgs.nur.repos.lschuermann.vivado-2022_2}/bin/vivado"; + }; + cfg = with lib; [ config.myOptions.programs.vivado ]; + username = with lib; [ config.myOptions.other.system.username ]; +in +{ + options.myOptions.programs.vivado.enable = mkEnableOption "vivado"; + + config = mkIf cfg.enable { + home-manager.users.${username} = { + environment.systemPackages = with pkgs; [ + # this propietary software is huge, but I need it for + # university + pkgs.nur.repos.lschuermann.vivado-2022_2 + vivado-desktop-symbol + ]; + + + # Create udev rules. Reference: https://blog.kotatsu.dev/posts/2021-09-14-vivado-on-nixos/ + services.udev.packages = [ + (pkgs.writeTextFile { + name = "xilinx-dilligent-usb-udev"; + destination = "/etc/udev/rules.d/52-xilinx-digilent-usb.rules"; + text = '' + ATTR{idVendor}=="1443", MODE:="666" + ACTION=="add", ATTR{idVendor}=="0403", ATTR{manufacturer}=="Digilent", MODE:="666" + ''; + }) + (pkgs.writeTextFile { + name = "xilinx-pcusb-udev"; + destination = "/etc/udev/rules.d/52-xilinx-pcusb.rules"; + text = '' + ATTR{idVendor}=="03fd", ATTR{idProduct}=="0008", MODE="666" + ATTR{idVendor}=="03fd", ATTR{idProduct}=="0007", MODE="666" + ATTR{idVendor}=="03fd", ATTR{idProduct}=="0009", MODE="666" + ATTR{idVendor}=="03fd", ATTR{idProduct}=="000d", MODE="666" + ATTR{idVendor}=="03fd", ATTR{idProduct}=="000f", MODE="666" + ATTR{idVendor}=="03fd", ATTR{idProduct}=="0013", MODE="666" + ATTR{idVendor}=="03fd", ATTR{idProduct}=="0015", MODE="666" + ''; + }) + (pkgs.writeTextFile { + name = "xilinx-ftdi-usb-udev"; + destination = "/etc/udev/rules.d/52-xilinx-ftdi-usb.rules"; + text = '' + ACTION=="add", ATTR{idVendor}=="0403", ATTR{manufacturer}=="Xilinx", MODE:="666" + ''; + }) + ]; + }; + }; +} diff --git a/modules/other/autorandr.nix b/modules/other/autorandr.nix new file mode 100644 index 0000000..f9b4d7c --- /dev/null +++ b/modules/other/autorandr.nix @@ -0,0 +1,370 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.services.autorandr; + hookType = types.lines; + + matrixOf = n: m: elemType: + mkOptionType rec { + name = "matrixOf"; + description = + "${toString n}×${toString m} matrix of ${elemType.description}s"; + check = xss: + let listOfSize = l: xs: isList xs && length xs == l; + in listOfSize n xss + && all (xs: listOfSize m xs && all elemType.check xs) xss; + merge = mergeOneOption; + getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "*" "*" ]); + getSubModules = elemType.getSubModules; + substSubModules = mod: matrixOf n m (elemType.substSubModules mod); + functor = (defaultFunctor name) // { wrapped = elemType; }; + }; + + profileModule = types.submodule { + options = { + fingerprint = mkOption { + type = types.attrsOf types.str; + description = lib.mdDoc '' + Output name to EDID mapping. + Use `autorandr --fingerprint` to get current setup values. + ''; + default = { }; + }; + + config = mkOption { + type = types.attrsOf configModule; + description = lib.mdDoc "Per output profile configuration."; + default = { }; + }; + + hooks = mkOption { + type = hooksModule; + description = lib.mdDoc "Profile hook scripts."; + default = { }; + }; + }; + }; + + configModule = types.submodule { + options = { + enable = mkOption { + type = types.bool; + description = lib.mdDoc "Whether to enable the output."; + default = true; + }; + + crtc = mkOption { + type = types.nullOr types.ints.unsigned; + description = lib.mdDoc "Output video display controller."; + default = null; + example = 0; + }; + + primary = mkOption { + type = types.bool; + description = lib.mdDoc "Whether output should be marked as primary"; + default = false; + }; + + position = mkOption { + type = types.str; + description = lib.mdDoc "Output position"; + default = ""; + example = "5760x0"; + }; + + mode = mkOption { + type = types.str; + description = lib.mdDoc "Output resolution."; + default = ""; + example = "3840x2160"; + }; + + rate = mkOption { + type = types.str; + description = lib.mdDoc "Output framerate."; + default = ""; + example = "60.00"; + }; + + gamma = mkOption { + type = types.str; + description = lib.mdDoc "Output gamma configuration."; + default = ""; + example = "1.0:0.909:0.833"; + }; + + rotate = mkOption { + type = types.nullOr (types.enum [ "normal" "left" "right" "inverted" ]); + description = lib.mdDoc "Output rotate configuration."; + default = null; + example = "left"; + }; + + transform = mkOption { + type = types.nullOr (matrixOf 3 3 types.float); + default = null; + example = literalExpression '' + [ + [ 0.6 0.0 0.0 ] + [ 0.0 0.6 0.0 ] + [ 0.0 0.0 1.0 ] + ] + ''; + description = lib.mdDoc '' + Refer to + {manpage}`xrandr(1)` + for the documentation of the transform matrix. + ''; + }; + + dpi = mkOption { + type = types.nullOr types.ints.positive; + description = lib.mdDoc "Output DPI configuration."; + default = null; + example = 96; + }; + + scale = mkOption { + type = types.nullOr (types.submodule { + options = { + method = mkOption { + type = types.enum [ "factor" "pixel" ]; + description = lib.mdDoc "Output scaling method."; + default = "factor"; + example = "pixel"; + }; + + x = mkOption { + type = types.either types.float types.ints.positive; + description = lib.mdDoc "Horizontal scaling factor/pixels."; + }; + + y = mkOption { + type = types.either types.float types.ints.positive; + description = lib.mdDoc "Vertical scaling factor/pixels."; + }; + }; + }); + description = lib.mdDoc '' + Output scale configuration. + + Either configure by pixels or a scaling factor. When using pixel method the + {manpage}`xrandr(1)` + option + `--scale-from` + will be used; when using factor method the option + `--scale` + will be used. + + This option is a shortcut version of the transform option and they are mutually + exclusive. + ''; + default = null; + example = literalExpression '' + { + x = 1.25; + y = 1.25; + } + ''; + }; + }; + }; + + hooksModule = types.submodule { + options = { + postswitch = mkOption { + type = types.attrsOf hookType; + description = lib.mdDoc "Postswitch hook executed after mode switch."; + default = { }; + }; + + preswitch = mkOption { + type = types.attrsOf hookType; + description = lib.mdDoc "Preswitch hook executed before mode switch."; + default = { }; + }; + + predetect = mkOption { + type = types.attrsOf hookType; + description = lib.mdDoc '' + Predetect hook executed before autorandr attempts to run xrandr. + ''; + default = { }; + }; + }; + }; + + hookToFile = folder: name: hook: + nameValuePair "xdg/autorandr/${folder}/${name}" { + source = "${pkgs.writeShellScriptBin "hook" hook}/bin/hook"; + }; + profileToFiles = name: profile: + with profile; + mkMerge ([ + { + "xdg/autorandr/${name}/setup".text = concatStringsSep "\n" + (mapAttrsToList fingerprintToString fingerprint); + "xdg/autorandr/${name}/config".text = + concatStringsSep "\n" (mapAttrsToList configToString profile.config); + } + (mapAttrs' (hookToFile "${name}/postswitch.d") hooks.postswitch) + (mapAttrs' (hookToFile "${name}/preswitch.d") hooks.preswitch) + (mapAttrs' (hookToFile "${name}/predetect.d") hooks.predetect) + ]); + fingerprintToString = name: edid: "${name} ${edid}"; + configToString = name: config: + if config.enable then + concatStringsSep "\n" ([ "output ${name}" ] + ++ optional (config.position != "") "pos ${config.position}" + ++ optional (config.crtc != null) "crtc ${toString config.crtc}" + ++ optional config.primary "primary" + ++ optional (config.dpi != null) "dpi ${toString config.dpi}" + ++ optional (config.gamma != "") "gamma ${config.gamma}" + ++ optional (config.mode != "") "mode ${config.mode}" + ++ optional (config.rate != "") "rate ${config.rate}" + ++ optional (config.rotate != null) "rotate ${config.rotate}" + ++ optional (config.transform != null) ("transform " + + concatMapStringsSep "," toString (flatten config.transform)) + ++ optional (config.scale != null) + ((if config.scale.method == "factor" then "scale" else "scale-from") + + " ${toString config.scale.x}x${toString config.scale.y}")) + else '' + output ${name} + off + ''; + +in { + + options = { + + services.autorandr = { + enable = mkEnableOption (lib.mdDoc "handling of hotplug and sleep events by autorandr"); + + defaultTarget = mkOption { + default = "default"; + type = types.str; + description = lib.mdDoc '' + Fallback if no monitor layout can be detected. See the docs + (https://github.com/phillipberndt/autorandr/blob/v1.0/README.md#how-to-use) + for further reference. + ''; + }; + + ignoreLid = mkOption { + default = false; + type = types.bool; + description = lib.mdDoc "Treat outputs as connected even if their lids are closed"; + }; + + matchEdid = mkOption { + default = false; + type = types.bool; + description = lib.mdDoc "Match displays based on edid instead of name"; + }; + + hooks = mkOption { + type = hooksModule; + description = lib.mdDoc "Global hook scripts"; + default = { }; + example = literalExpression '' + { + postswitch = { + "notify-i3" = "''${pkgs.i3}/bin/i3-msg restart"; + "change-background" = readFile ./change-background.sh; + "change-dpi" = ''' + case "$AUTORANDR_CURRENT_PROFILE" in + default) + DPI=120 + ;; + home) + DPI=192 + ;; + work) + DPI=144 + ;; + *) + echo "Unknown profle: $AUTORANDR_CURRENT_PROFILE" + exit 1 + esac + echo "Xft.dpi: $DPI" | ''${pkgs.xorg.xrdb}/bin/xrdb -merge + '''; + }; + } + ''; + }; + profiles = mkOption { + type = types.attrsOf profileModule; + description = lib.mdDoc "Autorandr profiles specification."; + default = { }; + example = literalExpression '' + { + "work" = { + fingerprint = { + eDP1 = ""; + DP1 = ""; + }; + config = { + eDP1.enable = false; + DP1 = { + enable = true; + crtc = 0; + primary = true; + position = "0x0"; + mode = "3840x2160"; + gamma = "1.0:0.909:0.833"; + rate = "60.00"; + rotate = "left"; + }; + }; + hooks.postswitch = readFile ./work-postswitch.sh; + }; + } + ''; + }; + + }; + + }; + + config = mkIf cfg.enable { + + services.udev.packages = [ pkgs.autorandr ]; + + environment = { + systemPackages = [ pkgs.autorandr ]; + etc = mkMerge ([ + (mapAttrs' (hookToFile "postswitch.d") cfg.hooks.postswitch) + (mapAttrs' (hookToFile "preswitch.d") cfg.hooks.preswitch) + (mapAttrs' (hookToFile "predetect.d") cfg.hooks.predetect) + (mkMerge (mapAttrsToList profileToFiles cfg.profiles)) + ]); + }; + + systemd.services.autorandr = { + wantedBy = [ "sleep.target" ]; + description = "Autorandr execution hook"; + after = [ "sleep.target" ]; + + startLimitIntervalSec = 5; + startLimitBurst = 1; + serviceConfig = { + ExecStart = '' + ${pkgs.autorandr}/bin/autorandr \ + --batch \ + --change \ + --default ${cfg.defaultTarget} \ + ${optionalString cfg.ignoreLid "--ignore-lid"} \ + ${optionalString cfg.matchEdid "--match-edid"} + ''; + Type = "oneshot"; + RemainAfterExit = false; + KillMode = "process"; + }; + }; + + }; + + meta.maintainers = with maintainers; [ alexnortung ]; +} diff --git a/notes.md b/notes.md index cc2d0a1..509de23 100644 --- a/notes.md +++ b/notes.md @@ -1 +1,5 @@ # Used Stuff +https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/misc/autorandr.nix +https://github.com/phillipberndt/autorandr + + diff --git a/options/common/gpu/nvidia_wayland.nix b/options/common/gpu/nvidia_wayland.nix new file mode 100644 index 0000000..2dcd218 --- /dev/null +++ b/options/common/gpu/nvidia_wayland.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ...}: +{ + services.xserver.videoDrivers = [ "nvidia" ]; + environment.variables = { + GBM_BACKEND = "nvidia-drm"; + WLR_NO_HARDWARE_CURSORS = "1"; + LIBVA_DRIVER_NAME = "nvidia"; + __GLX_VENDOR_LIBRARY_NAME = "nvidia"; + }; + environment.systemPackages = with pkgs; [ + vulkan-loader + vulkan-validation-layers + vulkan-tools + ]; + hardware = { + nvidia = { + open = true; + nvidiaSettings = false; + powerManagement.enable = true; + powerManagement.finegrained = false; + modesetting.enable = true; + package = config.boot.kernelPackages.nvidiaPackages.beta; + }; + }; + hardware.opengl = { + enable = true; + driSupport = true; + driSupport32Bit = true; + extraPackages = with pkgs; [ nvidia-vaapi-driver ]; + }; +} +