blob: 2fadacc420ce2c68be6771a5bb12d81a5746e392 [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))
38
39 logging.info('''
40 %s
41 E.g.
42 p.StartCapturingAudio(%d) to capture from LineIn.
43 p.StopCapturingAudio(%d) to stop capturing from LineIn.
44 p.Plug(%d) to plug HDMI.
Moja Hsu7ef568c2016-12-27 15:58:58 +080045 p.Unplug(%d) to unplug HDMI.''', '\n '.join(port_messages),
46 linein_port, linein_port, hdmi_port, hdmi_port)
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080047
48
Moja Hsu7ef568c2016-12-27 15:58:58 +080049def DetectAudioValue0(channels=None, margin=0.01, continuous_samples=5,
50 duration=3600, dump_samples=48000):
51 """Detects if Chameleon captures continuous audio data close to 0.
52
53 This function will get the audio streaming data from stream server and will
54 check if the audio data is close to 0 by the margin parameter.
55 -margin < value < margin will be considered to be close to 0.
56 If there are continuous audio samples close to 0 in the streamed data,
57 test_server will log it and save the audio data to a wav file.
58
59 E.g.
60 >>> ConnectCrosToLineIn()
61 >>> p.StartCapturingAudio(6, False)
62 >>> DetectAudioValue0(duration=24*3600, margin=0.001)
63
64 Args:
65 channels: Array of audio channels we want to check.
66 E.g. [0, 1] means we only care about channel 0 and channel 1.
67 margin: Used to decide if the value is closed to 0. Maximum value is 1.
68 continuous_samples: When continuous_samples samples are closed to 0, trigger
69 event.
70 duration: The duration of monitoring in seconds.
71 dump_samples: When event happens, how many audio samples we want to
72 save to file.
73 """
74 if not channels:
75 channels = [0, 1]
76 detecter = AudioValueDetector(options.host) # pylint: disable=undefined-variable
77 detecter.Detect(channels, margin, continuous_samples, duration, dump_samples)
78 return True
79
80
81def StartInteractiveShell(p, options): # pylint: disable=unused-argument
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080082 """Starts an interactive shell.
83
84 Args:
85 p: The xmlrpclib.ServerProxy to chameleond.
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +080086 options: The namespace from argparse.
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080087 """
Moja Hsu7ef568c2016-12-27 15:58:58 +080088 vars = globals() # pylint: disable=redefined-builtin
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +080089 vars.update(locals())
90 readline.set_completer(rlcompleter.Completer(vars).complete)
91 readline.parse_and_bind("tab: complete")
92 shell = code.InteractiveConsole(vars)
93 shell.interact()
94
95
96def ParseArgs():
97 """Parses the arguments.
98
Moja Hsu7ef568c2016-12-27 15:58:58 +080099 Returns:
100 the namespace containing parsed arguments.
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +0800101 """
102 parser = argparse.ArgumentParser(
103 description='Connect to Chameleond and use interactive shell.',
104 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
105 parser.add_argument('--chameleon_host', type=str, dest='host', required=True,
106 help='host address of Chameleond')
107 parser.add_argument('--port', type=int, dest='port', default=9992,
108 help='port number of Chameleond')
109 return parser.parse_args()
110
111
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800112def GetAndConvertRecordedFile(remote_path):
113 """Gets recorded file and converts it into a wav file.
114
115 A helper function to get recorded file from Chameleon host and do
116 file format conversion from 32 bit, 48000 rate, 8 channel raw file
117 to 2 channel wav file.
118
119 E.g.
120 >>> p.StartCapturingAudio(6)
121 >>> s = p.StopCapturingAudio(6)
122 >>> GetAndConvertRecordedFile(s[0])
123
124 The recorded raw file and converted wav file will be in current
125 directory.
126
127 Args:
128 remote_path: The file to copy from Chameleon host.
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800129 """
130 basename = os.path.basename(remote_path)
131 # options is already in the namespace.
132 subprocess.check_call(
Moja Hsu7ef568c2016-12-27 15:58:58 +0800133 ['scp', 'root@%s:%s' % (options.host, remote_path), basename]) # pylint: disable=undefined-variable
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800134 subprocess.check_call(
135 ['sox', '-b', '32', '-r', '48000', '-c', '8', '-e', 'signed',
136 basename, '-c', '2', basename + '.wav'])
137
138
139def ConnectCrosToLineIn():
140 """Connects a audio bus path from Cros headphone to Chameleon LineIn."""
Moja Hsu7ef568c2016-12-27 15:58:58 +0800141 p.AudioBoardConnect(1, 'Cros device headphone') # pylint: disable=undefined-variable
142 p.AudioBoardConnect(1, 'Chameleon FPGA line-in') # pylint: disable=undefined-variable
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800143
144
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +0800145def Main():
146 """The Main program."""
147 logging.basicConfig(
148 format='%(asctime)s:%(levelname)s:%(message)s', level=logging.DEBUG)
149
150 options = ParseArgs()
151
152 address = 'http://%s:%s' % (options.host, options.port)
153 proxy = xmlrpclib.ServerProxy(address)
154 logging.info('Connected to %s with MAC address %s',
155 address, proxy.GetMacAddress())
156 ShowMessages(proxy)
Cheng-Yi Chiangab747d82016-11-22 15:39:12 +0800157 StartInteractiveShell(proxy, options)
Cheng-Yi Chiang3f9cb972015-11-23 17:43:59 +0800158
159
160if __name__ == '__main__':
161 Main()