1 # Copyright (c) 2013 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 5 import re 6 7 from autotest_lib.client.bin import test, utils 8 from autotest_lib.client.common_lib import error 9 from autotest_lib.client.cros.audio import alsa_utils 10 11 12 APLAY_FILE = '/dev/zero' # raw data 13 14 # Expected results of 'aplay -v' commands. 15 APLAY_EXPECTED = set([ 16 ('stream', 'PLAYBACK')]) 17 18 19 def _play_audio(duration=1): 20 """Play a tone and try to ensure it played properly. 21 22 Sample output from aplay -v: 23 24 Playing raw data '/dev/zero' : Signed 16 bit Little Endian, Rate 44100 Hz, 25 Stereo 26 Hardware PCM card 0 'HDA Intel PCH' device 0 subdevice 0 27 Its setup is: 28 stream : PLAYBACK 29 access : RW_INTERLEAVED format : S16_LE 30 subformat : STD 31 channels : 2 32 rate : 44100 33 exact rate : 44100 (44100/1) 34 msbits : 16 35 buffer_size : 16384 36 period_size : 4096 37 period_time : 92879 38 tstamp_mode : NONE 39 period_step : 1 40 avail_min : 4096 41 period_event : 0 42 start_threshold : 16384 43 stop_threshold : 16384 44 silence_threshold: 0 45 silence_size : 0 46 boundary : 4611686018427387904 47 appl_ptr : 0 48 hw_ptr : 0 49 50 @param duration: Duration supplied to aplay. 51 @return String output from the command (may be empty). 52 @raises CmdError when cmd returns <> 0. 53 """ 54 device = alsa_utils.get_sysdefault_playback_device() 55 cmd = ['aplay', 56 '-v', # show verbose details 57 '-D %s' % device, # select default device 58 '-d %d' % duration, 59 '-f cd', # format 60 APLAY_FILE, 61 '2>&1'] # verbose details 62 return utils.system_output(' '.join(cmd)).strip() 63 64 65 def _check_play(duration, expected): 66 """Runs aplay command and checks the output against an expected result. 67 68 The expected results are compared as sets of tuples. 69 70 @param duration: Duration supplied to aplay. 71 @param expected: The set of expected tuples. 72 @raises error.TestError for invalid output or invalidly matching expected. 73 """ 74 error_msg = 'invalid response from aplay' 75 results = _play_audio(duration) 76 if not results.startswith("Playing raw data '%s' :" % APLAY_FILE): 77 raise error.TestError('%s: %s' % (error_msg, results)) 78 result_set = utils.set_from_keyval_output(results, '[\s]*:[\s]*') 79 if set(expected) <= result_set: 80 return 81 raise error.TestError('%s: expected=%s.' % 82 (error_msg, sorted(set(expected) - result_set))) 83 84 85 class audio_Aplay(test.test): 86 """Checks that simple aplay functions correctly.""" 87 version = 1 88 89 90 def run_once(self, duration=1): 91 """Run aplay and verify its output is as expected. 92 93 @param duration: the duration to run aplay in seconds. 94 """ 95 _check_play(duration, APLAY_EXPECTED) 96