• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2014 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""An adapter to remotely access the audio facade on DUT."""
6
7import os
8import tempfile
9
10
11class AudioFacadeError(Exception):
12    """Errors in audio facade."""
13    pass
14
15
16class AudioFacadeRemoteAdapter(object):
17    """AudioFacadeRemoteAdapter is an adapter to remotely control DUT audio.
18
19    The Autotest host object representing the remote DUT, passed to this
20    class on initialization, can be accessed from its _client property.
21
22    """
23    def __init__(self, host, remote_facade_proxy):
24        """Construct an AudioFacadeRemoteAdapter.
25
26        @param host: Host object representing a remote host.
27        @param remote_facade_proxy: RemoteFacadeProxy object.
28
29        """
30        self._client = host
31        self._proxy = remote_facade_proxy
32
33
34    @property
35    def _audio_proxy(self):
36        """Gets the proxy to DUT audio facade.
37
38        @return XML RPC proxy to DUT audio facade.
39
40        """
41        return self._proxy.audio
42
43
44    def playback(self, client_path, data_format, blocking=False):
45        """Playback an audio file on DUT.
46
47        @param client_path: The path to the file on DUT.
48        @param data_format: A dict containing data format including
49                            file_type, sample_format, channel, and rate.
50                            file_type: file type e.g. 'raw' or 'wav'.
51                            sample_format: One of the keys in
52                                           audio_data.SAMPLE_FORMAT.
53                            channel: number of channels.
54                            rate: sampling rate.
55        @param blocking: Blocks this call until playback finishes.
56
57        @returns: True
58
59        """
60        self._audio_proxy.playback(
61                client_path, data_format, blocking)
62
63
64    def stop_playback(self):
65        """Stops playback process."""
66        self._audio_proxy.stop_playback()
67
68
69    def set_playback_file(self, path):
70        """Copies a file to client.
71
72        @param path: A path to the file.
73
74        @returns: A new path to the file on client.
75
76        """
77        _, ext = os.path.splitext(path)
78        _, client_file_path = tempfile.mkstemp(
79                prefix='playback_', suffix=ext)
80        self._client.send_file(path, client_file_path)
81        return client_file_path
82
83
84    def start_recording(self, data_format):
85        """Starts recording an audio file on DUT.
86
87        @param data_format: A dict containing:
88                            file_type: 'raw'.
89                            sample_format: 'S16_LE' for 16-bit signed integer in
90                                           little-endian.
91                            channel: channel number.
92                            rate: sampling rate.
93
94        @returns: True
95
96        """
97        self._audio_proxy.start_recording(data_format)
98        return True
99
100
101    def stop_recording(self):
102        """Stops recording on DUT.
103
104        @returns: the path to the recorded file on DUT.
105
106        @raises: AudioFacadeError if recorded path is None
107        """
108        path = self._audio_proxy.stop_recording()
109        if not path:
110            raise AudioFacadeError(
111                    'Recording does not work on DUT. '
112                    'Suggest checking messages on DUT')
113        return path
114
115
116    def get_recorded_file(self, remote_path, local_path):
117        """Gets a recorded file from DUT.
118
119        @param remote_path: The path to the file on DUT.
120        @param local_path: The local path for copy destination.
121
122        """
123        self._client.get_file(remote_path, local_path)
124
125
126    def set_selected_output_volume(self, volume):
127        """Sets the selected output volume on DUT.
128
129        @param volume: the volume to be set(0-100).
130
131        """
132        self._audio_proxy.set_selected_output_volume(volume)
133
134
135    def set_input_gain(self, gain):
136        """Sets the system capture gain.
137
138        @param gain: the capture gain in db*100 (100 = 1dB)
139
140        """
141        self._audio_proxy.set_input_gain(gain)
142
143
144    def set_selected_node_types(self, output_node_types, input_node_types):
145        """Set selected node types.
146
147        The node types are defined in cras_utils.CRAS_NODE_TYPES.
148
149        @param output_node_types: A list of output node types.
150                                  None to skip setting.
151        @param input_node_types: A list of input node types.
152                                 None to skip setting.
153
154        """
155        self._audio_proxy.set_selected_node_types(
156                output_node_types, input_node_types)
157
158
159    def get_selected_node_types(self):
160        """Gets the selected output and input node types on DUT.
161
162        @returns: A tuple (output_node_types, input_node_types) where each
163                  field is a list of selected node types defined in
164                  cras_utils.CRAS_NODE_TYPES.
165
166        """
167        return self._audio_proxy.get_selected_node_types()
168
169
170    def get_plugged_node_types(self):
171        """Gets the plugged output and input node types on DUT.
172
173        @returns: A tuple (output_node_types, input_node_types) where each
174                  field is a list of plugged node types defined in
175                  cras_utils.CRAS_NODE_TYPES.
176
177        """
178        return self._audio_proxy.get_plugged_node_types()
179
180
181    def dump_diagnostics(self, file_path):
182        """Dumps audio diagnostics results to a file.
183
184        @param file_path: The path to dump results.
185
186        @returns: True
187
188        """
189        _, remote_path = tempfile.mkstemp(
190                prefix='audio_dump_', suffix='.txt')
191        self._audio_proxy.dump_diagnostics(remote_path)
192        self._client.get_file(remote_path, file_path)
193        return True
194
195
196    def start_counting_signal(self, signal_name):
197        """Starts counting DBus signal from Cras.
198
199        @param signal_name: Signal of interest.
200
201        """
202        self._audio_proxy.start_counting_signal(signal_name)
203
204
205    def stop_counting_signal(self):
206        """Stops counting DBus signal from Cras.
207
208        @returns: Number of signals counted starting from last
209                  start_counting_signal call.
210
211        """
212        return self._audio_proxy.stop_counting_signal()
213
214
215    def wait_for_unexpected_nodes_changed(self, timeout_secs):
216        """Waits for unexpected nodes changed signal.
217
218        @param timeout_secs: Timeout in seconds for waiting.
219
220        """
221        self._audio_proxy.wait_for_unexpected_nodes_changed(timeout_secs)
222
223
224    def set_chrome_active_volume(self, volume):
225        """Sets the active audio output volume using chrome.audio API.
226
227        @param volume: Volume to set (0~100).
228
229        """
230        self._audio_proxy.set_chrome_active_volume(volume)
231
232
233    def set_chrome_mute(self, mute):
234        """Mutes the active audio output using chrome.audio API.
235
236        @param mute: True to mute. False otherwise.
237
238        """
239        self._audio_proxy.set_chrome_mute(mute)
240
241
242    def get_chrome_active_volume_mute(self):
243        """Gets the volume state of active audio output using chrome.audio API.
244
245        @param returns: A tuple (volume, mute), where volume is 0~100, and mute
246                        is True if node is muted, False otherwise.
247
248        """
249        return self._audio_proxy.get_chrome_active_volume_mute()
250
251
252    def set_chrome_active_node_type(self, output_node_type, input_node_type):
253        """Sets active node type through chrome.audio API.
254
255        The node types are defined in cras_utils.CRAS_NODE_TYPES.
256        The current active node will be disabled first if the new active node
257        is different from the current one.
258
259        @param output_node_type: A node type defined in
260                                 cras_utils.CRAS_NODE_TYPES. None to skip.
261        @param input_node_type: A node type defined in
262                                 cras_utils.CRAS_NODE_TYPES. None to skip
263
264        """
265        self._audio_proxy.set_chrome_active_node_type(
266                output_node_type, input_node_type)
267
268
269    def start_arc_recording(self):
270        """Starts recording using microphone app in container."""
271        self._audio_proxy.start_arc_recording()
272
273
274    def stop_arc_recording(self):
275        """Checks the recording is stopped and gets the recorded path.
276
277        The recording duration of microphone app is fixed, so this method just
278        asks Cros device to copy the recorded result from container to a path
279        on Cros device.
280
281        @returns: Path to the recorded file on DUT.
282
283        """
284        return self._audio_proxy.stop_arc_recording()
285
286
287    def set_arc_playback_file(self, path):
288        """Copies the file from server to Cros host and into container.
289
290        @param path: Path to the file on server.
291
292        @returns: Path to the file in container on Cros host.
293
294        """
295        client_file_path = self.set_playback_file(path)
296        return self._audio_proxy.set_arc_playback_file(client_file_path)
297
298
299    def start_arc_playback(self, path):
300        """Starts playback through ARC on Cros host.
301
302        @param path: Path to the file in container on Cros host.
303
304        """
305        self._audio_proxy.start_arc_playback(path)
306
307
308    def stop_arc_playback(self):
309        """Stops playback through ARC on Cros host."""
310        self._audio_proxy.stop_arc_playback()
311