"Fossies" - the Fresh Open Source Software Archive

Member "pulseaudio-14.2/src/modules/alsa/alsa-util.c" (11 Jan 2021, 60686 Bytes) of package /linux/misc/pulseaudio-14.2.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "alsa-util.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 14.0_vs_14.2.

    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 
   51 static 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 
  129 try_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 
  145 static 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 
  170 static 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 
  184 static 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. */
  200 int 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 
  402 success:
  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 
  457 finish:
  458 
  459     return ret;
  460 }
  461 
  462 int 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 
  514 snd_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 
  623 snd_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 
  675 snd_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:%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 
  768 fail:
  769     pa_xfree(d);
  770 
  771     return NULL;
  772 }
  773 
  774 snd_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 
  818 void 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 
  837 void 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 
  865 finish:
  866 
  867     snd_output_close(out);
  868 }
  869 
  870 static 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 
  885 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
  886 
  887 void 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 
  894 void 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 
  905 bool 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 
  928 void 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 
  956 void 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 
 1015 void 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 
 1037 void 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 
 1067 int 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 
 1136 pa_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 
 1160 snd_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 
 1202 int 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 
 1313 int 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 
 1354 char *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 
 1372 char *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 
 1388 char *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 
 1409 unsigned 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 
 1460 pa_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 
 1538 bool 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 
 1550 bool 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 
 1562 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
 1563 
 1564 const 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 
 1589 bool 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 
 1613 static 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 
 1638 snd_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 
 1642 snd_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 
 1646 static 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 
 1652 static 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 
 1690 static int prepare_mixer(snd_mixer_t *mixer, const char *dev) {
 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(mixer, dev)) < 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 
 1729 snd_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 
 1736 snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, bool probe) {
 1737     int err;
 1738     snd_mixer_t *m;
 1739     pa_alsa_mixer *pm;
 1740     char *dev2;
 1741     void *state;
 1742 
 1743     pa_assert(mixers);
 1744     pa_assert(dev);
 1745 
 1746     pm = pa_hashmap_get(mixers, dev);
 1747 
 1748     /* The quick card number/index lookup (hw:#)
 1749      * We already know the card number/index, thus use the mixer
 1750      * from the cache at first.
 1751      */
 1752     if (!pm && pa_strneq(dev, "hw:", 3)) {
 1753         const char *s = dev + 3;
 1754         int card_index;
 1755         while (*s && *s >= '0' && *s <= '9') s++;
 1756         if (*s == '\0' && pa_atoi(dev + 3, &card_index) >= 0) {
 1757             PA_HASHMAP_FOREACH_KV(dev2, pm, mixers, state) {
 1758                 if (pm->card_index == card_index) {
 1759                     dev = dev2;
 1760                     pm = pa_hashmap_get(mixers, dev);
 1761                     break;
 1762                 }
 1763             }
 1764         }
 1765     }
 1766 
 1767     if (pm) {
 1768         if (!probe)
 1769             pm->used_for_probe_only = false;
 1770         return pm->mixer_handle;
 1771     }
 1772 
 1773     if ((err = snd_mixer_open(&m, 0)) < 0) {
 1774         pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
 1775         return NULL;
 1776     }
 1777 
 1778     if (prepare_mixer(m, dev) >= 0) {
 1779         pm = pa_xnew0(pa_alsa_mixer, 1);
 1780         if (pm) {
 1781             snd_hctl_t *hctl;
 1782             pm->card_index = -1;
 1783             /* determine the ALSA card number (index) and store it to card_index */
 1784             err = snd_mixer_get_hctl(m, dev, &hctl);
 1785             if (err >= 0) {
 1786                 snd_ctl_card_info_t *info;
 1787                 snd_ctl_card_info_alloca(&info);
 1788                 err = snd_ctl_card_info(snd_hctl_ctl(hctl), info);
 1789                 if (err >= 0)
 1790                     pm->card_index = snd_ctl_card_info_get_card(info);
 1791             }
 1792             pm->used_for_probe_only = probe;
 1793             pm->mixer_handle = m;
 1794             pa_hashmap_put(mixers, pa_xstrdup(dev), pm);
 1795             return m;
 1796         }
 1797     }
 1798 
 1799     snd_mixer_close(m);
 1800     return NULL;
 1801 }
 1802 
 1803 snd_mixer_t *pa_alsa_open_mixer_for_pcm(pa_hashmap *mixers, snd_pcm_t *pcm, bool probe) {
 1804     snd_pcm_info_t* info;
 1805     snd_pcm_info_alloca(&info);
 1806 
 1807     pa_assert(pcm);
 1808 
 1809     if (snd_pcm_info(pcm, info) >= 0) {
 1810         int card_idx;
 1811 
 1812         if ((card_idx = snd_pcm_info_get_card(info)) >= 0)
 1813             return pa_alsa_open_mixer(mixers, card_idx, probe);
 1814     }
 1815 
 1816     return NULL;
 1817 }
 1818 
 1819 void pa_alsa_mixer_set_fdlist(pa_hashmap *mixers, snd_mixer_t *mixer_handle, pa_mainloop_api *ml)
 1820 {
 1821     pa_alsa_mixer *pm;
 1822     void *state;
 1823 
 1824     PA_HASHMAP_FOREACH(pm, mixers, state)
 1825         if (pm->mixer_handle == mixer_handle) {
 1826             pm->used_for_probe_only = false;
 1827             if (!pm->fdl) {
 1828                 pm->fdl = pa_alsa_fdlist_new();
 1829                 if (pm->fdl)
 1830                     pa_alsa_fdlist_set_handle(pm->fdl, pm->mixer_handle, NULL, ml);
 1831             }
 1832         }
 1833 }
 1834 
 1835 void pa_alsa_mixer_free(pa_alsa_mixer *mixer)
 1836 {
 1837     if (mixer->fdl)
 1838         pa_alsa_fdlist_free(mixer->fdl);
 1839     if (mixer->mixer_handle)
 1840         snd_mixer_close(mixer->mixer_handle);
 1841     pa_xfree(mixer);
 1842 }
 1843 
 1844 int pa_alsa_get_hdmi_eld(snd_hctl_elem_t *elem, pa_hdmi_eld *eld) {
 1845 
 1846     /* The ELD format is specific to HDA Intel sound cards and defined in the
 1847        HDA specification: http://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html */
 1848     int err;
 1849     snd_ctl_elem_info_t *info;
 1850     snd_ctl_elem_value_t *value;
 1851     uint8_t *elddata;
 1852     unsigned int eldsize, mnl;
 1853     unsigned int device;
 1854 
 1855     pa_assert(eld != NULL);
 1856     pa_assert(elem != NULL);
 1857 
 1858     /* Does it have any contents? */
 1859     snd_ctl_elem_info_alloca(&info);
 1860     snd_ctl_elem_value_alloca(&value);
 1861     if ((err = snd_hctl_elem_info(elem, info)) < 0 ||
 1862        (err = snd_hctl_elem_read(elem, value)) < 0) {
 1863         pa_log_warn("Accessing ELD control failed with error %s", snd_strerror(err));
 1864         return -1;
 1865     }
 1866 
 1867     device = snd_hctl_elem_get_device(elem);
 1868     eldsize = snd_ctl_elem_info_get_count(info);
 1869     elddata = (unsigned char *) snd_ctl_elem_value_get_bytes(value);
 1870     if (elddata == NULL || eldsize == 0) {
 1871         pa_log_debug("ELD info empty (for device=%d)", device);
 1872         return -1;
 1873     }
 1874     if (eldsize < 20 || eldsize > 256) {
 1875         pa_log_debug("ELD info has wrong size (for device=%d)", device);
 1876         return -1;
 1877     }
 1878 
 1879     /* Try to fetch monitor name */
 1880     mnl = elddata[4] & 0x1f;
 1881     if (mnl == 0 || mnl > 16 || 20 + mnl > eldsize) {
 1882         pa_log_debug("No monitor name in ELD info (for device=%d)", device);
 1883         mnl = 0;
 1884     }
 1885     memcpy(eld->monitor_name, &elddata[20], mnl);
 1886     eld->monitor_name[mnl] = '\0';
 1887     if (mnl)
 1888         pa_log_debug("Monitor name in ELD info is '%s' (for device=%d)", eld->monitor_name, device);
 1889 
 1890     return 0;
 1891 }