| Updated: October 28, 2024 |
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