281 lines
9.2 KiB
Python
281 lines
9.2 KiB
Python
# Copyright 2015 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 board interface."""
|
|
|
|
import logging
|
|
|
|
from autotest_lib.client.cros.chameleon import chameleon_audio_ids as ids
|
|
|
|
|
|
class AudioBoard(object):
|
|
"""AudioBoard is an abstraction of an audio board on a Chameleon board.
|
|
|
|
It provides methods to control audio board.
|
|
|
|
A ChameleonConnection object is passed to the construction.
|
|
|
|
"""
|
|
|
|
def __init__(self, chameleon_connection):
|
|
"""Constructs an AudioBoard.
|
|
|
|
@param chameleon_connection: A ChameleonConnection object.
|
|
|
|
@returns: An AudioBoard object.
|
|
|
|
"""
|
|
self._audio_buses = {
|
|
1: AudioBus(1, chameleon_connection),
|
|
2: AudioBus(2, chameleon_connection)
|
|
}
|
|
self._chameleon_connection = chameleon_connection
|
|
self._jack_plugger = None
|
|
self._bluetooth_controller = BluetoothController(chameleon_connection)
|
|
|
|
def get_audio_bus(self, bus_index):
|
|
"""Gets an audio bus on this audio board.
|
|
|
|
@param bus_index: The bus index 1 or 2.
|
|
|
|
@returns: An AudioBus object.
|
|
|
|
"""
|
|
return self._audio_buses[bus_index]
|
|
|
|
def get_jack_plugger(self):
|
|
"""Gets an AudioJackPlugger on this audio board.
|
|
|
|
@returns: An AudioJackPlugger object if there is an audio jack plugger.
|
|
None if there is no audio jack plugger.
|
|
@raises:
|
|
AudioJackPluggerException if there is no jack plugger on this audio
|
|
board.
|
|
|
|
"""
|
|
if self._jack_plugger is None:
|
|
try:
|
|
self._jack_plugger = AudioJackPlugger(
|
|
self._chameleon_connection)
|
|
except AudioJackPluggerException as e:
|
|
logging.error(
|
|
'There is no jack plugger on this audio board. Please '
|
|
'check the jack plugger if all labels are correctly '
|
|
'configured.')
|
|
self._jack_plugger = None
|
|
return self._jack_plugger
|
|
|
|
def get_bluetooth_controller(self):
|
|
"""Gets an BluetoothController on this audio board.
|
|
|
|
@returns: An BluetoothController object.
|
|
|
|
"""
|
|
return self._bluetooth_controller
|
|
|
|
|
|
class AudioBus(object):
|
|
"""AudioBus is an abstraction of an audio bus on an audio board.
|
|
|
|
It provides methods to control audio bus.
|
|
|
|
A ChameleonConnection object is passed to the construction.
|
|
|
|
@properties:
|
|
bus_index: The bus index 1 or 2.
|
|
|
|
"""
|
|
# Maps port id defined in chameleon_audio_ids to endpoint name used in
|
|
# chameleond audio bus API.
|
|
_PORT_ID_AUDIO_BUS_ENDPOINT_MAP = {
|
|
ids.ChameleonIds.LINEIN: 'Chameleon FPGA line-in',
|
|
ids.ChameleonIds.LINEOUT: 'Chameleon FPGA line-out',
|
|
ids.CrosIds.HEADPHONE: 'Cros device headphone',
|
|
ids.CrosIds.EXTERNAL_MIC: 'Cros device external microphone',
|
|
ids.PeripheralIds.SPEAKER: 'Peripheral speaker',
|
|
ids.PeripheralIds.MIC: 'Peripheral microphone',
|
|
ids.PeripheralIds.BLUETOOTH_DATA_RX: 'Bluetooth module output',
|
|
ids.PeripheralIds.BLUETOOTH_DATA_TX: 'Bluetooth module input'
|
|
}
|
|
|
|
class AudioBusSnapshot(object):
|
|
"""Abstracts the snapshot of AudioBus for user to restore it later."""
|
|
|
|
def __init__(self, endpoints):
|
|
"""Initializes an AudioBusSnapshot.
|
|
|
|
@param endpoints: A set of endpoints to keep a copy.
|
|
|
|
"""
|
|
self._endpoints = endpoints.copy()
|
|
|
|
def __init__(self, bus_index, chameleon_connection):
|
|
"""Constructs an AudioBus.
|
|
|
|
@param bus_index: The bus index 1 or 2.
|
|
@param chameleon_connection: A ChameleonConnection object.
|
|
|
|
"""
|
|
self.bus_index = bus_index
|
|
self._chameleond_proxy = chameleon_connection
|
|
self._connected_endpoints = set()
|
|
|
|
def _get_endpoint_name(self, port_id):
|
|
"""Gets the endpoint name used in audio bus API.
|
|
|
|
@param port_id: A string, that is, id in ChameleonIds, CrosIds, or
|
|
PeripheralIds defined in chameleon_audio_ids.
|
|
|
|
@returns: The endpoint name for the port used in audio bus API.
|
|
|
|
"""
|
|
return self._PORT_ID_AUDIO_BUS_ENDPOINT_MAP[port_id]
|
|
|
|
def _connect_endpoint(self, endpoint):
|
|
"""Connects an endpoint to audio bus.
|
|
|
|
@param endpoint: An endpoint name in _PORT_ID_AUDIO_BUS_ENDPOINT_MAP.
|
|
|
|
"""
|
|
logging.debug('Audio bus %s is connecting endpoint %s', self.bus_index,
|
|
endpoint)
|
|
self._chameleond_proxy.AudioBoardConnect(self.bus_index, endpoint)
|
|
self._connected_endpoints.add(endpoint)
|
|
|
|
def _disconnect_endpoint(self, endpoint):
|
|
"""Disconnects an endpoint from audio bus.
|
|
|
|
@param endpoint: An endpoint name in _PORT_ID_AUDIO_BUS_ENDPOINT_MAP.
|
|
|
|
"""
|
|
logging.debug('Audio bus %s is disconnecting endpoint %s',
|
|
self.bus_index, endpoint)
|
|
self._chameleond_proxy.AudioBoardDisconnect(self.bus_index, endpoint)
|
|
self._connected_endpoints.remove(endpoint)
|
|
|
|
def connect(self, port_id):
|
|
"""Connects an audio port to this audio bus.
|
|
|
|
@param port_id: A string, that is, id in ChameleonIds, CrosIds, or
|
|
PeripheralIds defined in chameleon_audio_ids.
|
|
|
|
"""
|
|
endpoint = self._get_endpoint_name(port_id)
|
|
self._connect_endpoint(endpoint)
|
|
|
|
def disconnect(self, port_id):
|
|
"""Disconnects an audio port from this audio bus.
|
|
|
|
@param port_id: A string, that is, id in ChameleonIds, CrosIds, or
|
|
PeripheralIds defined in chameleon_audio_ids.
|
|
|
|
"""
|
|
endpoint = self._get_endpoint_name(port_id)
|
|
self._disconnect_endpoint(endpoint)
|
|
|
|
def clear(self):
|
|
"""Disconnects all audio port from this audio bus."""
|
|
self._disconnect_all_endpoints()
|
|
|
|
def _disconnect_all_endpoints(self):
|
|
"""Disconnects all endpoints from this audio bus."""
|
|
for endpoint in self._connected_endpoints.copy():
|
|
self._disconnect_endpoint(endpoint)
|
|
|
|
def get_snapshot(self):
|
|
"""Gets the snapshot of AudioBus so user can restore it later.
|
|
|
|
@returns: An AudioBus.AudioBusSnapshot object.
|
|
|
|
"""
|
|
return self.AudioBusSnapshot(self._connected_endpoints)
|
|
|
|
def restore_snapshot(self, snapshot):
|
|
"""Restore the snapshot.
|
|
|
|
@param: An AudioBus.AudioBusSnapshot object got from get_snapshot.
|
|
|
|
"""
|
|
self._disconnect_all_endpoints()
|
|
logging.debug('Restoring snapshot with %s', snapshot._endpoints)
|
|
for endpoint in snapshot._endpoints:
|
|
self._connect_endpoint(endpoint)
|
|
|
|
|
|
class AudioJackPluggerException(Exception):
|
|
"""Errors in AudioJackPlugger."""
|
|
pass
|
|
|
|
|
|
class AudioJackPlugger(object):
|
|
"""AudioJackPlugger is an abstraction of plugger controlled by audio board.
|
|
|
|
There is a motor in the audio box which can plug/unplug 3.5mm 4-ring
|
|
audio cable to/from audio jack of Cros deivce.
|
|
This motor is controlled by audio board.
|
|
|
|
A ChameleonConnection object is passed to the construction.
|
|
|
|
"""
|
|
|
|
def __init__(self, chameleon_connection):
|
|
"""Constructs an AudioJackPlugger.
|
|
|
|
@param chameleon_connection: A ChameleonConnection object.
|
|
|
|
@raises:
|
|
AudioJackPluggerException if there is no jack plugger on
|
|
this audio board.
|
|
|
|
"""
|
|
self._chameleond_proxy = chameleon_connection
|
|
if not self._chameleond_proxy.AudioBoardHasJackPlugger():
|
|
raise AudioJackPluggerException(
|
|
'There is no jack plugger on audio board. '
|
|
'Perhaps the audio board is not connected to audio box.')
|
|
|
|
def plug(self):
|
|
"""Plugs the audio cable into audio jack of Cros device."""
|
|
self._chameleond_proxy.AudioBoardAudioJackPlug()
|
|
logging.info('Plugged 3.5mm audio cable to Cros device.')
|
|
|
|
def unplug(self):
|
|
"""Unplugs the audio cable from audio jack of Cros device."""
|
|
self._chameleond_proxy.AudioBoardAudioJackUnplug()
|
|
logging.info('Unplugged 3.5mm audio cable from Cros device.')
|
|
|
|
|
|
class BluetoothController(object):
|
|
"""An abstraction of bluetooth module on audio board.
|
|
|
|
There is a bluetooth module on the audio board. It can be controlled through
|
|
API provided by chameleon proxy.
|
|
|
|
"""
|
|
|
|
def __init__(self, chameleon_connection):
|
|
"""Constructs an BluetoothController.
|
|
|
|
@param chameleon_connection: A ChameleonConnection object.
|
|
|
|
"""
|
|
self._chameleond_proxy = chameleon_connection
|
|
|
|
def reset(self):
|
|
"""Resets the bluetooth module."""
|
|
self._chameleond_proxy.AudioBoardResetBluetooth()
|
|
logging.info('Resets bluetooth module on audio board.')
|
|
|
|
def disable(self):
|
|
"""Disables the bluetooth module."""
|
|
self._chameleond_proxy.AudioBoardDisableBluetooth()
|
|
logging.info('Disables bluetooth module on audio board.')
|
|
|
|
def is_enabled(self):
|
|
"""Checks if the bluetooth module is enabled.
|
|
|
|
@returns: True if bluetooth module is enabled. False otherwise.
|
|
|
|
"""
|
|
return self._chameleond_proxy.AudioBoardIsBluetoothEnabled()
|