1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.redshift;
8 lcfg = config.location;
9
10in {
11
12 imports = [
13 (mkChangedOptionModule [ "services" "redshift" "latitude" ] [ "location" "latitude" ]
14 (config:
15 let value = getAttrFromPath [ "services" "redshift" "latitude" ] config;
16 in if value == null then
17 throw "services.redshift.latitude is set to null, you can remove this"
18 else builtins.fromJSON value))
19 (mkChangedOptionModule [ "services" "redshift" "longitude" ] [ "location" "longitude" ]
20 (config:
21 let value = getAttrFromPath [ "services" "redshift" "longitude" ] config;
22 in if value == null then
23 throw "services.redshift.longitude is set to null, you can remove this"
24 else builtins.fromJSON value))
25 (mkRenamedOptionModule [ "services" "redshift" "provider" ] [ "location" "provider" ])
26 ];
27
28 options.services.redshift = {
29 enable = mkOption {
30 type = types.bool;
31 default = false;
32 description = lib.mdDoc ''
33 Enable Redshift to change your screen's colour temperature depending on
34 the time of day.
35 '';
36 };
37
38 temperature = {
39 day = mkOption {
40 type = types.int;
41 default = 5500;
42 description = lib.mdDoc ''
43 Colour temperature to use during the day, between
44 `1000` and `25000` K.
45 '';
46 };
47 night = mkOption {
48 type = types.int;
49 default = 3700;
50 description = lib.mdDoc ''
51 Colour temperature to use at night, between
52 `1000` and `25000` K.
53 '';
54 };
55 };
56
57 brightness = {
58 day = mkOption {
59 type = types.str;
60 default = "1";
61 description = lib.mdDoc ''
62 Screen brightness to apply during the day,
63 between `0.1` and `1.0`.
64 '';
65 };
66 night = mkOption {
67 type = types.str;
68 default = "1";
69 description = lib.mdDoc ''
70 Screen brightness to apply during the night,
71 between `0.1` and `1.0`.
72 '';
73 };
74 };
75
76 package = mkOption {
77 type = types.package;
78 default = pkgs.redshift;
79 defaultText = literalExpression "pkgs.redshift";
80 description = lib.mdDoc ''
81 redshift derivation to use.
82 '';
83 };
84
85 executable = mkOption {
86 type = types.str;
87 default = "/bin/redshift";
88 example = "/bin/redshift-gtk";
89 description = lib.mdDoc ''
90 Redshift executable to use within the package.
91 '';
92 };
93
94 extraOptions = mkOption {
95 type = types.listOf types.str;
96 default = [];
97 example = [ "-v" "-m randr" ];
98 description = lib.mdDoc ''
99 Additional command-line arguments to pass to
100 {command}`redshift`.
101 '';
102 };
103 };
104
105 config = mkIf cfg.enable {
106 # needed so that .desktop files are installed, which geoclue cares about
107 environment.systemPackages = [ cfg.package ];
108
109 services.geoclue2.appConfig.redshift = {
110 isAllowed = true;
111 isSystem = true;
112 };
113
114 systemd.user.services.redshift =
115 let
116 providerString = if lcfg.provider == "manual"
117 then "${toString lcfg.latitude}:${toString lcfg.longitude}"
118 else lcfg.provider;
119 in
120 {
121 description = "Redshift colour temperature adjuster";
122 wantedBy = [ "graphical-session.target" ];
123 partOf = [ "graphical-session.target" ];
124 serviceConfig = {
125 ExecStart = ''
126 ${cfg.package}${cfg.executable} \
127 -l ${providerString} \
128 -t ${toString cfg.temperature.day}:${toString cfg.temperature.night} \
129 -b ${toString cfg.brightness.day}:${toString cfg.brightness.night} \
130 ${lib.strings.concatStringsSep " " cfg.extraOptions}
131 '';
132 RestartSec = 3;
133 Restart = "always";
134 };
135 };
136 };
137
138}