1# ALSA sound support.
2{ config, lib, pkgs, ... }:
3
4with lib;
5
6let
7
8 inherit (pkgs) alsaUtils;
9
10 pulseaudioEnabled = config.hardware.pulseaudio.enable;
11
12in
13
14{
15
16 ###### interface
17
18 options = {
19
20 sound = {
21
22 enable = mkOption {
23 type = types.bool;
24 default = true;
25 description = ''
26 Whether to enable ALSA sound.
27 '';
28 };
29
30 enableOSSEmulation = mkOption {
31 type = types.bool;
32 default = true;
33 description = ''
34 Whether to enable ALSA OSS emulation (with certain cards sound mixing may not work!).
35 '';
36 };
37
38 extraConfig = mkOption {
39 type = types.lines;
40 default = "";
41 example = ''
42 defaults.pcm.!card 3
43 '';
44 description = ''
45 Set addition configuration for system-wide alsa.
46 '';
47 };
48
49 mediaKeys = {
50
51 enable = mkOption {
52 type = types.bool;
53 default = false;
54 description = ''
55 Whether to enable volume and capture control with keyboard media keys.
56
57 Enabling this will turn on <option>services.actkbd</option>.
58 '';
59 };
60
61 volumeStep = mkOption {
62 type = types.string;
63 default = "1";
64 example = "1%";
65 description = ''
66 The value by which to increment/decrement volume on media keys.
67
68 See amixer(1) for allowed values.
69 '';
70 };
71
72 };
73
74 };
75
76 };
77
78
79 ###### implementation
80
81 config = mkIf config.sound.enable {
82
83 environment.systemPackages = [ alsaUtils ];
84
85 environment.etc = mkIf (!pulseaudioEnabled && config.sound.extraConfig != "")
86 [
87 { source = pkgs.writeText "asound.conf" config.sound.extraConfig;
88 target = "asound.conf";
89 }
90 ];
91
92 # ALSA provides a udev rule for restoring volume settings.
93 services.udev.packages = [ alsaUtils ];
94
95 boot.kernelModules = optional config.sound.enableOSSEmulation "snd_pcm_oss";
96
97 systemd.services."alsa-store" =
98 { description = "Store Sound Card State";
99 wantedBy = [ "multi-user.target" ];
100 unitConfig.RequiresMountsFor = "/var/lib/alsa";
101 unitConfig.ConditionVirtualization = "!systemd-nspawn";
102 serviceConfig = {
103 Type = "oneshot";
104 RemainAfterExit = true;
105 ExecStart = "${pkgs.coreutils}/bin/mkdir -p /var/lib/alsa";
106 ExecStop = "${alsaUtils}/sbin/alsactl store --ignore";
107 };
108 };
109
110 services.actkbd = mkIf config.sound.mediaKeys.enable {
111 enable = true;
112 bindings = [
113 # "Mute" media key
114 { keys = [ 113 ]; events = [ "key" ]; command = "${alsaUtils}/bin/amixer -q set Master toggle"; }
115
116 # "Lower Volume" media key
117 { keys = [ 114 ]; events = [ "key" "rep" ]; command = "${alsaUtils}/bin/amixer -q set Master ${config.sound.mediaKeys.volumeStep}- unmute"; }
118
119 # "Raise Volume" media key
120 { keys = [ 115 ]; events = [ "key" "rep" ]; command = "${alsaUtils}/bin/amixer -q set Master ${config.sound.mediaKeys.volumeStep}+ unmute"; }
121
122 # "Mic Mute" media key
123 { keys = [ 190 ]; events = [ "key" ]; command = "${alsaUtils}/bin/amixer -q set Capture toggle"; }
124 ];
125 };
126
127 };
128
129}