// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/media/audio/audio_core/audio_input.h"

#include "src/media/audio/audio_core/audio_device_manager.h"
#include "src/media/audio/audio_core/audio_driver.h"

namespace media::audio {

constexpr zx_duration_t kMinFenceDistance = ZX_MSEC(200);
constexpr zx_duration_t kMaxFenceDistance = kMinFenceDistance + ZX_MSEC(20);

// static
fbl::RefPtr<AudioInput> AudioInput::Create(zx::channel channel, AudioDeviceManager* manager) {
  return fbl::AdoptRef(new AudioInput(std::move(channel), manager));
}

AudioInput::AudioInput(zx::channel channel, AudioDeviceManager* manager)
    : AudioDevice(Type::Input, manager), initial_stream_channel_(std::move(channel)) {}

zx_status_t AudioInput::Init() {
  zx_status_t res = AudioDevice::Init();
  if (res != ZX_OK) {
    return res;
  }

  res = driver_->Init(std::move(initial_stream_channel_));
  if (res == ZX_OK) {
    state_ = State::Initialized;
  }

  return res;
}

void AudioInput::OnWakeup() {
  // We were poked.  Are we just starting up?
  if (state_ == State::Initialized) {
    if (driver_->GetDriverInfo() != ZX_OK) {
      ShutdownSelf();
    } else {
      state_ = State::FetchingFormats;
    }
    return;
  }

  UpdateDriverGainState();
}

void AudioInput::OnDriverInfoFetched() {
  state_ = State::Idle;

  uint32_t pref_fps = 48000;
  uint32_t pref_chan = 1;
  fuchsia::media::AudioSampleFormat pref_fmt = fuchsia::media::AudioSampleFormat::SIGNED_16;

  zx_status_t res = SelectBestFormat(driver_->format_ranges(), &pref_fps, &pref_chan, &pref_fmt);
  if (res != ZX_OK) {
    FXL_LOG(ERROR) << "Audio input failed to find any compatible driver formats.  Req was "
                   << pref_fps << " Hz " << pref_chan << " channel(s) sample format(0x" << std::hex
                   << static_cast<uint32_t>(pref_fmt) << ")";
    ShutdownSelf();
    return;
  }

  const auto& hw_gain = driver()->hw_gain_state();
  if (hw_gain.min_gain > hw_gain.max_gain) {
    FXL_LOG(ERROR) << "Audio input has invalid gain limits [" << hw_gain.min_gain << ", "
                   << hw_gain.max_gain << "].";
    ShutdownSelf();
    return;
  }

  // TODO(mpuryear): Save to the hub the configured format for this input.

  // Send config request; recompute distance between start|end sampling fences.
  driver_->Configure(pref_fps, pref_chan, pref_fmt, kMaxFenceDistance);

  int64_t dist = TimelineRate(pref_fps, ZX_SEC(1)).Scale(kMinFenceDistance);
  FXL_DCHECK(dist < std::numeric_limits<uint32_t>::max());
  driver_->SetEndFenceToStartFenceFrames(static_cast<uint32_t>(dist));

  // Tell AudioDeviceManager it can add us to the set of active audio devices.
  ActivateSelf();
}

void AudioInput::OnDriverConfigComplete() { driver_->SetPlugDetectEnabled(true); }

void AudioInput::OnDriverStartComplete() {
  // If we were unplugged while starting, stop now.
  if (!driver_->plugged()) {
    driver_->Stop();
  }
}

void AudioInput::OnDriverStopComplete() {
  // If we were plugged while stopping, start now.
  if (driver_->plugged()) {
    driver_->Start();
  }
}

void AudioInput::OnDriverPlugStateChange(bool plugged, zx_time_t plug_time) {
  if (plugged && (driver_->state() == AudioDriver::State::Configured)) {
    driver_->Start();
  } else if (!plugged && (driver_->state() == AudioDriver::State::Started)) {
    driver_->Stop();
  }

  // Reflect this message to the AudioDeviceManager so it can deal with the
  // routing consequences of the plug state change.
  manager_->ScheduleMainThreadTask(
      [manager = manager_, output = fbl::WrapRefPtr(this), plugged, plug_time]() {
        manager->HandlePlugStateChange(std::move(output), plugged, plug_time);
      });
}

void AudioInput::ApplyGainLimits(fuchsia::media::AudioGainInfo* in_out_info, uint32_t set_flags) {
  // By the time anyone is calling "ApplyGainLimits", we need to have our basic
  // audio gain control capabilities established.
  ZX_DEBUG_ASSERT(driver()->state() != AudioDriver::State::Uninitialized);
  ZX_DEBUG_ASSERT(driver()->state() != AudioDriver::State::MissingDriverInfo);

  const auto& caps = driver()->hw_gain_state();

  // If someone is trying to enable mute, but our hardware does not support
  // enabling mute, clear the flag.
  //
  // TODO(johngro): It should always be possible to mute.  We should maintain a
  // SW flag for implementing mute in case the hardware cannot.
  if (!caps.can_mute) {
    in_out_info->flags &= ~(fuchsia::media::AudioGainInfoFlag_Mute);
  }

  // Don't allow AGC unless HW supports it.
  if (!caps.can_agc) {
    in_out_info->flags &= ~(fuchsia::media::AudioGainInfoFlag_AgcEnabled);
  }

  // If the user is attempting to set gain, enforce the gain limits.
  if (set_flags & fuchsia::media::SetAudioGainFlag_GainValid) {
    // This should have been enforced in OnDriverInfoFetched.
    FXL_DCHECK(caps.min_gain <= caps.max_gain);

    // If the hardware has not supplied a valid gain step size, or an
    // ridiculously small step size, just apply a clamp based on min/max.
    constexpr float kStepSizeLimit = 1e-6;
    if (caps.gain_step <= kStepSizeLimit) {
      in_out_info->gain_db = fbl::clamp(in_out_info->gain_db, caps.min_gain, caps.max_gain);
    } else {
      auto min_steps = static_cast<int32_t>(caps.min_gain / caps.gain_step);
      auto max_steps = static_cast<int32_t>(caps.max_gain / caps.gain_step);
      int32_t steps = fbl::clamp(static_cast<int32_t>(in_out_info->gain_db / caps.gain_step),
                                 min_steps, max_steps);
      in_out_info->gain_db = static_cast<float>(steps) * caps.gain_step;
    }
  }
}

void AudioInput::UpdateDriverGainState() {
  if ((state_ != State::Idle) || (device_settings_ == nullptr)) {
    return;
  }

  AudioDeviceSettings::GainState state;
  audio_set_gain_flags_t dirty_flags = device_settings_->SnapshotGainState(&state);
  if (!dirty_flags) {
    return;
  }

  driver()->SendSetGain(state, dirty_flags);
}

}  // namespace media::audio
