summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-07-30 15:50:44 +0200
committerTakashi Iwai <tiwai@suse.de>2012-09-11 11:34:50 +0200
commit3fc13d6f5b08edee49b106cd711d51bf3aef6ab7 (patch)
treed111732b4f327649522424bc413617f9b68836d0
parent662f79d4ec6b52bbaab28d5a9b60cc8bcdf042f9 (diff)
downloadalsa-lib-3fc13d6f5b08edee49b106cd711d51bf3aef6ab7.tar.gz
Add test/chmap program
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--.gitignore1
-rw-r--r--test/Makefile.am3
-rw-r--r--test/chmap.c254
3 files changed, 257 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 092fe641..4ff5483c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,6 +51,7 @@ test/latency
test/midiloop
test/namehint
test/oldapi
+test/chmap
test/pcm
test/pcm_min
test/playmidi1
diff --git a/test/Makefile.am b/test/Makefile.am
index ae524a4d..3000bfd9 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -2,7 +2,7 @@ SUBDIRS=. lsb
check_PROGRAMS=control pcm pcm_min latency seq \
playmidi1 timer rawmidi midiloop \
- oldapi queue_timer namehint client_event_filter
+ oldapi queue_timer namehint client_event_filter chmap
control_LDADD=../src/libasound.la
pcm_LDADD=../src/libasound.la
@@ -18,6 +18,7 @@ queue_timer_LDADD=../src/libasound.la
namehint_LDADD=../src/libasound.la
client_event_filter_LDADD=../src/libasound.la
code_CFLAGS=-Wall -pipe -g -O2
+chmap_LDADD=../src/libasound.la
INCLUDES=-I$(top_srcdir)/include
AM_CFLAGS=-Wall -pipe -g
diff --git a/test/chmap.c b/test/chmap.c
new file mode 100644
index 00000000..d91297c2
--- /dev/null
+++ b/test/chmap.c
@@ -0,0 +1,254 @@
+/*
+ * 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");
+}
+
+static const char * const chname[] = {
+ "Unknown",
+ "FL", "FC", "FR",
+ "FLC", "FRC", "RL", "RC", "RR",
+ "RLC", "RRC", "SL", "SR", "LFE",
+ "FLW", "FRW", "FLH",
+ "FCH", "FCH", "FRH",
+ "TC"
+};
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+
+static void print_channels(int channels, int *map)
+{
+ int i;
+ printf(" ");
+ for (i = 0; i < channels; i++) {
+ unsigned int c = *map++;
+ if (c >= ARRAY_SIZE(chname))
+ printf(" Ch%d", c);
+ else
+ printf(" %s", chname[c]);
+ }
+ printf("\n");
+}
+
+static int to_channel(const char *name)
+{
+ unsigned int i;
+
+ if (isdigit(*name))
+ return atoi(name);
+ for (i = 0; i < ARRAY_SIZE(chname); i++)
+ if (!strcmp(chname[i], name))
+ return i;
+ return 0;
+}
+
+static const char *chmap_type(int type)
+{
+ switch (type) {
+ case SND_CHMAP_NONE:
+ return "None";
+ case SND_CHMAP_FIXED:
+ return "Fixed";
+ case SND_CHMAP_VAR:
+ return "Variable";
+ case SND_CHMAP_PAIRED:
+ return "Paired";
+ default:
+ return "Unknown";
+ }
+}
+
+static int query_chmaps(snd_pcm_t *pcm)
+{
+ int **maps = snd_pcm_query_chmaps(pcm);
+ int **p, *v;
+
+ if (!maps) {
+ printf("Cannot query maps\n");
+ return 1;
+ }
+ for (p = maps; (v = *p) != NULL; p++) {
+ printf("Type = %s, Channels = %d\n", chmap_type(v[0]), v[1]);
+ print_channels(v[1], v + 2);
+ }
+ 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(&params);
+ 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)
+{
+ int *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);
+ print_channels(*map, map + 1);
+ free(map);
+ return 0;
+}
+
+static int set_chmap(snd_pcm_t *pcm, int format, int channels, int rate,
+ int nargs, char **arg)
+{
+ int i;
+ int *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;
+ for (i = 0; i < channels; i++)
+ map[i + 1] = to_channel(arg[i]);
+ 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);
+ print_channels(*map, map + 1);
+ 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;
+}