Advertisement
Guest User

kilx

a guest
Jan 23rd, 2009
312
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.98 KB | None | 0 0
  1. /* Set the hardware parameters of the given ALSA device. Returns the
  2.  * selected fragment settings in *period and *period_size */
  3. int pa_alsa_set_hw_params(
  4.         snd_pcm_t *pcm_handle,
  5.         pa_sample_spec *ss,
  6.         uint32_t *periods,
  7.         snd_pcm_uframes_t *period_size,
  8.         snd_pcm_uframes_t tsched_size,
  9.         pa_bool_t *use_mmap,
  10.         pa_bool_t *use_tsched,
  11.         pa_bool_t require_exact_channel_number) {
  12.  
  13.     int ret = -1;
  14.     snd_pcm_uframes_t _period_size = *period_size;
  15.     unsigned int _periods = *periods;
  16.     snd_pcm_uframes_t buffer_size;
  17.     unsigned int r = ss->rate;
  18.     unsigned int c = ss->channels;
  19.     pa_sample_format_t f = ss->format;
  20.     snd_pcm_hw_params_t *hwparams;
  21.     pa_bool_t _use_mmap = use_mmap && *use_mmap;
  22.     pa_bool_t _use_tsched = use_tsched && *use_tsched;
  23.     int dir;
  24.  
  25.     pa_assert(pcm_handle);
  26.     pa_assert(ss);
  27.     pa_assert(periods);
  28.     pa_assert(period_size);
  29.  
  30.     snd_pcm_hw_params_alloca(&hwparams);
  31.  
  32.     if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0)
  33.         goto finish;
  34.  
  35.     if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0)
  36.         goto finish;
  37.  
  38.     if (_use_mmap) {
  39.         if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0) {
  40.  
  41.             /* mmap() didn't work, fall back to interleaved */
  42.  
  43.             if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
  44.                 goto finish;
  45.  
  46.             _use_mmap = FALSE;
  47.         }
  48.  
  49.     } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
  50.         goto finish;
  51.  
  52.     if (!_use_mmap)
  53.         _use_tsched = FALSE;
  54.  
  55.     if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
  56.         goto finish;
  57.  
  58.     if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0)
  59.         goto finish;
  60.  
  61.     /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
  62.     _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * r) / ss->rate);
  63.     tsched_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * r) / ss->rate);
  64.  
  65.     if (require_exact_channel_number) {
  66.         if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0)
  67.             goto finish;
  68.     } else {
  69.         if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0)
  70.             goto finish;
  71.     }
  72.  
  73.     if (_use_tsched) {
  74.         _period_size = tsched_size;
  75.         _periods = 1;
  76.  
  77.         pa_assert_se(snd_pcm_hw_params_get_buffer_size_max(hwparams, &buffer_size) == 0);
  78.         pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size * 1000 / r);
  79.     }
  80.  
  81.     buffer_size = _periods * _period_size;
  82.  
  83.     if ((ret = snd_pcm_hw_params_set_periods_integer(pcm_handle, hwparams)) < 0)
  84.         goto finish;
  85.  
  86.     if (_periods > 0) {
  87.  
  88.         /* First we pass 0 as direction to get exactly what we asked
  89.          * for. That this is necessary is presumably a bug in ALSA */
  90.  
  91.         dir = 0;
  92.         if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
  93.             dir = 1;
  94.             if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
  95.                 dir = -1;
  96.                 if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0)
  97.                     goto finish;
  98.             }
  99.         }
  100.     }
  101.  
  102.     if (_period_size > 0)
  103.         if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)
  104.             goto finish;
  105.  
  106.     if  ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
  107.         goto finish;
  108.  
  109.     if (ss->rate != r)
  110.         pa_log_warn("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r);
  111.  
  112.     if (ss->channels != c)
  113.         pa_log_warn("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c);
  114.  
  115.     if (ss->format != f)
  116.         pa_log_warn("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(f));
  117.  
  118.     if ((ret = snd_pcm_prepare(pcm_handle)) < 0)
  119.         goto finish;
  120.  
  121.     if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
  122.         (ret = snd_pcm_hw_params_get_periods(hwparams, &_periods, &dir)) < 0)
  123.         goto finish;
  124.  
  125.     /* If the sample rate deviates too much, we need to resample */
  126.     if (r < ss->rate*.95 || r > ss->rate*1.05)
  127.         ss->rate = r;
  128.     ss->channels = (uint8_t) c;
  129.     ss->format = f;
  130.  
  131.     pa_assert(_periods > 0);
  132.     pa_assert(_period_size > 0);
  133.  
  134.     *periods = _periods;
  135.     *period_size = _period_size;
  136.  
  137.     if (use_mmap)
  138.         *use_mmap = _use_mmap;
  139.  
  140.     if (use_tsched)
  141.         *use_tsched = _use_tsched;
  142.  
  143.     ret = 0;
  144.  
  145.     snd_pcm_nonblock(pcm_handle, 1);
  146.  
  147. finish:
  148.  
  149.     return ret;
  150. }
  151.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement