• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params);
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