This is the source for the apx_ctl utility.
For information about using this utility, see apx_ctl in the QNX Neutrino Utilities Reference.
/* * Copyright 2018, QNX Software Systems Ltd. All Rights Reserved. * * This source code may contain confidential information of QNX Software * Systems Ltd. (QSSL) and its licensors. Any use, reproduction, * modification, disclosure, distribution or transfer of this software, * or any software which includes or is based upon any of this code, is * prohibited unless expressly authorized by QSSL by written agreement. For * more information (including whether this source code file has been * published) please email licensing@qnx.com. */ #include <stdio.h> #include <stdlib.h> #include <sys/asoundlib.h> #include <string.h> #include <devctl.h> #include <errno.h> #include <ctype.h> #include <ioctl.h> //***************************************************************************** /* *INDENT-OFF* */ #ifdef __USAGE %C [Options] Options: -a [card#:]<dev#> the card & device number to access OR -a[name] the card name to access -e <chns:volume_chn0:...:volume_chnN> set volume of external amplifiers (outside of io-audio system) -u <user volume> override default user volume, with system output volume -t <apx_id:dataset> load runtime acoustic processing dataset -x <apx_id:param_id:chn>[:data] calls set/get data on apx for parameters of size int16_t -y <apx_id:param_id:chn>[:data] calls set/get data on apx for parameters of size int32_t SPM : apx_id=1 SFO : apx_id=2 #endif /* *INDENT-ON* */ //***************************************************************************** const char* optstring = "a:e:u:t:x:y:"; static snd_pcm_t* setup_pcm_handle(char* arg) { int rtn; int dev = 0, card = 0; const char* name = NULL; snd_pcm_t* pcm_handle = NULL; if (strchr (arg, ':')) { card = strtol (arg, &arg, 0); if (errno == ERANGE || errno == EINVAL) { fprintf(stderr, "Invalid card number\n"); return NULL; } if (*arg) arg++; dev = strtol (arg, NULL, 0); if (errno == ERANGE || errno == EINVAL) { fprintf(stderr, "Invalid device number\n"); return NULL; } } else if (isalpha (arg[0]) || arg[0] == '/') { name = arg; } else { dev = strtol (arg, NULL, 0); if (errno == ERANGE || errno == EINVAL) { fprintf(stderr, "Invalid device number\n"); return NULL; } } if (name) { fprintf (stderr, "Using device %s\n", name); rtn = snd_pcm_open_name(&pcm_handle, name, SND_PCM_OPEN_PLAYBACK); } else { fprintf (stderr, "Using card %d device %d \n", card, dev); rtn = snd_pcm_open (&pcm_handle, card, dev, SND_PCM_OPEN_PLAYBACK); } if (rtn < 0) { fprintf(stderr, "Cannot open pcm device\n"); return NULL; } return pcm_handle; } static int set_ext_vol(snd_pcm_t* pcm_handle, const char* arg) { int i, rtn; int16_t ext_vol [32] = {0}; int ext_vol_channels = strtol (optarg, &optarg, 0); if (errno == ERANGE || errno == EINVAL || ext_vol_channels > 32) { fprintf(stderr, "Invalid number of external volume channels\n"); return 1; } for (i = 0; (i < 32) && optarg && (*optarg == ':') && (errno != ERANGE) && (errno != EINVAL); i++) { optarg++; ext_vol[i] = strtol (optarg, &optarg, 0); } rtn = snd_pcm_set_apx_external_volume(pcm_handle, ext_vol_channels, ext_vol); printf("APX set external volume ret=%d -- %s\n", rtn, strerror(rtn)); return rtn; } static int set_user_vol(snd_pcm_t* pcm_handle, int16_t vol) { int rtn = snd_pcm_set_apx_user_volume(pcm_handle, vol); printf("APX set user volume to %d ret=%d -- %s\n", vol, rtn, strerror(rtn)); return rtn; } static int set_dataset(snd_pcm_t* pcm_handle, char* dataset) { int rtn, ap_status = 0; int32_t apx_id = strtol (dataset, &dataset, 0); if (errno == ERANGE || errno == EINVAL) { fprintf(stderr, "Invalid apx id\n"); return 1; } dataset++; printf("Loading dataset %s\n", dataset); if ((rtn = snd_pcm_load_apx_dataset(pcm_handle, apx_id, dataset, &ap_status)) != EOK) printf("Failed to load dataset: (%d) %s\n", rtn, snd_strerror(rtn)); if (ap_status != 0) { printf("Acoustic processing returned status=0x%04X\n", ap_status); } return rtn; } static int set_ap_data(snd_pcm_t* pcm_handle, char* arg, size_t data_size) { int set_data, rtn; int32_t apx_id; uint32_t data; snd_pcm_apx_param_t param = { .size = data_size, }; apx_id = strtol (arg, &arg, 0); if (errno == ERANGE || errno == EINVAL) { fprintf(stderr, "Invalid apx id\n"); return 1; } if (*arg) arg++; param.dataId = strtol (arg, &arg, 0); if (errno == ERANGE || errno == EINVAL) { fprintf(stderr, "Invalid apx data id\n"); return 1; } if (*arg) arg++; param.channel = strtol (arg, &arg, 0); if (errno == ERANGE || errno == EINVAL) { fprintf(stderr, "Invalid apx channel\n"); return 1; } if (*arg) arg++; data = strtol (arg, NULL, 0); set_data = (errno != ERANGE && errno != EINVAL); errno = EOK; if (set_data) { printf("APX set_ap_data apx=%d id=0x%04x data=%d ", apx_id, param.dataId, data); rtn = snd_pcm_set_apx_data(pcm_handle, apx_id, ¶m, &data); } else { printf("APX get_ap_data apx=%d id=0x%04x ", apx_id, param.dataId); rtn = snd_pcm_get_apx_data(pcm_handle, apx_id, ¶m, &data); } printf("ret=%d ap_ret=%d data_ret=%d -- %s\n", rtn, param.status, data, strerror(-rtn)); return rtn; } int main(int argc, char *argv[]) { int rtn = EOK; snd_pcm_t *pcm_handle = NULL; int c; /* first setup pcm handle */ while ((c = getopt(argc, argv, optstring)) != EOF) { switch (c) { case 'a': if (!(pcm_handle = setup_pcm_handle(optarg))) { return EXIT_FAILURE; } break; default: break; } } if (!pcm_handle) { fprintf (stderr, "Using preferred device \n"); if (snd_pcm_open_preferred(&pcm_handle, NULL, NULL, SND_PCM_OPEN_PLAYBACK) != EOK) { fprintf(stderr, "Cannot open pcm device\n"); return EXIT_FAILURE; } } /* reset optind and handle other options */ optind = 1; while (((c = getopt(argc, argv, optstring)) != EOF) && (rtn == EOK)) { switch (c) { case 'a': break; case 'e': rtn = set_ext_vol(pcm_handle, optarg); break; case 'u': rtn = set_user_vol(pcm_handle, atoi(optarg)); break; case 't': rtn = set_dataset(pcm_handle, optarg); break; case 'x': rtn = set_ap_data(pcm_handle, optarg, sizeof(uint16_t)); break; case 'y': rtn = set_ap_data(pcm_handle, optarg, sizeof(uint32_t)); break; default: printf("Invalid option '%c'\n", c); rtn = -1; break; } } snd_pcm_close(pcm_handle); return (rtn == EOK) ? EXIT_SUCCESS : EXIT_FAILURE; } #if defined(__QNXNTO__) && defined(__USESRCVERSION) #include <sys/srcversion.h> __SRCVERSION("$URL$ $Rev$") #endif