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