blob: 2529b85e8723691da560423c25942d47b558ef1a [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 Chiang3f9cb972015-11-23 17:43:59 +080015import xmlrpclib
16
Moja Hsu7ef568c2016-12-27 15:58:58 +080017from audio.audio_value_detector import AudioValueDetector
18
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080019
20def ShowMessages(proxy):
21 """Shows the messages for usage.
22
23 Args:
24 proxy: The xmlrpclib.ServerProxy to chameleond.
25 """
26 logging.info('In interactive shell, p is the proxy to chameleond server')
27 supported_ports = proxy.GetSupportedPorts()
28 linein_port = None
29 hdmi_port = None
30 port_messages = []
31 for port in supported_ports:
32 port_type = proxy.GetConnectorType(port)
33 if port_type == 'LineIn':
34 linein_port = port
35 if port_type == 'HDMI':
36 hdmi_port = port
37 port_messages.append('Port %d is %s.' % (port, port_type))
Moja Hsu28e1aab2017-03-30 15:24:35 +080038 message = '''
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080039 %s
Moja Hsu28e1aab2017-03-30 15:24:35 +080040 E.g.''' % '\n '.join(port_messages)
41 if linein_port:
42 message += '''
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080043 p.StartCapturingAudio(%d) to capture from LineIn.
Moja Hsu28e1aab2017-03-30 15:24:35 +080044 p.StopCapturingAudio(%d) to stop capturing from LineIn.''' % (
45 linein_port, linein_port)
46
47 if hdmi_port:
48 message += '''
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080049 p.Plug(%d) to plug HDMI.
Moja Hsu28e1aab2017-03-30 15:24:35 +080050 p.Unplug(%d) to unplug HDMI.''' % (hdmi_port, hdmi_port)
51
52 logging.info(message)
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080053
54
Moja Hsu7ef568c2016-12-27 15:58:58 +080055def DetectAudioValue0(channels=None, margin=0.01, continuous_samples=5,
56 duration=3600, dump_samples=48000):
57 """Detects if Chameleon captures continuous audio data close to 0.
58
59 This function will get the audio streaming data from stream server and will
60 check if the audio data is close to 0 by the margin parameter.
61 -margin < value < margin will be considered to be close to 0.
62 If there are continuous audio samples close to 0 in the streamed data,
63 test_server will log it and save the audio data to a wav file.
64
65 E.g.
66 >>> ConnectCrosToLineIn()
67 >>> p.StartCapturingAudio(6, False)
68 >>> DetectAudioValue0(duration=24*3600, margin=0.001)
69
70 Args:
71 channels: Array of audio channels we want to check.
72 E.g. [0, 1] means we only care about channel 0 and channel 1.
73 margin: Used to decide if the value is closed to 0. Maximum value is 1.
74 continuous_samples: When continuous_samples samples are closed to 0, trigger
75 event.
76 duration: The duration of monitoring in seconds.
77 dump_samples: When event happens, how many audio samples we want to
78 save to file.
79 """
80 if not channels:
81 channels = [0, 1]
82 detecter = AudioValueDetector(options.host) # pylint: disable=undefined-variable
83 detecter.Detect(channels, margin, continuous_samples, duration, dump_samples)
84 return True
85
86
87def StartInteractiveShell(p, options): # pylint: disable=unused-argument
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080088 """Starts an interactive shell.
89
90 Args:
91 p: The xmlrpclib.ServerProxy to chameleond.
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +080092 options: The namespace from argparse.
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080093 """
Moja Hsu7ef568c2016-12-27 15:58:58 +080094 vars = globals() # pylint: disable=redefined-builtin
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080095 vars.update(locals())
96 readline.set_completer(rlcompleter.Completer(vars).complete)
97 readline.parse_and_bind("tab: complete")
98 shell = code.InteractiveConsole(vars)
99 shell.interact()
100
101
102def ParseArgs():
103 """Parses the arguments.
104
Moja Hsu7ef568c2016-12-27 15:58:58 +0800105 Returns:
106 the namespace containing parsed arguments.
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +0800107 """
108 parser = argparse.ArgumentParser(
109 description='Connect to Chameleond and use interactive shell.',
110 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
111 parser.add_argument('--chameleon_host', type=str, dest='host', required=True,
112 help='host address of Chameleond')
113 parser.add_argument('--port', type=int, dest='port', default=9992,
114 help='port number of Chameleond')
115 return parser.parse_args()
116
117
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800118def GetAndConvertRecordedFile(remote_path):
119 """Gets recorded file and converts it into a wav file.
120
121 A helper function to get recorded file from Chameleon host and do
122 file format conversion from 32 bit, 48000 rate, 8 channel raw file
123 to 2 channel wav file.
124
125 E.g.
126 >>> p.StartCapturingAudio(6)
127 >>> s = p.StopCapturingAudio(6)
128 >>> GetAndConvertRecordedFile(s[0])
129
130 The recorded raw file and converted wav file will be in current
131 directory.
132
133 Args:
134 remote_path: The file to copy from Chameleon host.
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800135 """
136 basename = os.path.basename(remote_path)
137 # options is already in the namespace.
138 subprocess.check_call(
Moja Hsu7ef568c2016-12-27 15:58:58 +0800139 ['scp', 'root@%s:%s' % (options.host, remote_path), basename]) # pylint: disable=undefined-variable
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800140 subprocess.check_call(
141 ['sox', '-b', '32', '-r', '48000', '-c', '8', '-e', 'signed',
142 basename, '-c', '2', basename + '.wav'])
143
144
145def ConnectCrosToLineIn():
146 """Connects a audio bus path from Cros headphone to Chameleon LineIn."""
Moja Hsu7ef568c2016-12-27 15:58:58 +0800147 p.AudioBoardConnect(1, 'Cros device headphone') # pylint: disable=undefined-variable
148 p.AudioBoardConnect(1, 'Chameleon FPGA line-in') # pylint: disable=undefined-variable
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800149
150
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +0800151def Main():
152 """The Main program."""
153 logging.basicConfig(
154 format='%(asctime)s:%(levelname)s:%(message)s', level=logging.DEBUG)
155
156 options = ParseArgs()
157
158 address = 'http://%s:%s' % (options.host, options.port)
159 proxy = xmlrpclib.ServerProxy(address)
160 logging.info('Connected to %s with MAC address %s',
161 address, proxy.GetMacAddress())
162 ShowMessages(proxy)
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800163 StartInteractiveShell(proxy, options)
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +0800164
165
166if __name__ == '__main__':
167 Main()