OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_util.h" | 5 #include "media/audio/linux/alsa_util.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "media/audio/linux/alsa_wrapper.h" | 10 #include "media/audio/linux/alsa_wrapper.h" |
(...skipping 15 matching lines...) Expand all Loading... | |
26 return NULL; | 26 return NULL; |
27 } | 27 } |
28 | 28 |
29 error = wrapper->PcmSetParams(handle, pcm_format, | 29 error = wrapper->PcmSetParams(handle, pcm_format, |
30 SND_PCM_ACCESS_RW_INTERLEAVED, channels, | 30 SND_PCM_ACCESS_RW_INTERLEAVED, channels, |
31 sample_rate, 1, latency_us); | 31 sample_rate, 1, latency_us); |
32 if (error < 0) { | 32 if (error < 0) { |
33 LOG(WARNING) << "PcmSetParams: " << device_name << ", " | 33 LOG(WARNING) << "PcmSetParams: " << device_name << ", " |
34 << wrapper->StrError(error) << " - Format: " << pcm_format | 34 << wrapper->StrError(error) << " - Format: " << pcm_format |
35 << " Channels: " << channels << " Latency: " << latency_us; | 35 << " Channels: " << channels << " Latency: " << latency_us; |
36 if (!alsa_util::CloseDevice(wrapper, handle)) { | 36 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.
| |
37 // TODO(ajwong): Retry on certain errors? | 37 // TODO(ajwong): Retry on certain errors? |
38 LOG(WARNING) << "Unable to close audio device. Leaking handle."; | 38 LOG(WARNING) << "Unable to close audio device. Leaking handle."; |
39 } | 39 } |
40 return NULL; | 40 return NULL; |
41 } | 41 } |
42 | 42 |
43 return handle; | 43 return handle; |
44 } | 44 } |
45 | 45 |
46 static std::string DeviceNameToControlName(const std::string& device_name) { | |
47 const char kMixerPrefix[] = "hw"; | |
48 std::string control_name; | |
49 size_t pos1 = device_name.find(":"); | |
50 if (pos1 == std::string::npos) { | |
51 control_name = device_name; | |
52 } else { | |
53 // Examples: | |
54 // deviceName: "front:CARD=Intel,DEV=0", controlName: "hw:CARD=Intel". | |
55 // deviceName: "default:CARD=Intel", controlName: "CARD=Intel". | |
56 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.
| |
57 control_name = (pos2 == std::string::npos) ? | |
58 device_name.substr(pos1) : | |
59 kMixerPrefix + device_name.substr(pos1, pos2 - pos1); | |
60 } | |
61 | |
62 return control_name; | |
63 } | |
64 | |
46 snd_pcm_format_t BitsToFormat(int bits_per_sample) { | 65 snd_pcm_format_t BitsToFormat(int bits_per_sample) { |
47 switch (bits_per_sample) { | 66 switch (bits_per_sample) { |
48 case 8: | 67 case 8: |
49 return SND_PCM_FORMAT_U8; | 68 return SND_PCM_FORMAT_U8; |
50 | 69 |
51 case 16: | 70 case 16: |
52 return SND_PCM_FORMAT_S16; | 71 return SND_PCM_FORMAT_S16; |
53 | 72 |
54 case 24: | 73 case 24: |
55 return SND_PCM_FORMAT_S24; | 74 return SND_PCM_FORMAT_S24; |
(...skipping 30 matching lines...) Expand all Loading... | |
86 snd_pcm_t* OpenPlaybackDevice(AlsaWrapper* wrapper, | 105 snd_pcm_t* OpenPlaybackDevice(AlsaWrapper* wrapper, |
87 const char* device_name, | 106 const char* device_name, |
88 int channels, | 107 int channels, |
89 int sample_rate, | 108 int sample_rate, |
90 snd_pcm_format_t pcm_format, | 109 snd_pcm_format_t pcm_format, |
91 int latency_us) { | 110 int latency_us) { |
92 return OpenDevice(wrapper, device_name, SND_PCM_STREAM_PLAYBACK, channels, | 111 return OpenDevice(wrapper, device_name, SND_PCM_STREAM_PLAYBACK, channels, |
93 sample_rate, pcm_format, latency_us); | 112 sample_rate, pcm_format, latency_us); |
94 } | 113 } |
95 | 114 |
115 snd_mixer_t* OpenMixer(AlsaWrapper* wrapper, | |
116 const std::string& device_name) { | |
117 snd_mixer_t* mixer = NULL; | |
118 | |
119 int error = wrapper->MixerOpen(&mixer, 0); | |
120 if (error < 0) { | |
121 LOG(ERROR) << "MixerOpen: " << device_name << ", " | |
122 << wrapper->StrError(error); | |
123 return NULL; | |
124 } | |
125 | |
126 std::string control_name = DeviceNameToControlName(device_name); | |
127 error = wrapper->MixerAttach(mixer, control_name.c_str()); | |
128 if (error < 0) { | |
129 LOG(ERROR) << "MixerAttach, " << control_name << ", " | |
130 << wrapper->StrError(error); | |
131 alsa_util::CloseMixer(wrapper, mixer, device_name); | |
132 return NULL; | |
133 } | |
134 | |
135 error = wrapper->MixerElementRegister(mixer, NULL, NULL); | |
136 if (error < 0) { | |
137 LOG(ERROR) << "MixerElementRegister: " << control_name << ", " | |
138 << wrapper->StrError(error); | |
139 alsa_util::CloseMixer(wrapper, mixer, device_name); | |
140 return NULL; | |
141 } | |
142 | |
143 return mixer; | |
144 } | |
145 | |
146 void CloseMixer(AlsaWrapper* wrapper, snd_mixer_t* mixer, | |
147 const std::string& device_name) { | |
148 wrapper->MixerFree(mixer); | |
149 | |
150 int error = 0; | |
151 if (device_name.empty()) { | |
152 std::string control_name = DeviceNameToControlName(device_name); | |
153 error = wrapper->MixerDetach(mixer, control_name.c_str()); | |
154 if (error < 0) { | |
155 LOG(WARNING) << "MixerDetach: " << control_name << ", " | |
156 << wrapper->StrError(error); | |
157 } | |
158 } | |
159 | |
160 error = wrapper->MixerClose(mixer); | |
161 if (error < 0) { | |
162 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
| |
163 << wrapper->StrError(error); | |
164 } | |
165 } | |
166 | |
167 snd_mixer_elem_t* LoadCaptureMixerElement(AlsaWrapper* wrapper, | |
168 snd_mixer_t* mixer) { | |
169 int error = wrapper->MixerLoad(mixer); | |
170 if (error < 0) { | |
171 LOG(ERROR) << "MixerLoad: " << wrapper->StrError(error); | |
172 return NULL; | |
173 } | |
174 | |
175 snd_mixer_elem_t* elem = NULL; | |
176 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.
| |
177 const char kCaptureElemName[] = "Capture"; | |
178 const char kMicElemName[] = "Mic"; | |
179 for (elem = wrapper->MixerFirstElem(mixer); | |
180 elem; | |
181 elem = wrapper->MixerNextElem(elem)) { | |
182 if (wrapper->MixerSelemIsActive(elem)) { | |
183 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
| |
184 if (strcmp(selemName, kCaptureElemName) == 0) | |
185 return elem; | |
186 else if (strcmp(selemName, kMicElemName) == 0) | |
187 micElem = elem; | |
188 } | |
189 } | |
190 | |
191 // Did not find any Capture handle, use the Mic handle. | |
192 return micElem; | |
193 } | |
194 | |
96 } // namespace alsa_util | 195 } // namespace alsa_util |
OLD | NEW |