1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/browser/api/audio/audio_service.h"
7 #include "base/callback.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "chromeos/audio/audio_device.h"
11 #include "chromeos/audio/cras_audio_handler.h"
12 #include "content/public/browser/browser_thread.h"
14 using content::BrowserThread
;
16 namespace extensions
{
18 using core_api::audio::OutputDeviceInfo
;
19 using core_api::audio::InputDeviceInfo
;
21 class AudioServiceImpl
: public AudioService
,
22 public chromeos::CrasAudioHandler::AudioObserver
{
25 ~AudioServiceImpl() override
;
27 // Called by listeners to this service to add/remove themselves as observers.
28 void AddObserver(AudioService::Observer
* observer
) override
;
29 void RemoveObserver(AudioService::Observer
* observer
) override
;
31 // Start to query audio device information.
32 void StartGetInfo(const GetInfoCallback
& callback
) override
;
33 void SetActiveDevices(const DeviceIdList
& device_list
) override
;
34 bool SetDeviceProperties(const std::string
& device_id
,
40 // chromeos::CrasAudioHandler::AudioObserver overrides.
41 void OnOutputVolumeChanged() override
;
42 void OnInputGainChanged() override
;
43 void OnOutputMuteChanged() override
;
44 void OnInputMuteChanged() override
;
45 void OnAudioNodesChanged() override
;
46 void OnActiveOutputNodeChanged() override
;
47 void OnActiveInputNodeChanged() override
;
50 void NotifyDeviceChanged();
52 bool FindDevice(uint64 id
, chromeos::AudioDevice
* device
);
53 uint64
GetIdFromStr(const std::string
& id_str
);
56 ObserverList
<AudioService::Observer
> observer_list_
;
58 chromeos::CrasAudioHandler
* cras_audio_handler_
;
60 // Note: This should remain the last member so it'll be destroyed and
61 // invalidate the weak pointers before any other members are destroyed.
62 base::WeakPtrFactory
<AudioServiceImpl
> weak_ptr_factory_
;
64 DISALLOW_COPY_AND_ASSIGN(AudioServiceImpl
);
67 AudioServiceImpl::AudioServiceImpl()
68 : cras_audio_handler_(NULL
),
69 weak_ptr_factory_(this) {
70 if (chromeos::CrasAudioHandler::IsInitialized()) {
71 cras_audio_handler_
= chromeos::CrasAudioHandler::Get();
72 cras_audio_handler_
->AddAudioObserver(this);
76 AudioServiceImpl::~AudioServiceImpl() {
77 if (cras_audio_handler_
&& chromeos::CrasAudioHandler::IsInitialized()) {
78 cras_audio_handler_
->RemoveAudioObserver(this);
82 void AudioServiceImpl::AddObserver(AudioService::Observer
* observer
) {
83 observer_list_
.AddObserver(observer
);
86 void AudioServiceImpl::RemoveObserver(AudioService::Observer
* observer
) {
87 observer_list_
.RemoveObserver(observer
);
90 void AudioServiceImpl::StartGetInfo(const GetInfoCallback
& callback
) {
91 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
92 DCHECK(cras_audio_handler_
);
93 DCHECK(!callback
.is_null());
95 if (callback
.is_null())
98 OutputInfo output_info
;
100 if (!cras_audio_handler_
) {
101 callback
.Run(output_info
, input_info
, false);
105 chromeos::AudioDeviceList devices
;
106 cras_audio_handler_
->GetAudioDevices(&devices
);
107 for (size_t i
= 0; i
< devices
.size(); ++i
) {
108 if (!devices
[i
].is_input
) {
109 linked_ptr
<OutputDeviceInfo
> info(new OutputDeviceInfo());
110 info
->id
= base::Uint64ToString(devices
[i
].id
);
111 info
->name
= devices
[i
].device_name
+ ": " + devices
[i
].display_name
;
112 info
->is_active
= devices
[i
].active
;
114 cras_audio_handler_
->GetOutputVolumePercentForDevice(devices
[i
].id
);
116 cras_audio_handler_
->IsOutputMutedForDevice(devices
[i
].id
);
117 output_info
.push_back(info
);
119 linked_ptr
<InputDeviceInfo
> info(new InputDeviceInfo());
120 info
->id
= base::Uint64ToString(devices
[i
].id
);
121 info
->name
= devices
[i
].device_name
+ ": " + devices
[i
].display_name
;
122 info
->is_active
= devices
[i
].active
;
124 cras_audio_handler_
->GetInputGainPercentForDevice(devices
[i
].id
);
126 cras_audio_handler_
->IsInputMutedForDevice(devices
[i
].id
);
127 input_info
.push_back(info
);
130 callback
.Run(output_info
, input_info
, true);
133 void AudioServiceImpl::SetActiveDevices(const DeviceIdList
& device_list
) {
134 DCHECK(cras_audio_handler_
);
135 if (!cras_audio_handler_
)
138 chromeos::CrasAudioHandler::NodeIdList id_list
;
139 for (size_t i
= 0; i
< device_list
.size(); ++i
) {
140 chromeos::AudioDevice device
;
141 if (FindDevice(GetIdFromStr(device_list
[i
]), &device
))
142 id_list
.push_back(device
.id
);
144 cras_audio_handler_
->ChangeActiveNodes(id_list
);
147 bool AudioServiceImpl::SetDeviceProperties(const std::string
& device_id
,
151 DCHECK(cras_audio_handler_
);
152 if (!cras_audio_handler_
)
155 chromeos::AudioDevice device
;
156 bool found
= FindDevice(GetIdFromStr(device_id
), &device
);
160 cras_audio_handler_
->SetMuteForDevice(device
.id
, muted
);
162 if (!device
.is_input
&& volume
!= -1) {
163 cras_audio_handler_
->SetVolumeGainPercentForDevice(device
.id
, volume
);
165 } else if (device
.is_input
&& gain
!= -1) {
166 cras_audio_handler_
->SetVolumeGainPercentForDevice(device
.id
, gain
);
173 bool AudioServiceImpl::FindDevice(uint64 id
, chromeos::AudioDevice
* device
) {
174 chromeos::AudioDeviceList devices
;
175 cras_audio_handler_
->GetAudioDevices(&devices
);
177 for (size_t i
= 0; i
< devices
.size(); ++i
) {
178 if (devices
[i
].id
== id
) {
179 *device
= devices
[i
];
186 uint64
AudioServiceImpl::GetIdFromStr(const std::string
& id_str
) {
188 if (!base::StringToUint64(id_str
, &device_id
))
194 void AudioServiceImpl::OnOutputVolumeChanged() {
195 NotifyDeviceChanged();
198 void AudioServiceImpl::OnOutputMuteChanged() {
199 NotifyDeviceChanged();
202 void AudioServiceImpl::OnInputGainChanged() {
203 NotifyDeviceChanged();
206 void AudioServiceImpl::OnInputMuteChanged() {
207 NotifyDeviceChanged();
210 void AudioServiceImpl::OnAudioNodesChanged() {
211 NotifyDeviceChanged();
214 void AudioServiceImpl::OnActiveOutputNodeChanged() {
215 NotifyDeviceChanged();
218 void AudioServiceImpl::OnActiveInputNodeChanged() {
219 NotifyDeviceChanged();
222 void AudioServiceImpl::NotifyDeviceChanged() {
223 FOR_EACH_OBSERVER(AudioService::Observer
, observer_list_
, OnDeviceChanged());
226 AudioService
* AudioService::CreateInstance() {
227 return new AudioServiceImpl
;
230 } // namespace extensions