Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

pcm: add pcm_get_params API

This enables the capabilities of any given PCM to be queried.

Created with input from Priyesh Bisla and Gabriel Beddingfield.
  • Loading branch information...
commit 43544884f44313176621f57b370b4ba114fe5b8c 1 parent 2c3a8e2
Simon Wilson authored

Showing 2 changed files with 170 additions and 0 deletions. Show diff stats Hide diff stats

  1. +26 0 include/tinyalsa/asoundlib.h
  2. +144 0 pcm.c
26 include/tinyalsa/asoundlib.h
@@ -98,6 +98,23 @@ struct pcm_config {
98 98 unsigned int silence_threshold;
99 99 };
100 100
  101 +/* PCM parameters */
  102 +enum pcm_param
  103 +{
  104 + PCM_PARAM_SAMPLE_BITS,
  105 + PCM_PARAM_FRAME_BITS,
  106 + PCM_PARAM_CHANNELS,
  107 + PCM_PARAM_RATE,
  108 + PCM_PARAM_PERIOD_TIME,
  109 + PCM_PARAM_PERIOD_SIZE,
  110 + PCM_PARAM_PERIOD_BYTES,
  111 + PCM_PARAM_PERIODS,
  112 + PCM_PARAM_BUFFER_TIME,
  113 + PCM_PARAM_BUFFER_SIZE,
  114 + PCM_PARAM_BUFFER_BYTES,
  115 + PCM_PARAM_TICK_TIME,
  116 +};
  117 +
101 118 /* Mixer control types */
102 119 enum mixer_ctl_type {
103 120 MIXER_CTL_TYPE_BOOL,
@@ -117,6 +134,15 @@ struct pcm *pcm_open(unsigned int card, unsigned int device,
117 134 int pcm_close(struct pcm *pcm);
118 135 int pcm_is_ready(struct pcm *pcm);
119 136
  137 +/* Obtain the parameters for a PCM */
  138 +struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
  139 + unsigned int flags);
  140 +void pcm_params_free(struct pcm_params *pcm_params);
  141 +unsigned int pcm_params_get_min(struct pcm_params *pcm_params,
  142 + enum pcm_param param);
  143 +unsigned int pcm_params_get_max(struct pcm_params *pcm_params,
  144 + enum pcm_param param);
  145 +
120 146 /* Set and get config */
121 147 int pcm_get_config(struct pcm *pcm, struct pcm_config *config);
122 148 int pcm_set_config(struct pcm *pcm, struct pcm_config *config);
144 pcm.c
@@ -93,6 +93,24 @@ static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned int val)
93 93 }
94 94 }
95 95
  96 +static unsigned int param_get_min(struct snd_pcm_hw_params *p, int n)
  97 +{
  98 + if (param_is_interval(n)) {
  99 + struct snd_interval *i = param_to_interval(p, n);
  100 + return i->min;
  101 + }
  102 + return 0;
  103 +}
  104 +
  105 +static unsigned int param_get_max(struct snd_pcm_hw_params *p, int n)
  106 +{
  107 + if (param_is_interval(n)) {
  108 + struct snd_interval *i = param_to_interval(p, n);
  109 + return i->max;
  110 + }
  111 + return 0;
  112 +}
  113 +
96 114 static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned int val)
97 115 {
98 116 if (param_is_interval(n)) {
@@ -130,6 +148,9 @@ static void param_init(struct snd_pcm_hw_params *p)
130 148 i->min = 0;
131 149 i->max = ~0;
132 150 }
  151 + p->rmask = ~0U;
  152 + p->cmask = 0;
  153 + p->info = ~0U;
133 154 }
134 155
135 156 #define PCM_ERROR_MAX 128
@@ -423,6 +444,129 @@ static struct pcm bad_pcm = {
423 444 .fd = -1,
424 445 };
425 446
  447 +struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
  448 + unsigned int flags)
  449 +{
  450 + struct snd_pcm_hw_params *params;
  451 + char fn[256];
  452 + int fd;
  453 +
  454 + snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
  455 + flags & PCM_IN ? 'c' : 'p');
  456 +
  457 + fd = open(fn, O_RDWR);
  458 + if (fd < 0) {
  459 + fprintf(stderr, "cannot open device '%s'\n", fn);
  460 + goto err_open;
  461 + }
  462 +
  463 + params = calloc(1, sizeof(struct snd_pcm_hw_params));
  464 + if (!params)
  465 + goto err_calloc;
  466 +
  467 + param_init(params);
  468 + if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, params)) {
  469 + fprintf(stderr, "SNDRV_PCM_IOCTL_HW_REFINE error (%d)\n", errno);
  470 + goto err_hw_refine;
  471 + }
  472 +
  473 + close(fd);
  474 +
  475 + return (struct pcm_params *)params;
  476 +
  477 +err_hw_refine:
  478 + free(params);
  479 +err_calloc:
  480 + close(fd);
  481 +err_open:
  482 + return NULL;
  483 +}
  484 +
  485 +void pcm_params_free(struct pcm_params *pcm_params)
  486 +{
  487 + struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
  488 +
  489 + if (params)
  490 + free(params);
  491 +}
  492 +
  493 +static int pcm_param_to_alsa(enum pcm_param param)
  494 +{
  495 + switch (param) {
  496 + case PCM_PARAM_SAMPLE_BITS:
  497 + return SNDRV_PCM_HW_PARAM_SAMPLE_BITS;
  498 + break;
  499 + case PCM_PARAM_FRAME_BITS:
  500 + return SNDRV_PCM_HW_PARAM_FRAME_BITS;
  501 + break;
  502 + case PCM_PARAM_CHANNELS:
  503 + return SNDRV_PCM_HW_PARAM_CHANNELS;
  504 + break;
  505 + case PCM_PARAM_RATE:
  506 + return SNDRV_PCM_HW_PARAM_RATE;
  507 + break;
  508 + case PCM_PARAM_PERIOD_TIME:
  509 + return SNDRV_PCM_HW_PARAM_PERIOD_TIME;
  510 + break;
  511 + case PCM_PARAM_PERIOD_SIZE:
  512 + return SNDRV_PCM_HW_PARAM_PERIOD_SIZE;
  513 + break;
  514 + case PCM_PARAM_PERIOD_BYTES:
  515 + return SNDRV_PCM_HW_PARAM_PERIOD_BYTES;
  516 + break;
  517 + case PCM_PARAM_PERIODS:
  518 + return SNDRV_PCM_HW_PARAM_PERIODS;
  519 + break;
  520 + case PCM_PARAM_BUFFER_TIME:
  521 + return SNDRV_PCM_HW_PARAM_BUFFER_TIME;
  522 + break;
  523 + case PCM_PARAM_BUFFER_SIZE:
  524 + return SNDRV_PCM_HW_PARAM_BUFFER_SIZE;
  525 + break;
  526 + case PCM_PARAM_BUFFER_BYTES:
  527 + return SNDRV_PCM_HW_PARAM_BUFFER_BYTES;
  528 + break;
  529 + case PCM_PARAM_TICK_TIME:
  530 + return SNDRV_PCM_HW_PARAM_TICK_TIME;
  531 + break;
  532 +
  533 + default:
  534 + return -1;
  535 + }
  536 +}
  537 +
  538 +unsigned int pcm_params_get_min(struct pcm_params *pcm_params,
  539 + enum pcm_param param)
  540 +{
  541 + struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
  542 + int p;
  543 +
  544 + if (!params)
  545 + return 0;
  546 +
  547 + p = pcm_param_to_alsa(param);
  548 + if (p < 0)
  549 + return 0;
  550 +
  551 + return param_get_min(params, p);
  552 +}
  553 +
  554 +unsigned int pcm_params_get_max(struct pcm_params *pcm_params,
  555 + enum pcm_param param)
  556 +{
  557 + struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
  558 + int p;
  559 +
  560 + if (!params)
  561 + return 0;
  562 +
  563 + p = pcm_param_to_alsa(param);
  564 + if (p < 0)
  565 + return 0;
  566 +
  567 + return param_get_max(params, p);
  568 +}
  569 +
426 570 int pcm_close(struct pcm *pcm)
427 571 {
428 572 if (pcm == &bad_pcm)

0 comments on commit 4354488

Please sign in to comment.
Something went wrong with that request. Please try again.