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