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

Side by Side Diff: media/audio/linux/alsa_input.cc

Issue 9418042: Adding microphone volume support to chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: please review Created 8 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "media/audio/linux/alsa_input.h" 5 #include "media/audio/linux/alsa_input.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
(...skipping 19 matching lines...) Expand all
30 device_name_(device_name), 30 device_name_(device_name),
31 params_(params), 31 params_(params),
32 bytes_per_packet_(params.samples_per_packet * 32 bytes_per_packet_(params.samples_per_packet *
33 (params.channels * params.bits_per_sample) / 8), 33 (params.channels * params.bits_per_sample) / 8),
34 wrapper_(wrapper), 34 wrapper_(wrapper),
35 packet_duration_ms_( 35 packet_duration_ms_(
36 (params.samples_per_packet * base::Time::kMillisecondsPerSecond) / 36 (params.samples_per_packet * base::Time::kMillisecondsPerSecond) /
37 params.sample_rate), 37 params.sample_rate),
38 callback_(NULL), 38 callback_(NULL),
39 device_handle_(NULL), 39 device_handle_(NULL),
40 mixer_handle_(NULL),
41 mixer_element_handle_(NULL),
40 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 42 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
41 read_callback_behind_schedule_(false) { 43 read_callback_behind_schedule_(false) {
42 } 44 }
43 45
44 AlsaPcmInputStream::~AlsaPcmInputStream() {} 46 AlsaPcmInputStream::~AlsaPcmInputStream() {}
45 47
46 bool AlsaPcmInputStream::Open() { 48 bool AlsaPcmInputStream::Open() {
47 if (device_handle_) 49 if (device_handle_)
48 return false; // Already open. 50 return false; // Already open.
49 51
50 snd_pcm_format_t pcm_format = alsa_util::BitsToFormat( 52 snd_pcm_format_t pcm_format = alsa_util::BitsToFormat(
51 params_.bits_per_sample); 53 params_.bits_per_sample);
52 if (pcm_format == SND_PCM_FORMAT_UNKNOWN) { 54 if (pcm_format == SND_PCM_FORMAT_UNKNOWN) {
53 LOG(WARNING) << "Unsupported bits per sample: " 55 LOG(WARNING) << "Unsupported bits per sample: "
54 << params_.bits_per_sample; 56 << params_.bits_per_sample;
55 return false; 57 return false;
56 } 58 }
57 59
58 uint32 latency_us = packet_duration_ms_ * kNumPacketsInRingBuffer * 60 uint32 latency_us = packet_duration_ms_ * kNumPacketsInRingBuffer *
59 base::Time::kMicrosecondsPerMillisecond; 61 base::Time::kMicrosecondsPerMillisecond;
60 62
61 // Use the same minimum required latency as output. 63 // Use the same minimum required latency as output.
62 latency_us = std::max(latency_us, AlsaPcmOutputStream::kMinLatencyMicros); 64 latency_us = std::max(latency_us, AlsaPcmOutputStream::kMinLatencyMicros);
63 65
64 if (device_name_ == kAutoSelectDevice) { 66 if (device_name_ == kAutoSelectDevice) {
67 device_name_ = kDefaultDevice1;
65 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_, kDefaultDevice1, 68 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_, kDefaultDevice1,
66 params_.channels, 69 params_.channels,
67 params_.sample_rate, 70 params_.sample_rate,
68 pcm_format, latency_us); 71 pcm_format, latency_us);
tommi (sloooow) - chröme 2012/02/21 14:03:25 instead of assigning to device_name and copy paste
no longer working on chromium 2012/02/21 18:01:38 Done.
69 if (!device_handle_) { 72 if (!device_handle_) {
73 device_name_ = kDefaultDevice2;
70 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_, kDefaultDevice2, 74 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_, kDefaultDevice2,
71 params_.channels, 75 params_.channels,
72 params_.sample_rate, 76 params_.sample_rate,
73 pcm_format, latency_us); 77 pcm_format, latency_us);
74 } 78 }
75 } else { 79 } else {
76 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_, 80 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_,
77 device_name_.c_str(), 81 device_name_.c_str(),
78 params_.channels, 82 params_.channels,
79 params_.sample_rate, 83 params_.sample_rate,
80 pcm_format, latency_us); 84 pcm_format, latency_us);
81 } 85 }
82 86
83 if (device_handle_) 87 if (device_handle_) {
84 audio_packet_.reset(new uint8[bytes_per_packet_]); 88 audio_packet_.reset(new uint8[bytes_per_packet_]);
85 89
90 // Open the microphone mixer.
91 mixer_handle_ = alsa_util::OpenMixer(wrapper_, device_name_);
92 if (mixer_handle_) {
93 mixer_element_handle_ = alsa_util::LoadCaptureMixerElement(
94 wrapper_, mixer_handle_);
95 }
96 }
97
86 return device_handle_ != NULL; 98 return device_handle_ != NULL;
87 } 99 }
88 100
89 void AlsaPcmInputStream::Start(AudioInputCallback* callback) { 101 void AlsaPcmInputStream::Start(AudioInputCallback* callback) {
90 DCHECK(!callback_ && callback); 102 DCHECK(!callback_ && callback);
91 callback_ = callback; 103 callback_ = callback;
92 int error = wrapper_->PcmPrepare(device_handle_); 104 int error = wrapper_->PcmPrepare(device_handle_);
93 if (error < 0) { 105 if (error < 0) {
94 HandleError("PcmPrepare", error); 106 HandleError("PcmPrepare", error);
95 } else { 107 } else {
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read. 244 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read.
233 int error = wrapper_->PcmDrop(device_handle_); 245 int error = wrapper_->PcmDrop(device_handle_);
234 if (error < 0) 246 if (error < 0)
235 HandleError("PcmDrop", error); 247 HandleError("PcmDrop", error);
236 } 248 }
237 249
238 void AlsaPcmInputStream::Close() { 250 void AlsaPcmInputStream::Close() {
239 scoped_ptr<AlsaPcmInputStream> self_deleter(this); 251 scoped_ptr<AlsaPcmInputStream> self_deleter(this);
240 252
241 // Check in case we were already closed or not initialized yet. 253 // Check in case we were already closed or not initialized yet.
242 if (!device_handle_ || !callback_) 254 if (!device_handle_)
243 return; 255 return;
244 256
245 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read. 257 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read.
246 int error = alsa_util::CloseDevice(wrapper_, device_handle_); 258 int error = alsa_util::CloseDevice(wrapper_, device_handle_);
247 if (error < 0) 259 if (error < 0)
248 HandleError("PcmClose", error); 260 HandleError("PcmClose", error);
249 261
262 alsa_util::CloseMixer(wrapper_, mixer_handle_, device_name_);
250 audio_packet_.reset(); 263 audio_packet_.reset();
251 device_handle_ = NULL; 264 device_handle_ = NULL;
252 callback_->OnClose(this); 265
266 if (callback_)
267 callback_->OnClose(this);
268 }
269
270 void AlsaPcmInputStream::SetMicVolume(double volume) {
271 if (!mixer_handle_ || !mixer_element_handle_) {
272 DLOG(WARNING) << "SetMicVolume is not supported for " << device_name_;
273 return;
274 }
275
276 int error = wrapper_->MixerSelemSetCaptureVolumeAll(
277 mixer_element_handle_, static_cast<long>(volume));
278 if (error < 0) {
279 DLOG(WARNING) << "Unable to set volume for " << device_name_;
tommi (sloooow) - chröme 2012/02/21 14:03:25 do we never intend to support error notifications
no longer working on chromium 2012/02/21 18:01:38 My concern is that we may need to use IPC message
280 }
281 }
282
283 void AlsaPcmInputStream::GetMicVolume(double* volume) {
284 if (!mixer_handle_ || !mixer_element_handle_) {
285 DLOG(WARNING) << "GetMicVolume is not supported for " << device_name_;
286 return;
287 }
288
289 long current_volume = 0;
290 int error = wrapper_->MixerSelemGetCaptureVolume(
291 mixer_element_handle_, static_cast<snd_mixer_selem_channel_id_t>(0),
292 &current_volume);
293 if (error < 0) {
294 DLOG(WARNING) << "Unable to get volume for " << device_name_;
295 }
296 *volume = static_cast<double>(current_volume);
tommi (sloooow) - chröme 2012/02/21 14:03:25 this should be inside an else {}.
no longer working on chromium 2012/02/21 18:01:38 Done.
297 }
298
299 void AlsaPcmInputStream::GetMaxMicVolume(double* max_volume) {
300 if (!mixer_handle_ || !mixer_element_handle_) {
301 DLOG(WARNING) << "GetMaxVolume is not supported for " << device_name_;
302 return;
303 }
304
305 if (!wrapper_->MixerSelemHasCaptureVolume(mixer_element_handle_)) {
306 DLOG(WARNING) << "Unsupported microphone volume for " << device_name_;
307 return;
308 }
309
310 long min = 0;
311 long max = 0;
312 if (wrapper_->MixerSelemGetCaptureVolumeRange(
313 mixer_element_handle_, &min, &max)) {
tommi (sloooow) - chröme 2012/02/21 14:03:25 indentation feels off to me. Looks like this: Fo
no longer working on chromium 2012/02/21 18:01:38 Done.
314 DLOG(WARNING) << "Unsupported max microphone volume for " << device_name_;
315 return;
316 }
317 DCHECK(min == 0);
318 DCHECK(max > 0);
319
320 *max_volume = static_cast<double>(max);
253 } 321 }
254 322
255 void AlsaPcmInputStream::HandleError(const char* method, int error) { 323 void AlsaPcmInputStream::HandleError(const char* method, int error) {
256 LOG(WARNING) << method << ": " << wrapper_->StrError(error); 324 LOG(WARNING) << method << ": " << wrapper_->StrError(error);
257 callback_->OnError(this, error); 325 callback_->OnError(this, error);
258 } 326 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698