<commit_before>// Copyright (c) 2013 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 "chrome/browser/extensions/api/audio/audio_service.h"

#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "chromeos/audio/audio_device.h"
#include "chromeos/audio/cras_audio_handler.h"
#include "chromeos/dbus/audio_node.h"
#include "chromeos/dbus/cras_audio_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;

namespace extensions {

using api::audio::OutputDeviceInfo;
using api::audio::InputDeviceInfo;

class AudioServiceImpl : public AudioService,
                         public chromeos::CrasAudioHandler::AudioObserver {
 public:
  AudioServiceImpl();
  virtual ~AudioServiceImpl();

  // Called by listeners to this service to add/remove themselves as observers.
  virtual void AddObserver(AudioService::Observer* observer) OVERRIDE;
  virtual void RemoveObserver(AudioService::Observer* observer) OVERRIDE;

  // Start to query audio device information.
  virtual void StartGetInfo(const GetInfoCallback& callback) OVERRIDE;
  virtual void SetActiveDevices(const DeviceIdList& device_list) OVERRIDE;
  virtual bool SetDeviceProperties(const std::string& device_id,
                                   bool muted,
                                   int volume,
                                   int gain) OVERRIDE;

 protected:
  // chromeos::CrasAudioHandler::AudioObserver overrides.
  virtual void OnOutputVolumeChanged() OVERRIDE;
  virtual void OnInputGainChanged() OVERRIDE;
  virtual void OnOutputMuteChanged() OVERRIDE;
  virtual void OnInputMuteChanged() OVERRIDE;
  virtual void OnAudioNodesChanged() OVERRIDE;
  virtual void OnActiveOutputNodeChanged() OVERRIDE;
  virtual void OnActiveInputNodeChanged() OVERRIDE;

 private:
  void NotifyDeviceChanged();

  // Callback for CrasAudioClient::GetNodes().
  void OnGetNodes(const GetInfoCallback& callback,
                  const chromeos::AudioNodeList& audio_nodes,
                  bool success);

  bool FindDevice(uint64 id, chromeos::AudioDevice* device);
  uint64 GetIdFromStr(const std::string& id_str);

  // List of observers.
  ObserverList<AudioService::Observer> observer_list_;

  chromeos::CrasAudioClient* cras_audio_client_;
  chromeos::CrasAudioHandler* cras_audio_handler_;

  // Note: This should remain the last member so it'll be destroyed and
  // invalidate the weak pointers before any other members are destroyed.
  base::WeakPtrFactory<AudioServiceImpl> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(AudioServiceImpl);
};

AudioServiceImpl::AudioServiceImpl()
    : cras_audio_client_(NULL),
      cras_audio_handler_(NULL),
      weak_ptr_factory_(this) {
  if (chromeos::DBusThreadManager::IsInitialized() &&
      chromeos::DBusThreadManager::Get()) {
    cras_audio_client_ =
        chromeos::DBusThreadManager::Get()->GetCrasAudioClient();
    if (chromeos::CrasAudioHandler::IsInitialized()) {
      cras_audio_handler_ = chromeos::CrasAudioHandler::Get();
      cras_audio_handler_->AddAudioObserver(this);
    }
  }
}

AudioServiceImpl::~AudioServiceImpl() {
  if (cras_audio_handler_ && chromeos::CrasAudioHandler::IsInitialized()) {
    cras_audio_handler_->RemoveAudioObserver(this);
  }
}

void AudioServiceImpl::AddObserver(AudioService::Observer* observer) {
  observer_list_.AddObserver(observer);
}

void AudioServiceImpl::RemoveObserver(AudioService::Observer* observer) {
  observer_list_.RemoveObserver(observer);
}

void AudioServiceImpl::StartGetInfo(const GetInfoCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(cras_audio_client_);
  if (cras_audio_client_)
    cras_audio_client_->GetNodes(base::Bind(&AudioServiceImpl::OnGetNodes,
                                            weak_ptr_factory_.GetWeakPtr(),
                                            callback));
}

void AudioServiceImpl::SetActiveDevices(const DeviceIdList& device_list) {
  DCHECK(cras_audio_handler_);
  if (!cras_audio_handler_)
    return;

  bool input_device_set = false;
  bool output_device_set = false;

  for (size_t i = 0; i < device_list.size(); ++i) {
    chromeos::AudioDevice device;
    bool found = FindDevice(GetIdFromStr(device_list[i]), &device);
    if (found) {
      if (device.is_input && !input_device_set) {
        cras_audio_handler_->SwitchToDevice(device);
        input_device_set = true;
      } else if (!device.is_input && !output_device_set) {
        cras_audio_handler_->SwitchToDevice(device);
        output_device_set = true;
      }
    }
  }
}

bool AudioServiceImpl::SetDeviceProperties(const std::string& device_id,
                                           bool muted,
                                           int volume,
                                           int gain) {
  DCHECK(cras_audio_handler_);
  if (!cras_audio_handler_)
    return false;

  chromeos::AudioDevice device;
  bool found = FindDevice(GetIdFromStr(device_id), &device);
  if (!found)
    return false;

  cras_audio_handler_->SetMuteForDevice(device.id, muted);

  if (!device.is_input && volume != -1) {
    cras_audio_handler_->SetVolumeGainPercentForDevice(device.id, volume);
    return true;
  } else if (device.is_input && gain != -1) {
    cras_audio_handler_->SetVolumeGainPercentForDevice(device.id, gain);
    return true;
  }

  return false;
}

void AudioServiceImpl::OnGetNodes(const GetInfoCallback& callback,
                                  const chromeos::AudioNodeList& audio_nodes,
                                  bool success) {
  OutputInfo output_info;
  InputInfo input_info;
  if (success) {
    for (chromeos::AudioNodeList::const_iterator iter = audio_nodes.begin();
        iter != audio_nodes.end(); ++iter) {
      if (!iter->is_input) {
        linked_ptr<OutputDeviceInfo> info(new OutputDeviceInfo());
        info->id = base::Uint64ToString(iter->id);
        info->name = iter->name;
        info->is_active = iter->active;
        info->volume = cras_audio_handler_->GetOutputVolumePercentForDevice(
            iter->id);
        info->is_muted = cras_audio_handler_->IsOutputMutedForDevice(iter->id);
        output_info.push_back(info);
      } else {
        linked_ptr<InputDeviceInfo> info(new InputDeviceInfo());
        info->id = base::Uint64ToString(iter->id);
        info->name = iter->name;
        info->is_active = iter->active;
        info->gain = cras_audio_handler_->GetInputGainPercentForDevice(
            iter->id);
        info->is_muted = cras_audio_handler_->IsInputMutedForDevice(iter->id);
        input_info.push_back(info);
      }
    }
  }

  DCHECK(!callback.is_null());
  if (!callback.is_null())
    callback.Run(output_info, input_info, success);
}

bool AudioServiceImpl::FindDevice(uint64 id, chromeos::AudioDevice* device) {
  chromeos::AudioDeviceList devices;
  cras_audio_handler_->GetAudioDevices(&devices);
<commit_msg>Add DeviceName to the name returned by the Audio API. The Input/OutputInfo objects returned by GetNodes currently contain only the 'node name' of the device that is connected. This is not always the complete name of the device and can make device identification difficult to impossible. Prepend the device name to the node name to allow clear device identification.<commit_after>// Copyright (c) 2013 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 "chrome/browser/extensions/api/audio/audio_service.h"

#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "chromeos/audio/audio_device.h"
#include "chromeos/audio/cras_audio_handler.h"
#include "chromeos/dbus/audio_node.h"
#include "chromeos/dbus/cras_audio_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;

namespace extensions {

using api::audio::OutputDeviceInfo;
using api::audio::InputDeviceInfo;

class AudioServiceImpl : public AudioService,
                         public chromeos::CrasAudioHandler::AudioObserver {
 public:
  AudioServiceImpl();
  virtual ~AudioServiceImpl();

  // Called by listeners to this service to add/remove themselves as observers.
  virtual void AddObserver(AudioService::Observer* observer) OVERRIDE;
  virtual void RemoveObserver(AudioService::Observer* observer) OVERRIDE;

  // Start to query audio device information.
  virtual void StartGetInfo(const GetInfoCallback& callback) OVERRIDE;
  virtual void SetActiveDevices(const DeviceIdList& device_list) OVERRIDE;
  virtual bool SetDeviceProperties(const std::string& device_id,
                                   bool muted,
                                   int volume,
                                   int gain) OVERRIDE;

 protected:
  // chromeos::CrasAudioHandler::AudioObserver overrides.
  virtual void OnOutputVolumeChanged() OVERRIDE;
  virtual void OnInputGainChanged() OVERRIDE;
  virtual void OnOutputMuteChanged() OVERRIDE;
  virtual void OnInputMuteChanged() OVERRIDE;
  virtual void OnAudioNodesChanged() OVERRIDE;
  virtual void OnActiveOutputNodeChanged() OVERRIDE;
  virtual void OnActiveInputNodeChanged() OVERRIDE;

 private:
  void NotifyDeviceChanged();

  // Callback for CrasAudioClient::GetNodes().
  void OnGetNodes(const GetInfoCallback& callback,
                  const chromeos::AudioNodeList& audio_nodes,
                  bool success);

  bool FindDevice(uint64 id, chromeos::AudioDevice* device);
  uint64 GetIdFromStr(const std::string& id_str);

  // List of observers.
  ObserverList<AudioService::Observer> observer_list_;

  chromeos::CrasAudioClient* cras_audio_client_;
  chromeos::CrasAudioHandler* cras_audio_handler_;

  // Note: This should remain the last member so it'll be destroyed and
  // invalidate the weak pointers before any other members are destroyed.
  base::WeakPtrFactory<AudioServiceImpl> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(AudioServiceImpl);
};

AudioServiceImpl::AudioServiceImpl()
    : cras_audio_client_(NULL),
      cras_audio_handler_(NULL),
      weak_ptr_factory_(this) {
  if (chromeos::DBusThreadManager::IsInitialized() &&
      chromeos::DBusThreadManager::Get()) {
    cras_audio_client_ =
        chromeos::DBusThreadManager::Get()->GetCrasAudioClient();
    if (chromeos::CrasAudioHandler::IsInitialized()) {
      cras_audio_handler_ = chromeos::CrasAudioHandler::Get();
      cras_audio_handler_->AddAudioObserver(this);
    }
  }
}

AudioServiceImpl::~AudioServiceImpl() {
  if (cras_audio_handler_ && chromeos::CrasAudioHandler::IsInitialized()) {
    cras_audio_handler_->RemoveAudioObserver(this);
  }
}

void AudioServiceImpl::AddObserver(AudioService::Observer* observer) {
  observer_list_.AddObserver(observer);
}

void AudioServiceImpl::RemoveObserver(AudioService::Observer* observer) {
  observer_list_.RemoveObserver(observer);
}

void AudioServiceImpl::StartGetInfo(const GetInfoCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(cras_audio_client_);
  if (cras_audio_client_)
    cras_audio_client_->GetNodes(base::Bind(&AudioServiceImpl::OnGetNodes,
                                            weak_ptr_factory_.GetWeakPtr(),
                                            callback));
}

void AudioServiceImpl::SetActiveDevices(const DeviceIdList& device_list) {
  DCHECK(cras_audio_handler_);
  if (!cras_audio_handler_)
    return;

  bool input_device_set = false;
  bool output_device_set = false;

  for (size_t i = 0; i < device_list.size(); ++i) {
    chromeos::AudioDevice device;
    bool found = FindDevice(GetIdFromStr(device_list[i]), &device);
    if (found) {
      if (device.is_input && !input_device_set) {
        cras_audio_handler_->SwitchToDevice(device);
        input_device_set = true;
      } else if (!device.is_input && !output_device_set) {
        cras_audio_handler_->SwitchToDevice(device);
        output_device_set = true;
      }
    }
  }
}

bool AudioServiceImpl::SetDeviceProperties(const std::string& device_id,
                                           bool muted,
                                           int volume,
                                           int gain) {
  DCHECK(cras_audio_handler_);
  if (!cras_audio_handler_)
    return false;

  chromeos::AudioDevice device;
  bool found = FindDevice(GetIdFromStr(device_id), &device);
  if (!found)
    return false;

  cras_audio_handler_->SetMuteForDevice(device.id, muted);

  if (!device.is_input && volume != -1) {
    cras_audio_handler_->SetVolumeGainPercentForDevice(device.id, volume);
    return true;
  } else if (device.is_input && gain != -1) {
    cras_audio_handler_->SetVolumeGainPercentForDevice(device.id, gain);
    return true;
  }

  return false;
}

void AudioServiceImpl::OnGetNodes(const GetInfoCallback& callback,
                                  const chromeos::AudioNodeList& audio_nodes,
                                  bool success) {
  OutputInfo output_info;
  InputInfo input_info;
  if (success) {
    for (chromeos::AudioNodeList::const_iterator iter = audio_nodes.begin();
        iter != audio_nodes.end(); ++iter) {
      if (!iter->is_input) {
        linked_ptr<OutputDeviceInfo> info(new OutputDeviceInfo());
        info->id = base::Uint64ToString(iter->id);
        info->name = iter->device_name + ": " + iter->name;
        info->is_active = iter->active;
        info->volume = cras_audio_handler_->GetOutputVolumePercentForDevice(
            iter->id);
        info->is_muted = cras_audio_handler_->IsOutputMutedForDevice(iter->id);
        output_info.push_back(info);
      } else {
        linked_ptr<InputDeviceInfo> info(new InputDeviceInfo());
        info->id = base::Uint64ToString(iter->id);
        info->name = iter->device_name + ": " + iter->name;
        info->is_active = iter->active;
        info->gain = cras_audio_handler_->GetInputGainPercentForDevice(
            iter->id);
        info->is_muted = cras_audio_handler_->IsInputMutedForDevice(iter->id);
        input_info.push_back(info);
      }
    }
  }

  DCHECK(!callback.is_null());
  if (!callback.is_null())
    callback.Run(output_info, input_info, success);
}

bool AudioServiceImpl::FindDevice(uint64 id, chromeos::AudioDevice* device) {
  chromeos::AudioDeviceList devices;
  cras_audio_handler_->GetAudioDevices(&devices);

{'fraction_non_alphanumeric': 0.1030356898673595, 'fraction_numerical': 0.002324627375905921, 'mean_word_length': 3.605478589420655, 'pattern_counts': {'":': 2, '<': 13, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3400922', 'n_tokens_mistral': 4332, 'n_tokens_neox': 4199, 'n_words': 864}