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

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: added a comment about the number of channel, and fix a compiling issue on mac 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) {
65 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_, kDefaultDevice1, 67 const char* device_names[] = { kDefaultDevice1, kDefaultDevice2 };
66 params_.channels, 68 for (size_t i = 0; i < arraysize(device_names); ++i) {
67 params_.sample_rate, 69 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_, device_names[i],
68 pcm_format, latency_us);
69 if (!device_handle_) {
70 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_, kDefaultDevice2,
71 params_.channels, 70 params_.channels,
72 params_.sample_rate, 71 params_.sample_rate,
73 pcm_format, latency_us); 72 pcm_format, latency_us);
73 if (device_handle_) {
74 device_name_ = device_names[i];
75 break;
76 }
74 } 77 }
75 } else { 78 } else {
76 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_, 79 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_,
77 device_name_.c_str(), 80 device_name_.c_str(),
78 params_.channels, 81 params_.channels,
79 params_.sample_rate, 82 params_.sample_rate,
80 pcm_format, latency_us); 83 pcm_format, latency_us);
81 } 84 }
82 85
83 if (device_handle_) 86 if (device_handle_) {
84 audio_packet_.reset(new uint8[bytes_per_packet_]); 87 audio_packet_.reset(new uint8[bytes_per_packet_]);
85 88
89 // Open the microphone mixer.
90 mixer_handle_ = alsa_util::OpenMixer(wrapper_, device_name_);
91 if (mixer_handle_) {
92 mixer_element_handle_ = alsa_util::LoadCaptureMixerElement(
93 wrapper_, mixer_handle_);
94 }
95 }
96
86 return device_handle_ != NULL; 97 return device_handle_ != NULL;
87 } 98 }
88 99
89 void AlsaPcmInputStream::Start(AudioInputCallback* callback) { 100 void AlsaPcmInputStream::Start(AudioInputCallback* callback) {
90 DCHECK(!callback_ && callback); 101 DCHECK(!callback_ && callback);
91 callback_ = callback; 102 callback_ = callback;
92 int error = wrapper_->PcmPrepare(device_handle_); 103 int error = wrapper_->PcmPrepare(device_handle_);
93 if (error < 0) { 104 if (error < 0) {
94 HandleError("PcmPrepare", error); 105 HandleError("PcmPrepare", error);
95 } else { 106 } else {
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read. 243 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read.
233 int error = wrapper_->PcmDrop(device_handle_); 244 int error = wrapper_->PcmDrop(device_handle_);
234 if (error < 0) 245 if (error < 0)
235 HandleError("PcmDrop", error); 246 HandleError("PcmDrop", error);
236 } 247 }
237 248
238 void AlsaPcmInputStream::Close() { 249 void AlsaPcmInputStream::Close() {
239 scoped_ptr<AlsaPcmInputStream> self_deleter(this); 250 scoped_ptr<AlsaPcmInputStream> self_deleter(this);
240 251
241 // Check in case we were already closed or not initialized yet. 252 // Check in case we were already closed or not initialized yet.
242 if (!device_handle_ || !callback_) 253 if (!device_handle_)
243 return; 254 return;
244 255
245 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read. 256 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read.
246 int error = alsa_util::CloseDevice(wrapper_, device_handle_); 257 int error = alsa_util::CloseDevice(wrapper_, device_handle_);
247 if (error < 0) 258 if (error < 0)
248 HandleError("PcmClose", error); 259 HandleError("PcmClose", error);
249 260
261 if (mixer_handle_)
262 alsa_util::CloseMixer(wrapper_, mixer_handle_, device_name_);
263
250 audio_packet_.reset(); 264 audio_packet_.reset();
251 device_handle_ = NULL; 265 device_handle_ = NULL;
252 callback_->OnClose(this); 266
267 if (callback_)
268 callback_->OnClose(this);
269 }
270
271 double AlsaPcmInputStream::GetMaxVolume() {
272 if (!mixer_handle_ || !mixer_element_handle_) {
273 DLOG(WARNING) << "GetMaxVolume is not supported for " << device_name_;
274 return 0.0;
275 }
276
277 if (!wrapper_->MixerSelemHasCaptureVolume(mixer_element_handle_)) {
278 DLOG(WARNING) << "Unsupported microphone volume for " << device_name_;
279 return 0.0;
280 }
281
282 long min = 0;
283 long max = 0;
284 if (wrapper_->MixerSelemGetCaptureVolumeRange(mixer_element_handle_,
285 &min,
286 &max)) {
287 DLOG(WARNING) << "Unsupported max microphone volume for " << device_name_;
288 return 0.0;
289 }
290 DCHECK(min == 0);
291 DCHECK(max > 0);
292
293 return static_cast<double>(max);
294 }
295
296 void AlsaPcmInputStream::SetVolume(double volume) {
297 if (!mixer_handle_ || !mixer_element_handle_) {
298 DLOG(WARNING) << "SetVolume is not supported for " << device_name_;
299 return;
300 }
301
302 int error = wrapper_->MixerSelemSetCaptureVolumeAll(
303 mixer_element_handle_, static_cast<long>(volume));
304 if (error < 0) {
305 DLOG(WARNING) << "Unable to set volume for " << device_name_;
306 }
307 }
308
309 double AlsaPcmInputStream::GetVolume() {
310 if (!mixer_handle_ || !mixer_element_handle_) {
311 DLOG(WARNING) << "GetVolume is not supported for " << device_name_;
312 return 0.0;
313 }
314
315 long current_volume = 0;
316 int error = wrapper_->MixerSelemGetCaptureVolume(
317 mixer_element_handle_, static_cast<snd_mixer_selem_channel_id_t>(0),
318 &current_volume);
319 if (error < 0) {
320 DLOG(WARNING) << "Unable to get volume for " << device_name_;
321 return 0.0;
322 }
323
324 return static_cast<double>(current_volume);
253 } 325 }
254 326
255 void AlsaPcmInputStream::HandleError(const char* method, int error) { 327 void AlsaPcmInputStream::HandleError(const char* method, int error) {
256 LOG(WARNING) << method << ": " << wrapper_->StrError(error); 328 LOG(WARNING) << method << ": " << wrapper_->StrError(error);
257 callback_->OnError(this, error); 329 callback_->OnError(this, error);
258 } 330 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698