at 23.11-pre 4.0 kB view raw
1{ config, pkgs, lib, ... }: 2 3with lib; 4 5let 6 cfg = config.services.clight; 7 8 toConf = v: 9 if builtins.isFloat v then toString v 10 else if isInt v then toString v 11 else if isBool v then boolToString v 12 else if isString v then ''"${escape [''"''] v}"'' 13 else if isList v then "[ " + concatMapStringsSep ", " toConf v + " ]" 14 else if isAttrs v then "\n{\n" + convertAttrs v + "\n}" 15 else abort "clight.toConf: unexpected type (v = ${v})"; 16 17 getSep = v: 18 if isAttrs v then ":" 19 else "="; 20 21 convertAttrs = attrs: concatStringsSep "\n" (mapAttrsToList 22 (name: value: "${toString name} ${getSep value} ${toConf value};") 23 attrs); 24 25 clightConf = pkgs.writeText "clight.conf" (convertAttrs 26 (filterAttrs 27 (_: value: value != null) 28 cfg.settings)); 29in { 30 options.services.clight = { 31 enable = mkEnableOption (lib.mdDoc "clight"); 32 33 temperature = { 34 day = mkOption { 35 type = types.int; 36 default = 5500; 37 description = lib.mdDoc '' 38 Colour temperature to use during the day, between 39 `1000` and `25000` K. 40 ''; 41 }; 42 night = mkOption { 43 type = types.int; 44 default = 3700; 45 description = lib.mdDoc '' 46 Colour temperature to use at night, between 47 `1000` and `25000` K. 48 ''; 49 }; 50 }; 51 52 settings = let 53 validConfigTypes = with types; oneOf [ int str bool float ]; 54 collectionTypes = with types; oneOf [ validConfigTypes (listOf validConfigTypes) ]; 55 in mkOption { 56 type = with types; attrsOf (nullOr (either collectionTypes (attrsOf collectionTypes))); 57 default = {}; 58 example = { captures = 20; gamma_long_transition = true; ac_capture_timeouts = [ 120 300 60 ]; }; 59 description = lib.mdDoc '' 60 Additional configuration to extend clight.conf. See 61 <https://github.com/FedeDP/Clight/blob/master/Extra/clight.conf> for a 62 sample configuration file. 63 ''; 64 }; 65 }; 66 67 config = mkIf cfg.enable { 68 assertions = let 69 inRange = v: l: r: v >= l && v <= r; 70 in [ 71 { assertion = config.location.provider == "manual" -> 72 inRange config.location.latitude (-90) 90 && inRange config.location.longitude (-180) 180; 73 message = "You must specify a valid latitude and longitude if manually providing location"; } 74 ]; 75 76 boot.kernelModules = [ "i2c_dev" ]; 77 environment.systemPackages = with pkgs; [ clight clightd ]; 78 services.dbus.packages = with pkgs; [ clight clightd ]; 79 services.upower.enable = true; 80 81 services.clight.settings = { 82 gamma.temp = with cfg.temperature; mkDefault [ day night ]; 83 } // (optionalAttrs (config.location.provider == "manual") { 84 daytime.latitude = mkDefault config.location.latitude; 85 daytime.longitude = mkDefault config.location.longitude; 86 }); 87 88 services.geoclue2.appConfig.clightc = { 89 isAllowed = true; 90 isSystem = true; 91 }; 92 93 systemd.services.clightd = { 94 requires = [ "polkit.service" ]; 95 wantedBy = [ "multi-user.target" ]; 96 97 description = "Bus service to manage various screen related properties (gamma, dpms, backlight)"; 98 serviceConfig = { 99 Type = "dbus"; 100 BusName = "org.clightd.clightd"; 101 Restart = "on-failure"; 102 RestartSec = 5; 103 ExecStart = '' 104 ${pkgs.clightd}/bin/clightd 105 ''; 106 }; 107 }; 108 109 systemd.user.services.clight = { 110 after = [ "upower.service" "clightd.service" ]; 111 wants = [ "upower.service" "clightd.service" ]; 112 partOf = [ "graphical-session.target" ]; 113 wantedBy = [ "graphical-session.target" ]; 114 115 description = "C daemon to adjust screen brightness to match ambient brightness, as computed capturing frames from webcam"; 116 serviceConfig = { 117 Restart = "on-failure"; 118 RestartSec = 5; 119 ExecStart = '' 120 ${pkgs.clight}/bin/clight --conf-file ${clightConf} 121 ''; 122 }; 123 }; 124 }; 125}