Index: media/audio/linux/alsa_util.cc |
diff --git a/media/audio/linux/alsa_util.cc b/media/audio/linux/alsa_util.cc |
index 55aa50e77641e1afd2fe2abdad515e9576998787..559787fcf6c7cff91fd79a47b707c7c1bbdcae5d 100644 |
--- a/media/audio/linux/alsa_util.cc |
+++ b/media/audio/linux/alsa_util.cc |
@@ -33,7 +33,7 @@ static snd_pcm_t* OpenDevice(AlsaWrapper* wrapper, |
LOG(WARNING) << "PcmSetParams: " << device_name << ", " |
<< wrapper->StrError(error) << " - Format: " << pcm_format |
<< " Channels: " << channels << " Latency: " << latency_us; |
- if (!alsa_util::CloseDevice(wrapper, handle)) { |
+ if (alsa_util::CloseDevice(wrapper, handle)) { |
tommi (sloooow) - chröme
2012/02/21 14:03:25
should this be
if (alsa_util::CloseDevice(...) < 0
no longer working on chromium
2012/02/21 18:01:38
Done.
|
// TODO(ajwong): Retry on certain errors? |
LOG(WARNING) << "Unable to close audio device. Leaking handle."; |
} |
@@ -43,6 +43,25 @@ static snd_pcm_t* OpenDevice(AlsaWrapper* wrapper, |
return handle; |
} |
+static std::string DeviceNameToControlName(const std::string& device_name) { |
+ const char kMixerPrefix[] = "hw"; |
+ std::string control_name; |
+ size_t pos1 = device_name.find(":"); |
+ if (pos1 == std::string::npos) { |
+ control_name = device_name; |
+ } else { |
+ // Examples: |
+ // deviceName: "front:CARD=Intel,DEV=0", controlName: "hw:CARD=Intel". |
+ // deviceName: "default:CARD=Intel", controlName: "CARD=Intel". |
+ size_t pos2 = device_name.find(","); |
tommi (sloooow) - chröme
2012/02/21 14:03:25
nit: when searching for a single character, use '
no longer working on chromium
2012/02/21 18:01:38
Good tips, thanks.
|
+ control_name = (pos2 == std::string::npos) ? |
+ device_name.substr(pos1) : |
+ kMixerPrefix + device_name.substr(pos1, pos2 - pos1); |
+ } |
+ |
+ return control_name; |
+} |
+ |
snd_pcm_format_t BitsToFormat(int bits_per_sample) { |
switch (bits_per_sample) { |
case 8: |
@@ -93,4 +112,84 @@ snd_pcm_t* OpenPlaybackDevice(AlsaWrapper* wrapper, |
sample_rate, pcm_format, latency_us); |
} |
+snd_mixer_t* OpenMixer(AlsaWrapper* wrapper, |
+ const std::string& device_name) { |
+ snd_mixer_t* mixer = NULL; |
+ |
+ int error = wrapper->MixerOpen(&mixer, 0); |
+ if (error < 0) { |
+ LOG(ERROR) << "MixerOpen: " << device_name << ", " |
+ << wrapper->StrError(error); |
+ return NULL; |
+ } |
+ |
+ std::string control_name = DeviceNameToControlName(device_name); |
+ error = wrapper->MixerAttach(mixer, control_name.c_str()); |
+ if (error < 0) { |
+ LOG(ERROR) << "MixerAttach, " << control_name << ", " |
+ << wrapper->StrError(error); |
+ alsa_util::CloseMixer(wrapper, mixer, device_name); |
+ return NULL; |
+ } |
+ |
+ error = wrapper->MixerElementRegister(mixer, NULL, NULL); |
+ if (error < 0) { |
+ LOG(ERROR) << "MixerElementRegister: " << control_name << ", " |
+ << wrapper->StrError(error); |
+ alsa_util::CloseMixer(wrapper, mixer, device_name); |
+ return NULL; |
+ } |
+ |
+ return mixer; |
+} |
+ |
+void CloseMixer(AlsaWrapper* wrapper, snd_mixer_t* mixer, |
+ const std::string& device_name) { |
+ wrapper->MixerFree(mixer); |
+ |
+ int error = 0; |
+ if (device_name.empty()) { |
+ std::string control_name = DeviceNameToControlName(device_name); |
+ error = wrapper->MixerDetach(mixer, control_name.c_str()); |
+ if (error < 0) { |
+ LOG(WARNING) << "MixerDetach: " << control_name << ", " |
+ << wrapper->StrError(error); |
+ } |
+ } |
+ |
+ error = wrapper->MixerClose(mixer); |
+ if (error < 0) { |
+ LOG(WARNING) << "MixerClose: " << device_name << ", " |
tommi (sloooow) - chröme
2012/02/21 14:03:25
There's a lot of release logging code in this file
no longer working on chromium
2012/02/21 18:01:38
We can discuss it more. These ALSA functions are o
|
+ << wrapper->StrError(error); |
+ } |
+} |
+ |
+snd_mixer_elem_t* LoadCaptureMixerElement(AlsaWrapper* wrapper, |
+ snd_mixer_t* mixer) { |
+ int error = wrapper->MixerLoad(mixer); |
+ if (error < 0) { |
+ LOG(ERROR) << "MixerLoad: " << wrapper->StrError(error); |
+ return NULL; |
+ } |
+ |
+ snd_mixer_elem_t* elem = NULL; |
+ snd_mixer_elem_t* micElem = NULL; |
tommi (sloooow) - chröme
2012/02/21 14:03:25
mic_elem
no longer working on chromium
2012/02/21 18:01:38
Done.
|
+ const char kCaptureElemName[] = "Capture"; |
+ const char kMicElemName[] = "Mic"; |
+ for (elem = wrapper->MixerFirstElem(mixer); |
+ elem; |
+ elem = wrapper->MixerNextElem(elem)) { |
+ if (wrapper->MixerSelemIsActive(elem)) { |
+ const char *selemName = wrapper->MixerSelemName(elem); |
tommi (sloooow) - chröme
2012/02/21 14:03:25
const char* selemName
actually... it should be se
no longer working on chromium
2012/02/21 18:01:38
Thanks, I used elem_name then. It stands for "simp
|
+ if (strcmp(selemName, kCaptureElemName) == 0) |
+ return elem; |
+ else if (strcmp(selemName, kMicElemName) == 0) |
+ micElem = elem; |
+ } |
+ } |
+ |
+ // Did not find any Capture handle, use the Mic handle. |
+ return micElem; |
+} |
+ |
} // namespace alsa_util |