1# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import os
6import re
7import stat
8import subprocess
9
10from autotest_lib.client.common_lib import error
11from autotest_lib.client.bin import test
12
13_SND_DEV_DIR = '/dev/snd/'
14
15class sound_infrastructure(test.test):
16    """
17    Tests that the expected sound infrastructure is present.
18
19    Check that at least one playback and capture device exists and that their
20    permissions are configured properly.
21
22    """
23    version = 2
24
25    def check_snd_dev_perms(self, filename):
26        desired_mode = (stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP |
27                        stat.S_IWGRP | stat.S_IFCHR)
28        st = os.stat(filename)
29        if (st.st_mode != desired_mode):
30            raise error.TestError("Incorrect permissions for %s" % filename)
31
32    def check_sound_files(self):
33        patterns = {'^controlC(\d+)': False,
34                    '^pcmC(\d+)D(\d+)p$': False,
35                    '^pcmC(\d+)D(\d+)c$': False}
36
37        filenames = os.listdir(_SND_DEV_DIR)
38
39        for filename in filenames:
40            for pattern in patterns:
41                if re.match(pattern, filename):
42                    patterns[pattern] = True
43                    self.check_snd_dev_perms(_SND_DEV_DIR + filename)
44
45        for pattern in patterns:
46            if not patterns[pattern]:
47                raise error.TestError("Missing device %s" % pattern)
48
49    def check_aplay_list(self):
50        no_cards_pattern = '.*no soundcards found.*'
51
52        aplay = subprocess.Popen(["aplay", "-l"], stderr=subprocess.PIPE)
53        aplay_list = aplay.communicate()[1]
54        if aplay.returncode or re.match(no_cards_pattern, aplay_list):
55            raise error.TestError("No playback devices found by aplay")
56
57        arecord = subprocess.Popen(["arecord", "-l"], stderr=subprocess.PIPE)
58        arecord_list = arecord.communicate()[1]
59        if arecord.returncode or re.match(no_cards_pattern, arecord_list):
60            raise error.TestError("No playback devices found by arecord")
61
62    def run_once(self):
63        self.check_sound_files()
64        self.check_aplay_list()
65