• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2016 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"""This module provides the audio widgets related to ARC used in audio tests."""
6
7import copy
8import tempfile
9
10from autotest_lib.client.cros.audio import audio_test_data
11from autotest_lib.client.cros.chameleon import audio_widget
12
13class CrosInputWidgetARCHandler(audio_widget.CrosInputWidgetHandler):
14    """
15
16    This class abstracts a Cros device audio input widget ARC handler.
17
18    """
19    # AMR-NB uses variable bit rates so we set sample_format to None.
20    # Other format info are actually useless for sox because sox can read them
21    # from file header.
22    _SOURCE_FORMAT = dict(file_type='amr-nb',
23                          sample_format=None,
24                          channel=1,
25                          rate=8000)
26
27    def start_recording(self):
28        """Starts recording audio through ARC."""
29        self._audio_facade.start_arc_recording()
30
31
32    def stop_recording(self):
33        """Stops recording audio through ARC.
34
35        @returns:
36            A tuple (remote_path, format).
37                remote_path: The path to the recorded file on Cros device.
38                format: A dict containing:
39                    file_type: 'raw'.
40                    sample_format: 'S16_LE' for 16-bit signed integer in
41                                   little-endian.
42                    channel: channel number.
43                    rate: sampling rate.
44
45        """
46        return (self._audio_facade.stop_arc_recording(),
47                self._DEFAULT_DATA_FORMAT)
48
49
50    def get_recorded_binary(self, remote_path, record_format):
51        """Gets remote recorded file binary from Cros device..
52
53        Gets and reads recorded file from Cros device.
54        The argument 'record_format' is what API user want on output.
55        The real file format of file at 'remote_path' can be another source
56        format. This method handles the format conversion from source format
57        into record_format, and returns the converted binary.
58
59        Handle the format conversion from source format into record_format.
60
61        @param remote_path: The path to the recorded file on Cros device.
62        @param record_format: The data format of returned binary.
63                     A dict containing
64                     file_type: 'raw' or 'wav'.
65                     sample_format: 'S32_LE' for 32-bit signed integer in
66                                    little-endian. Refer to aplay manpage for
67                                    other formats.
68                     channel: channel number.
69                     rate: sampling rate.
70
71        @returns: The recorded binary.
72
73        @raises: CrosInputWidgetHandlerError if record_format is not correct.
74
75        """
76        if record_format != self._DEFAULT_DATA_FORMAT:
77            raise audio_widget.CrosInputWidgetHandlerError(
78                    'Record format %r is not valid' % record_format)
79
80        ext = '.' + self._SOURCE_FORMAT['file_type']
81        with tempfile.NamedTemporaryFile(prefix='recorded_', suffix=ext) as f:
82            self._audio_facade.get_recorded_file(remote_path, f.name)
83
84            # Handles conversion from source format into record_format.
85            test_data = audio_test_data.AudioTestData(
86                    self._SOURCE_FORMAT, f.name)
87            converted_test_data = test_data.convert(record_format, 1.0)
88            try:
89                return converted_test_data.get_binary()
90            finally:
91                converted_test_data.delete()
92
93
94class CrosOutputWidgetARCHandlerError(Exception):
95    """Error in CrosOutputWidgetARCHandler."""
96    pass
97
98
99class CrosOutputWidgetARCHandler(audio_widget.CrosOutputWidgetHandler):
100    """This class abstracts a Cros device audio output widget ARC handler."""
101    _SUPPORTED_FILE_TYPES = ['wav', 'mp3']
102    _DEFAULT_FILE_TYPE = 'wav'
103
104    def set_playback_data(self, test_data):
105        """Sets data to play.
106
107        @param test_data: An AudioTestData object.
108
109        @returns: Path to the file in container on Cros host.
110
111        """
112        # Handle the format conversion because ARC does not recognize raw file.
113        if test_data.data_format['file_type'] not in self._SUPPORTED_FILE_TYPES:
114            new_data_format = copy.deepcopy(test_data.data_format)
115            new_data_format['file_type'] = self._DEFAULT_FILE_TYPE
116            test_data = test_data.convert(new_data_format, 1.0)
117        return self._audio_facade.set_arc_playback_file(test_data.path)
118
119
120    def start_playback(self, path, blocking=False):
121        """Starts playing audio.
122
123        @param path: Path to the file to play in container on Cros host.
124        @param blocking: Blocks this call until playback finishes.
125
126        @raises: NotImplementedError if blocking is True.
127
128        """
129        if blocking:
130            raise NotImplementedError(
131                    'Blocking playback on ARC is not supported.')
132        self._audio_facade.start_arc_playback(path)
133
134
135    def stop_playback(self):
136        """Stops playing audio."""
137        self._audio_facade.stop_arc_playback()
138