Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1781)

Side by Side Diff: chromecast/media/cma/backend/alsa/volume_control.cc

Issue 2771133002: [chromcast] Still need to call StreamMixerAlsa::SetVolume, even when ALSA doesn't own the volume. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chromecast/media/cma/backend/alsa/BUILD.gn ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chromecast/public/volume_control.h" 5 #include "chromecast/public/volume_control.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <map> 9 #include <map>
10 #include <memory> 10 #include <memory>
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 127
128 float GetVolume(AudioContentType type) { 128 float GetVolume(AudioContentType type) {
129 base::AutoLock lock(volume_lock_); 129 base::AutoLock lock(volume_lock_);
130 return volumes_[type]; 130 return volumes_[type];
131 } 131 }
132 132
133 void SetVolume(AudioContentType type, float level) { 133 void SetVolume(AudioContentType type, float level) {
134 level = std::max(0.0f, std::min(level, 1.0f)); 134 level = std::max(0.0f, std::min(level, 1.0f));
135 thread_.task_runner()->PostTask( 135 thread_.task_runner()->PostTask(
136 FROM_HERE, base::Bind(&VolumeControlInternal::SetVolumeOnThread, 136 FROM_HERE, base::Bind(&VolumeControlInternal::SetVolumeOnThread,
137 base::Unretained(this), type, level)); 137 base::Unretained(this), type, level, false));
kmackay 2017/03/24 04:02:50 false /* from_alsa */
gfhuang 2017/03/24 06:29:59 Done.
138 } 138 }
139 139
140 bool IsMuted(AudioContentType type) { 140 bool IsMuted(AudioContentType type) {
141 base::AutoLock lock(volume_lock_); 141 base::AutoLock lock(volume_lock_);
142 return muted_[type]; 142 return muted_[type];
143 } 143 }
144 144
145 void SetMuted(AudioContentType type, bool muted) { 145 void SetMuted(AudioContentType type, bool muted) {
146 thread_.task_runner()->PostTask( 146 thread_.task_runner()->PostTask(
147 FROM_HERE, base::Bind(&VolumeControlInternal::SetMutedOnThread, 147 FROM_HERE, base::Bind(&VolumeControlInternal::SetMutedOnThread,
148 base::Unretained(this), type, muted)); 148 base::Unretained(this), type, muted, false));
kmackay 2017/03/24 04:02:50 /* from_alsa */
gfhuang 2017/03/24 06:30:00 Done.
149 } 149 }
150 150
151 void SetOutputLimit(AudioContentType type, float limit) { 151 void SetOutputLimit(AudioContentType type, float limit) {
152 if (BUILDFLAG(ALSA_CONTROLS_VOLUME)) { 152 if (BUILDFLAG(ALSA_OWNS_VOLUME)) {
153 return; 153 return;
154 } 154 }
155 limit = std::max(0.0f, std::min(limit, 1.0f)); 155 limit = std::max(0.0f, std::min(limit, 1.0f));
156 StreamMixerAlsa::Get()->SetOutputLimit( 156 StreamMixerAlsa::Get()->SetOutputLimit(
157 type, DbFsToScale(VolumeControl::VolumeToDbFS(limit))); 157 type, DbFsToScale(VolumeControl::VolumeToDbFS(limit)));
158 } 158 }
159 159
160 private: 160 private:
161 void InitializeOnThread() { 161 void InitializeOnThread() {
162 DCHECK(thread_.task_runner()->BelongsToCurrentThread()); 162 DCHECK(thread_.task_runner()->BelongsToCurrentThread());
163 alsa_volume_control_ = base::MakeUnique<AlsaVolumeControl>(this); 163 alsa_volume_control_ = base::MakeUnique<AlsaVolumeControl>(this);
164 164
165 double dbfs; 165 double dbfs;
166 for (auto type : {AudioContentType::kMedia, AudioContentType::kAlarm, 166 for (auto type : {AudioContentType::kMedia, AudioContentType::kAlarm,
167 AudioContentType::kCommunication}) { 167 AudioContentType::kCommunication}) {
168 CHECK(stored_values_.GetDouble(ContentTypeToDbFSKey(type), &dbfs)); 168 CHECK(stored_values_.GetDouble(ContentTypeToDbFSKey(type), &dbfs));
169 volumes_[type] = VolumeControl::DbFSToVolume(dbfs); 169 volumes_[type] = VolumeControl::DbFSToVolume(dbfs);
170 if (BUILDFLAG(ALSA_CONTROLS_VOLUME)) { 170 if (BUILDFLAG(ALSA_OWNS_VOLUME)) {
171 // If ALSA controls volume, our internal mixer should not apply any 171 // If ALSA owns volume, our internal mixer should not apply any scaling
172 // scaling multiplier. 172 // multiplier.
173 StreamMixerAlsa::Get()->SetVolume(type, 1.0f); 173 StreamMixerAlsa::Get()->SetVolume(type, 1.0f);
174 } else { 174 } else {
175 StreamMixerAlsa::Get()->SetVolume(type, DbFsToScale(dbfs)); 175 StreamMixerAlsa::Get()->SetVolume(type, DbFsToScale(dbfs));
176 } 176 }
177 177
178 // Note that mute state is not persisted across reboots. 178 // Note that mute state is not persisted across reboots.
179 muted_[type] = false; 179 muted_[type] = false;
180 } 180 }
181 181
182 if (BUILDFLAG(ALSA_CONTROLS_VOLUME)) { 182 if (BUILDFLAG(ALSA_OWNS_VOLUME)) {
183 // If ALSA controls the volume, then read the current volume and mute 183 // If ALSA owns the volume, then read the current volume and mute state
184 // state from the ALSA mixer element(s). 184 // from the ALSA mixer element(s).
185 volumes_[AudioContentType::kMedia] = alsa_volume_control_->GetVolume(); 185 volumes_[AudioContentType::kMedia] = alsa_volume_control_->GetVolume();
186 muted_[AudioContentType::kMedia] = alsa_volume_control_->IsMuted(); 186 muted_[AudioContentType::kMedia] = alsa_volume_control_->IsMuted();
187 } else { 187 } else {
188 // Otherwise, make sure the ALSA mixer element correctly reflects the 188 // Otherwise, make sure the ALSA mixer element correctly reflects the
189 // current volume state. 189 // current volume state.
190 alsa_volume_control_->SetVolume(volumes_[AudioContentType::kMedia]); 190 alsa_volume_control_->SetVolume(volumes_[AudioContentType::kMedia]);
191 alsa_volume_control_->SetMuted(false); 191 alsa_volume_control_->SetMuted(false);
192 } 192 }
193 193
194 initialize_complete_event_.Signal(); 194 initialize_complete_event_.Signal();
195 } 195 }
196 196
197 void SetVolumeOnThread(AudioContentType type, float level) { 197 void SetVolumeOnThread(AudioContentType type, float level, bool from_alsa) {
198 DCHECK(thread_.task_runner()->BelongsToCurrentThread()); 198 DCHECK(thread_.task_runner()->BelongsToCurrentThread());
199 DCHECK(!from_alsa || type == AudioContentType::kMedia);
199 { 200 {
200 base::AutoLock lock(volume_lock_); 201 base::AutoLock lock(volume_lock_);
202 if (from_alsa && alsa_volume_control_->VolumeThroughAlsa(
203 volumes_[AudioContentType::kMedia]) == level) {
204 return;
205 }
201 if (level == volumes_[type]) { 206 if (level == volumes_[type]) {
202 return; 207 return;
203 } 208 }
204 volumes_[type] = level; 209 volumes_[type] = level;
205 } 210 }
206 211
207 float dbfs = VolumeControl::VolumeToDbFS(level); 212 float dbfs = VolumeControl::VolumeToDbFS(level);
208 if (!BUILDFLAG(ALSA_CONTROLS_VOLUME)) { 213 if (!BUILDFLAG(ALSA_OWNS_VOLUME)) {
209 StreamMixerAlsa::Get()->SetVolume(type, DbFsToScale(dbfs)); 214 StreamMixerAlsa::Get()->SetVolume(type, DbFsToScale(dbfs));
210 } 215 }
211 216
212 if (type == AudioContentType::kMedia) { 217 if (!from_alsa && type == AudioContentType::kMedia) {
213 alsa_volume_control_->SetVolume(level); 218 alsa_volume_control_->SetVolume(level);
214 } 219 }
215 220
216 { 221 {
217 base::AutoLock lock(observer_lock_); 222 base::AutoLock lock(observer_lock_);
218 for (VolumeObserver* observer : volume_observers_) { 223 for (VolumeObserver* observer : volume_observers_) {
219 observer->OnVolumeChange(type, level); 224 observer->OnVolumeChange(type, level);
220 } 225 }
221 } 226 }
222 227
223 stored_values_.SetDouble(ContentTypeToDbFSKey(type), dbfs); 228 stored_values_.SetDouble(ContentTypeToDbFSKey(type), dbfs);
224 SerializeJsonToFile(storage_path_, stored_values_); 229 SerializeJsonToFile(storage_path_, stored_values_);
225 } 230 }
226 231
227 void SetMutedOnThread(AudioContentType type, bool muted) { 232 void SetMutedOnThread(AudioContentType type, bool muted, bool from_alsa) {
228 DCHECK(thread_.task_runner()->BelongsToCurrentThread()); 233 DCHECK(thread_.task_runner()->BelongsToCurrentThread());
229 { 234 {
230 base::AutoLock lock(volume_lock_); 235 base::AutoLock lock(volume_lock_);
231 if (muted == muted_[type]) { 236 if (muted == muted_[type]) {
232 return; 237 return;
233 } 238 }
234 muted_[type] = muted; 239 muted_[type] = muted;
235 } 240 }
236 241
237 if (!BUILDFLAG(ALSA_CONTROLS_VOLUME)) { 242 if (!BUILDFLAG(ALSA_OWNS_VOLUME)) {
238 StreamMixerAlsa::Get()->SetMuted(type, muted); 243 StreamMixerAlsa::Get()->SetMuted(type, muted);
239 } 244 }
240 245
241 if (type == AudioContentType::kMedia) { 246 if (!from_alsa && type == AudioContentType::kMedia) {
242 alsa_volume_control_->SetMuted(muted); 247 alsa_volume_control_->SetMuted(muted);
243 } 248 }
244 249
245 { 250 {
246 base::AutoLock lock(observer_lock_); 251 base::AutoLock lock(observer_lock_);
247 for (VolumeObserver* observer : volume_observers_) { 252 for (VolumeObserver* observer : volume_observers_) {
248 observer->OnMuteChange(type, muted); 253 observer->OnMuteChange(type, muted);
249 } 254 }
250 } 255 }
251 } 256 }
252 257
253 // AlsaVolumeControl::Delegate implementation: 258 // AlsaVolumeControl::Delegate implementation:
254 void OnAlsaVolumeOrMuteChange(float new_volume, bool new_mute) override { 259 void OnAlsaVolumeOrMuteChange(float new_volume, bool new_mute) override {
255 DCHECK(thread_.task_runner()->BelongsToCurrentThread()); 260 DCHECK(thread_.task_runner()->BelongsToCurrentThread());
256 bool volume_changed = false; 261 SetVolumeOnThread(AudioContentType::kMedia, new_volume,
257 bool mute_changed = false; 262 true /* from_alsa */);
258 { 263 SetMutedOnThread(AudioContentType::kMedia, new_mute, true /* from_alsa */);
259 base::AutoLock lock(volume_lock_);
260 if (alsa_volume_control_->VolumeThroughAlsa(
261 volumes_[AudioContentType::kMedia]) != new_volume) {
262 volume_changed = true;
263 volumes_[AudioContentType::kMedia] = new_volume;
264 }
265
266 if (muted_[AudioContentType::kMedia] != new_mute) {
267 mute_changed = true;
268 muted_[AudioContentType::kMedia] = new_mute;
269 }
270 }
271
272 if (!volume_changed && !mute_changed) {
273 return;
274 }
275
276 {
277 base::AutoLock lock(observer_lock_);
278 if (volume_changed) {
279 for (VolumeObserver* observer : volume_observers_) {
280 observer->OnVolumeChange(AudioContentType::kMedia, new_volume);
281 }
282 }
283 if (mute_changed) {
284 for (VolumeObserver* observer : volume_observers_) {
285 observer->OnMuteChange(AudioContentType::kMedia, new_mute);
286 }
287 }
288 }
289
290 if (volume_changed) {
291 float dbfs = VolumeControl::VolumeToDbFS(new_volume);
292 stored_values_.SetDouble(ContentTypeToDbFSKey(AudioContentType::kMedia),
293 dbfs);
294 SerializeJsonToFile(storage_path_, stored_values_);
295 }
296 } 264 }
297 265
298 base::FilePath storage_path_; 266 base::FilePath storage_path_;
299 base::DictionaryValue stored_values_; 267 base::DictionaryValue stored_values_;
300 268
301 base::Lock volume_lock_; 269 base::Lock volume_lock_;
302 std::map<AudioContentType, float> volumes_; 270 std::map<AudioContentType, float> volumes_;
303 std::map<AudioContentType, bool> muted_; 271 std::map<AudioContentType, bool> muted_;
304 272
305 base::Lock observer_lock_; 273 base::Lock observer_lock_;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 360
393 return kVolumeMap[i - 1].level + 361 return kVolumeMap[i - 1].level +
394 (db - kVolumeMap[i - 1].db) * y_diff / x_diff; 362 (db - kVolumeMap[i - 1].db) * y_diff / x_diff;
395 } 363 }
396 } 364 }
397 return kVolumeMap[arraysize(kVolumeMap) - 1].level; 365 return kVolumeMap[arraysize(kVolumeMap) - 1].level;
398 } 366 }
399 367
400 } // namespace media 368 } // namespace media
401 } // namespace chromecast 369 } // namespace chromecast
OLDNEW
« no previous file with comments | « chromecast/media/cma/backend/alsa/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698