Home | History | Annotate | Download | only in chameleon
      1 # Copyright 2015 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 board interface."""
      6 
      7 import logging
      8 
      9 from autotest_lib.client.cros.chameleon import chameleon_audio_ids as ids
     10 
     11 
     12 class AudioBoard(object):
     13     """AudioBoard is an abstraction of an audio board on a Chameleon board.
     14 
     15     It provides methods to control audio board.
     16 
     17     A ChameleonConnection object is passed to the construction.
     18 
     19     """
     20     def __init__(self, chameleon_connection):
     21         """Constructs an AudioBoard.
     22 
     23         @param chameleon_connection: A ChameleonConnection object.
     24 
     25         """
     26         self._audio_buses = {
     27                 1: AudioBus(1, chameleon_connection),
     28                 2: AudioBus(2, chameleon_connection)}
     29 
     30         self._jack_plugger = None
     31         try:
     32             self._jack_plugger = AudioJackPlugger(chameleon_connection)
     33         except AudioJackPluggerException:
     34             logging.warning(
     35                     'There is no jack plugger on this audio board.')
     36             self._jack_plugger = None
     37 
     38         self._bluetooth_controller = BluetoothController(chameleon_connection)
     39 
     40 
     41     def get_audio_bus(self, bus_index):
     42         """Gets an audio bus on this audio board.
     43 
     44         @param bus_index: The bus index 1 or 2.
     45 
     46         @returns: An AudioBus object.
     47 
     48         """
     49         return self._audio_buses[bus_index]
     50 
     51 
     52     def get_jack_plugger(self):
     53         """Gets an AudioJackPlugger on this audio board.
     54 
     55         @returns: An AudioJackPlugger object if there is an audio jack plugger.
     56                   None if there is no audio jack plugger.
     57 
     58         """
     59         return self._jack_plugger
     60 
     61 
     62     def get_bluetooth_controller(self):
     63         """Gets an BluetoothController on this audio board.
     64 
     65         @returns: An BluetoothController object.
     66 
     67         """
     68         return self._bluetooth_controller
     69 
     70 
     71 class AudioBus(object):
     72     """AudioBus is an abstraction of an audio bus on an audio board.
     73 
     74     It provides methods to control audio bus.
     75 
     76     A ChameleonConnection object is passed to the construction.
     77 
     78     @properties:
     79         bus_index: The bus index 1 or 2.
     80 
     81     """
     82     # Maps port id defined in chameleon_audio_ids to endpoint name used in
     83     # chameleond audio bus API.
     84     _PORT_ID_AUDIO_BUS_ENDPOINT_MAP = {
     85             ids.ChameleonIds.LINEIN: 'Chameleon FPGA line-in',
     86             ids.ChameleonIds.LINEOUT: 'Chameleon FPGA line-out',
     87             ids.CrosIds.HEADPHONE: 'Cros device headphone',
     88             ids.CrosIds.EXTERNAL_MIC: 'Cros device external microphone',
     89             ids.PeripheralIds.SPEAKER: 'Peripheral speaker',
     90             ids.PeripheralIds.MIC: 'Peripheral microphone',
     91             ids.PeripheralIds.BLUETOOTH_DATA_RX:
     92                     'Bluetooth module output',
     93             ids.PeripheralIds.BLUETOOTH_DATA_TX:
     94                     'Bluetooth module input'}
     95 
     96 
     97     class AudioBusSnapshot(object):
     98         """Abstracts the snapshot of AudioBus for user to restore it later."""
     99         def __init__(self, endpoints):
    100             """Initializes an AudioBusSnapshot.
    101 
    102             @param endpoints: A set of endpoints to keep a copy.
    103 
    104             """
    105             self._endpoints = endpoints.copy()
    106 
    107 
    108     def __init__(self, bus_index, chameleon_connection):
    109         """Constructs an AudioBus.
    110 
    111         @param bus_index: The bus index 1 or 2.
    112         @param chameleon_connection: A ChameleonConnection object.
    113 
    114         """
    115         self.bus_index = bus_index
    116         self._chameleond_proxy = chameleon_connection.chameleond_proxy
    117         self._connected_endpoints = set()
    118 
    119 
    120     def _get_endpoint_name(self, port_id):
    121         """Gets the endpoint name used in audio bus API.
    122 
    123         @param port_id: A string, that is, id in ChameleonIds, CrosIds, or
    124                         PeripheralIds defined in chameleon_audio_ids.
    125 
    126         @returns: The endpoint name for the port used in audio bus API.
    127 
    128         """
    129         return self._PORT_ID_AUDIO_BUS_ENDPOINT_MAP[port_id]
    130 
    131 
    132     def _connect_endpoint(self, endpoint):
    133         """Connects an endpoint to audio bus.
    134 
    135         @param endpoint: An endpoint name in _PORT_ID_AUDIO_BUS_ENDPOINT_MAP.
    136 
    137         """
    138         logging.debug(
    139                 'Audio bus %s is connecting endpoint %s',
    140                 self.bus_index, endpoint)
    141         self._chameleond_proxy.AudioBoardConnect(self.bus_index, endpoint)
    142         self._connected_endpoints.add(endpoint)
    143 
    144 
    145     def _disconnect_endpoint(self, endpoint):
    146         """Disconnects an endpoint from audio bus.
    147 
    148         @param endpoint: An endpoint name in _PORT_ID_AUDIO_BUS_ENDPOINT_MAP.
    149 
    150         """
    151         logging.debug(
    152                 'Audio bus %s is disconnecting endpoint %s',
    153                 self.bus_index, endpoint)
    154         self._chameleond_proxy.AudioBoardDisconnect(self.bus_index, endpoint)
    155         self._connected_endpoints.remove(endpoint)
    156 
    157 
    158     def connect(self, port_id):
    159         """Connects an audio port to this audio bus.
    160 
    161         @param port_id: A string, that is, id in ChameleonIds, CrosIds, or
    162                         PeripheralIds defined in chameleon_audio_ids.
    163 
    164         """
    165         endpoint = self._get_endpoint_name(port_id)
    166         self._connect_endpoint(endpoint)
    167 
    168 
    169     def disconnect(self, port_id):
    170         """Disconnects an audio port from this audio bus.
    171 
    172         @param port_id: A string, that is, id in ChameleonIds, CrosIds, or
    173                         PeripheralIds defined in chameleon_audio_ids.
    174 
    175         """
    176         endpoint = self._get_endpoint_name(port_id)
    177         self._disconnect_endpoint(endpoint)
    178 
    179 
    180     def clear(self):
    181         """Disconnects all audio port from this audio bus."""
    182         self._disconnect_all_endpoints()
    183 
    184 
    185     def _disconnect_all_endpoints(self):
    186         """Disconnects all endpoints from this audio bus."""
    187         for endpoint in self._connected_endpoints.copy():
    188             self._disconnect_endpoint(endpoint)
    189 
    190 
    191     def get_snapshot(self):
    192         """Gets the snapshot of AudioBus so user can restore it later.
    193 
    194         @returns: An AudioBus.AudioBusSnapshot object.
    195 
    196         """
    197         return self.AudioBusSnapshot(self._connected_endpoints)
    198 
    199 
    200     def restore_snapshot(self, snapshot):
    201         """Restore the snapshot.
    202 
    203         @param: An AudioBus.AudioBusSnapshot object got from get_snapshot.
    204 
    205         """
    206         self._disconnect_all_endpoints()
    207         logging.debug('Restoring snapshot with %s', snapshot._endpoints)
    208         for endpoint in snapshot._endpoints:
    209             self._connect_endpoint(endpoint)
    210 
    211 
    212 class AudioJackPluggerException(Exception):
    213     """Errors in AudioJackPlugger."""
    214     pass
    215 
    216 
    217 class AudioJackPlugger(object):
    218     """AudioJackPlugger is an abstraction of plugger controlled by audio board.
    219 
    220     There is a motor in the audio box which can plug/unplug 3.5mm 4-ring
    221     audio cable to/from audio jack of Cros deivce.
    222     This motor is controlled by audio board.
    223 
    224     A ChameleonConnection object is passed to the construction.
    225 
    226     """
    227     def __init__(self, chameleon_connection):
    228         """Constructs an AudioJackPlugger.
    229 
    230         @param chameleon_connection: A ChameleonConnection object.
    231 
    232         @raises:
    233             AudioJackPluggerException if there is no jack plugger on
    234             this audio board.
    235 
    236         """
    237         self._chameleond_proxy = chameleon_connection.chameleond_proxy
    238         if not self._chameleond_proxy.AudioBoardHasJackPlugger():
    239             raise AudioJackPluggerException(
    240                 'There is no jack plugger on audio board. '
    241                 'Perhaps the audio board is not connected to audio box.')
    242 
    243 
    244     def plug(self):
    245         """Plugs the audio cable into audio jack of Cros device."""
    246         self._chameleond_proxy.AudioBoardAudioJackPlug()
    247         logging.info('Plugged 3.5mm audio cable to Cros device')
    248 
    249 
    250     def unplug(self):
    251         """Unplugs the audio cable from audio jack of Cros device."""
    252         self._chameleond_proxy.AudioBoardAudioJackUnplug()
    253         logging.info('Unplugged 3.5mm audio cable from Cros device')
    254 
    255 
    256 class BluetoothController(object):
    257     """An abstraction of bluetooth module on audio board.
    258 
    259     There is a bluetooth module on the audio board. It can be controlled through
    260     API provided by chameleon proxy.
    261 
    262     """
    263     def __init__(self, chameleon_connection):
    264         """Constructs an BluetoothController.
    265 
    266         @param chameleon_connection: A ChameleonConnection object.
    267 
    268         """
    269         self._chameleond_proxy = chameleon_connection.chameleond_proxy
    270 
    271 
    272     def reset(self):
    273         """Resets the bluetooth module."""
    274         self._chameleond_proxy.AudioBoardResetBluetooth()
    275         logging.info('Resets bluetooth module on audio board.')
    276 
    277 
    278     def disable(self):
    279         """Disables the bluetooth module."""
    280         self._chameleond_proxy.AudioBoardDisableBluetooth()
    281         logging.info('Disables bluetooth module on audio board.')
    282 
    283 
    284     def is_enabled(self):
    285         """Checks if the bluetooth module is enabled.
    286 
    287         @returns: True if bluetooth module is enabled. False otherwise.
    288 
    289         """
    290         return self._chameleond_proxy.AudioBoardIsBluetoothEnabled()
    291