Commit 42fc2d39 authored by Simon Wilson's avatar Simon Wilson
Browse files

Update to latest tinyalsa

f7f35cc Add tinypcminfo utility
4354488 pcm: add pcm_get_params API

Change-Id: I50e196bc299734b6e020bdcededa4f903ee5c5c2
parent da39e0b0
......@@ -45,3 +45,12 @@ LOCAL_SHARED_LIBRARIES:= libcutils libutils libtinyalsa
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES:= external/tinyalsa/include
LOCAL_SRC_FILES:= tinypcminfo.c
LOCAL_MODULE := tinypcminfo
LOCAL_SHARED_LIBRARIES:= libcutils libutils libtinyalsa
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
......@@ -104,6 +104,23 @@ struct pcm_config {
int avail_min;
};
/* PCM parameters */
enum pcm_param
{
PCM_PARAM_SAMPLE_BITS,
PCM_PARAM_FRAME_BITS,
PCM_PARAM_CHANNELS,
PCM_PARAM_RATE,
PCM_PARAM_PERIOD_TIME,
PCM_PARAM_PERIOD_SIZE,
PCM_PARAM_PERIOD_BYTES,
PCM_PARAM_PERIODS,
PCM_PARAM_BUFFER_TIME,
PCM_PARAM_BUFFER_SIZE,
PCM_PARAM_BUFFER_BYTES,
PCM_PARAM_TICK_TIME,
};
/* Mixer control types */
enum mixer_ctl_type {
MIXER_CTL_TYPE_BOOL,
......@@ -123,6 +140,15 @@ struct pcm *pcm_open(unsigned int card, unsigned int device,
int pcm_close(struct pcm *pcm);
int pcm_is_ready(struct pcm *pcm);
/* Obtain the parameters for a PCM */
struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
unsigned int flags);
void pcm_params_free(struct pcm_params *pcm_params);
unsigned int pcm_params_get_min(struct pcm_params *pcm_params,
enum pcm_param param);
unsigned int pcm_params_get_max(struct pcm_params *pcm_params,
enum pcm_param param);
/* Set and get config */
int pcm_get_config(struct pcm *pcm, struct pcm_config *config);
int pcm_set_config(struct pcm *pcm, struct pcm_config *config);
......
......@@ -93,6 +93,24 @@ static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned int val)
}
}
static unsigned int param_get_min(struct snd_pcm_hw_params *p, int n)
{
if (param_is_interval(n)) {
struct snd_interval *i = param_to_interval(p, n);
return i->min;
}
return 0;
}
static unsigned int param_get_max(struct snd_pcm_hw_params *p, int n)
{
if (param_is_interval(n)) {
struct snd_interval *i = param_to_interval(p, n);
return i->max;
}
return 0;
}
static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned int val)
{
if (param_is_interval(n)) {
......@@ -130,6 +148,9 @@ static void param_init(struct snd_pcm_hw_params *p)
i->min = 0;
i->max = ~0;
}
p->rmask = ~0U;
p->cmask = 0;
p->info = ~0U;
}
#define PCM_ERROR_MAX 128
......@@ -433,6 +454,129 @@ static struct pcm bad_pcm = {
.fd = -1,
};
struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
unsigned int flags)
{
struct snd_pcm_hw_params *params;
char fn[256];
int fd;
snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
flags & PCM_IN ? 'c' : 'p');
fd = open(fn, O_RDWR);
if (fd < 0) {
fprintf(stderr, "cannot open device '%s'\n", fn);
goto err_open;
}
params = calloc(1, sizeof(struct snd_pcm_hw_params));
if (!params)
goto err_calloc;
param_init(params);
if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, params)) {
fprintf(stderr, "SNDRV_PCM_IOCTL_HW_REFINE error (%d)\n", errno);
goto err_hw_refine;
}
close(fd);
return (struct pcm_params *)params;
err_hw_refine:
free(params);
err_calloc:
close(fd);
err_open:
return NULL;
}
void pcm_params_free(struct pcm_params *pcm_params)
{
struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
if (params)
free(params);
}
static int pcm_param_to_alsa(enum pcm_param param)
{
switch (param) {
case PCM_PARAM_SAMPLE_BITS:
return SNDRV_PCM_HW_PARAM_SAMPLE_BITS;
break;
case PCM_PARAM_FRAME_BITS:
return SNDRV_PCM_HW_PARAM_FRAME_BITS;
break;
case PCM_PARAM_CHANNELS:
return SNDRV_PCM_HW_PARAM_CHANNELS;
break;
case PCM_PARAM_RATE:
return SNDRV_PCM_HW_PARAM_RATE;
break;
case PCM_PARAM_PERIOD_TIME:
return SNDRV_PCM_HW_PARAM_PERIOD_TIME;
break;
case PCM_PARAM_PERIOD_SIZE:
return SNDRV_PCM_HW_PARAM_PERIOD_SIZE;
break;
case PCM_PARAM_PERIOD_BYTES:
return SNDRV_PCM_HW_PARAM_PERIOD_BYTES;
break;
case PCM_PARAM_PERIODS:
return SNDRV_PCM_HW_PARAM_PERIODS;
break;
case PCM_PARAM_BUFFER_TIME:
return SNDRV_PCM_HW_PARAM_BUFFER_TIME;
break;
case PCM_PARAM_BUFFER_SIZE:
return SNDRV_PCM_HW_PARAM_BUFFER_SIZE;
break;
case PCM_PARAM_BUFFER_BYTES:
return SNDRV_PCM_HW_PARAM_BUFFER_BYTES;
break;
case PCM_PARAM_TICK_TIME:
return SNDRV_PCM_HW_PARAM_TICK_TIME;
break;
default:
return -1;
}
}
unsigned int pcm_params_get_min(struct pcm_params *pcm_params,
enum pcm_param param)
{
struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
int p;
if (!params)
return 0;
p = pcm_param_to_alsa(param);
if (p < 0)
return 0;
return param_get_min(params, p);
}
unsigned int pcm_params_get_max(struct pcm_params *pcm_params,
enum pcm_param param)
{
struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
int p;
if (!params)
return 0;
p = pcm_param_to_alsa(param);
if (p < 0)
return 0;
return param_get_max(params, p);
}
int pcm_close(struct pcm *pcm)
{
if (pcm == &bad_pcm)
......
/* tinypcminfo.c
**
** Copyright 2012, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of The Android Open Source Project nor the names of
** its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
** DAMAGE.
*/
#include <tinyalsa/asoundlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
unsigned int device = 0;
unsigned int card = 0;
int i;
if (argc < 3) {
fprintf(stderr, "Usage: %s -D card -d device\n", argv[0]);
return 1;
}
/* parse command line arguments */
argv += 1;
while (*argv) {
if (strcmp(*argv, "-D") == 0) {
argv++;
if (*argv)
card = atoi(*argv);
}
if (strcmp(*argv, "-d") == 0) {
argv++;
if (*argv)
device = atoi(*argv);
}
if (*argv)
argv++;
}
printf("Info for card %d, device %d:\n", card, device);
for (i = 0; i < 2; i++) {
struct pcm_params *params;
unsigned int min;
unsigned int max;
printf("\nPCM %s:\n", i == 0 ? "out" : "in");
params = pcm_params_get(card, device, i == 0 ? PCM_OUT : PCM_IN);
if (params == NULL) {
printf("Device does not exist.\n");
continue;
}
min = pcm_params_get_min(params, PCM_PARAM_RATE);
max = pcm_params_get_max(params, PCM_PARAM_RATE);
printf(" Rate:\tmin=%uHz\tmax=%uHz\n", min, max);
min = pcm_params_get_min(params, PCM_PARAM_CHANNELS);
max = pcm_params_get_max(params, PCM_PARAM_CHANNELS);
printf(" Channels:\tmin=%u\t\tmax=%u\n", min, max);
min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS);
max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS);
printf(" Sample bits:\tmin=%u\t\tmax=%u\n", min, max);
min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE);
max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE);
printf(" Period size:\tmin=%u\t\tmax=%u\n", min, max);
min = pcm_params_get_min(params, PCM_PARAM_PERIODS);
max = pcm_params_get_max(params, PCM_PARAM_PERIODS);
printf("Period count:\tmin=%u\t\tmax=%u\n", min, max);
pcm_params_free(params);
}
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment