mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			214 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			214 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * 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"
 | 
						|
	       "  -s stream     Specify PCM stream direction (playback/capture)\n"
 | 
						|
	       "  -f format     PCM format\n"
 | 
						|
	       "  -c channels   Channels\n"
 | 
						|
	       "  -r rate       Sample rate\n");
 | 
						|
}
 | 
						|
 | 
						|
static void print_channels(const snd_pcm_chmap_t *map)
 | 
						|
{
 | 
						|
	char tmp[128];
 | 
						|
	if (snd_pcm_chmap_print(map, sizeof(tmp), tmp) > 0)
 | 
						|
		printf("  %s\n", tmp);
 | 
						|
}
 | 
						|
 | 
						|
static int query_chmaps(snd_pcm_t *pcm)
 | 
						|
{
 | 
						|
	snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps(pcm);
 | 
						|
	snd_pcm_chmap_query_t **p, *v;
 | 
						|
 | 
						|
	if (!maps) {
 | 
						|
		printf("Cannot query maps\n");
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
	for (p = maps; (v = *p) != NULL; p++) {
 | 
						|
		printf("Type = %s, Channels = %d\n",
 | 
						|
		       snd_pcm_chmap_type_name(v->type),
 | 
						|
		       v->map.channels);
 | 
						|
		print_channels(&v->map);
 | 
						|
	}
 | 
						|
	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(¶ms);
 | 
						|
	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)
 | 
						|
{
 | 
						|
	snd_pcm_chmap_t *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->channels);
 | 
						|
	print_channels(map);
 | 
						|
	free(map);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int set_chmap(snd_pcm_t *pcm, int format, int channels, int rate,
 | 
						|
		     int nargs, char **arg)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	snd_pcm_chmap_t *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 = channels;
 | 
						|
	for (i = 0; i < channels; i++) {
 | 
						|
		int val = snd_pcm_chmap_from_string(arg[i]);
 | 
						|
		if (val < 0)
 | 
						|
			val = SND_CHMAP_UNKNOWN;
 | 
						|
		map->pos[i] = val;
 | 
						|
	}
 | 
						|
	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->channels);
 | 
						|
	print_channels(map);
 | 
						|
	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;
 | 
						|
}
 |