Chromium Code Reviews| 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 |