hardware/libaudio
Revision | 3ac75230e3ea49f9c8bbae5f1f48a2442ad907cd (tree) |
---|---|
Zeit | 2016-08-15 22:23:39 |
Autor | Chih-Wei Huang <cwhuang@linu...> |
Commiter | Chih-Wei Huang |
audio_hw: cache HDMI audio interface
Now we cache the HDMI audio interface as well to avoid misusing them.
We are near to fully support HDMI audio. What missed is the events
to trigger the switching between primary speaker and HDMI.
@@ -179,20 +179,21 @@ static void release_buffer(struct resampler_buffer_provider *buffer_provider, | ||
179 | 179 | |
180 | 180 | struct snd_pcm_info *select_card(unsigned int device __unused, unsigned int flags) |
181 | 181 | { |
182 | - static struct snd_pcm_info *cached_info[2]; | |
182 | + static struct snd_pcm_info *cached_info[4]; | |
183 | + struct snd_pcm_info *info; | |
183 | 184 | int d = !!(flags & PCM_IN); |
184 | - if (!cached_info[d]) { | |
185 | + if (!cached_info[d] && !cached_info[d + 2]) { | |
185 | 186 | struct dirent **namelist; |
186 | 187 | char path[PATH_MAX] = "/dev/snd/"; |
187 | 188 | int n = scandir(path, &namelist, NULL, alphasort); |
188 | 189 | if (n >= 0) { |
189 | 190 | int i, fd; |
190 | - struct snd_pcm_info *info = malloc(sizeof(*info)); | |
191 | 191 | for (i = 0; i < n; i++) { |
192 | 192 | struct dirent *de = namelist[i]; |
193 | - if (!cached_info[d] && !strncmp(de->d_name, "pcmC", 4)) { | |
193 | + if (!strncmp(de->d_name, "pcmC", 4)) { | |
194 | 194 | strcpy(path + 9, de->d_name); |
195 | 195 | if ((fd = open(path, O_RDWR)) >= 0) { |
196 | + info = malloc(sizeof(*info)); | |
196 | 197 | if (!ioctl(fd, SNDRV_PCM_IOCTL_INFO, info)) { |
197 | 198 | if (info->stream == d && /* ignore IntelHDMI */ |
198 | 199 | !strstr((const char *)info->id, "IntelHDMI")) { |
@@ -200,10 +201,17 @@ struct snd_pcm_info *select_card(unsigned int device __unused, unsigned int flag | ||
200 | 201 | d ? "in" : "out", path, |
201 | 202 | info->card, info->device, info->id, |
202 | 203 | info->name, info->subname, info->stream); |
203 | - cached_info[d] = info; | |
204 | + int hdmi = (!!strstr((const char *)info->id, "HDMI")) * 2; | |
205 | + if (cached_info[d + hdmi]) { | |
206 | + ALOGD("ignore %s", de->d_name); | |
207 | + free(info); | |
208 | + } else { | |
209 | + cached_info[d + hdmi] = info; | |
210 | + } | |
204 | 211 | } |
205 | 212 | } else { |
206 | 213 | ALOGV("can't get info of %s", path); |
214 | + free(info); | |
207 | 215 | } |
208 | 216 | close(fd); |
209 | 217 | } |
@@ -211,12 +219,11 @@ struct snd_pcm_info *select_card(unsigned int device __unused, unsigned int flag | ||
211 | 219 | free(de); |
212 | 220 | } |
213 | 221 | free(namelist); |
214 | - if (!cached_info[d]) { | |
215 | - free(info); | |
216 | - } | |
217 | 222 | } |
218 | 223 | } |
219 | - return cached_info[d]; | |
224 | + info = cached_info[d] ? cached_info[d] : cached_info[d + 2]; | |
225 | + ALOGI_IF(info, "choose pcmC%dD%d%c", info->card, info->device, d ? 'c' : 'p'); | |
226 | + return info; | |
220 | 227 | } |
221 | 228 | |
222 | 229 | struct pcm *my_pcm_open(unsigned int device, unsigned int flags, struct pcm_config *config) |