/* * channel mapping API test program */ #include #include #include #include #include #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" " -s stream Specify PCM stream direction (playback/capture)\n" " -f format PCM format\n" " -c channels Channels\n" " -r rate Sample rate\n"); } static void print_channels(const snd_pcm_chmap_t *map) { char tmp[128]; if (snd_pcm_chmap_print(map, sizeof(tmp), tmp) > 0) printf(" %s\n", tmp); } static int query_chmaps(snd_pcm_t *pcm) { snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps(pcm); snd_pcm_chmap_query_t **p, *v; if (!maps) { printf("Cannot query maps\n"); return 1; } for (p = maps; (v = *p) != NULL; p++) { printf("Type = %s, Channels = %d\n", snd_pcm_chmap_type_name(v->type), v->map.channels); print_channels(&v->map); } 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) { snd_pcm_chmap_t *map; if (setup_pcm(pcm, format, channels, rate)) return 1; map = snd_pcm_get_chmap(pcm); if (!map) { printf("Cannot get chmap\n"); return 1; } printf("Channels = %d\n", map->channels); print_channels(map); free(map); return 0; } static int set_chmap(snd_pcm_t *pcm, int format, int channels, int rate, int nargs, char **arg) { int i; snd_pcm_chmap_t *map; 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; map = malloc(sizeof(int) * (channels + 1)); if (!map) { printf("cannot malloc\n"); return 1; } map->channels = channels; 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; } 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; } printf("Get channels = %d\n", map->channels); print_channels(map); 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; }