Merge ~ssweeny/snappy-hwe-snaps/+git/alsa-utils:workaround-save-restore into ~snappy-hwe-team/snappy-hwe-snaps/+git/alsa-utils:master

Proposed by Scott Sweeny
Status: Merged
Approved by: Simon Fels
Approved revision: 6cf55a2ee065a80627adb47f837fd8eb22bb7b32
Merged at revision: 53029e71760eed16791d5a3b159091050f78afcc
Proposed branch: ~ssweeny/snappy-hwe-snaps/+git/alsa-utils:workaround-save-restore
Merge into: ~snappy-hwe-team/snappy-hwe-snaps/+git/alsa-utils:master
Diff against target: 464 lines (+373/-4)
10 files modified
.tests_config (+1/-0)
bin/alsa-stated (+26/-0)
docs/index.md (+4/-2)
docs/metadata.yaml (+2/-0)
docs/reference/content-mixer-state.md (+57/-0)
run-tests.sh (+7/-1)
snapcraft.yaml (+17/-1)
tests/integration/main/content-statefile/asound.state (+149/-0)
tests/integration/main/content-statefile/task.yaml (+81/-0)
tests/integration/main/save-restore/task.yaml (+29/-0)
Reviewer Review Type Date Requested Status
Simon Fels Approve
System Enablement Bot continuous-integration Approve
Review via email: mp+318915@code.launchpad.net

Commit message

Add mixer state save/restore

Adds a small daemon which does little but call alsactl store/restore upon startup and shutdown.

Also adds the ability to read an initial state file provided via the content interface.

Description of the change

Add mixer state save/restore

Adds a small daemon which does little but call alsactl store/restore upon startup and shutdown.

Also adds the ability to read an initial state file provided via the content interface.

To post a comment you must log in.
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Simon Fels (morphis) :
Revision history for this message
Scott Sweeny (ssweeny) :
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Simon Fels (morphis) :
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Simon Fels (morphis) wrote :

Gernally LGTM, but a few comments inline.

review: Needs Fixing
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Simon Fels (morphis) :
Revision history for this message
Simon Fels (morphis) wrote :

A few last comments otherwise this looks ready to me. Lets try to get this in today and a new snap pushed to candidate.

Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Simon Fels (morphis) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/.tests_config b/.tests_config
2new file mode 100644
3index 0000000..8d460d9
4--- /dev/null
5+++ b/.tests_config
6@@ -0,0 +1 @@
7+export EXTRA_ARGS="--image-unsigned-gadget"
8diff --git a/bin/alsa-stated b/bin/alsa-stated
9new file mode 100755
10index 0000000..4a55a7f
11--- /dev/null
12+++ b/bin/alsa-stated
13@@ -0,0 +1,26 @@
14+#!/bin/bash
15+
16+LOCAL_STATEFILE=$SNAP_COMMON/asound.state
17+GADGET_STATEFILE=$SNAP/var/lib/alsa/asound.state
18+
19+store() {
20+ echo "Caught SIGTERM, storing state..."
21+ $SNAP/usr/sbin/alsactl -f $LOCAL_STATEFILE store
22+}
23+
24+# Store the state on SIGTERM
25+trap store SIGTERM
26+
27+# On first run we won't have our own state file yet
28+if [ -f $LOCAL_STATEFILE ]; then
29+ echo "Restoring from local state file"
30+ $SNAP/usr/sbin/alsactl -f $LOCAL_STATEFILE restore
31+
32+# If the gadget snap provided one use that on first run
33+elif [ -f $GADGET_STATEFILE ]; then
34+ echo "Loading gadget state file"
35+ $SNAP/usr/sbin/alsactl -f $GADGET_STATEFILE restore
36+fi
37+
38+# Wait to be SIGTERM'd
39+sleep infinity
40diff --git a/docs/index.md b/docs/index.md
41index d267a7c..f059bb2 100644
42--- a/docs/index.md
43+++ b/docs/index.md
44@@ -5,8 +5,10 @@ table_of_contents: True
45
46 # About alsa-utils
47
48-The alsa-utils snap provides a few very basic utilities to deal with the
49-Linux kernel ALSA audio subsystem.
50+The alsa-utils snap provides a few very basic utilities to deal with the Linux
51+kernel ALSA audio subsystem. It also supports automatic saving and restoring of
52+the mixer state, as well as importing a mixer state file via the content
53+interface.
54
55 ## Upstream documentation
56
57diff --git a/docs/metadata.yaml b/docs/metadata.yaml
58index 05475a0..bd330f4 100644
59--- a/docs/metadata.yaml
60+++ b/docs/metadata.yaml
61@@ -7,3 +7,5 @@ navigation:
62 children:
63 - title: Available tools
64 location: reference/available-utilities.md
65+ - title: Device-specific initial ALSA state configuration
66+ location: reference/content-mixer-state.md
67diff --git a/docs/reference/content-mixer-state.md b/docs/reference/content-mixer-state.md
68new file mode 100644
69index 0000000..baaac89
70--- /dev/null
71+++ b/docs/reference/content-mixer-state.md
72@@ -0,0 +1,57 @@
73+---
74+title: "Device-specific initial ALSA state configuration"
75+table_of_contents: True
76+---
77+
78+# Device-specific initial ALSA state configuration
79+
80+The alsa-utils snap supports importing a mixer state file from the device
81+gadget snap. It defines a [content
82+interface](https://snapcraft.io/docs/reference/interfaces) plug which will be
83+connected to a slot on the gadget snap which then allows both snaps to share
84+the initial ALSA state configuration.
85+
86+Here's a simple example of how to modify the gadget snap's `snapcraft.yaml` to
87+provide the necessary content interface slot:
88+
89+```
90+# This part adds the state file to the snap in the path expected by the
91+# content stanza below
92+parts:
93+ alsa-state:
94+ plugin: dump
95+ source: alsa
96+ organize:
97+ asound.state: alsa-conf/asound.state
98+
99+slots:
100+ alsa:
101+ content: alsa-conf
102+ interface: content
103+ read:
104+ - alsa-conf
105+```
106+
107+*NOTE:* The alsa-utils snap expects the content field to specify `alsa-conf`.
108+
109+After installing the alsa-utils snap you will need to manually connect the
110+content interface and restart the alsa-utils service, like so:
111+
112+```
113+$ snap disable alsa-utils
114+$ rm -f /var/snap/alsa-utils/common/asound.state
115+$ snap connect alsa-utils:device-conf <your-snap>:alsa
116+$ snap enable alsa-utils
117+```
118+
119+*NOTE:* Because of a [bug in snapd](https://bugs.launchpad.net/bugs/1645731)
120+you currently need to take some additional manual steps to ensure that the file
121+is properly imported. The full set of steps is as follows:
122+
123+```
124+$ snap disable alsa-utils
125+$ rm -f /var/snap/alsa-utils/common/asound.state
126+$ snap connect alsa-utils:device-conf <your-snap>:alsa
127+$ /usr/lib/snapd/snap-discard-ns alsa-utils
128+$ snap enable alsa-utils
129+```
130diff --git a/run-tests.sh b/run-tests.sh
131index fdba1d8..f030283 100755
132--- a/run-tests.sh
133+++ b/run-tests.sh
134@@ -75,5 +75,11 @@ else
135 clone_tests_extras
136 fi
137
138+# Any project-specific options for test-runner should be specified in
139+# .tests_config
140+if [ -e ".tests_config" ]; then
141+ . .tests_config
142+fi
143+
144 echo "INFO: Executing tests runner"
145-cd $TESTS_EXTRAS_PATH && ./tests-runner.sh $@
146+cd $TESTS_EXTRAS_PATH && ./tests-runner.sh "$@" "$EXTRA_ARGS"
147diff --git a/snapcraft.yaml b/snapcraft.yaml
148index d7c0091..7b5efbf 100644
149--- a/snapcraft.yaml
150+++ b/snapcraft.yaml
151@@ -10,6 +10,10 @@ confinement: strict
152 grade: stable
153
154 apps:
155+ alsa-restore:
156+ daemon: simple
157+ command: bin/alsa-stated
158+ plugs: [alsa, gadget]
159 speaker-test:
160 command: usr/bin/speaker-test
161 plugs: [ alsa, home ]
162@@ -96,6 +100,12 @@ apps:
163 aliases:
164 - arecord
165
166+plugs:
167+ device-conf:
168+ interface: content
169+ content: alsa-conf
170+ target: var/lib/alsa
171+
172 parts:
173 alsa-lib:
174 plugin: autotools
175@@ -139,5 +149,11 @@ parts:
176 - libncursesw5
177 - libsamplerate0
178 - libtinfo5
179- snap:
180+ prime:
181 - -usr/include
182+
183+ alsa-stated:
184+ plugin: dump
185+ source: bin
186+ organize:
187+ alsa-stated: bin/
188diff --git a/tests/integration/main/content-statefile/asound.state b/tests/integration/main/content-statefile/asound.state
189new file mode 100644
190index 0000000..dc1f935
191--- /dev/null
192+++ b/tests/integration/main/content-statefile/asound.state
193@@ -0,0 +1,149 @@
194+state.Dummy {
195+ control.1 {
196+ iface MIXER
197+ name 'Master Volume'
198+ value.0 34
199+ value.1 34
200+ comment {
201+ access 'read write'
202+ type INTEGER
203+ count 2
204+ range '-50 - 100'
205+ dbmin -4500
206+ dbmax 0
207+ dbvalue.0 -1980
208+ dbvalue.1 -1980
209+ }
210+ }
211+ control.2 {
212+ iface MIXER
213+ name 'Master Capture Switch'
214+ value.0 false
215+ value.1 false
216+ comment {
217+ access 'read write'
218+ type BOOLEAN
219+ count 2
220+ }
221+ }
222+ control.3 {
223+ iface MIXER
224+ name 'Synth Volume'
225+ value.0 0
226+ value.1 0
227+ comment {
228+ access 'read write'
229+ type INTEGER
230+ count 2
231+ range '-50 - 100'
232+ dbmin -4500
233+ dbmax 0
234+ dbvalue.0 -3000
235+ dbvalue.1 -3000
236+ }
237+ }
238+ control.4 {
239+ iface MIXER
240+ name 'Synth Capture Switch'
241+ value.0 false
242+ value.1 false
243+ comment {
244+ access 'read write'
245+ type BOOLEAN
246+ count 2
247+ }
248+ }
249+ control.5 {
250+ iface MIXER
251+ name 'Line Volume'
252+ value.0 0
253+ value.1 0
254+ comment {
255+ access 'read write'
256+ type INTEGER
257+ count 2
258+ range '-50 - 100'
259+ dbmin -4500
260+ dbmax 0
261+ dbvalue.0 -3000
262+ dbvalue.1 -3000
263+ }
264+ }
265+ control.6 {
266+ iface MIXER
267+ name 'Line Capture Switch'
268+ value.0 false
269+ value.1 false
270+ comment {
271+ access 'read write'
272+ type BOOLEAN
273+ count 2
274+ }
275+ }
276+ control.7 {
277+ iface MIXER
278+ name 'Mic Volume'
279+ value.0 72
280+ value.1 72
281+ comment {
282+ access 'read write'
283+ type INTEGER
284+ count 2
285+ range '-50 - 100'
286+ dbmin -4500
287+ dbmax 0
288+ dbvalue.0 -840
289+ dbvalue.1 -840
290+ }
291+ }
292+ control.8 {
293+ iface MIXER
294+ name 'Mic Capture Switch'
295+ value.0 false
296+ value.1 false
297+ comment {
298+ access 'read write'
299+ type BOOLEAN
300+ count 2
301+ }
302+ }
303+ control.9 {
304+ iface MIXER
305+ name 'CD Volume'
306+ value.0 -6
307+ value.1 -6
308+ comment {
309+ access 'read write'
310+ type INTEGER
311+ count 2
312+ range '-50 - 100'
313+ dbmin -4500
314+ dbmax 0
315+ dbvalue.0 -3180
316+ dbvalue.1 -3180
317+ }
318+ }
319+ control.10 {
320+ iface MIXER
321+ name 'CD Capture Switch'
322+ value.0 false
323+ value.1 false
324+ comment {
325+ access 'read write'
326+ type BOOLEAN
327+ count 2
328+ }
329+ }
330+ control.11 {
331+ iface MIXER
332+ name 'External I/O Box'
333+ value 'CD Player'
334+ comment {
335+ access 'read write'
336+ type ENUMERATED
337+ count 1
338+ item.0 None
339+ item.1 'CD Player'
340+ }
341+ }
342+}
343diff --git a/tests/integration/main/content-statefile/task.yaml b/tests/integration/main/content-statefile/task.yaml
344new file mode 100644
345index 0000000..2782c35
346--- /dev/null
347+++ b/tests/integration/main/content-statefile/task.yaml
348@@ -0,0 +1,81 @@
349+summary: Verify that initial state file can be pulled over the content interface
350+
351+prepare: |
352+ . $TESTSLIB/snap-names.sh
353+ snap list | grep $gadget_name | awk '{print $2}' > gadget_version
354+
355+restore: |
356+ . $TESTSLIB/snap-names.sh
357+ # Restore the original gadget snap so that any following tests don't suffer
358+ # from our modified gadget
359+ original_revision=`cat gadget_version`
360+ current_revision=`snap list | grep $gadget_name | awk '{print $2}'`
361+ if [ $current_revision -ne $original_revision ]; then
362+ snap revert --revision=$original_revision $gadget_name
363+ fi
364+
365+execute: |
366+ . $TESTSLIB/snap-names.sh
367+ . $TESTSLIB/utilities.sh
368+
369+ # Load a dummy sound card so alsa is happy
370+ modprobe snd-dummy
371+ modprobe snd-pcm-oss
372+ modprobe snd-mixer-oss
373+
374+ if [ $SPREAD_REBOOT = 0 ]; then
375+ snap install --edge --devmode se-test-tools
376+
377+ # We need a custom gadget snap for this so let's fetch one from the store
378+ # and modify it
379+ snap download --stable $gadget_name
380+ /snap/bin/se-test-tools.unsquashfs -d gadget ${gadget_name}_*.snap
381+ cat << EOF >> gadget/meta/snap.yaml
382+ slots:
383+ alsa:
384+ content: alsa-conf
385+ interface: content
386+ read:
387+ - alsa-conf
388+ EOF
389+ mkdir gadget/alsa-conf
390+ cp asound.state gadget/alsa-conf/
391+ /snap/bin/se-test-tools.mksquashfs gadget $gadget_name.snap -comp xz -no-xattrs
392+ snap install --dangerous $gadget_name.snap
393+
394+ systemctl stop snap.alsa-utils.alsa-restore
395+ rm -f /var/snap/alsa-utils/common/asound.state # Simulate starting from scratch
396+ # The content interface will be hooked up automatically on a real system,
397+ # but we lack the assertions here so we need to fake it
398+ snap connect alsa-utils:device-conf pc:alsa
399+ /usr/lib/snapd/snap-discard-ns alsa-utils # Work around LP: #1645731
400+ systemctl start snap.alsa-utils.alsa-restore
401+ wait_for_systemd_service snap.alsa-utils.alsa-restore
402+
403+ # Make sure we found the right file
404+ journalctl -u snap.alsa-utils.alsa-restore | grep "Loading gadget state file"
405+
406+ # Make sure there were no errors
407+ systemctl show snap.alsa-utils.alsa-restore | grep ActiveState=active
408+ systemctl show snap.alsa-utils.alsa-restore | grep SubState=running
409+
410+ # Make sure the mixer values represent what's in the state file
411+ /snap/bin/amixer -c 0 get Master | grep "Front Left: 34 \[56%\] \[-19.80dB\] Capture \[off\]"
412+ /snap/bin/amixer -c 0 get Master | grep "Front Right: 34 \[56%\] \[-19.80dB\] Capture \[off\]"
413+
414+ # Make sure changes are saved over a reboot
415+ /snap/bin/amixer -c 0 set Master 50,50
416+ REBOOT
417+ fi
418+
419+ # Make sure alsa starts up with the dummy drivers present
420+ systemctl restart snap.alsa-utils.alsa-restore
421+ wait_for_systemd_service snap.alsa-utils.alsa-restore
422+
423+ # Make sure there were no errors
424+ systemctl show snap.alsa-utils.alsa-restore | grep ActiveState=active
425+ systemctl show snap.alsa-utils.alsa-restore | grep SubState=running
426+
427+ /snap/bin/amixer -c 0 get Master | grep "Front Left: 50 \[67%\] \[-15.00dB\] Capture \[off\]"
428+ /snap/bin/amixer -c 0 get Master | grep "Front Right: 50 \[67%\] \[-15.00dB\] Capture \[off\]"
429+
430diff --git a/tests/integration/main/save-restore/task.yaml b/tests/integration/main/save-restore/task.yaml
431new file mode 100644
432index 0000000..c34252f
433--- /dev/null
434+++ b/tests/integration/main/save-restore/task.yaml
435@@ -0,0 +1,29 @@
436+summary: Verify that mixer state is saved and restored on shutdown/startup
437+
438+execute: |
439+ . $TESTSLIB/utilities.sh
440+
441+ # Load a dummy sound card so alsa is happy
442+ modprobe snd-dummy
443+ modprobe snd-pcm-oss
444+ modprobe snd-mixer-oss
445+
446+ # Make sure alsa sees the dummy sound card
447+ systemctl restart snap.alsa-utils.alsa-restore
448+
449+ wait_for_systemd_service snap.alsa-utils.alsa-restore
450+
451+ systemctl stop snap.alsa-utils.alsa-restore
452+
453+ wait_for_systemd_service_exit snap.alsa-utils.alsa-restore
454+
455+ # Make sure we saved a state file
456+ test -f /var/snap/alsa-utils/common/asound.state
457+
458+ systemctl start snap.alsa-utils.alsa-restore
459+
460+ wait_for_systemd_service snap.alsa-utils.alsa-restore
461+
462+ # Make sure there were no errors
463+ systemctl show snap.alsa-utils.alsa-restore | grep ActiveState=active
464+ systemctl show snap.alsa-utils.alsa-restore | grep SubState=running

Subscribers

People subscribed via source and target branches

to all changes: