| # Copyright 2016 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """This module provides the audio widgets related to ARC used in audio tests.""" |
| |
| import copy |
| import tempfile |
| |
| from autotest_lib.client.cros.audio import audio_test_data |
| from autotest_lib.client.cros.chameleon import audio_widget |
| |
| class CrosInputWidgetARCHandler(audio_widget.CrosInputWidgetHandler): |
| """ |
| |
| This class abstracts a Cros device audio input widget ARC handler. |
| |
| """ |
| # AMR-NB uses variable bit rates so we set sample_format to None. |
| # Other format info are actually useless for sox because sox can read them |
| # from file header. |
| _SOURCE_FORMAT = dict(file_type='amr-nb', |
| sample_format=None, |
| channel=1, |
| rate=8000) |
| |
| def start_recording(self): |
| """Starts recording audio through ARC.""" |
| self._audio_facade.start_arc_recording() |
| |
| |
| def stop_recording(self): |
| """Stops recording audio through ARC. |
| |
| @returns: |
| A tuple (remote_path, format). |
| remote_path: The path to the recorded file on Cros device. |
| format: A dict containing: |
| file_type: 'raw'. |
| sample_format: 'S16_LE' for 16-bit signed integer in |
| little-endian. |
| channel: channel number. |
| rate: sampling rate. |
| |
| """ |
| return (self._audio_facade.stop_arc_recording(), |
| self._DEFAULT_DATA_FORMAT) |
| |
| |
| def get_recorded_binary(self, remote_path, record_format): |
| """Gets remote recorded file binary from Cros device.. |
| |
| Gets and reads recorded file from Cros device. |
| The argument 'record_format' is what API user want on output. |
| The real file format of file at 'remote_path' can be another source |
| format. This method handles the format conversion from source format |
| into record_format, and returns the converted binary. |
| |
| Handle the format conversion from source format into record_format. |
| |
| @param remote_path: The path to the recorded file on Cros device. |
| @param record_format: The data format of returned binary. |
| A dict containing |
| file_type: 'raw' or 'wav'. |
| sample_format: 'S32_LE' for 32-bit signed integer in |
| little-endian. Refer to aplay manpage for |
| other formats. |
| channel: channel number. |
| rate: sampling rate. |
| |
| @returns: The recorded binary. |
| |
| @raises: CrosInputWidgetHandlerError if record_format is not correct. |
| |
| """ |
| if record_format != self._DEFAULT_DATA_FORMAT: |
| raise audio_widget.CrosInputWidgetHandlerError( |
| 'Record format %r is not valid' % record_format) |
| |
| ext = '.' + self._SOURCE_FORMAT['file_type'] |
| with tempfile.NamedTemporaryFile(prefix='recorded_', suffix=ext) as f: |
| self._audio_facade.get_recorded_file(remote_path, f.name) |
| |
| # Handles conversion from source format into record_format. |
| test_data = audio_test_data.AudioTestData( |
| self._SOURCE_FORMAT, f.name) |
| converted_test_data = test_data.convert(record_format, 1.0) |
| try: |
| return converted_test_data.get_binary() |
| finally: |
| converted_test_data.delete() |
| |
| |
| class CrosOutputWidgetARCHandlerError(Exception): |
| """Error in CrosOutputWidgetARCHandler.""" |
| pass |
| |
| |
| class CrosOutputWidgetARCHandler(audio_widget.CrosOutputWidgetHandler): |
| """This class abstracts a Cros device audio output widget ARC handler.""" |
| _SUPPORTED_FILE_TYPES = ['wav', 'mp3'] |
| _DEFAULT_FILE_TYPE = 'wav' |
| |
| def set_playback_data(self, test_data): |
| """Sets data to play. |
| |
| @param test_data: An AudioTestData object. |
| |
| @returns: Path to the file in container on Cros host. |
| |
| """ |
| # Handle the format conversion because ARC does not recognize raw file. |
| if test_data.data_format['file_type'] not in self._SUPPORTED_FILE_TYPES: |
| new_data_format = copy.deepcopy(test_data.data_format) |
| new_data_format['file_type'] = self._DEFAULT_FILE_TYPE |
| test_data = test_data.convert(new_data_format, 1.0) |
| return self._audio_facade.set_arc_playback_file(test_data.path) |
| |
| |
| def start_playback(self, path, blocking=False): |
| """Starts playing audio. |
| |
| @param path: Path to the file to play in container on Cros host. |
| @param blocking: Blocks this call until playback finishes. |
| |
| @raises: NotImplementedError if blocking is True. |
| |
| """ |
| if blocking: |
| raise NotImplementedError( |
| 'Blocking playback on ARC is not supported.') |
| self._audio_facade.start_arc_playback(path) |
| |
| |
| def stop_playback(self): |
| """Stops playing audio.""" |
| self._audio_facade.stop_arc_playback() |