// Copyright (c) 2012 The Chromium 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 "media/audio/win/audio_device_listener_win.h"

#include <Audioclient.h>

#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/system_monitor.h"
#include "base/time/default_tick_clock.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/windows_version.h"
#include "media/audio/win/core_audio_util_win.h"

using base::win::ScopedCoMem;

namespace media {

static std::string FlowToString(EDataFlow flow) {
  return flow == eRender ? "eRender" : "eCapture";
}

static std::string RoleToString(ERole role) {
  switch (role) {
    case eConsole:
      return "eConsole";
    case eMultimedia:
      return "eMultimedia";
    case eCommunications:
      return "eCommunications";
    default:
      return "undefined";
  }
}

AudioDeviceListenerWin::AudioDeviceListenerWin(
    base::RepeatingClosure listener_cb)
    : listener_cb_(std::move(listener_cb)),
      tick_clock_(base::DefaultTickClock::GetInstance()) {
  // CreateDeviceEnumerator can fail on some installations of Windows such
  // as "Windows Server 2008 R2" where the desktop experience isn't available.
  auto device_enumerator = CoreAudioUtil::CreateDeviceEnumerator();
  if (!device_enumerator) {
    DLOG(ERROR) << "Failed to create device enumeration.";
    return;
  }

  HRESULT hr = device_enumerator->RegisterEndpointNotificationCallback(this);
  if (FAILED(hr)) {
    DLOG(ERROR) << "RegisterEndpointNotificationCallback failed: " << std::hex
                << hr;
    return;
  }

  device_enumerator_ = device_enumerator;
}

AudioDeviceListenerWin::~AudioDeviceListenerWin() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (!device_enumerator_)
    return;

  HRESULT hr = device_enumerator_->UnregisterEndpointNotificationCallback(this);
  DLOG_IF(ERROR, FAILED(hr)) << "UnregisterEndpointNotificationCallback() "
                             << "failed: " << std::hex << hr;
}

ULONG AudioDeviceListenerWin::AddRef() {
  return 1;
}

ULONG AudioDeviceListenerWin::Release() {
  return 1;
}

HRESULT AudioDeviceListenerWin::QueryInterface(REFIID iid, void** object) {
  if (iid == IID_IUnknown || iid == __uuidof(IMMNotificationClient)) {
    *object = static_cast<IMMNotificationClient*>(this);
    return S_OK;
  }

  *object = nullptr;
  return E_NOINTERFACE;
}

HRESULT AudioDeviceListenerWin::OnPropertyValueChanged(LPCWSTR device_id,
                                                       const PROPERTYKEY key) {
  // Property changes are handled by IAudioSessionControl listeners hung off of
  // each WASAPIAudioOutputStream() since not all property changes make it to
  // this method and those that do are spammed 10s of times.
  return S_OK;
}

HRESULT AudioDeviceListenerWin::OnDeviceAdded(LPCWSTR device_id) {
  // We don't care when devices are added.
  return S_OK;
}

HRESULT AudioDeviceListenerWin::OnDeviceRemoved(LPCWSTR device_id) {
  // We don't care when devices are removed.
  return S_OK;
}

HRESULT AudioDeviceListenerWin::OnDeviceStateChanged(LPCWSTR device_id,
                                                     DWORD new_state) {
  if (auto* monitor = base::SystemMonitor::Get())
    monitor->ProcessDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO);
  return S_OK;
}

HRESULT AudioDeviceListenerWin::OnDefaultDeviceChanged(
    EDataFlow flow,
    ERole role,
    LPCWSTR new_default_device_id) {
  // Only listen for console and communication device changes.
  if ((role != eConsole && role != eCommunications) ||
      (flow != eRender && flow != eCapture)) {
    return S_OK;
  }

  // If no device is now available, |new_default_device_id| will be NULL.
  std::string new_device_id;
  if (new_default_device_id)
    new_device_id = base::WideToUTF8(new_default_device_id);

  // Only output device changes should be forwarded.  Do not attempt to filter
  // changes based on device id since some devices may not change their device
  // id and instead trigger some internal flow change: http://crbug.com/506712
  //
  // We rate limit device changes to avoid a single device change causing back
  // to back changes for eCommunications and eConsole; this is worth doing as
  // it provides a substantially faster resumption of playback.
  bool did_run_listener_cb = false;
  const base::TimeTicks now = tick_clock_->NowTicks();
  if (flow == eRender && (now - last_device_change_time_ > kDeviceChangeLimit ||
                          new_device_id.compare(last_device_id_) != 0)) {
    last_device_change_time_ = now;
    last_device_id_ = new_device_id;
    listener_cb_.Run();
    did_run_listener_cb = true;
  }

  if (auto* monitor = base::SystemMonitor::Get())
    monitor->ProcessDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO);

  DVLOG(1) << "OnDefaultDeviceChanged() "
           << "new_default_device: "
           << (new_default_device_id
                   ? CoreAudioUtil::GetFriendlyName(new_device_id, flow, role)
                   : "no device")
           << ", flow: " << FlowToString(flow)
           << ", role: " << RoleToString(role)
           << ", notified manager: " << (did_run_listener_cb ? "Yes" : "No");

  return S_OK;
}

}  // namespace media
