OLD | NEW |
---|---|
1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import copy, logging, os, pprint, re, threading, time, urllib | 5 import copy, logging, os, pprint, re, threading, time, urllib |
6 | 6 |
7 from autotest_lib.client.bin import site_ui_test | 7 from autotest_lib.client.bin import site_ui_test |
8 from autotest_lib.client.common_lib import error, site_httpd, site_ui, utils | 8 from autotest_lib.client.common_lib import error, site_httpd, site_ui, utils |
9 | 9 |
10 # HTML templates. | 10 # HTML templates. |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 <td>%(name)s</td> | 82 <td>%(name)s</td> |
83 <td>%(index)d</td> | 83 <td>%(index)d</td> |
84 <td>%(channels)d</td> | 84 <td>%(channels)d</td> |
85 <td>%(is_hardware)d</td> | 85 <td>%(is_hardware)d</td> |
86 <td>%(sample_format)s</td> | 86 <td>%(sample_format)s</td> |
87 <td>%(sample_rate)s</td> | 87 <td>%(sample_rate)s</td> |
88 <td>%(ports)s</td> | 88 <td>%(ports)s</td> |
89 </tr> | 89 </tr> |
90 ''' | 90 ''' |
91 | 91 |
92 _DEVICE_SECTION_ENTRY_PORT_START_TMPL = '''<tr> | |
93 <td>%(name)s</td> | |
94 <td>%(index)d</td> | |
95 <td>%(channels)d</td> | |
96 <td>%(is_hardware)d</td> | |
97 <td>%(sample_format)s</td> | |
98 <td>%(sample_rate)s</td> | |
99 ''' | |
100 _DEVICE_SECTION_ENTRY_PORT_END_TMPL = '''<td>%s</td> | |
101 </tr> | |
102 ''' | |
103 | |
92 _DEVICE_LIST_TEST = ''' | 104 _DEVICE_LIST_TEST = ''' |
93 <tr><td><table> <tr> | 105 <tr><td><table> <tr> |
94 <td>Device List Looks Correct?</td> | 106 <td>Device List Looks Correct?</td> |
95 <td class="action" id="summary"><a href="?test=summary&result=pass">pass</a> | 107 <td class="action" id="summary"><a href="?test=summary&result=pass">pass</a> |
96 <a href="?test=summary&result=fail">fail</a> | 108 <a href="?test=summary&result=fail">fail</a> |
97 </td> | 109 </td> |
98 </tr></table></td></tr> | 110 </tr></table></td></tr> |
99 ''' | 111 ''' |
100 | 112 |
101 _TEST_CONTROL_START = '<table><th>Test description</th><th>Invoke Link</th>' | 113 _TEST_CONTROL_START = '<table><th>Test description</th><th>Invoke Link</th>' |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
204 _STANZA_START_RE = re.compile(' (\*| ) index: (\d+)') | 216 _STANZA_START_RE = re.compile(' (\*| ) index: (\d+)') |
205 _NAME_RE = re.compile('\tname:\s+<(.+)>') | 217 _NAME_RE = re.compile('\tname:\s+<(.+)>') |
206 _FLAGS_RE = re.compile('\tflags:\s+(.+)') | 218 _FLAGS_RE = re.compile('\tflags:\s+(.+)') |
207 _MAX_VOLUME_RE = re.compile('\tvolume steps:\s+(\d+)') | 219 _MAX_VOLUME_RE = re.compile('\tvolume steps:\s+(\d+)') |
208 _BASE_VOLUME_RE = re.compile('\tbase volume:\s+(\d+)%') | 220 _BASE_VOLUME_RE = re.compile('\tbase volume:\s+(\d+)%') |
209 _SAMPLE_SPEC_RE = re.compile('\tsample spec:\s+(\S+) (\d+)ch (\d+)Hz') | 221 _SAMPLE_SPEC_RE = re.compile('\tsample spec:\s+(\S+) (\d+)ch (\d+)Hz') |
210 _CHANNEL_MAP_RE = re.compile('\tchannel map:\s+(.+)') | 222 _CHANNEL_MAP_RE = re.compile('\tchannel map:\s+(.+)') |
211 _TOP_LEVEL_RE = re.compile('\t\S') | 223 _TOP_LEVEL_RE = re.compile('\t\S') |
212 _PORTS_RE = re.compile('\tports:') | 224 _PORTS_RE = re.compile('\tports:') |
213 _PORT_SPEC_RE = re.compile('\t\t(\S+): .* \(priority \d+\)') | 225 _PORT_SPEC_RE = re.compile('\t\t(\S+): .* \(priority \d+\)') |
214 | 226 _ACTIVE_PORT_RE = re.compile('\tactive port: <(.+)>') |
215 | 227 |
216 class ToneThread(threading.Thread): | 228 class ToneThread(threading.Thread): |
217 """Wraps the running of test_tones in a thread.""" | 229 """Wraps the running of test_tones in a thread.""" |
218 def __init__(self, audio, config): | 230 def __init__(self, audio, config): |
219 threading.Thread.__init__(self) | 231 threading.Thread.__init__(self) |
220 self.audio = audio | 232 self.audio = audio |
221 self.config = config | 233 self.config = config |
222 | 234 |
223 def run(self): | 235 def run(self): |
224 self.audio.run_test_tones(self.config) | 236 self.audio.run_test_tones(self.config) |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
313 | 325 |
314 # Run test server. | 326 # Run test server. |
315 self._server_root = 'http://localhost:8000/' | 327 self._server_root = 'http://localhost:8000/' |
316 self._testServer = site_httpd.HTTPListener(port=8000, | 328 self._testServer = site_httpd.HTTPListener(port=8000, |
317 docroot=self.bindir) | 329 docroot=self.bindir) |
318 self._testServer.run() | 330 self._testServer.run() |
319 site_ui_test.UITest.initialize(self, creds) | 331 site_ui_test.UITest.initialize(self, creds) |
320 | 332 |
321 | 333 |
322 def cleanup(self): | 334 def cleanup(self): |
335 for device in self._playback_devices['info']: | |
336 if device['is_hardware']: | |
337 self.restore_playback_port(device) | |
323 self._testServer.stop() | 338 self._testServer.stop() |
324 site_ui_test.UITest.cleanup(self) | 339 site_ui_test.UITest.cleanup(self) |
325 | 340 |
326 | 341 |
327 def run_once(self, timeout=10000): | 342 def run_once(self, timeout=10000): |
328 self._testServer.add_url_handler( | 343 self._testServer.add_url_handler( |
329 '/%s' % _CONTROL_ENDPOINT, | 344 '/%s' % _CONTROL_ENDPOINT, |
330 lambda server, form, o=self: o.handle_control(server, form)) | 345 lambda server, form, o=self: o.handle_control(server, form)) |
331 self._testServer.add_url_handler( | 346 self._testServer.add_url_handler( |
332 '/%s' % _LIST_ENDPOINT, | 347 '/%s' % _LIST_ENDPOINT, |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
439 test_data = { | 454 test_data = { |
440 'test': _VOLUME_ENDPOINT, | 455 'test': _VOLUME_ENDPOINT, |
441 'device': device_num, | 456 'device': device_num, |
442 'port': port_num | 457 'port': port_num |
443 } | 458 } |
444 server.wfile.write( | 459 server.wfile.write( |
445 self.get_pass_fail_div(_CONTROL_ENDPOINT, test_data)) | 460 self.get_pass_fail_div(_CONTROL_ENDPOINT, test_data)) |
446 | 461 |
447 server.wfile.write(_VOLUME_INSTRUCTIONS) | 462 server.wfile.write(_VOLUME_INSTRUCTIONS) |
448 | 463 |
449 self.render_single_device_summary(server, device) | 464 self.render_single_device_summary(server, device, port) |
450 | 465 |
451 server.wfile.write(_VOLUME_TEST_DETAILS % device) | 466 server.wfile.write(_VOLUME_TEST_DETAILS % device) |
452 if device.has_key('channel_map'): | 467 if device.has_key('channel_map'): |
453 server.wfile.write('<p>Channels are: %s' % | 468 server.wfile.write('<p>Channels are: %s' % |
454 self._pp.pformat(device['channel_map'])) | 469 self._pp.pformat(device['channel_map'])) |
455 | 470 |
456 # End Page. | 471 # End Page. |
457 server.wfile.write(_HTML_FOOTER) | 472 server.wfile.write(_HTML_FOOTER) |
458 | 473 |
459 self._running_test = threading.Thread( | 474 self._running_test = threading.Thread( |
(...skipping 16 matching lines...) Expand all Loading... | |
476 test_data = { | 491 test_data = { |
477 'test': _PLAYBACK_ENDPOINT, | 492 'test': _PLAYBACK_ENDPOINT, |
478 'device': device_num, | 493 'device': device_num, |
479 'port': port_num | 494 'port': port_num |
480 } | 495 } |
481 server.wfile.write( | 496 server.wfile.write( |
482 self.get_pass_fail_div(_CONTROL_ENDPOINT, test_data)) | 497 self.get_pass_fail_div(_CONTROL_ENDPOINT, test_data)) |
483 | 498 |
484 server.wfile.write(_PLAYBACK_INSTRUCTIONS) | 499 server.wfile.write(_PLAYBACK_INSTRUCTIONS) |
485 | 500 |
486 self.render_single_device_summary(server, device) | 501 self.render_single_device_summary(server, device, port) |
487 self.render_channel_test_order(server, device, port) | 502 self.render_channel_test_order(server, device, port) |
488 | 503 |
489 # End Page. | 504 # End Page. |
490 server.wfile.write(_HTML_FOOTER) | 505 server.wfile.write(_HTML_FOOTER) |
491 | 506 |
492 self.wait_for_current_test() | 507 self.wait_for_current_test() |
493 self._running_test = threading.Thread( | 508 self._running_test = threading.Thread( |
494 target=lambda d=device,p=port: self.do_playback_test(d,p)) | 509 target=lambda d=device,p=port: self.do_playback_test(d,p)) |
495 self._running_test.start() | 510 self._running_test.start() |
496 | 511 |
(...skipping 13 matching lines...) Expand all Loading... | |
510 test_data = { | 525 test_data = { |
511 'test': _RECORD_ENDPOINT, | 526 'test': _RECORD_ENDPOINT, |
512 'device': device_num, | 527 'device': device_num, |
513 'port': port_num | 528 'port': port_num |
514 } | 529 } |
515 server.wfile.write( | 530 server.wfile.write( |
516 self.get_pass_fail_div(_CONTROL_ENDPOINT, test_data)) | 531 self.get_pass_fail_div(_CONTROL_ENDPOINT, test_data)) |
517 | 532 |
518 server.wfile.write(_RECORD_INSTRUCTIONS) | 533 server.wfile.write(_RECORD_INSTRUCTIONS) |
519 | 534 |
520 self.render_single_device_summary(server, device) | 535 self.render_single_device_summary(server, device, port) |
521 self.render_channel_test_order(server, device, port) | 536 self.render_channel_test_order(server, device, port) |
522 | 537 |
523 # End Page. | 538 # End Page. |
524 server.wfile.write(_HTML_FOOTER) | 539 server.wfile.write(_HTML_FOOTER) |
525 | 540 |
526 self.wait_for_current_test() | 541 self.wait_for_current_test() |
527 self._running_test = threading.Thread( | 542 self._running_test = threading.Thread( |
528 target=lambda d=device,p=port: self.do_record_test(d,p)) | 543 target=lambda d=device,p=port: self.do_record_test(d,p)) |
529 self._running_test.start() | 544 self._running_test.start() |
530 | 545 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
593 server.wfile.write( | 608 server.wfile.write( |
594 self.get_record_item(device_num, port_num)) | 609 self.get_record_item(device_num, port_num)) |
595 else: | 610 else: |
596 server.wfile.write(self.get_record_item(device_num)) | 611 server.wfile.write(self.get_record_item(device_num)) |
597 server.wfile.write(_TEST_CONTROL_END) | 612 server.wfile.write(_TEST_CONTROL_END) |
598 | 613 |
599 # End Page. | 614 # End Page. |
600 server.wfile.write(_HTML_FOOTER) | 615 server.wfile.write(_HTML_FOOTER) |
601 | 616 |
602 | 617 |
603 def render_single_device_summary(self, server, device): | 618 def render_single_device_summary(self, server, device, port): |
604 """Output a HTML table with information on a single device""" | 619 """Output a HTML table with information on a single device""" |
605 server.wfile.write(_DEVICE_LIST_START) | 620 server.wfile.write(_DEVICE_LIST_START) |
606 server.wfile.write(_DEVICE_SECTION_START) | 621 server.wfile.write(_DEVICE_SECTION_START) |
607 server.wfile.write(_DEVICE_SECTION_ENTRY_TMPL % device) | 622 server.wfile.write(_DEVICE_SECTION_ENTRY_PORT_START_TMPL % device) |
623 server.wfile.write(_DEVICE_SECTION_ENTRY_PORT_END_TMPL % port) | |
608 server.wfile.write(_DEVICE_SECTION_END) | 624 server.wfile.write(_DEVICE_SECTION_END) |
davejcool
2010/09/04 00:45:44
On the performing test page, it was listing ALL po
| |
609 server.wfile.write(_DEVICE_LIST_END) | 625 server.wfile.write(_DEVICE_LIST_END) |
610 | 626 |
611 | 627 |
612 def render_channel_test_order(self, server, device, port): | 628 def render_channel_test_order(self, server, device, port): |
613 """Output HTML a table with device channel ordering info.""" | 629 """Output HTML a table with device channel ordering info.""" |
614 if port != None: | 630 if port != None: |
615 server.wfile.write('<p>Active port on device: %s' % port) | 631 server.wfile.write('<p>Active port on device: %s' % port) |
616 else: | 632 else: |
617 server.wfile.write('<p>Use default (only) port.') | 633 server.wfile.write('<p>Use default (only) port.') |
618 | 634 |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
760 current_sink['sample_format'] = m.group(1) | 776 current_sink['sample_format'] = m.group(1) |
761 current_sink['channels'] = int(m.group(2)) | 777 current_sink['channels'] = int(m.group(2)) |
762 current_sink['sample_rate'] = int(m.group(3)) | 778 current_sink['sample_rate'] = int(m.group(3)) |
763 | 779 |
764 m = _CHANNEL_MAP_RE.match(line) | 780 m = _CHANNEL_MAP_RE.match(line) |
765 if m is not None: | 781 if m is not None: |
766 channel_map = [] | 782 channel_map = [] |
767 for channel in m.group(1).split(','): | 783 for channel in m.group(1).split(','): |
768 channel_map.append(channel) | 784 channel_map.append(channel) |
769 current_sink['channel_map'] = channel_map | 785 current_sink['channel_map'] = channel_map |
786 | |
787 m = _ACTIVE_PORT_RE.match(line) | |
788 if m is not None: | |
789 current_sink['active_port'] = m.group(1) | |
770 | 790 |
771 | 791 |
772 def parse_device_info(self, device_info_output): | 792 def parse_device_info(self, device_info_output): |
773 """Parses the output of a pacmd list-sources or list-sinks call.""" | 793 """Parses the output of a pacmd list-sources or list-sinks call.""" |
774 device_info = { 'info' : [] } | 794 device_info = { 'info' : [] } |
775 current_device = None | 795 current_device = None |
776 port_parsing_mode = False | 796 port_parsing_mode = False |
777 for line in device_info_output.split('\n'): | 797 for line in device_info_output.split('\n'): |
778 # Leave port_parsing_mode if we find a top-level attribute. | 798 # Leave port_parsing_mode if we find a top-level attribute. |
779 if port_parsing_mode and _TOP_LEVEL_RE.match(line) is not None: | 799 if port_parsing_mode and _TOP_LEVEL_RE.match(line) is not None: |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
843 """ | 863 """ |
844 self.do_pacmd('set-default-%s %d' % (type, device['index'])) | 864 self.do_pacmd('set-default-%s %d' % (type, device['index'])) |
845 logging.info( | 865 logging.info( |
846 '* Testing device %d (%s)' % (device['index'], device['name'])) | 866 '* Testing device %d (%s)' % (device['index'], device['name'])) |
847 | 867 |
848 if port is not None: | 868 if port is not None: |
849 self.do_pacmd('set-%s-port %d %s' % (type, device['index'], port)) | 869 self.do_pacmd('set-%s-port %d %s' % (type, device['index'], port)) |
850 logging.info('-- setting port %s' % port) | 870 logging.info('-- setting port %s' % port) |
851 | 871 |
852 | 872 |
873 def restore_playback_port(self, device): | |
874 """Restores the sink's active port to what it was before testing. | |
875 | |
876 Args: | |
877 device: A dictionary with the parsed device information. | |
878 """ | |
879 if device['active_port'] is not None: | |
880 self.do_pacmd('set-sink-port %d %s' % | |
881 (device['index'], device['active_port'])) | |
882 logging.info('Restoring device %d to port %s' % | |
883 (device['index'], device['active_port'])) | |
884 | |
885 | |
853 def do_signal_test_end(self): | 886 def do_signal_test_end(self): |
854 """Play 3 short 1000Hz tones to signal a test case's completion. | 887 """Play 3 short 1000Hz tones to signal a test case's completion. |
855 | 888 |
856 Playback is done on whatever the current default device is. | 889 Playback is done on whatever the current default device is. |
857 """ | 890 """ |
858 config = self.default_tone_config() | 891 config = self.default_tone_config() |
859 config['tone_length_sec'] = 0.3 | 892 config['tone_length_sec'] = 0.3 |
860 self.play_tone(config, 1000) | 893 self.play_tone(config, 1000) |
861 self.play_tone(config, 1000) | 894 self.play_tone(config, 1000) |
862 self.play_tone(config, 1000) | 895 self.play_tone(config, 1000) |
863 | 896 |
864 | 897 |
865 def do_record_test(self, device, port): | 898 def do_record_test(self, device, port): |
866 """Performs a record test for the given device and port. | 899 """Performs a record test for the given device and port. |
867 | 900 |
868 This sets the default playback device is set to whatever device | 901 This sets the default playback device is set to whatever device |
869 is returned first in enumerate_playback_devices(). The playback | 902 is returned first in enumerate_playback_devices(). The playback |
870 device is set to use its first port, unmuted, and set to the | 903 device is set to use the default port (active port before running |
871 test_volume. | 904 tests), unmuted, and set to the test_volume. |
872 | 905 |
873 For each channel on the given device and port, a sample is recorded | 906 For each channel on the given device and port, a sample is recorded |
874 and played-back at max source volume. Then once again with all | 907 and played-back at max source volume. Then once again with all |
875 channel enabled. | 908 channel enabled. |
876 | 909 |
877 Next, a sample is taken at base volume (no amplification) if | 910 Next, a sample is taken at base volume (no amplification) if |
878 that is available, and played back. | 911 that is available, and played back. |
879 | 912 |
880 This is followed by a sample at 1/2 amplifcation, and again with | 913 This is followed by a sample at 1/2 amplifcation, and again with |
881 the record device muted. | 914 the record device muted. |
882 | 915 |
883 Args: | 916 Args: |
884 device: device info dictionary gotten from | 917 device: device info dictionary gotten from |
885 enumerate_record devices() | 918 enumerate_record devices() |
886 port: String with the name of the port to use on the device. | 919 port: String with the name of the port to use on the device. |
887 Can be None if the device does not have multiple ports. | 920 Can be None if the device does not have multiple ports. |
888 """ | 921 """ |
889 # Configure the playback device to something normal. | 922 # Configure the playback device to something normal. |
890 playback_device = self._playback_devices['info'][0] | 923 playback_device = self._playback_devices['info'][0] |
891 playback_volume = self.get_test_volume(playback_device) | 924 playback_volume = self.get_test_volume(playback_device) |
892 playback_port = None | 925 playback_port = None |
davejcool
2010/09/04 00:45:44
Setting playback port the the system default, most
| |
893 if len(playback_device['ports']): | 926 if playback_device['active_port'] is not None: |
927 self.restore_playback_port(playback_device) | |
928 elif len(playback_device['ports']): | |
894 playback_port = playback_device['ports'][0] | 929 playback_port = playback_device['ports'][0] |
895 self.set_default_device_and_port('sink', playback_device, | 930 self.set_default_device_and_port('sink', playback_device, |
896 playback_port) | 931 playback_port) |
897 self.do_set_mute('sink', playback_device['index'], False) | 932 self.do_set_mute('sink', playback_device['index'], False) |
898 self.do_set_volume('sink', playback_device['index'], playback_volume) | 933 self.do_set_volume('sink', playback_device['index'], playback_volume) |
899 | 934 |
900 # Set record device. | 935 # Set record device. |
901 self.set_default_device_and_port('source', device, port) | 936 self.set_default_device_and_port('source', device, port) |
902 | 937 |
903 # Set to max hardware amplification volume. | 938 # Set to max hardware amplification volume. |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1242 cmd = ('%(exec)s ' | 1277 cmd = ('%(exec)s ' |
1243 '-t %(type)s -h %(frequency)f -l %(tone_length_sec)f ' | 1278 '-t %(type)s -h %(frequency)f -l %(tone_length_sec)f ' |
1244 '-c %(channels)d' % args) | 1279 '-c %(channels)d' % args) |
1245 if args['active_channel'] is not None: | 1280 if args['active_channel'] is not None: |
1246 cmd += ' -a %s' % args['active_channel'] | 1281 cmd += ' -a %s' % args['active_channel'] |
1247 if args['type'] == 'tone': | 1282 if args['type'] == 'tone': |
1248 logging.info('[tone %dHz]' % args['frequency']) | 1283 logging.info('[tone %dHz]' % args['frequency']) |
1249 elif args['type'] == 'scale': | 1284 elif args['type'] == 'scale': |
1250 logging.info('[A# harmonic minor scale]') | 1285 logging.info('[A# harmonic minor scale]') |
1251 utils.system(self.pacmd(cmd)) | 1286 utils.system(self.pacmd(cmd)) |
OLD | NEW |