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

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: [chromcast] Still need to call StreamMixerAlsa::SetVolume, even when ALSA doesn't own the volume. 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 } 126 }
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,
137 base::Unretained(this), type, level)); 137 base::Bind(&VolumeControlInternal::SetVolumeOnThread,
138 base::Unretained(this), type, level, false /* from_alsa */));
138 } 139 }
139 140
140 bool IsMuted(AudioContentType type) { 141 bool IsMuted(AudioContentType type) {
141 base::AutoLock lock(volume_lock_); 142 base::AutoLock lock(volume_lock_);
142 return muted_[type]; 143 return muted_[type];
143 } 144 }
144 145
145 void SetMuted(AudioContentType type, bool muted) { 146 void SetMuted(AudioContentType type, bool muted) {
146 thread_.task_runner()->PostTask( 147 thread_.task_runner()->PostTask(
147 FROM_HERE, base::Bind(&VolumeControlInternal::SetMutedOnThread, 148 FROM_HERE,
148 base::Unretained(this), type, muted)); 149 base::Bind(&VolumeControlInternal::SetMutedOnThread,
150 base::Unretained(this), type, muted, false /* from_alsa */));
149 } 151 }
150 152
151 void SetOutputLimit(AudioContentType type, float limit) { 153 void SetOutputLimit(AudioContentType type, float limit) {
152 if (BUILDFLAG(ALSA_CONTROLS_VOLUME)) { 154 if (BUILDFLAG(ALSA_OWNS_VOLUME)) {
153 return; 155 return;
154 } 156 }
155 limit = std::max(0.0f, std::min(limit, 1.0f)); 157 limit = std::max(0.0f, std::min(limit, 1.0f));
156 StreamMixerAlsa::Get()->SetOutputLimit( 158 StreamMixerAlsa::Get()->SetOutputLimit(
157 type, DbFsToScale(VolumeControl::VolumeToDbFS(limit))); 159 type, DbFsToScale(VolumeControl::VolumeToDbFS(limit)));
158 } 160 }
159 161
160 private: 162 private:
161 void InitializeOnThread() { 163 void InitializeOnThread() {
162 DCHECK(thread_.task_runner()->BelongsToCurrentThread()); 164 DCHECK(thread_.task_runner()->BelongsToCurrentThread());
163 alsa_volume_control_ = base::MakeUnique<AlsaVolumeControl>(this); 165 alsa_volume_control_ = base::MakeUnique<AlsaVolumeControl>(this);
164 166
165 double dbfs; 167 double dbfs;
166 for (auto type : {AudioContentType::kMedia, AudioContentType::kAlarm, 168 for (auto type : {AudioContentType::kMedia, AudioContentType::kAlarm,
167 AudioContentType::kCommunication}) { 169 AudioContentType::kCommunication}) {
168 CHECK(stored_values_.GetDouble(ContentTypeToDbFSKey(type), &dbfs)); 170 CHECK(stored_values_.GetDouble(ContentTypeToDbFSKey(type), &dbfs));
169 volumes_[type] = VolumeControl::DbFSToVolume(dbfs); 171 volumes_[type] = VolumeControl::DbFSToVolume(dbfs);
170 if (BUILDFLAG(ALSA_CONTROLS_VOLUME)) { 172 if (BUILDFLAG(ALSA_OWNS_VOLUME)) {
171 // If ALSA controls volume, our internal mixer should not apply any 173 // If ALSA owns volume, our internal mixer should not apply any scaling
172 // scaling multiplier. 174 // multiplier.
173 StreamMixerAlsa::Get()->SetVolume(type, 1.0f); 175 StreamMixerAlsa::Get()->SetVolume(type, 1.0f);
174 } else { 176 } else {
175 StreamMixerAlsa::Get()->SetVolume(type, DbFsToScale(dbfs)); 177 StreamMixerAlsa::Get()->SetVolume(type, DbFsToScale(dbfs));
176 } 178 }
177 179
178 // Note that mute state is not persisted across reboots. 180 // Note that mute state is not persisted across reboots.
179 muted_[type] = false; 181 muted_[type] = false;
180 } 182 }
181 183
182 if (BUILDFLAG(ALSA_CONTROLS_VOLUME)) { 184 if (BUILDFLAG(ALSA_OWNS_VOLUME)) {
183 // If ALSA controls the volume, then read the current volume and mute 185 // If ALSA owns the volume, then read the current volume and mute state
184 // state from the ALSA mixer element(s). 186 // from the ALSA mixer element(s).
185 volumes_[AudioContentType::kMedia] = alsa_volume_control_->GetVolume(); 187 volumes_[AudioContentType::kMedia] = alsa_volume_control_->GetVolume();
186 muted_[AudioContentType::kMedia] = alsa_volume_control_->IsMuted(); 188 muted_[AudioContentType::kMedia] = alsa_volume_control_->IsMuted();
187 } else { 189 } else {
188 // Otherwise, make sure the ALSA mixer element correctly reflects the 190 // Otherwise, make sure the ALSA mixer element correctly reflects the
189 // current volume state. 191 // current volume state.
190 alsa_volume_control_->SetVolume(volumes_[AudioContentType::kMedia]); 192 alsa_volume_control_->SetVolume(volumes_[AudioContentType::kMedia]);
191 alsa_volume_control_->SetMuted(false); 193 alsa_volume_control_->SetMuted(false);
192 } 194 }
193 195
194 initialize_complete_event_.Signal(); 196 initialize_complete_event_.Signal();
195 } 197 }
196 198
197 void SetVolumeOnThread(AudioContentType type, float level) { 199 void SetVolumeOnThread(AudioContentType type, float level, bool from_alsa) {
198 DCHECK(thread_.task_runner()->BelongsToCurrentThread()); 200 DCHECK(thread_.task_runner()->BelongsToCurrentThread());
201 DCHECK(!from_alsa || type == AudioContentType::kMedia);
199 { 202 {
200 base::AutoLock lock(volume_lock_); 203 base::AutoLock lock(volume_lock_);
204 if (from_alsa && alsa_volume_control_->VolumeThroughAlsa(
205 volumes_[AudioContentType::kMedia]) == level) {
206 return;
207 }
201 if (level == volumes_[type]) { 208 if (level == volumes_[type]) {
202 return; 209 return;
203 } 210 }
204 volumes_[type] = level; 211 volumes_[type] = level;
205 } 212 }
206 213
207 float dbfs = VolumeControl::VolumeToDbFS(level); 214 float dbfs = VolumeControl::VolumeToDbFS(level);
208 if (!BUILDFLAG(ALSA_CONTROLS_VOLUME)) { 215 if (!BUILDFLAG(ALSA_OWNS_VOLUME)) {
209 StreamMixerAlsa::Get()->SetVolume(type, DbFsToScale(dbfs)); 216 StreamMixerAlsa::Get()->SetVolume(type, DbFsToScale(dbfs));
210 } 217 }
211 218
212 if (type == AudioContentType::kMedia) { 219 if (!from_alsa && type == AudioContentType::kMedia) {
213 alsa_volume_control_->SetVolume(level); 220 alsa_volume_control_->SetVolume(level);
214 } 221 }
215 222
216 { 223 {
217 base::AutoLock lock(observer_lock_); 224 base::AutoLock lock(observer_lock_);
218 for (VolumeObserver* observer : volume_observers_) { 225 for (VolumeObserver* observer : volume_observers_) {
219 observer->OnVolumeChange(type, level); 226 observer->OnVolumeChange(type, level);
220 } 227 }
221 } 228 }
222 229
223 stored_values_.SetDouble(ContentTypeToDbFSKey(type), dbfs); 230 stored_values_.SetDouble(ContentTypeToDbFSKey(type), dbfs);
224 SerializeJsonToFile(storage_path_, stored_values_); 231 SerializeJsonToFile(storage_path_, stored_values_);
225 } 232 }
226 233
227 void SetMutedOnThread(AudioContentType type, bool muted) { 234 void SetMutedOnThread(AudioContentType type, bool muted, bool from_alsa) {
228 DCHECK(thread_.task_runner()->BelongsToCurrentThread()); 235 DCHECK(thread_.task_runner()->BelongsToCurrentThread());
229 { 236 {
230 base::AutoLock lock(volume_lock_); 237 base::AutoLock lock(volume_lock_);
231 if (muted == muted_[type]) { 238 if (muted == muted_[type]) {
232 return; 239 return;
233 } 240 }
234 muted_[type] = muted; 241 muted_[type] = muted;
235 } 242 }
236 243
237 if (!BUILDFLAG(ALSA_CONTROLS_VOLUME)) { 244 if (!BUILDFLAG(ALSA_OWNS_VOLUME)) {
238 StreamMixerAlsa::Get()->SetMuted(type, muted); 245 StreamMixerAlsa::Get()->SetMuted(type, muted);
239 } 246 }
240 247
241 if (type == AudioContentType::kMedia) { 248 if (!from_alsa && type == AudioContentType::kMedia) {
242 alsa_volume_control_->SetMuted(muted); 249 alsa_volume_control_->SetMuted(muted);
243 } 250 }
244 251
245 { 252 {
246 base::AutoLock lock(observer_lock_); 253 base::AutoLock lock(observer_lock_);
247 for (VolumeObserver* observer : volume_observers_) { 254 for (VolumeObserver* observer : volume_observers_) {
248 observer->OnMuteChange(type, muted); 255 observer->OnMuteChange(type, muted);
249 } 256 }
250 } 257 }
251 } 258 }
252 259
253 // AlsaVolumeControl::Delegate implementation: 260 // AlsaVolumeControl::Delegate implementation:
254 void OnAlsaVolumeOrMuteChange(float new_volume, bool new_mute) override { 261 void OnAlsaVolumeOrMuteChange(float new_volume, bool new_mute) override {
255 DCHECK(thread_.task_runner()->BelongsToCurrentThread()); 262 DCHECK(thread_.task_runner()->BelongsToCurrentThread());
256 bool volume_changed = false; 263 SetVolumeOnThread(AudioContentType::kMedia, new_volume,
257 bool mute_changed = false; 264 true /* from_alsa */);
258 { 265 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 } 266 }
297 267
298 base::FilePath storage_path_; 268 base::FilePath storage_path_;
299 base::DictionaryValue stored_values_; 269 base::DictionaryValue stored_values_;
300 270
301 base::Lock volume_lock_; 271 base::Lock volume_lock_;
302 std::map<AudioContentType, float> volumes_; 272 std::map<AudioContentType, float> volumes_;
303 std::map<AudioContentType, bool> muted_; 273 std::map<AudioContentType, bool> muted_;
304 274
305 base::Lock observer_lock_; 275 base::Lock observer_lock_;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 362
393 return kVolumeMap[i - 1].level + 363 return kVolumeMap[i - 1].level +
394 (db - kVolumeMap[i - 1].db) * y_diff / x_diff; 364 (db - kVolumeMap[i - 1].db) * y_diff / x_diff;
395 } 365 }
396 } 366 }
397 return kVolumeMap[arraysize(kVolumeMap) - 1].level; 367 return kVolumeMap[arraysize(kVolumeMap) - 1].level;
398 } 368 }
399 369
400 } // namespace media 370 } // namespace media
401 } // namespace chromecast 371 } // 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