# 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.

"""Audio query delegates."""

import subprocess

import common
from autotest_lib.client.common_lib import site_utils
from autotest_lib.client.common_lib.feedback import client
from autotest_lib.client.common_lib.feedback import tester_feedback_client
from autotest_lib.server.brillo import audio_utils

import input_handlers
import query_delegate
import sequenced_request


# Supported WAVE playback commands in decreasing order of preference.
_KNOWN_WAV_PLAYBACK_METHODS = (
        # Alsa command-line tool, most straightforward to use (if available).
        ('aplay', ('aplay', '%(file)s')),
        # Sox's play command.
        ('play', ('play', '-q', '%(file)s')),
        # VLC command-line tool.
        ('cvlc', ('cvlc', '-q', '--play-and-exit', '%(file)s')),
        # Mplayer; might choke when using Alsa and therefore least preferred.
        ('mplayer', ('mplayer', '-quiet', '-novideo', '%(file)s')),
)


class PlaybackMixin(object):
    """Mixin for adding playback capabilities to a query."""

    # TODO(garnold) The provided audio file path is local to the test host,
    # which isn't necessarily the same as the host running the feedback
    # service. To support other use cases (Moblab, client-side testing) we'll
    # need to properly identify such cases and fetch the file (b/26927734).
    def _playback_wav_file(self, msg, audio_file):
        """Plays a WAV file via user selected method.

        Looks for available playback commands and presents them to the user to
        choose from. Also lists "manual playback" as the last option.

        @param msg: Introductory message to present to the user.
        @param audio_file: The audio file to play.

        @return: Whether playback was successful.
        """
        choices = []
        cmds = []
        for tool, cmd in _KNOWN_WAV_PLAYBACK_METHODS:
            if site_utils.which(tool):
                choices.append(tool)
                cmds.append(cmd)
        choices.append('Manual playback')

        msg += (' The audio file is %s. Available playback methods include:' %
                audio_file)
        req = sequenced_request.SequencedFeedbackRequest(self.test, self.dut,
                                                         None)
        req.append_question(
                msg,
                input_handlers.MultipleChoiceInputHandler(choices, default=1),
                prompt='Choose your playback method')
        idx, _ = self._process_request(req)
        if idx < len(choices) - 1:
            cmd = [tok % {'file': audio_file} for tok in cmds[idx]]
            return subprocess.call(cmd) == 0

        return True


class AudiblePlaybackQueryDelegate(query_delegate.OutputQueryDelegate,
                                   PlaybackMixin):
    """Query delegate for validating audible feedback."""

    def _prepare_impl(self, **kwargs):
        """Prepare for audio playback (interface override)."""
        req = sequenced_request.SequencedFeedbackRequest(
                self.test, self.dut, 'Audible playback')
        req.append_question(
                'Device %(dut)s will play a short audible sample. Please '
                'prepare for listening to this playback and hit Enter to '
                'continue...',
                input_handlers.PauseInputHandler())
        self._process_request(req)


    def _validate_impl(self, audio_file=None):
        """Validate playback (interface override).

        @param audio_file: Name of audio file on the test host to validate
                           against.
        """
        req = sequenced_request.SequencedFeedbackRequest(
                self.test, self.dut, None)
        msg = 'Playback finished on %(dut)s.'
        if audio_file is None:
            req.append_question(
                    msg, input_handlers.YesNoInputHandler(default=True),
                    prompt='Did you hear audible sound?')
            err_msg = 'User did not hear audible feedback'
        else:
            if not self._playback_wav_file(msg, audio_file):
                return (tester_feedback_client.QUERY_RET_ERROR,
                        'Failed to playback recorded audio')
            req.append_question(
                    None, input_handlers.YesNoInputHandler(default=True),
                    prompt=('Was the audio produced identical to the refernce '
                            'audio file?'))
            err_msg = ('Audio produced was not identical to the reference '
                       'audio file')

        if not self._process_request(req):
            return (tester_feedback_client.QUERY_RET_FAIL, err_msg)


class SilentPlaybackQueryDelegate(query_delegate.OutputQueryDelegate):
    """Query delegate for validating silent feedback."""

    def _prepare_impl(self, **kwargs):
        """Prepare for silent playback (interface override)."""
        req = sequenced_request.SequencedFeedbackRequest(
                self.test, self.dut, 'Silent playback')
        req.append_question(
                'Device %(dut)s will play nothing for a short time. Please '
                'prepare for listening to this silence and hit Enter to '
                'continue...',
                input_handlers.PauseInputHandler())
        self._process_request(req)


    def _validate_impl(self, audio_file=None):
        """Validate silence (interface override).

        @param audio_file: Name of audio file on the test host to validate
                           against.
        """
        if audio_file is not None:
            return (tester_feedback_client.QUERY_RET_ERROR,
                    'Not expecting an audio file entry when validating silence')
        req = sequenced_request.SequencedFeedbackRequest(
                self.test, self.dut, None)
        req.append_question(
                'Silence playback finished on %(dut)s.',
                input_handlers.YesNoInputHandler(default=True),
                prompt='Did you hear silence?')
        if not self._process_request(req):
            return (tester_feedback_client.QUERY_RET_FAIL,
                    'User did not hear silence')


class RecordingQueryDelegate(query_delegate.InputQueryDelegate, PlaybackMixin):
    """Query delegate for validating audible feedback."""

    def _prepare_impl(self, use_file, sample_width, sample_rate,
                      num_channels, frequency):
        """Prepare for audio recording (interface override).

        @param use_file: If a file was used to produce audio. This is necessary
                         if audio of a particular frequency is being produced.
        @param sample_width: The recorded sample width.
        @param sample_rate: The recorded sample rate.
        @param num_channels: The number of recorded channels.
        @param frequency: Frequency of audio being produced.
        """
        req = sequenced_request.SequencedFeedbackRequest(
                self.test, self.dut, 'Audio recording')
        # TODO(ralphnathan) Lift the restriction regarding recording time once
        # the test allows recording for arbitrary periods of time (b/26924426).
        req.append_question(
                'Device %(dut)s will start recording audio for 10 seconds. '
                'Please prepare for producing sound and hit Enter to '
                'continue...',
                input_handlers.PauseInputHandler())
        self._process_request(req)
        self._sample_width = sample_width
        self._sample_rate = sample_rate
        self._num_channels = num_channels
        if use_file:
            self._frequency = frequency
        else:
            self._frequency = None


    def _emit_impl(self):
        """Emit sound for recording (interface override)."""
        req = sequenced_request.SequencedFeedbackRequest(
                self.test, self.dut, None)
        req.append_question(
                'Device %(dut)s is recording audio, hit Enter when done '
                'producing sound...',
                input_handlers.PauseInputHandler())
        self._process_request(req)


    def _validate_impl(self, captured_audio_file):
        """Validate recording (interface override).

        @param captured_audio_file: Path to the recorded WAV file.
        """
        # Check the WAV file properties first.
        try:
            audio_utils.check_wav_file(
                    captured_audio_file, num_channels=self._num_channels,
                    sample_rate=self._sample_rate,
                    sample_width=self._sample_width)
        except ValueError as e:
            return (tester_feedback_client.QUERY_RET_FAIL,
                    'Recorded audio file is invalid: %s' % e)


        # Verify playback of the recorded audio.
        props = ['as sample width of %d' % self._sample_width,
                 'has sample rate of %d' % self._sample_rate,
                 'has %d recorded channels' % self._num_channels]
        if self._frequency is not None:
            props.append('has frequency of %d Hz' % self._frequency)
        props_str = '%s%s%s' % (', '.join(props[:-1]),
                                ', and ' if len(props) > 1 else '',
                                props[-1])

        msg = 'Recording finished on %%(dut)s. It %s.' % props_str
        if not self._playback_wav_file(msg, captured_audio_file):
            return (tester_feedback_client.QUERY_RET_ERROR,
                    'Failed to playback recorded audio')

        req = sequenced_request.SequencedFeedbackRequest(
                self.test, self.dut, None)
        req.append_question(
                None,
                input_handlers.YesNoInputHandler(default=True),
                prompt='Did the recording capture the sound produced?')
        if not self._process_request(req):
            return (tester_feedback_client.QUERY_RET_FAIL,
                    'Recorded audio is not identical to what the user produced')


query_delegate.register_delegate_cls(client.QUERY_AUDIO_PLAYBACK_AUDIBLE,
                                     AudiblePlaybackQueryDelegate)

query_delegate.register_delegate_cls(client.QUERY_AUDIO_PLAYBACK_SILENT,
                                     SilentPlaybackQueryDelegate)

query_delegate.register_delegate_cls(client.QUERY_AUDIO_RECORDING,
                                     RecordingQueryDelegate)
