/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_device/mac/audio_mixer_manager_mac.h"
#include "webrtc/system_wrappers/include/trace.h"

#include <unistd.h>  // getpid()

namespace webrtc {

#define WEBRTC_CA_RETURN_ON_ERR(expr)                                  \
  do {                                                                 \
    err = expr;                                                        \
    if (err != noErr) {                                                \
      logCAMsg(kTraceError, kTraceAudioDevice, _id, "Error in " #expr, \
               (const char*) & err);                                   \
      return -1;                                                       \
    }                                                                  \
  } while (0)

#define WEBRTC_CA_LOG_ERR(expr)                                        \
  do {                                                                 \
    err = expr;                                                        \
    if (err != noErr) {                                                \
      logCAMsg(kTraceError, kTraceAudioDevice, _id, "Error in " #expr, \
               (const char*) & err);                                   \
    }                                                                  \
  } while (0)

#define WEBRTC_CA_LOG_WARN(expr)                                         \
  do {                                                                   \
    err = expr;                                                          \
    if (err != noErr) {                                                  \
      logCAMsg(kTraceWarning, kTraceAudioDevice, _id, "Error in " #expr, \
               (const char*) & err);                                     \
    }                                                                    \
  } while (0)

AudioMixerManagerMac::AudioMixerManagerMac(const int32_t id)
    : _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
      _id(id),
      _inputDeviceID(kAudioObjectUnknown),
      _outputDeviceID(kAudioObjectUnknown),
      _noInputChannels(0),
      _noOutputChannels(0) {
  WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s constructed",
               __FUNCTION__);
}

AudioMixerManagerMac::~AudioMixerManagerMac() {
  WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destructed",
               __FUNCTION__);

  Close();

  delete &_critSect;
}

// ============================================================================
//	                                PUBLIC METHODS
// ============================================================================

int32_t AudioMixerManagerMac::Close() {
  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);

  CriticalSectionScoped lock(&_critSect);

  CloseSpeaker();
  CloseMicrophone();

  return 0;
}

int32_t AudioMixerManagerMac::CloseSpeaker() {
  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);

  CriticalSectionScoped lock(&_critSect);

  _outputDeviceID = kAudioObjectUnknown;
  _noOutputChannels = 0;

  return 0;
}

int32_t AudioMixerManagerMac::CloseMicrophone() {
  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);

  CriticalSectionScoped lock(&_critSect);

  _inputDeviceID = kAudioObjectUnknown;
  _noInputChannels = 0;

  return 0;
}

int32_t AudioMixerManagerMac::OpenSpeaker(AudioDeviceID deviceID) {
  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
               "AudioMixerManagerMac::OpenSpeaker(id=%d)", deviceID);

  CriticalSectionScoped lock(&_critSect);

  OSStatus err = noErr;
  UInt32 size = 0;
  pid_t hogPid = -1;

  _outputDeviceID = deviceID;

  // Check which process, if any, has hogged the device.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyHogMode, kAudioDevicePropertyScopeOutput, 0};

  size = sizeof(hogPid);
  WEBRTC_CA_RETURN_ON_ERR(AudioObjectGetPropertyData(
      _outputDeviceID, &propertyAddress, 0, NULL, &size, &hogPid));

  if (hogPid == -1) {
    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
                 " No process has hogged the input device");
  }
  // getpid() is apparently "always successful"
  else if (hogPid == getpid()) {
    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
                 " Our process has hogged the input device");
  } else {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 " Another process (pid = %d) has hogged the input device",
                 static_cast<int>(hogPid));

    return -1;
  }

  // get number of channels from stream format
  propertyAddress.mSelector = kAudioDevicePropertyStreamFormat;

  // Get the stream format, to be able to read the number of channels.
  AudioStreamBasicDescription streamFormat;
  size = sizeof(AudioStreamBasicDescription);
  memset(&streamFormat, 0, size);
  WEBRTC_CA_RETURN_ON_ERR(AudioObjectGetPropertyData(
      _outputDeviceID, &propertyAddress, 0, NULL, &size, &streamFormat));

  _noOutputChannels = streamFormat.mChannelsPerFrame;

  return 0;
}

int32_t AudioMixerManagerMac::OpenMicrophone(AudioDeviceID deviceID) {
  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
               "AudioMixerManagerMac::OpenMicrophone(id=%d)", deviceID);

  CriticalSectionScoped lock(&_critSect);

  OSStatus err = noErr;
  UInt32 size = 0;
  pid_t hogPid = -1;

  _inputDeviceID = deviceID;

  // Check which process, if any, has hogged the device.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyHogMode, kAudioDevicePropertyScopeInput, 0};
  size = sizeof(hogPid);
  WEBRTC_CA_RETURN_ON_ERR(AudioObjectGetPropertyData(
      _inputDeviceID, &propertyAddress, 0, NULL, &size, &hogPid));
  if (hogPid == -1) {
    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
                 " No process has hogged the input device");
  }
  // getpid() is apparently "always successful"
  else if (hogPid == getpid()) {
    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
                 " Our process has hogged the input device");
  } else {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 " Another process (pid = %d) has hogged the input device",
                 static_cast<int>(hogPid));

    return -1;
  }

  // get number of channels from stream format
  propertyAddress.mSelector = kAudioDevicePropertyStreamFormat;

  // Get the stream format, to be able to read the number of channels.
  AudioStreamBasicDescription streamFormat;
  size = sizeof(AudioStreamBasicDescription);
  memset(&streamFormat, 0, size);
  WEBRTC_CA_RETURN_ON_ERR(AudioObjectGetPropertyData(
      _inputDeviceID, &propertyAddress, 0, NULL, &size, &streamFormat));

  _noInputChannels = streamFormat.mChannelsPerFrame;

  return 0;
}

bool AudioMixerManagerMac::SpeakerIsInitialized() const {
  WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);

  return (_outputDeviceID != kAudioObjectUnknown);
}

bool AudioMixerManagerMac::MicrophoneIsInitialized() const {
  WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);

  return (_inputDeviceID != kAudioObjectUnknown);
}

int32_t AudioMixerManagerMac::SetSpeakerVolume(uint32_t volume) {
  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
               "AudioMixerManagerMac::SetSpeakerVolume(volume=%u)", volume);

  CriticalSectionScoped lock(&_critSect);

  if (_outputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  OSStatus err = noErr;
  UInt32 size = 0;
  bool success = false;

  // volume range is 0.0 - 1.0, convert from 0 -255
  const Float32 vol = (Float32)(volume / 255.0);

  assert(vol <= 1.0 && vol >= 0.0);

  // Does the capture device have a master volume control?
  // If so, use it exclusively.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, 0};
  Boolean isSettable = false;
  err = AudioObjectIsPropertySettable(_outputDeviceID, &propertyAddress,
                                      &isSettable);
  if (err == noErr && isSettable) {
    size = sizeof(vol);
    WEBRTC_CA_RETURN_ON_ERR(AudioObjectSetPropertyData(
        _outputDeviceID, &propertyAddress, 0, NULL, size, &vol));

    return 0;
  }

  // Otherwise try to set each channel.
  for (UInt32 i = 1; i <= _noOutputChannels; i++) {
    propertyAddress.mElement = i;
    isSettable = false;
    err = AudioObjectIsPropertySettable(_outputDeviceID, &propertyAddress,
                                        &isSettable);
    if (err == noErr && isSettable) {
      size = sizeof(vol);
      WEBRTC_CA_RETURN_ON_ERR(AudioObjectSetPropertyData(
          _outputDeviceID, &propertyAddress, 0, NULL, size, &vol));
    }
    success = true;
  }

  if (!success) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 " Unable to set a volume on any output channel");
    return -1;
  }

  return 0;
}

int32_t AudioMixerManagerMac::SpeakerVolume(uint32_t& volume) const {
  if (_outputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  OSStatus err = noErr;
  UInt32 size = 0;
  unsigned int channels = 0;
  Float32 channelVol = 0;
  Float32 vol = 0;

  // Does the device have a master volume control?
  // If so, use it exclusively.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, 0};
  Boolean hasProperty =
      AudioObjectHasProperty(_outputDeviceID, &propertyAddress);
  if (hasProperty) {
    size = sizeof(vol);
    WEBRTC_CA_RETURN_ON_ERR(AudioObjectGetPropertyData(
        _outputDeviceID, &propertyAddress, 0, NULL, &size, &vol));

    // vol 0.0 to 1.0 -> convert to 0 - 255
    volume = static_cast<uint32_t>(vol * 255 + 0.5);
  } else {
    // Otherwise get the average volume across channels.
    vol = 0;
    for (UInt32 i = 1; i <= _noOutputChannels; i++) {
      channelVol = 0;
      propertyAddress.mElement = i;
      hasProperty = AudioObjectHasProperty(_outputDeviceID, &propertyAddress);
      if (hasProperty) {
        size = sizeof(channelVol);
        WEBRTC_CA_RETURN_ON_ERR(AudioObjectGetPropertyData(
            _outputDeviceID, &propertyAddress, 0, NULL, &size, &channelVol));

        vol += channelVol;
        channels++;
      }
    }

    if (channels == 0) {
      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                   " Unable to get a volume on any channel");
      return -1;
    }

    assert(channels > 0);
    // vol 0.0 to 1.0 -> convert to 0 - 255
    volume = static_cast<uint32_t>(255 * vol / channels + 0.5);
  }

  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
               "     AudioMixerManagerMac::SpeakerVolume() => vol=%i", vol);

  return 0;
}

int32_t AudioMixerManagerMac::MaxSpeakerVolume(uint32_t& maxVolume) const {
  if (_outputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  // volume range is 0.0 to 1.0
  // we convert that to 0 - 255
  maxVolume = 255;

  return 0;
}

int32_t AudioMixerManagerMac::MinSpeakerVolume(uint32_t& minVolume) const {
  if (_outputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  // volume range is 0.0 to 1.0
  // we convert that to 0 - 255
  minVolume = 0;

  return 0;
}

int32_t AudioMixerManagerMac::SpeakerVolumeStepSize(uint16_t& stepSize) const {
  if (_outputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  // volume range is 0.0 to 1.0
  // we convert that to 0 - 255
  stepSize = 1;

  return 0;
}

int32_t AudioMixerManagerMac::SpeakerVolumeIsAvailable(bool& available) {
  if (_outputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  OSStatus err = noErr;

  // Does the capture device have a master volume control?
  // If so, use it exclusively.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, 0};
  Boolean isSettable = false;
  err = AudioObjectIsPropertySettable(_outputDeviceID, &propertyAddress,
                                      &isSettable);
  if (err == noErr && isSettable) {
    available = true;
    return 0;
  }

  // Otherwise try to set each channel.
  for (UInt32 i = 1; i <= _noOutputChannels; i++) {
    propertyAddress.mElement = i;
    isSettable = false;
    err = AudioObjectIsPropertySettable(_outputDeviceID, &propertyAddress,
                                        &isSettable);
    if (err != noErr || !isSettable) {
      available = false;
      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                   " Volume cannot be set for output channel %d, err=%d", i,
                   err);
      return -1;
    }
  }

  available = true;
  return 0;
}

int32_t AudioMixerManagerMac::SpeakerMuteIsAvailable(bool& available) {
  if (_outputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  OSStatus err = noErr;

  // Does the capture device have a master mute control?
  // If so, use it exclusively.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyMute, kAudioDevicePropertyScopeOutput, 0};
  Boolean isSettable = false;
  err = AudioObjectIsPropertySettable(_outputDeviceID, &propertyAddress,
                                      &isSettable);
  if (err == noErr && isSettable) {
    available = true;
    return 0;
  }

  // Otherwise try to set each channel.
  for (UInt32 i = 1; i <= _noOutputChannels; i++) {
    propertyAddress.mElement = i;
    isSettable = false;
    err = AudioObjectIsPropertySettable(_outputDeviceID, &propertyAddress,
                                        &isSettable);
    if (err != noErr || !isSettable) {
      available = false;
      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                   " Mute cannot be set for output channel %d, err=%d", i, err);
      return -1;
    }
  }

  available = true;
  return 0;
}

int32_t AudioMixerManagerMac::SetSpeakerMute(bool enable) {
  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
               "AudioMixerManagerMac::SetSpeakerMute(enable=%u)", enable);

  CriticalSectionScoped lock(&_critSect);

  if (_outputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  OSStatus err = noErr;
  UInt32 size = 0;
  UInt32 mute = enable ? 1 : 0;
  bool success = false;

  // Does the render device have a master mute control?
  // If so, use it exclusively.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyMute, kAudioDevicePropertyScopeOutput, 0};
  Boolean isSettable = false;
  err = AudioObjectIsPropertySettable(_outputDeviceID, &propertyAddress,
                                      &isSettable);
  if (err == noErr && isSettable) {
    size = sizeof(mute);
    WEBRTC_CA_RETURN_ON_ERR(AudioObjectSetPropertyData(
        _outputDeviceID, &propertyAddress, 0, NULL, size, &mute));

    return 0;
  }

  // Otherwise try to set each channel.
  for (UInt32 i = 1; i <= _noOutputChannels; i++) {
    propertyAddress.mElement = i;
    isSettable = false;
    err = AudioObjectIsPropertySettable(_outputDeviceID, &propertyAddress,
                                        &isSettable);
    if (err == noErr && isSettable) {
      size = sizeof(mute);
      WEBRTC_CA_RETURN_ON_ERR(AudioObjectSetPropertyData(
          _outputDeviceID, &propertyAddress, 0, NULL, size, &mute));
    }
    success = true;
  }

  if (!success) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 " Unable to set mute on any input channel");
    return -1;
  }

  return 0;
}

int32_t AudioMixerManagerMac::SpeakerMute(bool& enabled) const {
  if (_outputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  OSStatus err = noErr;
  UInt32 size = 0;
  unsigned int channels = 0;
  UInt32 channelMuted = 0;
  UInt32 muted = 0;

  // Does the device have a master volume control?
  // If so, use it exclusively.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyMute, kAudioDevicePropertyScopeOutput, 0};
  Boolean hasProperty =
      AudioObjectHasProperty(_outputDeviceID, &propertyAddress);
  if (hasProperty) {
    size = sizeof(muted);
    WEBRTC_CA_RETURN_ON_ERR(AudioObjectGetPropertyData(
        _outputDeviceID, &propertyAddress, 0, NULL, &size, &muted));

    // 1 means muted
    enabled = static_cast<bool>(muted);
  } else {
    // Otherwise check if all channels are muted.
    for (UInt32 i = 1; i <= _noOutputChannels; i++) {
      muted = 0;
      propertyAddress.mElement = i;
      hasProperty = AudioObjectHasProperty(_outputDeviceID, &propertyAddress);
      if (hasProperty) {
        size = sizeof(channelMuted);
        WEBRTC_CA_RETURN_ON_ERR(AudioObjectGetPropertyData(
            _outputDeviceID, &propertyAddress, 0, NULL, &size, &channelMuted));

        muted = (muted && channelMuted);
        channels++;
      }
    }

    if (channels == 0) {
      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                   " Unable to get mute for any channel");
      return -1;
    }

    assert(channels > 0);
    // 1 means muted
    enabled = static_cast<bool>(muted);
  }

  WEBRTC_TRACE(
      kTraceInfo, kTraceAudioDevice, _id,
      "     AudioMixerManagerMac::SpeakerMute() => enabled=%d, enabled");

  return 0;
}

int32_t AudioMixerManagerMac::StereoPlayoutIsAvailable(bool& available) {
  if (_outputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  available = (_noOutputChannels == 2);
  return 0;
}

int32_t AudioMixerManagerMac::StereoRecordingIsAvailable(bool& available) {
  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  available = (_noInputChannels == 2);
  return 0;
}

int32_t AudioMixerManagerMac::MicrophoneMuteIsAvailable(bool& available) {
  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  OSStatus err = noErr;

  // Does the capture device have a master mute control?
  // If so, use it exclusively.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyMute, kAudioDevicePropertyScopeInput, 0};
  Boolean isSettable = false;
  err = AudioObjectIsPropertySettable(_inputDeviceID, &propertyAddress,
                                      &isSettable);
  if (err == noErr && isSettable) {
    available = true;
    return 0;
  }

  // Otherwise try to set each channel.
  for (UInt32 i = 1; i <= _noInputChannels; i++) {
    propertyAddress.mElement = i;
    isSettable = false;
    err = AudioObjectIsPropertySettable(_inputDeviceID, &propertyAddress,
                                        &isSettable);
    if (err != noErr || !isSettable) {
      available = false;
      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                   " Mute cannot be set for output channel %d, err=%d", i, err);
      return -1;
    }
  }

  available = true;
  return 0;
}

int32_t AudioMixerManagerMac::SetMicrophoneMute(bool enable) {
  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
               "AudioMixerManagerMac::SetMicrophoneMute(enable=%u)", enable);

  CriticalSectionScoped lock(&_critSect);

  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  OSStatus err = noErr;
  UInt32 size = 0;
  UInt32 mute = enable ? 1 : 0;
  bool success = false;

  // Does the capture device have a master mute control?
  // If so, use it exclusively.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyMute, kAudioDevicePropertyScopeInput, 0};
  Boolean isSettable = false;
  err = AudioObjectIsPropertySettable(_inputDeviceID, &propertyAddress,
                                      &isSettable);
  if (err == noErr && isSettable) {
    size = sizeof(mute);
    WEBRTC_CA_RETURN_ON_ERR(AudioObjectSetPropertyData(
        _inputDeviceID, &propertyAddress, 0, NULL, size, &mute));

    return 0;
  }

  // Otherwise try to set each channel.
  for (UInt32 i = 1; i <= _noInputChannels; i++) {
    propertyAddress.mElement = i;
    isSettable = false;
    err = AudioObjectIsPropertySettable(_inputDeviceID, &propertyAddress,
                                        &isSettable);
    if (err == noErr && isSettable) {
      size = sizeof(mute);
      WEBRTC_CA_RETURN_ON_ERR(AudioObjectSetPropertyData(
          _inputDeviceID, &propertyAddress, 0, NULL, size, &mute));
    }
    success = true;
  }

  if (!success) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 " Unable to set mute on any input channel");
    return -1;
  }

  return 0;
}

int32_t AudioMixerManagerMac::MicrophoneMute(bool& enabled) const {
  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  OSStatus err = noErr;
  UInt32 size = 0;
  unsigned int channels = 0;
  UInt32 channelMuted = 0;
  UInt32 muted = 0;

  // Does the device have a master volume control?
  // If so, use it exclusively.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyMute, kAudioDevicePropertyScopeInput, 0};
  Boolean hasProperty =
      AudioObjectHasProperty(_inputDeviceID, &propertyAddress);
  if (hasProperty) {
    size = sizeof(muted);
    WEBRTC_CA_RETURN_ON_ERR(AudioObjectGetPropertyData(
        _inputDeviceID, &propertyAddress, 0, NULL, &size, &muted));

    // 1 means muted
    enabled = static_cast<bool>(muted);
  } else {
    // Otherwise check if all channels are muted.
    for (UInt32 i = 1; i <= _noInputChannels; i++) {
      muted = 0;
      propertyAddress.mElement = i;
      hasProperty = AudioObjectHasProperty(_inputDeviceID, &propertyAddress);
      if (hasProperty) {
        size = sizeof(channelMuted);
        WEBRTC_CA_RETURN_ON_ERR(AudioObjectGetPropertyData(
            _inputDeviceID, &propertyAddress, 0, NULL, &size, &channelMuted));

        muted = (muted && channelMuted);
        channels++;
      }
    }

    if (channels == 0) {
      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                   " Unable to get mute for any channel");
      return -1;
    }

    assert(channels > 0);
    // 1 means muted
    enabled = static_cast<bool>(muted);
  }

  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
               "     AudioMixerManagerMac::MicrophoneMute() => enabled=%d",
               enabled);

  return 0;
}

int32_t AudioMixerManagerMac::MicrophoneBoostIsAvailable(bool& available) {
  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  available = false;  // No AudioObjectPropertySelector value for Mic Boost

  return 0;
}

int32_t AudioMixerManagerMac::SetMicrophoneBoost(bool enable) {
  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
               "AudioMixerManagerMac::SetMicrophoneBoost(enable=%u)", enable);

  CriticalSectionScoped lock(&_critSect);

  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  // Ensure that the selected microphone has a valid boost control.
  bool available(false);
  MicrophoneBoostIsAvailable(available);
  if (!available) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  it is not possible to enable microphone boost");
    return -1;
  }

  // It is assumed that the call above fails!
  return 0;
}

int32_t AudioMixerManagerMac::MicrophoneBoost(bool& enabled) const {
  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  // Microphone boost cannot be enabled on this platform!
  enabled = false;

  return 0;
}

int32_t AudioMixerManagerMac::MicrophoneVolumeIsAvailable(bool& available) {
  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  OSStatus err = noErr;

  // Does the capture device have a master volume control?
  // If so, use it exclusively.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeInput, 0};
  Boolean isSettable = false;
  err = AudioObjectIsPropertySettable(_inputDeviceID, &propertyAddress,
                                      &isSettable);
  if (err == noErr && isSettable) {
    available = true;
    return 0;
  }

  // Otherwise try to set each channel.
  for (UInt32 i = 1; i <= _noInputChannels; i++) {
    propertyAddress.mElement = i;
    isSettable = false;
    err = AudioObjectIsPropertySettable(_inputDeviceID, &propertyAddress,
                                        &isSettable);
    if (err != noErr || !isSettable) {
      available = false;
      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                   " Volume cannot be set for input channel %d, err=%d", i,
                   err);
      return -1;
    }
  }

  available = true;
  return 0;
}

int32_t AudioMixerManagerMac::SetMicrophoneVolume(uint32_t volume) {
  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
               "AudioMixerManagerMac::SetMicrophoneVolume(volume=%u)", volume);

  CriticalSectionScoped lock(&_critSect);

  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  OSStatus err = noErr;
  UInt32 size = 0;
  bool success = false;

  // volume range is 0.0 - 1.0, convert from 0 - 255
  const Float32 vol = (Float32)(volume / 255.0);

  assert(vol <= 1.0 && vol >= 0.0);

  // Does the capture device have a master volume control?
  // If so, use it exclusively.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeInput, 0};
  Boolean isSettable = false;
  err = AudioObjectIsPropertySettable(_inputDeviceID, &propertyAddress,
                                      &isSettable);
  if (err == noErr && isSettable) {
    size = sizeof(vol);
    WEBRTC_CA_RETURN_ON_ERR(AudioObjectSetPropertyData(
        _inputDeviceID, &propertyAddress, 0, NULL, size, &vol));

    return 0;
  }

  // Otherwise try to set each channel.
  for (UInt32 i = 1; i <= _noInputChannels; i++) {
    propertyAddress.mElement = i;
    isSettable = false;
    err = AudioObjectIsPropertySettable(_inputDeviceID, &propertyAddress,
                                        &isSettable);
    if (err == noErr && isSettable) {
      size = sizeof(vol);
      WEBRTC_CA_RETURN_ON_ERR(AudioObjectSetPropertyData(
          _inputDeviceID, &propertyAddress, 0, NULL, size, &vol));
    }
    success = true;
  }

  if (!success) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 " Unable to set a level on any input channel");
    return -1;
  }

  return 0;
}

int32_t AudioMixerManagerMac::MicrophoneVolume(uint32_t& volume) const {
  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  OSStatus err = noErr;
  UInt32 size = 0;
  unsigned int channels = 0;
  Float32 channelVol = 0;
  Float32 volFloat32 = 0;

  // Does the device have a master volume control?
  // If so, use it exclusively.
  AudioObjectPropertyAddress propertyAddress = {
      kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeInput, 0};
  Boolean hasProperty =
      AudioObjectHasProperty(_inputDeviceID, &propertyAddress);
  if (hasProperty) {
    size = sizeof(volFloat32);
    WEBRTC_CA_RETURN_ON_ERR(AudioObjectGetPropertyData(
        _inputDeviceID, &propertyAddress, 0, NULL, &size, &volFloat32));

    // vol 0.0 to 1.0 -> convert to 0 - 255
    volume = static_cast<uint32_t>(volFloat32 * 255 + 0.5);
  } else {
    // Otherwise get the average volume across channels.
    volFloat32 = 0;
    for (UInt32 i = 1; i <= _noInputChannels; i++) {
      channelVol = 0;
      propertyAddress.mElement = i;
      hasProperty = AudioObjectHasProperty(_inputDeviceID, &propertyAddress);
      if (hasProperty) {
        size = sizeof(channelVol);
        WEBRTC_CA_RETURN_ON_ERR(AudioObjectGetPropertyData(
            _inputDeviceID, &propertyAddress, 0, NULL, &size, &channelVol));

        volFloat32 += channelVol;
        channels++;
      }
    }

    if (channels == 0) {
      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                   " Unable to get a level on any channel");
      return -1;
    }

    assert(channels > 0);
    // vol 0.0 to 1.0 -> convert to 0 - 255
    volume = static_cast<uint32_t>(255 * volFloat32 / channels + 0.5);
  }

  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
               "     AudioMixerManagerMac::MicrophoneVolume() => vol=%u",
               volume);

  return 0;
}

int32_t AudioMixerManagerMac::MaxMicrophoneVolume(uint32_t& maxVolume) const {
  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  // volume range is 0.0 to 1.0
  // we convert that to 0 - 255
  maxVolume = 255;

  return 0;
}

int32_t AudioMixerManagerMac::MinMicrophoneVolume(uint32_t& minVolume) const {
  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  // volume range is 0.0 to 1.0
  // we convert that to 0 - 10
  minVolume = 0;

  return 0;
}

int32_t AudioMixerManagerMac::MicrophoneVolumeStepSize(
    uint16_t& stepSize) const {
  if (_inputDeviceID == kAudioObjectUnknown) {
    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                 "  device ID has not been set");
    return -1;
  }

  // volume range is 0.0 to 1.0
  // we convert that to 0 - 10
  stepSize = 1;

  return 0;
}

// ============================================================================
//                                 Private Methods
// ============================================================================

// CoreAudio errors are best interpreted as four character strings.
void AudioMixerManagerMac::logCAMsg(const TraceLevel level,
                                    const TraceModule module,
                                    const int32_t id,
                                    const char* msg,
                                    const char* err) {
  assert(msg != NULL);
  assert(err != NULL);

#ifdef WEBRTC_ARCH_BIG_ENDIAN
  WEBRTC_TRACE(level, module, id, "%s: %.4s", msg, err);
#else
  // We need to flip the characters in this case.
  WEBRTC_TRACE(level, module, id, "%s: %.1s%.1s%.1s%.1s", msg, err + 3, err + 2,
               err + 1, err);
#endif
}

}  // namespace webrtc
// EOF
