# 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, **kargs):
        """Starts recording audio through ARC.

        @param kargs: Other arguments that ARC doesn't support.

        """
        self._audio_facade.start_arc_recording()


    def stop_recording(self, **kargs):
        """Stops recording audio through ARC.

        @param kargs: Other arguments that ARC doesn't support.

        @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, **kargs):
        """Starts playing audio.

        @param path: Path to the file to play in container on Cros host.
        @param blocking: Blocks this call until playback finishes.
        @param kargs: Other arguments that ARC doesn't support.

        @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()
