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