OLD | NEW |
(Empty) | |
| 1 # -*- coding: utf-8 -*- |
| 2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 |
| 7 # DESCRIPTION : |
| 8 # |
| 9 # This is a factory test to test the audio. |
| 10 # UI based heavily on factory_Display |
| 11 |
| 12 |
| 13 import gtk |
| 14 import logging |
| 15 import os |
| 16 import re |
| 17 import sys |
| 18 |
| 19 from autotest_lib.client.bin import factory |
| 20 from autotest_lib.client.bin import factory_ui_lib as ful |
| 21 from autotest_lib.client.bin import test |
| 22 from autotest_lib.client.common_lib import error, utils |
| 23 |
| 24 |
| 25 _LABEL_BIG_SIZE = (280, 60) |
| 26 _LABEL_STATUS_SIZE = (140, 30) |
| 27 _LABEL_START_STR = 'hit SPACE to start each audio test\n' +\ |
| 28 '按空白鍵開始各項聲音測試\n\n' |
| 29 _LABEL_RESPONSE_STR = ful.USER_PASS_FAIL_SELECT_STR + '\n' |
| 30 _SAMPLE_LIST = ['Headset Audio Test', 'Built-in Audio Test'] |
| 31 _VERBOSE = False |
| 32 |
| 33 |
| 34 # FIXME: tbroch : refactor from factory_ui -> factory_ui_lib.py |
| 35 _SEP_COLOR = gtk.gdk.color_parse('grey50') |
| 36 def make_vsep(width=1): |
| 37 frame = gtk.EventBox() |
| 38 frame.set_size_request(width, -1) |
| 39 frame.modify_bg(gtk.STATE_NORMAL, _SEP_COLOR) |
| 40 return frame |
| 41 |
| 42 def make_hsep(width=1): |
| 43 frame = gtk.EventBox() |
| 44 frame.set_size_request(-1, width) |
| 45 frame.modify_bg(gtk.STATE_NORMAL, _SEP_COLOR) |
| 46 return frame |
| 47 |
| 48 |
| 49 class factory_Audio(test.test): |
| 50 version = 1 |
| 51 |
| 52 |
| 53 def audio_subtest_widget(self, name): |
| 54 window = gtk.Window(gtk.WINDOW_TOPLEVEL) |
| 55 screen = window.get_screen() |
| 56 screen_size = (screen.get_width(), screen.get_height()) |
| 57 window.set_size_request(*self._test_widget_size) |
| 58 |
| 59 vb = gtk.VBox() |
| 60 ebh = gtk.EventBox() |
| 61 ebh.modify_bg(gtk.STATE_NORMAL, ful.LABEL_COLORS[ful.ACTIVE]) |
| 62 ebh.add(ful.make_label(name, size=_LABEL_BIG_SIZE, |
| 63 fg=ful.BLACK)) |
| 64 vb.pack_start(ebh) |
| 65 vb.pack_start(make_vsep(3), False, False) |
| 66 if re.search('Headset', name): |
| 67 lab_str = 'Connect headset to device\n將耳機接上音源孔' |
| 68 else: |
| 69 lab_str = 'Remove headset from device\n將耳機移開音源孔' |
| 70 vb.pack_start(ful.make_label(lab_str, fg=ful.WHITE)) |
| 71 vb.pack_start(make_vsep(3), False, False) |
| 72 vb.pack_start(ful.make_label(\ |
| 73 'Press & hold \'r\' to record\n壓住 \'r\' 鍵開始錄音\n' + \ |
| 74 '[Playback will follow]\n[之後會重播錄到的聲音]\n\n' + \ |
| 75 'Press & hold \'p\' to play sample\n' + \ |
| 76 '壓住 \'p\' 鍵以播放範例')) |
| 77 vb.pack_start(make_vsep(3), False, False) |
| 78 vb.pack_start(ful.make_label(ful.USER_PASS_FAIL_SELECT_STR, |
| 79 fg=ful.WHITE)) |
| 80 |
| 81 # need event box to effect bg color |
| 82 eb = gtk.EventBox() |
| 83 eb.modify_bg(gtk.STATE_NORMAL, ful.BLACK) |
| 84 eb.add(vb) |
| 85 window.add(eb) |
| 86 window.show_all() |
| 87 self._fs_window = window |
| 88 |
| 89 def close_bgjob(self, sample_name): |
| 90 job = self._job |
| 91 if job: |
| 92 utils.nuke_subprocess(job.sp) |
| 93 utils.join_bg_jobs([job], timeout=1) |
| 94 result = job.result |
| 95 if _VERBOSE and (result.stdout or result.stderr): |
| 96 raise error.CmdError( |
| 97 sample_name, result, |
| 98 'stdout: %s\nstderr: %s' % (result.stdout, result.stderr)) |
| 99 self._job = None |
| 100 |
| 101 def goto_next_sample(self): |
| 102 if not self._sample_queue: |
| 103 gtk.main_quit() |
| 104 return |
| 105 self._current_sample = self._sample_queue.pop() |
| 106 name = self._current_sample |
| 107 self._status_map[name] = ful.ACTIVE |
| 108 |
| 109 def cleanup_sample(self): |
| 110 factory.log('Inside cleanup_sample') |
| 111 self._fs_window.destroy() |
| 112 self._fs_window = None |
| 113 self.goto_next_sample() |
| 114 |
| 115 def key_press_callback(self, widget, event): |
| 116 name = self._current_sample |
| 117 if event.keyval == gtk.keysyms.space and not self._fs_window: |
| 118 # start the subtest |
| 119 self.audio_subtest_widget(name) |
| 120 else: |
| 121 self.close_bgjob(name) |
| 122 cmd = None |
| 123 if event.keyval == ord('r'): |
| 124 # record via mic |
| 125 if os.path.isfile('rec.wav'): |
| 126 os.unlink('rec.wav') |
| 127 cmd = 'arecord -f dat -t wav rec.wav' |
| 128 elif event.keyval == ord('p'): |
| 129 # playback canned audio |
| 130 cmd = 'aplay %s' % self._sample |
| 131 if cmd: |
| 132 self._job = utils.BgJob(cmd, stderr_level=logging.DEBUG) |
| 133 factory.log("cmd: " + cmd) |
| 134 self._test_widget.queue_draw() |
| 135 return True |
| 136 |
| 137 def key_release_callback(self, widget, event): |
| 138 name = self._current_sample |
| 139 if event.keyval == gtk.keysyms.Tab: |
| 140 self._status_map[name] = ful.FAILED |
| 141 self.cleanup_sample() |
| 142 elif event.keyval == gtk.keysyms.Return: |
| 143 self._status_map[name] = ful.PASSED |
| 144 self.cleanup_sample() |
| 145 elif event.keyval == ord('Q'): |
| 146 gtk.main_quit() |
| 147 elif event.keyval == ord('r'): |
| 148 self.close_bgjob(name) |
| 149 cmd = 'aplay rec.wav' |
| 150 self._job = utils.BgJob(cmd, stderr_level=logging.DEBUG) |
| 151 factory.log("cmd: " + cmd) |
| 152 elif event.keyval == ord('p'): |
| 153 self.close_bgjob(name) |
| 154 else: |
| 155 self._ft_state.exit_on_trigger(event) |
| 156 |
| 157 self._test_widget.queue_draw() |
| 158 return True |
| 159 |
| 160 def label_status_expose(self, widget, event, name=None): |
| 161 status = self._status_map[name] |
| 162 widget.set_text(status) |
| 163 widget.modify_fg(gtk.STATE_NORMAL, ful.LABEL_COLORS[status]) |
| 164 |
| 165 def make_sample_label_box(self, name): |
| 166 eb = gtk.EventBox() |
| 167 eb.modify_bg(gtk.STATE_NORMAL, ful.BLACK) |
| 168 label_status = ful.make_label(ful.UNTESTED, size=_LABEL_STATUS_SIZE, |
| 169 alignment=(0, 0.5), |
| 170 fg=ful.LABEL_COLORS['UNTESTED']) |
| 171 expose_cb = lambda *x: self.label_status_expose(*x, **{'name':name}) |
| 172 label_status.connect('expose_event', expose_cb) |
| 173 label_en = ful.make_label(name, alignment=(1,0.5)) |
| 174 label_sep = ful.make_label(' : ', alignment=(0.5, 0.5)) |
| 175 hbox = gtk.HBox() |
| 176 hbox.pack_end(label_status, False, False) |
| 177 hbox.pack_end(label_sep, False, False) |
| 178 hbox.pack_end(label_en, False, False) |
| 179 eb.add(hbox) |
| 180 return eb |
| 181 |
| 182 def register_callbacks(self, window): |
| 183 window.connect('key-press-event', self.key_press_callback) |
| 184 window.add_events(gtk.gdk.KEY_PRESS_MASK) |
| 185 window.connect('key-release-event', self.key_release_callback) |
| 186 window.add_events(gtk.gdk.KEY_RELEASE_MASK) |
| 187 |
| 188 def locate_asample(self, sample): |
| 189 if not sample: |
| 190 raise error.TestFail('ERROR: Must provide an audio sample') |
| 191 if not os.path.isabs(sample): |
| 192 # assume its in deps |
| 193 sample = self.autodir + '/' + sample |
| 194 if not os.path.exists(sample): |
| 195 raise error.TestFail('ERROR: Unable to find audio sample %s' \ |
| 196 % sample) |
| 197 self._sample=sample |
| 198 |
| 199 def run_once(self, |
| 200 test_widget_size=None, |
| 201 trigger_set=None, |
| 202 sample=None, |
| 203 ): |
| 204 |
| 205 factory.log('%s run_once' % self.__class__) |
| 206 |
| 207 self._job = None |
| 208 self._test_widget_size = test_widget_size |
| 209 self.locate_asample(sample) |
| 210 # to write the recordings |
| 211 os.chdir(self.tmpdir) |
| 212 |
| 213 xset_status = os.system('LD_LIBRARY_PATH=/usr/local/lib xset r off') |
| 214 if xset_status: |
| 215 raise error.TestFail('ERROR: disabling key repeat') |
| 216 |
| 217 self._ft_state = ful.State(trigger_set=trigger_set) |
| 218 |
| 219 self._sample_queue = [x for x in reversed(_SAMPLE_LIST)] |
| 220 self._status_map = dict((n, ful.UNTESTED) for n in _SAMPLE_LIST) |
| 221 |
| 222 prompt_label = ful.make_label(_LABEL_START_STR, alignment=(0.5, 0.5)) |
| 223 |
| 224 vbox = gtk.VBox() |
| 225 vbox.pack_start(prompt_label, False, False) |
| 226 |
| 227 for name in _SAMPLE_LIST: |
| 228 label_box = self.make_sample_label_box(name) |
| 229 vbox.pack_start(label_box, False, False) |
| 230 |
| 231 test_widget = gtk.EventBox() |
| 232 test_widget.modify_bg(gtk.STATE_NORMAL, ful.BLACK) |
| 233 test_widget.add(vbox) |
| 234 self._test_widget = test_widget |
| 235 |
| 236 self.goto_next_sample() |
| 237 |
| 238 self._fs_window = None |
| 239 |
| 240 self._ft_state.run_test_widget( |
| 241 test_widget=test_widget, |
| 242 test_widget_size=test_widget_size, |
| 243 window_registration_callback=self.register_callbacks) |
| 244 |
| 245 failed_set = set(name for name, status in self._status_map.items() |
| 246 if status is not ful.PASSED) |
| 247 if failed_set: |
| 248 raise error.TestFail('some samples failed (%s)' % |
| 249 ', '.join(failed_set)) |
| 250 |
| 251 factory.log('%s run_once finished' % self.__class__) |
OLD | NEW |