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