15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/audio_input_device_manager.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/media_stream_request.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_input_ipc.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager_base.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_parameters.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/channel_layout.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "media/base/scoped_histogram_timer.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromeos/audio/cras_audio_handler.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int AudioInputDeviceManager::kFakeOpenSessionId = 1;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Starting id for the first capture session.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDeviceManager::AudioInputDeviceManager(
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::AudioManager* audio_manager)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : listener_(NULL),
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_capture_session_id_(kFirstSessionId),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_fake_device_(false),
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      keyboard_mic_streams_count_(0),
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_manager_(audio_manager) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDeviceManager::~AudioInputDeviceManager() {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const StreamDeviceInfo* AudioInputDeviceManager::GetOpenedDeviceInfoById(
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int session_id) {
46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StreamDeviceList::iterator device = GetDevice(session_id);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (device == devices_.end())
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return &(*device);
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDeviceManager::Register(
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaStreamProviderListener* listener,
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) {
57effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!listener_);
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!device_task_runner_.get());
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener_ = listener;
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  device_task_runner_ = device_task_runner;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDeviceManager::Unregister() {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(listener_);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener_ = NULL;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioInputDeviceManager::EnumerateDevices(MediaStreamType stream_type) {
70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(listener_);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  device_task_runner_->PostTask(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&AudioInputDeviceManager::EnumerateOnDeviceThread,
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 this, stream_type));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int AudioInputDeviceManager::Open(const StreamDeviceInfo& device) {
80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate a new id for this device.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int session_id = next_capture_session_id_++;
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  device_task_runner_->PostTask(
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AudioInputDeviceManager::OpenOnDeviceThread,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 this, session_id, device));
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return session_id;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDeviceManager::Close(int session_id) {
92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(listener_);
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StreamDeviceList::iterator device = GetDevice(session_id);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (device == devices_.end())
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const MediaStreamType stream_type = device->device.type;
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (session_id != kFakeOpenSessionId)
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    devices_.erase(device);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Post a callback through the listener on IO thread since
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // MediaStreamManager is expecting the callback asynchronously.
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO,
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          FROM_HERE,
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          base::Bind(&AudioInputDeviceManager::ClosedOnIOThread,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     this, stream_type, session_id));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDeviceManager::UseFakeDevice() {
110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  use_fake_device_ = true;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AudioInputDeviceManager::ShouldUseFakeDevice() const {
115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return use_fake_device_;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AudioInputDeviceManager::RegisterKeyboardMicStream(
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::Closure& callback) {
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ++keyboard_mic_streams_count_;
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (keyboard_mic_streams_count_ == 1) {
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    BrowserThread::PostTaskAndReply(
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        BrowserThread::UI,
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FROM_HERE,
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            &AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread,
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            this,
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            true),
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        callback);
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run();
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AudioInputDeviceManager::UnregisterKeyboardMicStream() {
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  --keyboard_mic_streams_count_;
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_GE(keyboard_mic_streams_count_, 0);
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (keyboard_mic_streams_count_ == 0) {
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    BrowserThread::PostTask(
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        BrowserThread::UI,
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FROM_HERE,
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            &AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread,
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            this,
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            false));
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioInputDeviceManager::EnumerateOnDeviceThread(
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaStreamType stream_type) {
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SCOPED_UMA_HISTOGRAM_TIMER(
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "Media.AudioInputDeviceManager.EnumerateOnDeviceThreadTime");
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsOnDeviceThread());
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_EQ(MEDIA_DEVICE_AUDIO_CAPTURE, stream_type);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::AudioDeviceNames device_names;
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (use_fake_device_) {
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Use the fake devices.
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GetFakeDeviceNames(&device_names);
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Enumerate the devices on the OS.
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // AudioManager is guaranteed to outlive MediaStreamManager in
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // BrowserMainloop.
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    audio_manager_->GetAudioInputDeviceNames(&device_names);
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<StreamDeviceInfoArray> devices(new StreamDeviceInfoArray());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (media::AudioDeviceNames::iterator it = device_names.begin();
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != device_names.end(); ++it) {
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Add device information to device vector.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    devices->push_back(StreamDeviceInfo(
1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        stream_type, it->device_name, it->unique_id));
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return the device list through the listener by posting a task on
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IO thread since MediaStreamManager handles the callback asynchronously.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AudioInputDeviceManager::DevicesEnumeratedOnIOThread,
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 this, stream_type, base::Passed(&devices)));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDeviceManager::OpenOnDeviceThread(
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int session_id, const StreamDeviceInfo& info) {
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SCOPED_UMA_HISTOGRAM_TIMER(
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "Media.AudioInputDeviceManager.OpenOnDeviceThreadTime");
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsOnDeviceThread());
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StreamDeviceInfo out(info.device.type, info.device.name, info.device.id,
1988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       0, 0, 0);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out.session_id = session_id;
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  MediaStreamDevice::AudioDeviceParameters& input_params = out.device.input;
20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (use_fake_device_) {
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Don't need to query the hardware information if using fake device.
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    input_params.sample_rate = 44100;
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    input_params.channel_layout = media::CHANNEL_LAYOUT_STEREO;
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Get the preferred sample rate and channel configuration for the
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // audio device.
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    media::AudioParameters params =
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        audio_manager_->GetInputStreamParameters(info.device.id);
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    input_params.sample_rate = params.sample_rate();
21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    input_params.channel_layout = params.channel_layout();
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    input_params.frames_per_buffer = params.frames_per_buffer();
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    input_params.effects = params.effects();
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Add preferred output device information if a matching output device
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // exists.
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    out.device.matched_output_device_id =
22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        audio_manager_->GetAssociatedOutputDeviceID(info.device.id);
22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!out.device.matched_output_device_id.empty()) {
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      params = audio_manager_->GetOutputStreamParameters(
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          out.device.matched_output_device_id);
22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      MediaStreamDevice::AudioDeviceParameters& matched_output_params =
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          out.device.matched_output;
22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matched_output_params.sample_rate = params.sample_rate();
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matched_output_params.channel_layout = params.channel_layout();
22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matched_output_params.frames_per_buffer = params.frames_per_buffer();
22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return the |session_id| through the listener by posting a task on
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IO thread since MediaStreamManager handles the callback asynchronously.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          FROM_HERE,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::Bind(&AudioInputDeviceManager::OpenedOnIOThread,
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     this, session_id, out));
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDeviceManager::DevicesEnumeratedOnIOThread(
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaStreamType stream_type,
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<StreamDeviceInfoArray> devices) {
243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that |devices| gets deleted on exit.
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (listener_)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    listener_->DevicesEnumerated(stream_type, *devices);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioInputDeviceManager::OpenedOnIOThread(int session_id,
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               const StreamDeviceInfo& info) {
251effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(session_id, info.session_id);
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(GetDevice(session_id) == devices_.end());
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  devices_.push_back(info);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listener_)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    listener_->Opened(info.device.type, session_id);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioInputDeviceManager::ClosedOnIOThread(MediaStreamType stream_type,
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               int session_id) {
263effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listener_)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listener_->Closed(stream_type, session_id);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AudioInputDeviceManager::IsOnDeviceThread() const {
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return device_task_runner_->BelongsToCurrentThread();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AudioInputDeviceManager::StreamDeviceList::iterator
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AudioInputDeviceManager::GetDevice(int session_id) {
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (StreamDeviceList::iterator i(devices_.begin()); i != devices_.end();
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i->session_id == session_id)
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return i;
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return devices_.end();
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AudioInputDeviceManager::GetFakeDeviceNames(
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    media::AudioDeviceNames* device_names) {
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static const char kFakeDeviceName1[] = "Fake Audio 1";
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static const char kFakeDeviceId1[] = "fake_audio_1";
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static const char kFakeDeviceName2[] = "Fake Audio 2";
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static const char kFakeDeviceId2[] = "fake_audio_2";
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(device_names->empty());
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(use_fake_device_);
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  device_names->push_back(media::AudioDeviceName(kFakeDeviceName1,
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                 kFakeDeviceId1));
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  device_names->push_back(media::AudioDeviceName(kFakeDeviceName2,
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                 kFakeDeviceId2));
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread(
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool active) {
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_CURRENTLY_ON(BrowserThread::UI);
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  chromeos::CrasAudioHandler::Get()->SetKeyboardMicActive(active);
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
307