1/*** 2 This file is part of PulseAudio. 3 4 Copyright 2004-2009 Lennart Poettering 5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB 6 7 PulseAudio is free software; you can redistribute it and/or modify 8 it under the terms of the GNU Lesser General Public License as published 9 by the Free Software Foundation; either version 2.1 of the License, 10 or (at your option) any later version. 11 12 PulseAudio is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU Lesser General Public License 18 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 19***/ 20 21#ifdef HAVE_CONFIG_H 22#include <config.h> 23#endif 24 25#include <sys/types.h> 26#include <alsa/asoundlib.h> 27 28#include <pulse/sample.h> 29#include <pulse/xmalloc.h> 30#include <pulse/timeval.h> 31#include <pulse/util.h> 32#include <pulse/utf8.h> 33 34#include <pulsecore/i18n.h> 35#include <pulsecore/log.h> 36#include <pulsecore/macro.h> 37#include <pulsecore/core-util.h> 38#include <pulsecore/atomic.h> 39#include <pulsecore/core-error.h> 40#include <pulsecore/thread.h> 41#include <pulsecore/conf-parser.h> 42#include <pulsecore/core-rtclock.h> 43 44#include "alsa-util.h" 45#include "alsa-mixer.h" 46 47#ifdef HAVE_UDEV 48#include <modules/udev-util.h> 49#endif 50 51static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) { 52 53 static const snd_pcm_format_t format_trans[] = { 54 [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8, 55 [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW, 56 [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW, 57 [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE, 58 [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE, 59 [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE, 60 [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE, 61 [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE, 62 [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE, 63 [PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE, 64 [PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE, 65 [PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE, 66 [PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE, 67 }; 68 69 static const pa_sample_format_t try_order[] = { 70 PA_SAMPLE_FLOAT32NE, 71 PA_SAMPLE_FLOAT32RE, 72 PA_SAMPLE_S32NE, 73 PA_SAMPLE_S32RE, 74 PA_SAMPLE_S24_32NE, 75 PA_SAMPLE_S24_32RE, 76 PA_SAMPLE_S24NE, 77 PA_SAMPLE_S24RE, 78 PA_SAMPLE_S16NE, 79 PA_SAMPLE_S16RE, 80 PA_SAMPLE_ALAW, 81 PA_SAMPLE_ULAW, 82 PA_SAMPLE_U8 83 }; 84 85 unsigned i; 86 int ret; 87 88 pa_assert(pcm_handle); 89 pa_assert(hwparams); 90 pa_assert(f); 91 92 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0) 93 return ret; 94 95 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s", 96 snd_pcm_format_description(format_trans[*f]), 97 pa_alsa_strerror(ret)); 98 99 if (*f == PA_SAMPLE_FLOAT32BE) 100 *f = PA_SAMPLE_FLOAT32LE; 101 else if (*f == PA_SAMPLE_FLOAT32LE) 102 *f = PA_SAMPLE_FLOAT32BE; 103 else if (*f == PA_SAMPLE_S24BE) 104 *f = PA_SAMPLE_S24LE; 105 else if (*f == PA_SAMPLE_S24LE) 106 *f = PA_SAMPLE_S24BE; 107 else if (*f == PA_SAMPLE_S24_32BE) 108 *f = PA_SAMPLE_S24_32LE; 109 else if (*f == PA_SAMPLE_S24_32LE) 110 *f = PA_SAMPLE_S24_32BE; 111 else if (*f == PA_SAMPLE_S16BE) 112 *f = PA_SAMPLE_S16LE; 113 else if (*f == PA_SAMPLE_S16LE) 114 *f = PA_SAMPLE_S16BE; 115 else if (*f == PA_SAMPLE_S32BE) 116 *f = PA_SAMPLE_S32LE; 117 else if (*f == PA_SAMPLE_S32LE) 118 *f = PA_SAMPLE_S32BE; 119 else 120 goto try_auto; 121 122 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0) 123 return ret; 124 125 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s", 126 snd_pcm_format_description(format_trans[*f]), 127 pa_alsa_strerror(ret)); 128 129try_auto: 130 131 for (i = 0; i < PA_ELEMENTSOF(try_order); i++) { 132 *f = try_order[i]; 133 134 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0) 135 return ret; 136 137 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s", 138 snd_pcm_format_description(format_trans[*f]), 139 pa_alsa_strerror(ret)); 140 } 141 142 return -1; 143} 144 145static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) { 146 snd_pcm_uframes_t s; 147 int d, ret; 148 149 pa_assert(pcm_handle); 150 pa_assert(hwparams); 151 152 s = size; 153 d = 0; 154 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) { 155 s = size; 156 d = -1; 157 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) { 158 s = size; 159 d = 1; 160 if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) { 161 pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret)); 162 return ret; 163 } 164 } 165 } 166 167 return 0; 168} 169 170static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) { 171 int ret; 172 173 pa_assert(pcm_handle); 174 pa_assert(hwparams); 175 176 if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) { 177 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret)); 178 return ret; 179 } 180 181 return 0; 182} 183 184static void check_access(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, bool use_mmap) { 185 if ((use_mmap && !snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED)) || 186 !snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) 187 pa_log_error("Weird, PCM claims to support interleaved access, but snd_pcm_hw_params_set_access() failed."); 188 189 if ((use_mmap && !snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) || 190 !snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_NONINTERLEAVED)) 191 pa_log_debug("PCM seems to support non-interleaved access, but PA doesn't."); 192 else if (use_mmap && !snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_COMPLEX)) { 193 pa_log_debug("PCM seems to support mmapped complex access, but PA doesn't."); 194 } 195} 196 197/* Set the hardware parameters of the given ALSA device. Returns the 198 * selected fragment settings in *buffer_size and *period_size. Determine 199 * whether mmap and tsched mode can be enabled. */ 200int pa_alsa_set_hw_params( 201 snd_pcm_t *pcm_handle, 202 pa_sample_spec *ss, 203 snd_pcm_uframes_t *period_size, 204 snd_pcm_uframes_t *buffer_size, 205 snd_pcm_uframes_t tsched_size, 206 bool *use_mmap, 207 bool *use_tsched, 208 bool require_exact_channel_number) { 209 210 int ret = -1; 211 snd_pcm_hw_params_t *hwparams, *hwparams_copy; 212 int dir; 213 snd_pcm_uframes_t _period_size = period_size ? *period_size : 0; 214 snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0; 215 bool _use_mmap = use_mmap && *use_mmap; 216 bool _use_tsched = use_tsched && *use_tsched; 217 pa_sample_spec _ss = *ss; 218 219 pa_assert(pcm_handle); 220 pa_assert(ss); 221 222 snd_pcm_hw_params_alloca(&hwparams); 223 snd_pcm_hw_params_alloca(&hwparams_copy); 224 225 if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) { 226 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret)); 227 goto finish; 228 } 229 230 if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) { 231 pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret)); 232 goto finish; 233 } 234 235 if (_use_mmap) { 236 237 if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) { 238 239 /* mmap() didn't work, fall back to interleaved */ 240 241 if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { 242 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret)); 243 check_access(pcm_handle, hwparams, true); 244 goto finish; 245 } 246 247 _use_mmap = false; 248 } 249 250 } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { 251 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret)); 252 check_access(pcm_handle, hwparams, false); 253 goto finish; 254 } 255 256 if (!_use_mmap) 257 _use_tsched = false; 258 259 if (!pa_alsa_pcm_is_hw(pcm_handle)) 260 _use_tsched = false; 261 262 /* The PCM pointer is only updated with period granularity */ 263 if (snd_pcm_hw_params_is_batch(hwparams)) { 264 bool is_usb = false; 265 const char *id; 266 snd_pcm_info_t* pcm_info; 267 snd_pcm_info_alloca(&pcm_info); 268 269 if (snd_pcm_info(pcm_handle, pcm_info) == 0 && 270 (id = snd_pcm_info_get_id(pcm_info))) { 271 /* This horrible hack makes sure we don't disable tsched on USB 272 * devices, which have a low enough transfer size for timer-based 273 * scheduling to work. This can go away when the ALSA API supprots 274 * querying the block transfer size. */ 275 if (pa_streq(id, "USB Audio")) 276 is_usb = true; 277 } 278 279 if (!is_usb) { 280 pa_log_info("Disabling tsched mode since BATCH flag is set"); 281 _use_tsched = false; 282 } 283 } 284 285#if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */ 286 if (_use_tsched) { 287 288 /* try to disable period wakeups if hardware can do so */ 289 if (snd_pcm_hw_params_can_disable_period_wakeup(hwparams)) { 290 291 if ((ret = snd_pcm_hw_params_set_period_wakeup(pcm_handle, hwparams, false)) < 0) 292 /* don't bail, keep going with default mode with period wakeups */ 293 pa_log_debug("snd_pcm_hw_params_set_period_wakeup() failed: %s", pa_alsa_strerror(ret)); 294 else 295 pa_log_info("Trying to disable ALSA period wakeups, using timers only"); 296 } else 297 pa_log_info("Cannot disable ALSA period wakeups"); 298 } 299#endif 300 301 if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0) 302 goto finish; 303 304 if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) { 305 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret)); 306 goto finish; 307 } 308 309 /* We ignore very small sampling rate deviations */ 310 if (_ss.rate >= ss->rate*.95 && _ss.rate <= ss->rate*1.05) 311 _ss.rate = ss->rate; 312 313 if (require_exact_channel_number) { 314 if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) { 315 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret)); 316 goto finish; 317 } 318 } else { 319 unsigned int c = _ss.channels; 320 321 if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) { 322 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret)); 323 goto finish; 324 } 325 326 _ss.channels = c; 327 } 328 329 if (_use_tsched && tsched_size > 0) { 330 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate); 331 _period_size = _buffer_size; 332 } else { 333 _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate); 334 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate); 335 } 336 337 if (_buffer_size > 0 || _period_size > 0) { 338 snd_pcm_uframes_t max_frames = 0; 339 340 if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0) 341 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret)); 342 else 343 pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate)); 344 345 /* Some ALSA drivers really don't like if we set the buffer 346 * size first and the number of periods second (which would 347 * make a lot more sense to me). So, try a few combinations 348 * before we give up. */ 349 350 if (_buffer_size > 0 && _period_size > 0) { 351 snd_pcm_hw_params_copy(hwparams_copy, hwparams); 352 353 /* First try: set buffer size first, followed by period size */ 354 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 && 355 set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 && 356 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) { 357 pa_log_debug("Set buffer size first (to %lu samples), period size second (to %lu samples).", (unsigned long) _buffer_size, (unsigned long) _period_size); 358 goto success; 359 } 360 361 snd_pcm_hw_params_copy(hwparams_copy, hwparams); 362 /* Second try: set period size first, followed by buffer size */ 363 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 && 364 set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 && 365 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) { 366 pa_log_debug("Set period size first (to %lu samples), buffer size second (to %lu samples).", (unsigned long) _period_size, (unsigned long) _buffer_size); 367 goto success; 368 } 369 } 370 371 if (_buffer_size > 0) { 372 snd_pcm_hw_params_copy(hwparams_copy, hwparams); 373 374 /* Third try: set only buffer size */ 375 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 && 376 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) { 377 pa_log_debug("Set only buffer size (to %lu samples).", (unsigned long) _buffer_size); 378 goto success; 379 } 380 } 381 382 if (_period_size > 0) { 383 snd_pcm_hw_params_copy(hwparams_copy, hwparams); 384 385 /* Fourth try: set only period size */ 386 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 && 387 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) { 388 pa_log_debug("Set only period size (to %lu samples).", (unsigned long) _period_size); 389 goto success; 390 } 391 } 392 } 393 394 pa_log_debug("Set neither period nor buffer size."); 395 396 /* Last chance, set nothing */ 397 if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) { 398 pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret)); 399 goto finish; 400 } 401 402success: 403 404 if (ss->rate != _ss.rate) 405 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate); 406 407 if (ss->channels != _ss.channels) 408 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels); 409 410 if (ss->format != _ss.format) 411 pa_log_info("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(_ss.format)); 412 413 if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) { 414 pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret)); 415 goto finish; 416 } 417 418 if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 || 419 (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) { 420 pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret)); 421 goto finish; 422 } 423 424#if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */ 425 if (_use_tsched) { 426 unsigned int no_wakeup; 427 /* see if period wakeups were disabled */ 428 snd_pcm_hw_params_get_period_wakeup(pcm_handle, hwparams, &no_wakeup); 429 if (no_wakeup == 0) 430 pa_log_info("ALSA period wakeups disabled"); 431 else 432 pa_log_info("ALSA period wakeups were not disabled"); 433 } 434#endif 435 436 ss->rate = _ss.rate; 437 ss->channels = _ss.channels; 438 ss->format = _ss.format; 439 440 pa_assert(_period_size > 0); 441 pa_assert(_buffer_size > 0); 442 443 if (buffer_size) 444 *buffer_size = _buffer_size; 445 446 if (period_size) 447 *period_size = _period_size; 448 449 if (use_mmap) 450 *use_mmap = _use_mmap; 451 452 if (use_tsched) 453 *use_tsched = _use_tsched; 454 455 ret = 0; 456 457finish: 458 459 return ret; 460} 461 462int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool period_event) { 463 snd_pcm_sw_params_t *swparams; 464 snd_pcm_uframes_t boundary; 465 int err; 466 467 pa_assert(pcm); 468 469 snd_pcm_sw_params_alloca(&swparams); 470 471 if ((err = snd_pcm_sw_params_current(pcm, swparams)) < 0) { 472 pa_log_warn("Unable to determine current swparams: %s", pa_alsa_strerror(err)); 473 return err; 474 } 475 476 if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) { 477 pa_log_warn("Unable to disable period event: %s", pa_alsa_strerror(err)); 478 return err; 479 } 480 481 if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) { 482 pa_log_warn("Unable to enable time stamping: %s", pa_alsa_strerror(err)); 483 return err; 484 } 485 486 if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) { 487 pa_log_warn("Unable to get boundary: %s", pa_alsa_strerror(err)); 488 return err; 489 } 490 491 if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) { 492 pa_log_warn("Unable to set stop threshold: %s", pa_alsa_strerror(err)); 493 return err; 494 } 495 496 if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) { 497 pa_log_warn("Unable to set start threshold: %s", pa_alsa_strerror(err)); 498 return err; 499 } 500 501 if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) { 502 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err)); 503 return err; 504 } 505 506 if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) { 507 pa_log_warn("Unable to set sw params: %s", pa_alsa_strerror(err)); 508 return err; 509 } 510 511 return 0; 512} 513 514snd_pcm_t *pa_alsa_open_by_device_id_auto( 515 const char *dev_id, 516 char **dev, 517 pa_sample_spec *ss, 518 pa_channel_map* map, 519 int mode, 520 snd_pcm_uframes_t *period_size, 521 snd_pcm_uframes_t *buffer_size, 522 snd_pcm_uframes_t tsched_size, 523 bool *use_mmap, 524 bool *use_tsched, 525 pa_alsa_profile_set *ps, 526 pa_alsa_mapping **mapping) { 527 528 char *d; 529 snd_pcm_t *pcm_handle; 530 void *state; 531 pa_alsa_mapping *m; 532 533 pa_assert(dev_id); 534 pa_assert(dev); 535 pa_assert(ss); 536 pa_assert(map); 537 pa_assert(ps); 538 539 /* First we try to find a device string with a superset of the 540 * requested channel map. We iterate through our device table from 541 * top to bottom and take the first that matches. If we didn't 542 * find a working device that way, we iterate backwards, and check 543 * all devices that do not provide a superset of the requested 544 * channel map.*/ 545 546 PA_HASHMAP_FOREACH(m, ps->mappings, state) { 547 if (!pa_channel_map_superset(&m->channel_map, map)) 548 continue; 549 550 pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]); 551 552 pcm_handle = pa_alsa_open_by_device_id_mapping( 553 dev_id, 554 dev, 555 ss, 556 map, 557 mode, 558 period_size, 559 buffer_size, 560 tsched_size, 561 use_mmap, 562 use_tsched, 563 m); 564 565 if (pcm_handle) { 566 if (mapping) 567 *mapping = m; 568 569 return pcm_handle; 570 } 571 } 572 573 PA_HASHMAP_FOREACH_BACKWARDS(m, ps->mappings, state) { 574 if (pa_channel_map_superset(&m->channel_map, map)) 575 continue; 576 577 pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]); 578 579 pcm_handle = pa_alsa_open_by_device_id_mapping( 580 dev_id, 581 dev, 582 ss, 583 map, 584 mode, 585 period_size, 586 buffer_size, 587 tsched_size, 588 use_mmap, 589 use_tsched, 590 m); 591 592 if (pcm_handle) { 593 if (mapping) 594 *mapping = m; 595 596 return pcm_handle; 597 } 598 } 599 600 /* OK, we didn't find any good device, so let's try the raw hw: stuff */ 601 d = pa_sprintf_malloc("hw:%s", dev_id); 602 pa_log_debug("Trying %s as last resort...", d); 603 pcm_handle = pa_alsa_open_by_device_string( 604 d, 605 dev, 606 ss, 607 map, 608 mode, 609 period_size, 610 buffer_size, 611 tsched_size, 612 use_mmap, 613 use_tsched, 614 false); 615 pa_xfree(d); 616 617 if (pcm_handle && mapping) 618 *mapping = NULL; 619 620 return pcm_handle; 621} 622 623snd_pcm_t *pa_alsa_open_by_device_id_mapping( 624 const char *dev_id, 625 char **dev, 626 pa_sample_spec *ss, 627 pa_channel_map* map, 628 int mode, 629 snd_pcm_uframes_t *period_size, 630 snd_pcm_uframes_t *buffer_size, 631 snd_pcm_uframes_t tsched_size, 632 bool *use_mmap, 633 bool *use_tsched, 634 pa_alsa_mapping *m) { 635 636 snd_pcm_t *pcm_handle; 637 pa_sample_spec try_ss; 638 pa_channel_map try_map; 639 640 pa_assert(dev_id); 641 pa_assert(dev); 642 pa_assert(ss); 643 pa_assert(map); 644 pa_assert(m); 645 646 try_ss.channels = m->channel_map.channels; 647 try_ss.rate = ss->rate; 648 try_ss.format = ss->format; 649 try_map = m->channel_map; 650 651 pcm_handle = pa_alsa_open_by_template( 652 m->device_strings, 653 dev_id, 654 dev, 655 &try_ss, 656 &try_map, 657 mode, 658 period_size, 659 buffer_size, 660 tsched_size, 661 use_mmap, 662 use_tsched, 663 pa_channel_map_valid(&m->channel_map) /* Query the channel count if we don't know what we want */); 664 665 if (!pcm_handle) 666 return NULL; 667 668 *ss = try_ss; 669 *map = try_map; 670 pa_assert(map->channels == ss->channels); 671 672 return pcm_handle; 673} 674 675snd_pcm_t *pa_alsa_open_by_device_string( 676 const char *device, 677 char **dev, 678 pa_sample_spec *ss, 679 pa_channel_map* map, 680 int mode, 681 snd_pcm_uframes_t *period_size, 682 snd_pcm_uframes_t *buffer_size, 683 snd_pcm_uframes_t tsched_size, 684 bool *use_mmap, 685 bool *use_tsched, 686 bool require_exact_channel_number) { 687 688 int err; 689 char *d; 690 snd_pcm_t *pcm_handle; 691 bool reformat = false; 692 693 pa_assert(device); 694 pa_assert(ss); 695 pa_assert(map); 696 697 d = pa_xstrdup(device); 698 699 for (;;) { 700 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with"); 701 702 if ((err = snd_pcm_open(&pcm_handle, d, mode, 703 SND_PCM_NONBLOCK| 704 SND_PCM_NO_AUTO_RESAMPLE| 705 SND_PCM_NO_AUTO_CHANNELS| 706 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) { 707 pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err)); 708 goto fail; 709 } 710 711 pa_log_debug("Managed to open %s", d); 712 713 if ((err = pa_alsa_set_hw_params( 714 pcm_handle, 715 ss, 716 period_size, 717 buffer_size, 718 tsched_size, 719 use_mmap, 720 use_tsched, 721 require_exact_channel_number)) < 0) { 722 723 if (!reformat) { 724 reformat = true; 725 726 snd_pcm_close(pcm_handle); 727 continue; 728 } 729 730 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */ 731 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) { 732 char *t; 733 734 t = pa_sprintf_malloc("plug:SLAVE='%s'", d); 735 pa_xfree(d); 736 d = t; 737 738 reformat = false; 739 740 snd_pcm_close(pcm_handle); 741 continue; 742 } 743 744 pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err)); 745 snd_pcm_close(pcm_handle); 746 747 goto fail; 748 } 749 750 if (ss->channels > PA_CHANNELS_MAX) { 751 pa_log("Device %s has %u channels, but PulseAudio supports only %u channels. Unable to use the device.", 752 d, ss->channels, PA_CHANNELS_MAX); 753 snd_pcm_close(pcm_handle); 754 goto fail; 755 } 756 757 if (dev) 758 *dev = d; 759 else 760 pa_xfree(d); 761 762 if (ss->channels != map->channels) 763 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA); 764 765 return pcm_handle; 766 } 767 768fail: 769 pa_xfree(d); 770 771 return NULL; 772} 773 774snd_pcm_t *pa_alsa_open_by_template( 775 char **template, 776 const char *dev_id, 777 char **dev, 778 pa_sample_spec *ss, 779 pa_channel_map* map, 780 int mode, 781 snd_pcm_uframes_t *period_size, 782 snd_pcm_uframes_t *buffer_size, 783 snd_pcm_uframes_t tsched_size, 784 bool *use_mmap, 785 bool *use_tsched, 786 bool require_exact_channel_number) { 787 788 snd_pcm_t *pcm_handle; 789 char **i; 790 791 for (i = template; *i; i++) { 792 char *d; 793 794 d = pa_replace(*i, "%f", dev_id); 795 796 pcm_handle = pa_alsa_open_by_device_string( 797 d, 798 dev, 799 ss, 800 map, 801 mode, 802 period_size, 803 buffer_size, 804 tsched_size, 805 use_mmap, 806 use_tsched, 807 require_exact_channel_number); 808 809 pa_xfree(d); 810 811 if (pcm_handle) 812 return pcm_handle; 813 } 814 815 return NULL; 816} 817 818void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) { 819 int err; 820 snd_output_t *out; 821 822 pa_assert(pcm); 823 824 pa_assert_se(snd_output_buffer_open(&out) == 0); 825 826 if ((err = snd_pcm_dump(pcm, out)) < 0) 827 pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err)); 828 else { 829 char *s = NULL; 830 snd_output_buffer_string(out, &s); 831 pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s)); 832 } 833 834 pa_assert_se(snd_output_close(out) == 0); 835} 836 837void pa_alsa_dump_status(snd_pcm_t *pcm) { 838 int err; 839 snd_output_t *out; 840 snd_pcm_status_t *status; 841 char *s = NULL; 842 843 pa_assert(pcm); 844 845 snd_pcm_status_alloca(&status); 846 847 if ((err = snd_output_buffer_open(&out)) < 0) { 848 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err)); 849 return; 850 } 851 852 if ((err = snd_pcm_status(pcm, status)) < 0) { 853 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err)); 854 goto finish; 855 } 856 857 if ((err = snd_pcm_status_dump(status, out)) < 0) { 858 pa_log_debug("snd_pcm_status_dump(): %s", pa_alsa_strerror(err)); 859 goto finish; 860 } 861 862 snd_output_buffer_string(out, &s); 863 pa_log_debug("snd_pcm_status_dump():\n%s", pa_strnull(s)); 864 865finish: 866 867 snd_output_close(out); 868} 869 870static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) { 871 va_list ap; 872 char *alsa_file; 873 874 alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file); 875 876 va_start(ap, fmt); 877 878 pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap); 879 880 va_end(ap); 881 882 pa_xfree(alsa_file); 883} 884 885static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0); 886 887void pa_alsa_refcnt_inc(void) { 888 /* This is not really thread safe, but we do our best */ 889 890 if (pa_atomic_inc(&n_error_handler_installed) == 0) 891 snd_lib_error_set_handler(alsa_error_handler); 892} 893 894void pa_alsa_refcnt_dec(void) { 895 int r; 896 897 pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1); 898 899 if (r == 1) { 900 snd_lib_error_set_handler(NULL); 901 snd_config_update_free_global(); 902 } 903} 904 905bool pa_alsa_init_description(pa_proplist *p, pa_card *card) { 906 const char *d, *k; 907 pa_assert(p); 908 909 if (pa_device_init_description(p, card)) 910 return true; 911 912 if (!(d = pa_proplist_gets(p, "alsa.card_name"))) 913 d = pa_proplist_gets(p, "alsa.name"); 914 915 if (!d) 916 return false; 917 918 k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION); 919 920 if (d && k) 921 pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s %s", d, k); 922 else if (d) 923 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d); 924 925 return false; 926} 927 928void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) { 929 char *cn, *lcn, *dn; 930 931 pa_assert(p); 932 pa_assert(card >= 0); 933 934 pa_proplist_setf(p, "alsa.card", "%i", card); 935 936 if (snd_card_get_name(card, &cn) >= 0) { 937 pa_proplist_sets(p, "alsa.card_name", pa_strip(cn)); 938 free(cn); 939 } 940 941 if (snd_card_get_longname(card, &lcn) >= 0) { 942 pa_proplist_sets(p, "alsa.long_card_name", pa_strip(lcn)); 943 free(lcn); 944 } 945 946 if ((dn = pa_alsa_get_driver_name(card))) { 947 pa_proplist_sets(p, "alsa.driver_name", dn); 948 pa_xfree(dn); 949 } 950 951#ifdef HAVE_UDEV 952 pa_udev_get_info(card, p); 953#endif 954} 955 956void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) { 957 958 static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = { 959 [SND_PCM_CLASS_GENERIC] = "generic", 960 [SND_PCM_CLASS_MULTI] = "multi", 961 [SND_PCM_CLASS_MODEM] = "modem", 962 [SND_PCM_CLASS_DIGITIZER] = "digitizer" 963 }; 964 static const char * const class_table[SND_PCM_CLASS_LAST+1] = { 965 [SND_PCM_CLASS_GENERIC] = "sound", 966 [SND_PCM_CLASS_MULTI] = NULL, 967 [SND_PCM_CLASS_MODEM] = "modem", 968 [SND_PCM_CLASS_DIGITIZER] = NULL 969 }; 970 static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = { 971 [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix", 972 [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix" 973 }; 974 975 snd_pcm_class_t class; 976 snd_pcm_subclass_t subclass; 977 const char *n, *id, *sdn; 978 int card; 979 980 pa_assert(p); 981 pa_assert(pcm_info); 982 983 pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa"); 984 985 if ((class = snd_pcm_info_get_class(pcm_info)) <= SND_PCM_CLASS_LAST) { 986 if (class_table[class]) 987 pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]); 988 if (alsa_class_table[class]) 989 pa_proplist_sets(p, "alsa.class", alsa_class_table[class]); 990 } 991 992 if ((subclass = snd_pcm_info_get_subclass(pcm_info)) <= SND_PCM_SUBCLASS_LAST) 993 if (alsa_subclass_table[subclass]) 994 pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]); 995 996 if ((n = snd_pcm_info_get_name(pcm_info))) { 997 char *t = pa_xstrdup(n); 998 pa_proplist_sets(p, "alsa.name", pa_strip(t)); 999 pa_xfree(t); 1000 } 1001 1002 if ((id = snd_pcm_info_get_id(pcm_info))) 1003 pa_proplist_sets(p, "alsa.id", id); 1004 1005 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info)); 1006 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info))) 1007 pa_proplist_sets(p, "alsa.subdevice_name", sdn); 1008 1009 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info)); 1010 1011 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0) 1012 pa_alsa_init_proplist_card(c, p, card); 1013} 1014 1015void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) { 1016 snd_pcm_hw_params_t *hwparams; 1017 snd_pcm_info_t *info; 1018 int bits, err; 1019 1020 snd_pcm_hw_params_alloca(&hwparams); 1021 snd_pcm_info_alloca(&info); 1022 1023 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0) 1024 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err)); 1025 else { 1026 1027 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0) 1028 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits); 1029 } 1030 1031 if ((err = snd_pcm_info(pcm, info)) < 0) 1032 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err)); 1033 else 1034 pa_alsa_init_proplist_pcm_info(c, p, info); 1035} 1036 1037void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) { 1038 int err; 1039 snd_ctl_t *ctl; 1040 snd_ctl_card_info_t *info; 1041 const char *t; 1042 1043 pa_assert(p); 1044 1045 snd_ctl_card_info_alloca(&info); 1046 1047 if ((err = snd_ctl_open(&ctl, name, 0)) < 0) { 1048 pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err)); 1049 return; 1050 } 1051 1052 if ((err = snd_ctl_card_info(ctl, info)) < 0) { 1053 pa_log_warn("Control device %s card info: %s", name, snd_strerror(err)); 1054 snd_ctl_close(ctl); 1055 return; 1056 } 1057 1058 if ((t = snd_ctl_card_info_get_mixername(info)) && *t) 1059 pa_proplist_sets(p, "alsa.mixer_name", t); 1060 1061 if ((t = snd_ctl_card_info_get_components(info)) && *t) 1062 pa_proplist_sets(p, "alsa.components", t); 1063 1064 snd_ctl_close(ctl); 1065} 1066 1067int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) { 1068 snd_pcm_state_t state; 1069 snd_pcm_hw_params_t *hwparams; 1070 int err; 1071 1072 pa_assert(pcm); 1073 1074 if (revents & POLLERR) 1075 pa_log_debug("Got POLLERR from ALSA"); 1076 if (revents & POLLNVAL) 1077 pa_log_warn("Got POLLNVAL from ALSA"); 1078 if (revents & POLLHUP) 1079 pa_log_warn("Got POLLHUP from ALSA"); 1080 if (revents & POLLPRI) 1081 pa_log_warn("Got POLLPRI from ALSA"); 1082 if (revents & POLLIN) 1083 pa_log_debug("Got POLLIN from ALSA"); 1084 if (revents & POLLOUT) 1085 pa_log_debug("Got POLLOUT from ALSA"); 1086 1087 state = snd_pcm_state(pcm); 1088 pa_log_debug("PCM state is %s", snd_pcm_state_name(state)); 1089 1090 /* Try to recover from this error */ 1091 1092 switch (state) { 1093 1094 case SND_PCM_STATE_DISCONNECTED: 1095 /* Do not try to recover */ 1096 pa_log_info("Device disconnected."); 1097 return -1; 1098 1099 case SND_PCM_STATE_XRUN: 1100 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) { 1101 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err)); 1102 return -1; 1103 } 1104 break; 1105 1106 case SND_PCM_STATE_SUSPENDED: 1107 snd_pcm_hw_params_alloca(&hwparams); 1108 1109 if ((err = snd_pcm_hw_params_any(pcm, hwparams)) < 0) { 1110 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(err)); 1111 return -1; 1112 } 1113 1114 if (snd_pcm_hw_params_can_resume(hwparams)) { 1115 /* Retry resume 3 times before giving up, then fallback to restarting the stream. */ 1116 for (int i = 0; i < 3; i++) { 1117 if ((err = snd_pcm_resume(pcm)) == 0) 1118 return 0; 1119 if (err != -EAGAIN) 1120 break; 1121 pa_msleep(25); 1122 } 1123 pa_log_warn("Could not recover alsa device from SUSPENDED state, trying to restart PCM"); 1124 } 1125 /* Fall through */ 1126 1127 default: 1128 1129 snd_pcm_drop(pcm); 1130 return 1; 1131 } 1132 1133 return 0; 1134} 1135 1136pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) { 1137 int n, err; 1138 struct pollfd *pollfd; 1139 pa_rtpoll_item *item; 1140 1141 pa_assert(pcm); 1142 1143 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) { 1144 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n)); 1145 return NULL; 1146 } 1147 1148 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n); 1149 pollfd = pa_rtpoll_item_get_pollfd(item, NULL); 1150 1151 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) { 1152 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err)); 1153 pa_rtpoll_item_free(item); 1154 return NULL; 1155 } 1156 1157 return item; 1158} 1159 1160snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) { 1161 snd_pcm_sframes_t n; 1162 size_t k; 1163 1164 pa_assert(pcm); 1165 pa_assert(hwbuf_size > 0); 1166 pa_assert(ss); 1167 1168 /* Some ALSA driver expose weird bugs, let's inform the user about 1169 * what is going on */ 1170 1171 n = snd_pcm_avail(pcm); 1172 1173 if (n <= 0) 1174 return n; 1175 1176 k = (size_t) n * pa_frame_size(ss); 1177 1178 if (PA_UNLIKELY(k >= hwbuf_size * 5 || 1179 k >= pa_bytes_per_second(ss)*10)) { 1180 1181 PA_ONCE_BEGIN { 1182 char *dn = pa_alsa_get_driver_name_by_pcm(pcm); 1183 pa_log_debug(ngettext("snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu ms).\n" 1184 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.", 1185 "snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n" 1186 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.", 1187 (unsigned long) k), 1188 (unsigned long) k, 1189 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC), 1190 pa_strnull(dn)); 1191 pa_xfree(dn); 1192 pa_alsa_dump(PA_LOG_DEBUG, pcm); 1193 } PA_ONCE_END; 1194 1195 /* Mhmm, let's try not to fail completely */ 1196 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss)); 1197 } 1198 1199 return n; 1200} 1201 1202int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_status_t *status, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss, 1203 bool capture) { 1204 ssize_t k; 1205 size_t abs_k; 1206 int err; 1207 snd_pcm_sframes_t avail = 0; 1208#if (SND_LIB_VERSION >= ((1<<16)|(1<<8)|0)) /* API additions in 1.1.0 */ 1209 snd_pcm_audio_tstamp_config_t tstamp_config; 1210#endif 1211 1212 pa_assert(pcm); 1213 pa_assert(delay); 1214 pa_assert(hwbuf_size > 0); 1215 pa_assert(ss); 1216 1217 /* Some ALSA driver expose weird bugs, let's inform the user about 1218 * what is going on. We're going to get both the avail and delay values so 1219 * that we can compare and check them for capture. 1220 * This is done with snd_pcm_status() which provides 1221 * avail, delay and timestamp values in a single kernel call to improve 1222 * timer-based scheduling */ 1223 1224#if (SND_LIB_VERSION >= ((1<<16)|(1<<8)|0)) /* API additions in 1.1.0 */ 1225 1226 /* The time stamp configuration needs to be set so that the 1227 * ALSA code will use the internal delay reported by the driver. 1228 * The time stamp configuration was introduced in alsa version 1.1.0. */ 1229 tstamp_config.type_requested = 1; /* ALSA default time stamp type */ 1230 tstamp_config.report_delay = 1; 1231 snd_pcm_status_set_audio_htstamp_config(status, &tstamp_config); 1232#endif 1233 1234 if ((err = snd_pcm_status(pcm, status)) < 0) 1235 return err; 1236 1237 avail = snd_pcm_status_get_avail(status); 1238 *delay = snd_pcm_status_get_delay(status); 1239 1240 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss); 1241 1242 abs_k = k >= 0 ? (size_t) k : (size_t) -k; 1243 1244 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 || 1245 abs_k >= pa_bytes_per_second(ss)*10)) { 1246 1247 PA_ONCE_BEGIN { 1248 char *dn = pa_alsa_get_driver_name_by_pcm(pcm); 1249 pa_log_debug(ngettext("snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s%lu ms).\n" 1250 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.", 1251 "snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n" 1252 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.", 1253 (signed long) k), 1254 (signed long) k, 1255 k < 0 ? "-" : "", 1256 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC), 1257 pa_strnull(dn)); 1258 pa_xfree(dn); 1259 pa_alsa_dump(PA_LOG_DEBUG, pcm); 1260 } PA_ONCE_END; 1261 1262 /* Mhmm, let's try not to fail completely */ 1263 if (k < 0) 1264 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss)); 1265 else 1266 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss)); 1267 } 1268 1269 if (capture) { 1270 abs_k = (size_t) avail * pa_frame_size(ss); 1271 1272 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 || 1273 abs_k >= pa_bytes_per_second(ss)*10)) { 1274 1275 PA_ONCE_BEGIN { 1276 char *dn = pa_alsa_get_driver_name_by_pcm(pcm); 1277 pa_log_debug(ngettext("snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu ms).\n" 1278 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.", 1279 "snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n" 1280 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.", 1281 (unsigned long) k), 1282 (unsigned long) k, 1283 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC), 1284 pa_strnull(dn)); 1285 pa_xfree(dn); 1286 pa_alsa_dump(PA_LOG_DEBUG, pcm); 1287 } PA_ONCE_END; 1288 1289 /* Mhmm, let's try not to fail completely */ 1290 avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss)); 1291 } 1292 1293 if (PA_UNLIKELY(*delay < avail)) { 1294 PA_ONCE_BEGIN { 1295 char *dn = pa_alsa_get_driver_name_by_pcm(pcm); 1296 pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n" 1297 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."), 1298 (unsigned long) *delay, 1299 (unsigned long) avail, 1300 pa_strnull(dn)); 1301 pa_xfree(dn); 1302 pa_alsa_dump(PA_LOG_ERROR, pcm); 1303 } PA_ONCE_END; 1304 1305 /* try to fixup */ 1306 *delay = avail; 1307 } 1308 } 1309 1310 return 0; 1311} 1312 1313int pa_alsa_safe_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames, size_t hwbuf_size, const pa_sample_spec *ss) { 1314 int r; 1315 snd_pcm_uframes_t before; 1316 size_t k; 1317 1318 pa_assert(pcm); 1319 pa_assert(areas); 1320 pa_assert(offset); 1321 pa_assert(frames); 1322 pa_assert(hwbuf_size > 0); 1323 pa_assert(ss); 1324 1325 before = *frames; 1326 1327 r = snd_pcm_mmap_begin(pcm, areas, offset, frames); 1328 1329 if (r < 0) 1330 return r; 1331 1332 k = (size_t) *frames * pa_frame_size(ss); 1333 1334 if (PA_UNLIKELY(*frames > before || 1335 k >= hwbuf_size * 3 || 1336 k >= pa_bytes_per_second(ss)*10)) 1337 PA_ONCE_BEGIN { 1338 char *dn = pa_alsa_get_driver_name_by_pcm(pcm); 1339 pa_log_debug(ngettext("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte (%lu ms).\n" 1340 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.", 1341 "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n" 1342 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.", 1343 (unsigned long) k), 1344 (unsigned long) k, 1345 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC), 1346 pa_strnull(dn)); 1347 pa_xfree(dn); 1348 pa_alsa_dump(PA_LOG_DEBUG, pcm); 1349 } PA_ONCE_END; 1350 1351 return r; 1352} 1353 1354char *pa_alsa_get_driver_name(int card) { 1355 char *t, *m, *n; 1356 1357 pa_assert(card >= 0); 1358 1359 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card); 1360 m = pa_readlink(t); 1361 pa_xfree(t); 1362 1363 if (!m) 1364 return NULL; 1365 1366 n = pa_xstrdup(pa_path_get_filename(m)); 1367 pa_xfree(m); 1368 1369 return n; 1370} 1371 1372char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) { 1373 int card; 1374 snd_pcm_info_t* info; 1375 snd_pcm_info_alloca(&info); 1376 1377 pa_assert(pcm); 1378 1379 if (snd_pcm_info(pcm, info) < 0) 1380 return NULL; 1381 1382 if ((card = snd_pcm_info_get_card(info)) < 0) 1383 return NULL; 1384 1385 return pa_alsa_get_driver_name(card); 1386} 1387 1388char *pa_alsa_get_reserve_name(const char *device) { 1389 const char *t; 1390 int i; 1391 1392 pa_assert(device); 1393 1394 if ((t = strchr(device, ':'))) 1395 device = t+1; 1396 1397 if ((i = snd_card_get_index(device)) < 0) { 1398 int32_t k; 1399 1400 if (pa_atoi(device, &k) < 0) 1401 return NULL; 1402 1403 i = (int) k; 1404 } 1405 1406 return pa_sprintf_malloc("Audio%i", i); 1407} 1408 1409unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) { 1410 static unsigned int all_rates[] = { 8000, 11025, 12000, 1411 16000, 22050, 24000, 1412 32000, 44100, 48000, 1413 64000, 88200, 96000, 1414 128000, 176400, 192000, 1415 384000 }; 1416 bool supported[PA_ELEMENTSOF(all_rates)] = { false, }; 1417 snd_pcm_hw_params_t *hwparams; 1418 unsigned int i, j, n, *rates = NULL; 1419 int ret; 1420 1421 snd_pcm_hw_params_alloca(&hwparams); 1422 1423 if ((ret = snd_pcm_hw_params_any(pcm, hwparams)) < 0) { 1424 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret)); 1425 return NULL; 1426 } 1427 1428 for (i = 0, n = 0; i < PA_ELEMENTSOF(all_rates); i++) { 1429 if (snd_pcm_hw_params_test_rate(pcm, hwparams, all_rates[i], 0) == 0) { 1430 supported[i] = true; 1431 n++; 1432 } 1433 } 1434 1435 if (n > 0) { 1436 rates = pa_xnew(unsigned int, n + 1); 1437 1438 for (i = 0, j = 0; i < PA_ELEMENTSOF(all_rates); i++) { 1439 if (supported[i]) 1440 rates[j++] = all_rates[i]; 1441 } 1442 1443 rates[j] = 0; 1444 } else { 1445 rates = pa_xnew(unsigned int, 2); 1446 1447 rates[0] = fallback_rate; 1448 if ((ret = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rates[0], NULL)) < 0) { 1449 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret)); 1450 pa_xfree(rates); 1451 return NULL; 1452 } 1453 1454 rates[1] = 0; 1455 } 1456 1457 return rates; 1458} 1459 1460pa_sample_format_t *pa_alsa_get_supported_formats(snd_pcm_t *pcm, pa_sample_format_t fallback_format) { 1461 static const snd_pcm_format_t format_trans_to_pa[] = { 1462 [SND_PCM_FORMAT_U8] = PA_SAMPLE_U8, 1463 [SND_PCM_FORMAT_A_LAW] = PA_SAMPLE_ALAW, 1464 [SND_PCM_FORMAT_MU_LAW] = PA_SAMPLE_ULAW, 1465 [SND_PCM_FORMAT_S16_LE] = PA_SAMPLE_S16LE, 1466 [SND_PCM_FORMAT_S16_BE] = PA_SAMPLE_S16BE, 1467 [SND_PCM_FORMAT_FLOAT_LE] = PA_SAMPLE_FLOAT32LE, 1468 [SND_PCM_FORMAT_FLOAT_BE] = PA_SAMPLE_FLOAT32BE, 1469 [SND_PCM_FORMAT_S32_LE] = PA_SAMPLE_S32LE, 1470 [SND_PCM_FORMAT_S32_BE] = PA_SAMPLE_S32BE, 1471 [SND_PCM_FORMAT_S24_3LE] = PA_SAMPLE_S24LE, 1472 [SND_PCM_FORMAT_S24_3BE] = PA_SAMPLE_S24BE, 1473 [SND_PCM_FORMAT_S24_LE] = PA_SAMPLE_S24_32LE, 1474 [SND_PCM_FORMAT_S24_BE] = PA_SAMPLE_S24_32BE, 1475 }; 1476 static const snd_pcm_format_t all_formats[] = { 1477 SND_PCM_FORMAT_U8, 1478 SND_PCM_FORMAT_A_LAW, 1479 SND_PCM_FORMAT_MU_LAW, 1480 SND_PCM_FORMAT_S16_LE, 1481 SND_PCM_FORMAT_S16_BE, 1482 SND_PCM_FORMAT_FLOAT_LE, 1483 SND_PCM_FORMAT_FLOAT_BE, 1484 SND_PCM_FORMAT_S32_LE, 1485 SND_PCM_FORMAT_S32_BE, 1486 SND_PCM_FORMAT_S24_3LE, 1487 SND_PCM_FORMAT_S24_3BE, 1488 SND_PCM_FORMAT_S24_LE, 1489 SND_PCM_FORMAT_S24_BE, 1490 }; 1491 bool supported[PA_ELEMENTSOF(all_formats)] = { 1492 false, 1493 }; 1494 snd_pcm_hw_params_t *hwparams; 1495 unsigned int i, j, n; 1496 pa_sample_format_t *formats = NULL; 1497 int ret; 1498 1499 snd_pcm_hw_params_alloca(&hwparams); 1500 1501 if ((ret = snd_pcm_hw_params_any(pcm, hwparams)) < 0) { 1502 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret)); 1503 return NULL; 1504 } 1505 1506 for (i = 0, n = 0; i < PA_ELEMENTSOF(all_formats); i++) { 1507 if (snd_pcm_hw_params_test_format(pcm, hwparams, all_formats[i]) == 0) { 1508 supported[i] = true; 1509 n++; 1510 } 1511 } 1512 1513 if (n > 0) { 1514 formats = pa_xnew(pa_sample_format_t, n + 1); 1515 1516 for (i = 0, j = 0; i < PA_ELEMENTSOF(all_formats); i++) { 1517 if (supported[i]) 1518 formats[j++] = format_trans_to_pa[all_formats[i]]; 1519 } 1520 1521 formats[j] = PA_SAMPLE_MAX; 1522 } else { 1523 formats = pa_xnew(pa_sample_format_t, 2); 1524 1525 formats[0] = fallback_format; 1526 if ((ret = snd_pcm_hw_params_set_format(pcm, hwparams, format_trans_to_pa[formats[0]])) < 0) { 1527 pa_log_debug("snd_pcm_hw_params_set_format() failed: %s", pa_alsa_strerror(ret)); 1528 pa_xfree(formats); 1529 return NULL; 1530 } 1531 1532 formats[1] = PA_SAMPLE_MAX; 1533 } 1534 1535 return formats; 1536} 1537 1538bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm) { 1539 snd_pcm_info_t* info; 1540 snd_pcm_info_alloca(&info); 1541 1542 pa_assert(pcm); 1543 1544 if (snd_pcm_info(pcm, info) < 0) 1545 return false; 1546 1547 return snd_pcm_info_get_card(info) >= 0; 1548} 1549 1550bool pa_alsa_pcm_is_modem(snd_pcm_t *pcm) { 1551 snd_pcm_info_t* info; 1552 snd_pcm_info_alloca(&info); 1553 1554 pa_assert(pcm); 1555 1556 if (snd_pcm_info(pcm, info) < 0) 1557 return false; 1558 1559 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM; 1560} 1561 1562PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree); 1563 1564const char* pa_alsa_strerror(int errnum) { 1565 const char *original = NULL; 1566 char *translated, *t; 1567 char errbuf[128]; 1568 1569 if ((t = PA_STATIC_TLS_GET(cstrerror))) 1570 pa_xfree(t); 1571 1572 original = snd_strerror(errnum); 1573 1574 if (!original) { 1575 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum); 1576 original = errbuf; 1577 } 1578 1579 if (!(translated = pa_locale_to_utf8(original))) { 1580 pa_log_warn("Unable to convert error string to locale, filtering."); 1581 translated = pa_utf8_filter(original); 1582 } 1583 1584 PA_STATIC_TLS_SET(cstrerror, translated); 1585 1586 return translated; 1587} 1588 1589bool pa_alsa_may_tsched(bool want) { 1590 1591 if (!want) 1592 return false; 1593 1594 if (!pa_rtclock_hrtimer()) { 1595 /* We cannot depend on being woken up in time when the timers 1596 are inaccurate, so let's fallback to classic IO based playback 1597 then. */ 1598 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel."); 1599 return false; } 1600 1601 if (pa_running_in_vm()) { 1602 /* We cannot depend on being woken up when we ask for in a VM, 1603 * so let's fallback to classic IO based playback then. */ 1604 pa_log_notice("Disabling timer-based scheduling because running inside a VM."); 1605 return false; 1606 } 1607 1608 return true; 1609} 1610 1611#define SND_MIXER_ELEM_PULSEAUDIO (SND_MIXER_ELEM_LAST + 10) 1612 1613static snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, 1614 snd_ctl_elem_iface_t iface, 1615 const char *name, 1616 unsigned int index, 1617 unsigned int device) { 1618 snd_mixer_elem_t *elem; 1619 1620 for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) { 1621 snd_hctl_elem_t *helem; 1622 if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_PULSEAUDIO) 1623 continue; 1624 helem = snd_mixer_elem_get_private(elem); 1625 if (snd_hctl_elem_get_interface(helem) != iface) 1626 continue; 1627 if (!pa_streq(snd_hctl_elem_get_name(helem), name)) 1628 continue; 1629 if (snd_hctl_elem_get_index(helem) != index) 1630 continue; 1631 if (snd_hctl_elem_get_device(helem) != device) 1632 continue; 1633 return elem; 1634 } 1635 return NULL; 1636} 1637 1638snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, struct pa_alsa_mixer_id *alsa_id, unsigned int device) { 1639 return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, alsa_id->name, alsa_id->index, device); 1640} 1641 1642snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device) { 1643 return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_PCM, name, 0, device); 1644} 1645 1646static int mixer_class_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2) 1647{ 1648 /* Dummy compare function */ 1649 return c1 == c2 ? 0 : (c1 > c2 ? 1 : -1); 1650} 1651 1652static int mixer_class_event(snd_mixer_class_t *class, unsigned int mask, 1653 snd_hctl_elem_t *helem, snd_mixer_elem_t *melem) 1654{ 1655 int err; 1656 const char *name = snd_hctl_elem_get_name(helem); 1657 if (mask & SND_CTL_EVENT_MASK_ADD) { 1658 snd_ctl_elem_iface_t iface = snd_hctl_elem_get_interface(helem); 1659 if (iface == SND_CTL_ELEM_IFACE_CARD || iface == SND_CTL_ELEM_IFACE_PCM) { 1660 snd_mixer_elem_t *new_melem; 1661 1662 /* Put the hctl pointer as our private data - it will be useful for callbacks */ 1663 if ((err = snd_mixer_elem_new(&new_melem, SND_MIXER_ELEM_PULSEAUDIO, 0, helem, NULL)) < 0) { 1664 pa_log_warn("snd_mixer_elem_new failed: %s", pa_alsa_strerror(err)); 1665 return 0; 1666 } 1667 1668 if ((err = snd_mixer_elem_attach(new_melem, helem)) < 0) { 1669 pa_log_warn("snd_mixer_elem_attach failed: %s", pa_alsa_strerror(err)); 1670 snd_mixer_elem_free(melem); 1671 return 0; 1672 } 1673 1674 if ((err = snd_mixer_elem_add(new_melem, class)) < 0) { 1675 pa_log_warn("snd_mixer_elem_add failed: %s", pa_alsa_strerror(err)); 1676 return 0; 1677 } 1678 } 1679 } 1680 else if (mask & SND_CTL_EVENT_MASK_VALUE) { 1681 snd_mixer_elem_value(melem); /* Calls the element callback */ 1682 return 0; 1683 } 1684 else 1685 pa_log_info("Got an unknown mixer class event for %s: mask 0x%x", name, mask); 1686 1687 return 0; 1688} 1689 1690static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t *hctl) { 1691 int err; 1692 snd_mixer_class_t *class; 1693 1694 pa_assert(mixer); 1695 pa_assert(dev); 1696 1697 if ((err = snd_mixer_attach_hctl(mixer, hctl)) < 0) { 1698 pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err)); 1699 return -1; 1700 } 1701 1702 if (snd_mixer_class_malloc(&class)) { 1703 pa_log_info("Failed to allocate mixer class for %s", dev); 1704 return -1; 1705 } 1706 snd_mixer_class_set_event(class, mixer_class_event); 1707 snd_mixer_class_set_compare(class, mixer_class_compare); 1708 if ((err = snd_mixer_class_register(class, mixer)) < 0) { 1709 pa_log_info("Unable register mixer class for %s: %s", dev, pa_alsa_strerror(err)); 1710 snd_mixer_class_free(class); 1711 return -1; 1712 } 1713 /* From here on, the mixer class is deallocated by alsa on snd_mixer_close/free. */ 1714 1715 if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) { 1716 pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err)); 1717 return -1; 1718 } 1719 1720 if ((err = snd_mixer_load(mixer)) < 0) { 1721 pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err)); 1722 return -1; 1723 } 1724 1725 pa_log_info("Successfully attached to mixer '%s'", dev); 1726 return 0; 1727} 1728 1729snd_mixer_t *pa_alsa_open_mixer(pa_hashmap *mixers, int alsa_card_index, bool probe) { 1730 char *md = pa_sprintf_malloc("hw:%i", alsa_card_index); 1731 snd_mixer_t *m = pa_alsa_open_mixer_by_name(mixers, md, probe); 1732 pa_xfree(md); 1733 return m; 1734} 1735 1736pa_alsa_mixer *pa_alsa_create_mixer(pa_hashmap *mixers, const char *dev, snd_mixer_t *m, bool probe) { 1737 pa_alsa_mixer *pm; 1738 1739 pm = pa_xnew0(pa_alsa_mixer, 1); 1740 if (pm == NULL) 1741 return NULL; 1742 1743 pm->used_for_probe_only = probe; 1744 pm->mixer_handle = m; 1745 pa_hashmap_put(mixers, pa_xstrdup(dev), pm); 1746 return pm; 1747} 1748 1749snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, bool probe) { 1750 int err; 1751 snd_mixer_t *m; 1752 snd_hctl_t *hctl; 1753 pa_alsa_mixer *pm; 1754 1755 pa_assert(mixers); 1756 pa_assert(dev); 1757 1758 pm = pa_hashmap_get(mixers, dev); 1759 if (pm) { 1760 if (!probe) 1761 pm->used_for_probe_only = false; 1762 return pm->mixer_handle; 1763 } 1764 1765 if ((err = snd_mixer_open(&m, 0)) < 0) { 1766 pa_log("Error opening mixer: %s", pa_alsa_strerror(err)); 1767 return NULL; 1768 } 1769 1770 err = snd_hctl_open(&hctl, dev, 0); 1771 if (err < 0) { 1772 pa_log("Error opening hctl device: %s", pa_alsa_strerror(err)); 1773 goto __close; 1774 } 1775 1776 if (prepare_mixer(m, dev, hctl) >= 0) { 1777 /* get the ALSA card number (index) and ID (alias) and create two identical mixers */ 1778 char *p, *dev2, *dev_idx, *dev_id; 1779 snd_ctl_card_info_t *info; 1780 snd_ctl_card_info_alloca(&info); 1781 err = snd_ctl_card_info(snd_hctl_ctl(hctl), info); 1782 if (err < 0) 1783 goto __std; 1784 dev2 = pa_xstrdup(dev); 1785 if (dev2 == NULL) 1786 goto __close; 1787 p = strchr(dev2, ':'); 1788 /* sanity check - only hw: devices */ 1789 if (p == NULL || (p - dev2) < 2 || !pa_strneq(p - 2, "hw:", 3)) { 1790 pa_xfree(dev2); 1791 goto __std; 1792 } 1793 *p = '\0'; 1794 dev_idx = pa_sprintf_malloc("%s:%u", dev2, snd_ctl_card_info_get_card(info)); 1795 dev_id = pa_sprintf_malloc("%s:%s", dev2, snd_ctl_card_info_get_id(info)); 1796 pa_log_debug("ALSA alias mixers: %s = %s", dev_idx, dev_id); 1797 if (dev_idx && dev_id && (strcmp(dev, dev_idx) == 0 || strcmp(dev, dev_id) == 0)) { 1798 pm = pa_alsa_create_mixer(mixers, dev_idx, m, probe); 1799 if (pm) { 1800 pa_alsa_mixer *pm2; 1801 pm2 = pa_alsa_create_mixer(mixers, dev_id, m, probe); 1802 if (pm2) { 1803 pm->alias = pm2; 1804 pm2->alias = pm; 1805 } 1806 } 1807 } 1808 pa_xfree(dev_id); 1809 pa_xfree(dev_idx); 1810 pa_xfree(dev2); 1811 __std: 1812 if (pm == NULL) 1813 pm = pa_alsa_create_mixer(mixers, dev, m, probe); 1814 if (pm) 1815 return m; 1816 } 1817 1818__close: 1819 snd_mixer_close(m); 1820 return NULL; 1821} 1822 1823snd_mixer_t *pa_alsa_open_mixer_for_pcm(pa_hashmap *mixers, snd_pcm_t *pcm, bool probe) { 1824 snd_pcm_info_t* info; 1825 snd_pcm_info_alloca(&info); 1826 1827 pa_assert(pcm); 1828 1829 if (snd_pcm_info(pcm, info) >= 0) { 1830 int card_idx; 1831 1832 if ((card_idx = snd_pcm_info_get_card(info)) >= 0) 1833 return pa_alsa_open_mixer(mixers, card_idx, probe); 1834 } 1835 1836 return NULL; 1837} 1838 1839void pa_alsa_mixer_set_fdlist(pa_hashmap *mixers, snd_mixer_t *mixer_handle, pa_mainloop_api *ml) 1840{ 1841 pa_alsa_mixer *pm; 1842 void *state; 1843 1844 PA_HASHMAP_FOREACH(pm, mixers, state) 1845 if (pm->mixer_handle == mixer_handle) { 1846 pm->used_for_probe_only = false; 1847 if (!pm->fdl) { 1848 pm->fdl = pa_alsa_fdlist_new(); 1849 if (pm->fdl) 1850 pa_alsa_fdlist_set_handle(pm->fdl, pm->mixer_handle, NULL, ml); 1851 } 1852 } 1853} 1854 1855void pa_alsa_mixer_free(pa_alsa_mixer *mixer) 1856{ 1857 if (mixer->fdl) 1858 pa_alsa_fdlist_free(mixer->fdl); 1859 if (mixer->mixer_handle && mixer->alias == NULL) 1860 snd_mixer_close(mixer->mixer_handle); 1861 if (mixer->alias) 1862 mixer->alias->alias = NULL; 1863 pa_xfree(mixer); 1864} 1865 1866int pa_alsa_get_hdmi_eld(snd_hctl_elem_t *elem, pa_hdmi_eld *eld) { 1867 1868 /* The ELD format is specific to HDA Intel sound cards and defined in the 1869 HDA specification: http://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html */ 1870 int err; 1871 snd_ctl_elem_info_t *info; 1872 snd_ctl_elem_value_t *value; 1873 uint8_t *elddata; 1874 unsigned int eldsize, mnl; 1875 unsigned int device; 1876 1877 pa_assert(eld != NULL); 1878 pa_assert(elem != NULL); 1879 1880 /* Does it have any contents? */ 1881 snd_ctl_elem_info_alloca(&info); 1882 snd_ctl_elem_value_alloca(&value); 1883 if ((err = snd_hctl_elem_info(elem, info)) < 0 || 1884 (err = snd_hctl_elem_read(elem, value)) < 0) { 1885 pa_log_warn("Accessing ELD control failed with error %s", snd_strerror(err)); 1886 return -1; 1887 } 1888 1889 device = snd_hctl_elem_get_device(elem); 1890 eldsize = snd_ctl_elem_info_get_count(info); 1891 elddata = (unsigned char *) snd_ctl_elem_value_get_bytes(value); 1892 if (elddata == NULL || eldsize == 0) { 1893 pa_log_debug("ELD info empty (for device=%d)", device); 1894 return -1; 1895 } 1896 if (eldsize < 20 || eldsize > 256) { 1897 pa_log_debug("ELD info has wrong size (for device=%d)", device); 1898 return -1; 1899 } 1900 1901 /* Try to fetch monitor name */ 1902 mnl = elddata[4] & 0x1f; 1903 if (mnl == 0 || mnl > 16 || 20 + mnl > eldsize) { 1904 pa_log_debug("No monitor name in ELD info (for device=%d)", device); 1905 mnl = 0; 1906 } 1907 memcpy(eld->monitor_name, &elddata[20], mnl); 1908 eld->monitor_name[mnl] = '\0'; 1909 if (mnl) 1910 pa_log_debug("Monitor name in ELD info is '%s' (for device=%d)", eld->monitor_name, device); 1911 1912 return 0; 1913} 1914