1 /*
2 * channel mapping API test program
3 */
4
5 #include "config.h"
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <ctype.h>
10 #include <getopt.h>
11 #include "../include/asoundlib.h"
12
usage(void)13 static void usage(void)
14 {
15 printf("usage: chmap [options] query\n"
16 " chmap [options] get\n"
17 " chmap [options] set CH0 CH1 CH2...\n"
18 "options:\n"
19 " -D device Specify PCM device to handle\n"
20 " -s stream Specify PCM stream direction (playback/capture)\n"
21 " -f format PCM format\n"
22 " -c channels Channels\n"
23 " -r rate Sample rate\n");
24 }
25
print_channels(const snd_pcm_chmap_t * map)26 static void print_channels(const snd_pcm_chmap_t *map)
27 {
28 char tmp[128];
29 if (snd_pcm_chmap_print(map, sizeof(tmp), tmp) > 0)
30 printf(" %s\n", tmp);
31 }
32
query_chmaps(snd_pcm_t * pcm)33 static int query_chmaps(snd_pcm_t *pcm)
34 {
35 snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps(pcm);
36 snd_pcm_chmap_query_t **p, *v;
37
38 if (!maps) {
39 printf("Cannot query maps\n");
40 return 1;
41 }
42 for (p = maps; (v = *p) != NULL; p++) {
43 printf("Type = %s, Channels = %d\n",
44 snd_pcm_chmap_type_name(v->type),
45 v->map.channels);
46 print_channels(&v->map);
47 }
48 snd_pcm_free_chmaps(maps);
49 return 0;
50 }
51
setup_pcm(snd_pcm_t * pcm,int format,int channels,int rate)52 static int setup_pcm(snd_pcm_t *pcm, int format, int channels, int rate)
53 {
54 snd_pcm_hw_params_t *params;
55
56 snd_pcm_hw_params_alloca(¶ms);
57 if (snd_pcm_hw_params_any(pcm, params) < 0) {
58 printf("Cannot init hw_params\n");
59 return -1;
60 }
61 if (format != SND_PCM_FORMAT_UNKNOWN) {
62 if (snd_pcm_hw_params_set_format(pcm, params, format) < 0) {
63 printf("Cannot set format %s\n",
64 snd_pcm_format_name(format));
65 return -1;
66 }
67 }
68 if (channels > 0) {
69 if (snd_pcm_hw_params_set_channels(pcm, params, channels) < 0) {
70 printf("Cannot set channels %d\n", channels);
71 return -1;
72 }
73 }
74 if (rate > 0) {
75 if (snd_pcm_hw_params_set_rate_near(pcm, params, (unsigned int *)&rate, 0) < 0) {
76 printf("Cannot set rate %d\n", rate);
77 return -1;
78 }
79 }
80 if (snd_pcm_hw_params(pcm, params) < 0) {
81 printf("Cannot set hw_params\n");
82 return -1;
83 }
84 return 0;
85 }
86
get_chmap(snd_pcm_t * pcm,int format,int channels,int rate)87 static int get_chmap(snd_pcm_t *pcm, int format, int channels, int rate)
88 {
89 snd_pcm_chmap_t *map;
90
91 if (setup_pcm(pcm, format, channels, rate))
92 return 1;
93 map = snd_pcm_get_chmap(pcm);
94 if (!map) {
95 printf("Cannot get chmap\n");
96 return 1;
97 }
98 printf("Channels = %d\n", map->channels);
99 print_channels(map);
100 free(map);
101 return 0;
102 }
103
set_chmap(snd_pcm_t * pcm,int format,int channels,int rate,int nargs,char ** arg)104 static int set_chmap(snd_pcm_t *pcm, int format, int channels, int rate,
105 int nargs, char **arg)
106 {
107 int i;
108 snd_pcm_chmap_t *map;
109
110 if (channels && channels != nargs) {
111 printf("Inconsistent channels %d vs %d\n", channels, nargs);
112 return 1;
113 }
114 if (!channels) {
115 if (!nargs) {
116 printf("No channels are given\n");
117 return 1;
118 }
119 channels = nargs;
120 }
121 if (setup_pcm(pcm, format, channels, rate))
122 return 1;
123 map = malloc(sizeof(int) * (channels + 1));
124 if (!map) {
125 printf("cannot malloc\n");
126 return 1;
127 }
128 map->channels = channels;
129 for (i = 0; i < channels; i++) {
130 int val = snd_pcm_chmap_from_string(arg[i]);
131 if (val < 0)
132 val = SND_CHMAP_UNKNOWN;
133 map->pos[i] = val;
134 }
135 if (snd_pcm_set_chmap(pcm, map) < 0) {
136 printf("Cannot set chmap\n");
137 return 1;
138 }
139 free(map);
140
141 map = snd_pcm_get_chmap(pcm);
142 if (!map) {
143 printf("Cannot get chmap\n");
144 return 1;
145 }
146 printf("Get channels = %d\n", map->channels);
147 print_channels(map);
148 free(map);
149 return 0;
150 }
151
main(int argc,char ** argv)152 int main(int argc, char **argv)
153 {
154 char *device = NULL;
155 int stream = SND_PCM_STREAM_PLAYBACK;
156 int format = SND_PCM_FORMAT_UNKNOWN;
157 int channels = 0;
158 int rate = 0;
159 snd_pcm_t *pcm;
160 int c;
161
162 while ((c = getopt(argc, argv, "D:s:f:c:r:")) != -1) {
163 switch (c) {
164 case 'D':
165 device = optarg;
166 break;
167 case 's':
168 if (*optarg == 'c' || *optarg == 'C')
169 stream = SND_PCM_STREAM_CAPTURE;
170 else
171 stream = SND_PCM_STREAM_PLAYBACK;
172 break;
173 case 'f':
174 format = snd_pcm_format_value(optarg);
175 break;
176 case 'c':
177 channels = atoi(optarg);
178 break;
179 case 'r':
180 rate = atoi(optarg);
181 break;
182 default:
183 usage();
184 return 1;
185 }
186 }
187
188 if (argc <= optind) {
189 usage();
190 return 1;
191 }
192
193 if (!device) {
194 printf("No device is specified\n");
195 return 1;
196 }
197
198 if (snd_pcm_open(&pcm, device, stream, SND_PCM_NONBLOCK) < 0) {
199 printf("Cannot open PCM stream %s for %s\n", device,
200 snd_pcm_stream_name(stream));
201 return 1;
202 }
203
204 switch (*argv[optind]) {
205 case 'q':
206 return query_chmaps(pcm);
207 case 'g':
208 return get_chmap(pcm, format, channels, rate);
209 case 's':
210 return set_chmap(pcm, format, channels, rate,
211 argc - optind - 1, argv + optind + 1);
212 }
213 usage();
214 return 1;
215 }
216