Add test/chmap program
authorTakashi Iwai <tiwai@suse.de>
Mon, 30 Jul 2012 13:50:44 +0000 (15:50 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 11 Sep 2012 09:34:50 +0000 (11:34 +0200)
Signed-off-by: Takashi Iwai <tiwai@suse.de>

.gitignore
test/Makefile.am
test/chmap.c [new file with mode: 0644]

index 092fe64..4ff5483 100644 (file)
@@ -51,6 +51,7 @@ test/latency
 test/midiloop
 test/namehint
 test/oldapi
+test/chmap
 test/pcm
 test/pcm_min
 test/playmidi1
index ae524a4..3000bfd 100644 (file)
@@ -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 (file)
index 0000000..d91297c
--- /dev/null
@@ -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;
+}