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