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