2012-07-30 15:50:44 +02:00
|
|
|
/*
|
|
|
|
|
* channel mapping API test program
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <getopt.h>
|
|
|
|
|
#include "../include/asoundlib.h"
|
|
|
|
|
|
|
|
|
|
static void usage(void)
|
|
|
|
|
{
|
|
|
|
|
printf("usage: chmap [options] query\n"
|
|
|
|
|
" chmap [options] get\n"
|
|
|
|
|
" chmap [options] set CH0 CH1 CH2...\n"
|
|
|
|
|
"options:\n"
|
|
|
|
|
" -D device Specify PCM device to handle\n"
|
|
|
|
|
" -f format PCM format\n"
|
|
|
|
|
" -c channels Channels\n"
|
|
|
|
|
" -r rate Sample rate\n");
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-04 17:26:43 +02:00
|
|
|
static void print_channels(const snd_pcm_chmap_t *map)
|
2012-07-30 15:50:44 +02:00
|
|
|
{
|
2012-09-10 18:07:36 +02:00
|
|
|
char tmp[128];
|
|
|
|
|
if (snd_pcm_chmap_print(map, sizeof(tmp), tmp) > 0)
|
|
|
|
|
printf(" %s\n", tmp);
|
2012-07-30 15:50:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int query_chmaps(snd_pcm_t *pcm)
|
|
|
|
|
{
|
2012-09-04 17:26:43 +02:00
|
|
|
snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps(pcm);
|
|
|
|
|
snd_pcm_chmap_query_t **p, *v;
|
2012-07-30 15:50:44 +02:00
|
|
|
|
|
|
|
|
if (!maps) {
|
|
|
|
|
printf("Cannot query maps\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
for (p = maps; (v = *p) != NULL; p++) {
|
2012-09-10 18:07:36 +02:00
|
|
|
printf("Type = %s, Channels = %d\n",
|
|
|
|
|
snd_pcm_chmap_type_name(v->type),
|
|
|
|
|
v->map.channels);
|
2012-09-04 17:26:43 +02:00
|
|
|
print_channels(&v->map);
|
2012-07-30 15:50:44 +02:00
|
|
|
}
|
|
|
|
|
snd_pcm_free_chmaps(maps);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int setup_pcm(snd_pcm_t *pcm, int format, int channels, int rate)
|
|
|
|
|
{
|
|
|
|
|
snd_pcm_hw_params_t *params;
|
|
|
|
|
|
|
|
|
|
snd_pcm_hw_params_alloca(¶ms);
|
|
|
|
|
if (snd_pcm_hw_params_any(pcm, params) < 0) {
|
|
|
|
|
printf("Cannot init hw_params\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (format != SND_PCM_FORMAT_UNKNOWN) {
|
|
|
|
|
if (snd_pcm_hw_params_set_format(pcm, params, format) < 0) {
|
|
|
|
|
printf("Cannot set format %s\n",
|
|
|
|
|
snd_pcm_format_name(format));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (channels > 0) {
|
|
|
|
|
if (snd_pcm_hw_params_set_channels(pcm, params, channels) < 0) {
|
|
|
|
|
printf("Cannot set channels %d\n", channels);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (rate > 0) {
|
|
|
|
|
if (snd_pcm_hw_params_set_rate_near(pcm, params, (unsigned int *)&rate, 0) < 0) {
|
|
|
|
|
printf("Cannot set rate %d\n", rate);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (snd_pcm_hw_params(pcm, params) < 0) {
|
|
|
|
|
printf("Cannot set hw_params\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int get_chmap(snd_pcm_t *pcm, int format, int channels, int rate)
|
|
|
|
|
{
|
2012-09-04 17:26:43 +02:00
|
|
|
snd_pcm_chmap_t *map;
|
2012-07-30 15:50:44 +02:00
|
|
|
|
|
|
|
|
if (setup_pcm(pcm, format, channels, rate))
|
|
|
|
|
return 1;
|
|
|
|
|
map = snd_pcm_get_chmap(pcm);
|
|
|
|
|
if (!map) {
|
|
|
|
|
printf("Cannot get chmap\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2012-09-04 17:26:43 +02:00
|
|
|
printf("Channels = %d\n", map->channels);
|
|
|
|
|
print_channels(map);
|
2012-07-30 15:50:44 +02:00
|
|
|
free(map);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int set_chmap(snd_pcm_t *pcm, int format, int channels, int rate,
|
|
|
|
|
int nargs, char **arg)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
2012-09-04 17:26:43 +02:00
|
|
|
snd_pcm_chmap_t *map;
|
2012-07-30 15:50:44 +02:00
|
|
|
|
|
|
|
|
if (channels && channels != nargs) {
|
|
|
|
|
printf("Inconsistent channels %d vs %d\n", channels, nargs);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (!channels) {
|
|
|
|
|
if (!nargs) {
|
|
|
|
|
printf("No channels are given\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
channels = nargs;
|
|
|
|
|
}
|
|
|
|
|
if (setup_pcm(pcm, format, channels, rate))
|
|
|
|
|
return 1;
|
2012-09-13 08:06:26 +02:00
|
|
|
map = malloc(sizeof(int) * (channels + 1));
|
2012-07-30 15:50:44 +02:00
|
|
|
if (!map) {
|
|
|
|
|
printf("cannot malloc\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2012-09-04 17:26:43 +02:00
|
|
|
map->channels = channels;
|
2012-09-10 18:07:36 +02:00
|
|
|
for (i = 0; i < channels; i++) {
|
|
|
|
|
int val = snd_pcm_chmap_from_string(arg[i]);
|
|
|
|
|
if (val < 0)
|
|
|
|
|
val = SND_CHMAP_UNKNOWN;
|
|
|
|
|
map->pos[i] = val;
|
|
|
|
|
}
|
2012-07-30 15:50:44 +02:00
|
|
|
if (snd_pcm_set_chmap(pcm, map) < 0) {
|
|
|
|
|
printf("Cannot set chmap\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
free(map);
|
|
|
|
|
|
|
|
|
|
map = snd_pcm_get_chmap(pcm);
|
|
|
|
|
if (!map) {
|
|
|
|
|
printf("Cannot get chmap\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2012-09-04 17:26:43 +02:00
|
|
|
printf("Get channels = %d\n", map->channels);
|
|
|
|
|
print_channels(map);
|
2012-07-30 15:50:44 +02:00
|
|
|
free(map);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
char *device = NULL;
|
|
|
|
|
int stream = SND_PCM_STREAM_PLAYBACK;
|
|
|
|
|
int format = SND_PCM_FORMAT_UNKNOWN;
|
|
|
|
|
int channels = 0;
|
|
|
|
|
int rate = 0;
|
|
|
|
|
snd_pcm_t *pcm;
|
|
|
|
|
int c;
|
|
|
|
|
|
|
|
|
|
while ((c = getopt(argc, argv, "D:s:f:c:r:")) != -1) {
|
|
|
|
|
switch (c) {
|
|
|
|
|
case 'D':
|
|
|
|
|
device = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 's':
|
|
|
|
|
if (*optarg == 'c' || *optarg == 'C')
|
|
|
|
|
stream = SND_PCM_STREAM_CAPTURE;
|
|
|
|
|
else
|
|
|
|
|
stream = SND_PCM_STREAM_PLAYBACK;
|
|
|
|
|
break;
|
|
|
|
|
case 'f':
|
|
|
|
|
format = snd_pcm_format_value(optarg);
|
|
|
|
|
break;
|
|
|
|
|
case 'c':
|
|
|
|
|
channels = atoi(optarg);
|
|
|
|
|
break;
|
|
|
|
|
case 'r':
|
|
|
|
|
rate = atoi(optarg);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
usage();
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (argc <= optind) {
|
|
|
|
|
usage();
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!device) {
|
|
|
|
|
printf("No device is specified\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (snd_pcm_open(&pcm, device, stream, SND_PCM_NONBLOCK) < 0) {
|
|
|
|
|
printf("Cannot open PCM stream %s for %s\n", device,
|
|
|
|
|
snd_pcm_stream_name(stream));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (*argv[optind]) {
|
|
|
|
|
case 'q':
|
|
|
|
|
return query_chmaps(pcm);
|
|
|
|
|
case 'g':
|
|
|
|
|
return get_chmap(pcm, format, channels, rate);
|
|
|
|
|
case 's':
|
|
|
|
|
return set_chmap(pcm, format, channels, rate,
|
|
|
|
|
argc - optind - 1, argv + optind + 1);
|
|
|
|
|
}
|
|
|
|
|
usage();
|
|
|
|
|
return 1;
|
|
|
|
|
}
|