a9c9ebd1a4ce5e0669e2f6f7b46b6d83d82a843f
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / audio / audio_service_chromeos.cc
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.
4
5 #include "chrome/browser/extensions/api/audio/audio_service.h"
6
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"
13
14 using content::BrowserThread;
15
16 namespace extensions {
17
18 using api::audio::OutputDeviceInfo;
19 using api::audio::InputDeviceInfo;
20
21 class AudioServiceImpl : public AudioService,
22                          public chromeos::CrasAudioHandler::AudioObserver {
23  public:
24   AudioServiceImpl();
25   virtual ~AudioServiceImpl();
26
27   // Called by listeners to this service to add/remove themselves as observers.
28   virtual void AddObserver(AudioService::Observer* observer) OVERRIDE;
29   virtual void RemoveObserver(AudioService::Observer* observer) OVERRIDE;
30
31   // Start to query audio device information.
32   virtual void StartGetInfo(const GetInfoCallback& callback) OVERRIDE;
33   virtual void SetActiveDevices(const DeviceIdList& device_list) OVERRIDE;
34   virtual bool SetDeviceProperties(const std::string& device_id,
35                                    bool muted,
36                                    int volume,
37                                    int gain) OVERRIDE;
38
39  protected:
40   // chromeos::CrasAudioHandler::AudioObserver overrides.
41   virtual void OnOutputVolumeChanged() OVERRIDE;
42   virtual void OnInputGainChanged() OVERRIDE;
43   virtual void OnOutputMuteChanged() OVERRIDE;
44   virtual void OnInputMuteChanged() OVERRIDE;
45   virtual void OnAudioNodesChanged() OVERRIDE;
46   virtual void OnActiveOutputNodeChanged() OVERRIDE;
47   virtual void OnActiveInputNodeChanged() OVERRIDE;
48
49  private:
50   void NotifyDeviceChanged();
51
52   bool FindDevice(uint64 id, chromeos::AudioDevice* device);
53   uint64 GetIdFromStr(const std::string& id_str);
54
55   // List of observers.
56   ObserverList<AudioService::Observer> observer_list_;
57
58   chromeos::CrasAudioHandler* cras_audio_handler_;
59
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_;
63
64   DISALLOW_COPY_AND_ASSIGN(AudioServiceImpl);
65 };
66
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);
73   }
74 }
75
76 AudioServiceImpl::~AudioServiceImpl() {
77   if (cras_audio_handler_ && chromeos::CrasAudioHandler::IsInitialized()) {
78     cras_audio_handler_->RemoveAudioObserver(this);
79   }
80 }
81
82 void AudioServiceImpl::AddObserver(AudioService::Observer* observer) {
83   observer_list_.AddObserver(observer);
84 }
85
86 void AudioServiceImpl::RemoveObserver(AudioService::Observer* observer) {
87   observer_list_.RemoveObserver(observer);
88 }
89
90 void AudioServiceImpl::StartGetInfo(const GetInfoCallback& callback) {
91   DCHECK_CURRENTLY_ON(BrowserThread::UI);
92   DCHECK(cras_audio_handler_);
93   DCHECK(!callback.is_null());
94
95   if (callback.is_null())
96     return;
97
98   OutputInfo output_info;
99   InputInfo input_info;
100   if (!cras_audio_handler_) {
101     callback.Run(output_info, input_info, false);
102     return;
103   }
104
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;
113       info->volume =
114           cras_audio_handler_->GetOutputVolumePercentForDevice(devices[i].id);
115       info->is_muted =
116           cras_audio_handler_->IsOutputMutedForDevice(devices[i].id);
117       output_info.push_back(info);
118     } else {
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;
123       info->gain =
124           cras_audio_handler_->GetInputGainPercentForDevice(devices[i].id);
125       info->is_muted =
126           cras_audio_handler_->IsInputMutedForDevice(devices[i].id);
127       input_info.push_back(info);
128     }
129   }
130   callback.Run(output_info, input_info, true);
131 }
132
133 void AudioServiceImpl::SetActiveDevices(const DeviceIdList& device_list) {
134   DCHECK(cras_audio_handler_);
135   if (!cras_audio_handler_)
136     return;
137
138   cras_audio_handler_->RemoveAllActiveNodes();
139
140   for (size_t i = 0; i < device_list.size(); ++i) {
141     chromeos::AudioDevice device;
142     if (FindDevice(GetIdFromStr(device_list[i]), &device))
143       cras_audio_handler_->AddActiveNode(device.id);
144   }
145 }
146
147 bool AudioServiceImpl::SetDeviceProperties(const std::string& device_id,
148                                            bool muted,
149                                            int volume,
150                                            int gain) {
151   DCHECK(cras_audio_handler_);
152   if (!cras_audio_handler_)
153     return false;
154
155   chromeos::AudioDevice device;
156   bool found = FindDevice(GetIdFromStr(device_id), &device);
157   if (!found)
158     return false;
159
160   cras_audio_handler_->SetMuteForDevice(device.id, muted);
161
162   if (!device.is_input && volume != -1) {
163     cras_audio_handler_->SetVolumeGainPercentForDevice(device.id, volume);
164     return true;
165   } else if (device.is_input && gain != -1) {
166     cras_audio_handler_->SetVolumeGainPercentForDevice(device.id, gain);
167     return true;
168   }
169
170   return false;
171 }
172
173 bool AudioServiceImpl::FindDevice(uint64 id, chromeos::AudioDevice* device) {
174   chromeos::AudioDeviceList devices;
175   cras_audio_handler_->GetAudioDevices(&devices);
176
177   for (size_t i = 0; i < devices.size(); ++i) {
178     if (devices[i].id == id) {
179       *device = devices[i];
180       return true;
181     }
182   }
183   return false;
184 }
185
186 uint64 AudioServiceImpl::GetIdFromStr(const std::string& id_str) {
187   uint64 device_id;
188   if (!base::StringToUint64(id_str, &device_id))
189     return 0;
190   else
191     return device_id;
192 }
193
194 void AudioServiceImpl::OnOutputVolumeChanged() {
195   NotifyDeviceChanged();
196 }
197
198 void AudioServiceImpl::OnOutputMuteChanged() {
199   NotifyDeviceChanged();
200 }
201
202 void AudioServiceImpl::OnInputGainChanged() {
203   NotifyDeviceChanged();
204 }
205
206 void AudioServiceImpl::OnInputMuteChanged() {
207   NotifyDeviceChanged();
208 }
209
210 void AudioServiceImpl::OnAudioNodesChanged() {
211   NotifyDeviceChanged();
212 }
213
214 void AudioServiceImpl::OnActiveOutputNodeChanged() {
215   NotifyDeviceChanged();
216 }
217
218 void AudioServiceImpl::OnActiveInputNodeChanged() {
219   NotifyDeviceChanged();
220 }
221
222 void AudioServiceImpl::NotifyDeviceChanged() {
223   FOR_EACH_OBSERVER(AudioService::Observer, observer_list_, OnDeviceChanged());
224 }
225
226 AudioService* AudioService::CreateInstance() {
227   return new AudioServiceImpl;
228 }
229
230 }  // namespace extensions