blob: f7d249da6105ccd460feb10b25dfb8a823eb3b22 [file] [log] [blame]
Moja Hsu7ef568c2016-12-27 15:58:58 +08001#!/usr/bin/env python2
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +08002# Copyright 2015 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"""A simple utility to connect to Chameleond in an interactive shell."""
7
8import argparse
9import code
10import logging
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +080011import os
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080012import readline
13import rlcompleter
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +080014import subprocess
Cheng-Yi Chiang852e13e2017-04-17 19:02:22 +080015import time
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080016import xmlrpclib
17
Moja Hsu7ef568c2016-12-27 15:58:58 +080018from audio.audio_value_detector import AudioValueDetector
19
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080020
21def ShowMessages(proxy):
22 """Shows the messages for usage.
23
24 Args:
25 proxy: The xmlrpclib.ServerProxy to chameleond.
26 """
27 logging.info('In interactive shell, p is the proxy to chameleond server')
28 supported_ports = proxy.GetSupportedPorts()
29 linein_port = None
30 hdmi_port = None
31 port_messages = []
32 for port in supported_ports:
33 port_type = proxy.GetConnectorType(port)
34 if port_type == 'LineIn':
35 linein_port = port
36 if port_type == 'HDMI':
37 hdmi_port = port
38 port_messages.append('Port %d is %s.' % (port, port_type))
Moja Hsu28e1aab2017-03-30 15:24:35 +080039 message = '''
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080040 %s
Moja Hsu28e1aab2017-03-30 15:24:35 +080041 E.g.''' % '\n '.join(port_messages)
42 if linein_port:
43 message += '''
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080044 p.StartCapturingAudio(%d) to capture from LineIn.
Moja Hsu28e1aab2017-03-30 15:24:35 +080045 p.StopCapturingAudio(%d) to stop capturing from LineIn.''' % (
46 linein_port, linein_port)
47
48 if hdmi_port:
49 message += '''
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080050 p.Plug(%d) to plug HDMI.
Moja Hsu28e1aab2017-03-30 15:24:35 +080051 p.Unplug(%d) to unplug HDMI.''' % (hdmi_port, hdmi_port)
52
53 logging.info(message)
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080054
55
Moja Hsu7ef568c2016-12-27 15:58:58 +080056def DetectAudioValue0(channels=None, margin=0.01, continuous_samples=5,
57 duration=3600, dump_samples=48000):
58 """Detects if Chameleon captures continuous audio data close to 0.
59
60 This function will get the audio streaming data from stream server and will
61 check if the audio data is close to 0 by the margin parameter.
62 -margin < value < margin will be considered to be close to 0.
63 If there are continuous audio samples close to 0 in the streamed data,
64 test_server will log it and save the audio data to a wav file.
65
66 E.g.
67 >>> ConnectCrosToLineIn()
68 >>> p.StartCapturingAudio(6, False)
69 >>> DetectAudioValue0(duration=24*3600, margin=0.001)
70
71 Args:
72 channels: Array of audio channels we want to check.
73 E.g. [0, 1] means we only care about channel 0 and channel 1.
74 margin: Used to decide if the value is closed to 0. Maximum value is 1.
75 continuous_samples: When continuous_samples samples are closed to 0, trigger
76 event.
77 duration: The duration of monitoring in seconds.
78 dump_samples: When event happens, how many audio samples we want to
79 save to file.
80 """
81 if not channels:
82 channels = [0, 1]
83 detecter = AudioValueDetector(options.host) # pylint: disable=undefined-variable
84 detecter.Detect(channels, margin, continuous_samples, duration, dump_samples)
85 return True
86
87
88def StartInteractiveShell(p, options): # pylint: disable=unused-argument
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080089 """Starts an interactive shell.
90
91 Args:
92 p: The xmlrpclib.ServerProxy to chameleond.
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +080093 options: The namespace from argparse.
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080094 """
Moja Hsu7ef568c2016-12-27 15:58:58 +080095 vars = globals() # pylint: disable=redefined-builtin
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080096 vars.update(locals())
97 readline.set_completer(rlcompleter.Completer(vars).complete)
98 readline.parse_and_bind("tab: complete")
99 shell = code.InteractiveConsole(vars)
100 shell.interact()
101
102
103def ParseArgs():
104 """Parses the arguments.
105
Moja Hsu7ef568c2016-12-27 15:58:58 +0800106 Returns:
107 the namespace containing parsed arguments.
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +0800108 """
109 parser = argparse.ArgumentParser(
110 description='Connect to Chameleond and use interactive shell.',
111 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
112 parser.add_argument('--chameleon_host', type=str, dest='host', required=True,
113 help='host address of Chameleond')
114 parser.add_argument('--port', type=int, dest='port', default=9992,
115 help='port number of Chameleond')
116 return parser.parse_args()
117
118
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800119def GetAndConvertRecordedFile(remote_path):
120 """Gets recorded file and converts it into a wav file.
121
122 A helper function to get recorded file from Chameleon host and do
123 file format conversion from 32 bit, 48000 rate, 8 channel raw file
124 to 2 channel wav file.
125
126 E.g.
127 >>> p.StartCapturingAudio(6)
128 >>> s = p.StopCapturingAudio(6)
129 >>> GetAndConvertRecordedFile(s[0])
130
131 The recorded raw file and converted wav file will be in current
132 directory.
133
134 Args:
135 remote_path: The file to copy from Chameleon host.
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800136 """
137 basename = os.path.basename(remote_path)
138 # options is already in the namespace.
139 subprocess.check_call(
Moja Hsu7ef568c2016-12-27 15:58:58 +0800140 ['scp', 'root@%s:%s' % (options.host, remote_path), basename]) # pylint: disable=undefined-variable
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800141 subprocess.check_call(
142 ['sox', '-b', '32', '-r', '48000', '-c', '8', '-e', 'signed',
143 basename, '-c', '2', basename + '.wav'])
144
145
146def ConnectCrosToLineIn():
147 """Connects a audio bus path from Cros headphone to Chameleon LineIn."""
Moja Hsu7ef568c2016-12-27 15:58:58 +0800148 p.AudioBoardConnect(1, 'Cros device headphone') # pylint: disable=undefined-variable
149 p.AudioBoardConnect(1, 'Chameleon FPGA line-in') # pylint: disable=undefined-variable
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800150
151
Cheng-Yi Chiang852e13e2017-04-17 19:02:22 +0800152def TestMotors():
153 """Test motors by touching and releasing each button once."""
154 for func in ['Call', 'Hang Up', 'Mute', 'Vol Up', 'Vol Down']:
155 PressOneFunc(func)
156
157
158def PressOneFunc(func, time_sec=0):
159 """Test motors by touching and releasing one button.
160
161 Args:
162 func: The motor function. One of 'Call', 'Hang Up', 'Mute', 'Vol Up',
163 'Vol Down'.
164 time_sec: Hold time in seconds after touch and before release.
165 """
166 logging.info('Testing %s button, press and hold for %f seconds',
167 func, time_sec)
168 p.motor_board.Touch(func)
169 time.sleep(time_sec)
170 p.motor_board.Release(func)
171
172
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +0800173def Main():
174 """The Main program."""
175 logging.basicConfig(
176 format='%(asctime)s:%(levelname)s:%(message)s', level=logging.DEBUG)
177
178 options = ParseArgs()
179
180 address = 'http://%s:%s' % (options.host, options.port)
181 proxy = xmlrpclib.ServerProxy(address)
182 logging.info('Connected to %s with MAC address %s',
183 address, proxy.GetMacAddress())
184 ShowMessages(proxy)
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800185 StartInteractiveShell(proxy, options)
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +0800186
187
188if __name__ == '__main__':
189 Main()