# Lint as: python2, python3
# 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 is a server side USB playback/record audio test using the
Chameleon board.
"""

import logging
import os
import time

from autotest_lib.client.cros.audio import audio_test_data
from autotest_lib.client.cros.chameleon import audio_test_utils
from autotest_lib.client.cros.chameleon import chameleon_audio_ids
from autotest_lib.client.cros.chameleon import chameleon_audio_helper
from autotest_lib.server.cros.audio import audio_test


class audio_AudioBasicUSBPlaybackRecord(audio_test.AudioTest):
    """Server side USB playback/record audio test.

    This test talks to a Chameleon board and a Cros device to verify
    USB audio playback/record function of the Cros device.

    """
    version = 1
    RECORD_SECONDS = 5

    def run_once(self, suspend=False):
        """Runs Basic Audio USB playback/record test.

        @param suspend: True for suspend the device before playback/record.
                        False for not suspend.

        """
        golden_file = audio_test_data.GenerateAudioTestData(
                path=os.path.join(self.bindir, 'fix_1k_440_16.wav'),
                duration_secs=6,
                frequencies=[1000, 440])

        playback_source = self.widget_factory.create_widget(
                chameleon_audio_ids.CrosIds.USBOUT)
        playback_recorder = self.widget_factory.create_widget(
                chameleon_audio_ids.ChameleonIds.USBIN)
        playback_binder = self.widget_factory.create_binder(
                playback_source, playback_recorder)

        record_source = self.widget_factory.create_widget(
                chameleon_audio_ids.ChameleonIds.USBOUT)
        record_recorder = self.widget_factory.create_widget(
                chameleon_audio_ids.CrosIds.USBIN)
        record_binder = self.widget_factory.create_binder(
                record_source, record_recorder)

        with chameleon_audio_helper.bind_widgets(playback_binder):
            with chameleon_audio_helper.bind_widgets(record_binder):
                # Checks the node selected by cras is correct.
                audio_test_utils.dump_cros_audio_logs(self.host, self.facade,
                                                      self.resultsdir,
                                                      'after_binding')

                audio_test_utils.check_and_set_chrome_active_node_types(
                        self.facade, 'USB', 'USB')
                audio_test_utils.dump_cros_audio_logs(self.host, self.facade,
                                                      self.resultsdir,
                                                      'after_select')

                audio_test_utils.check_audio_nodes(self.facade,
                                                   (['USB'], ['USB']))

                logging.info('Setting playback data on Cros device')

                self.facade.set_selected_output_volume(70)

                playback_source.set_playback_data(golden_file)
                record_source.set_playback_data(golden_file)

                if suspend:
                    audio_test_utils.suspend_resume_and_verify(
                            self.host, self.factory)

                    audio_test_utils.dump_cros_audio_logs(
                            self.host, self.facade, self.resultsdir,
                            'after_suspend')

                    # Explicitly select the node as there is a known issue
                    # that the selected node might change after a suspension.
                    # We should remove this after the issue is addressed
                    # (crbug:987529).
                    # Directly select the node through cras
                    # Should switch to check_and_set_chrome_active_node_types
                    # to set the active node through chrome.audio API when
                    # the telemetry bug is fixed (crbug.com/965704)
                    self.facade.set_selected_node_types(['USB'], ['USB'])

                    audio_test_utils.dump_cros_audio_logs(
                            self.host, self.facade, self.resultsdir,
                            'after_resume_select')

                    audio_test_utils.check_audio_nodes(self.facade,
                                                       (['USB'], ['USB']))

                logging.info('Start recording from Chameleon.')
                playback_recorder.start_recording()
                logging.info('Start recording from Cros device.')
                record_recorder.start_recording(block_size=1024)

                logging.info('Start playing %s on Cros device',
                             golden_file.path)
                playback_source.start_playback(block_size=1024)
                logging.info('Start playing %s on Chameleon', golden_file.path)
                record_source.start_playback()

                time.sleep(self.RECORD_SECONDS)

                audio_test_utils.dump_cros_audio_logs(self.host, self.facade,
                                                      self.resultsdir,
                                                      'during_recording')

                playback_recorder.stop_recording()
                logging.info('Stopped recording from Chameleon.')
                record_recorder.stop_recording()
                logging.info('Stopped recording from Cros device.')

                audio_test_utils.dump_cros_audio_logs(self.host, self.facade,
                                                      self.resultsdir,
                                                      'after_recording')

                playback_recorder.read_recorded_binary()
                logging.info('Read recorded binary from Chameleon.')
                record_recorder.read_recorded_binary()
                logging.info('Read recorded binary from Cros device.')

        playback_recorded_file = os.path.join(self.resultsdir,
                                              "playback_recorded.raw")
        logging.info('Saving Cros playback recorded data to %s',
                     playback_recorded_file)
        playback_recorder.save_file(playback_recorded_file)

        record_recorded_file = os.path.join(self.resultsdir,
                                            "record_recorded.raw")
        logging.info('Saving Cros record recorded data to %s',
                     record_recorded_file)
        record_recorder.save_file(record_recorded_file)

        audio_test_utils.check_recorded_frequency(golden_file,
                                                  playback_recorder)
        audio_test_utils.check_recorded_frequency(golden_file, record_recorder)
