This is a sample application shows how to get the current active audio types.
/* * $QNXLicenseC: * Copyright 2017, QNX Software Systems. * * Licensed under the Apache License, Version 2.0 (the "License"). You * may not reproduce, modify or distribute this software except in * compliance with the License. You may obtain a copy of the License * at: http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * * This file may contain contributions from others, either as * contributors under the License or as licensors under other terms. * Please review this entire file for other proprietary rights or license * notices, as well as the QNX Development Suite License Guide at * http://licensing.qnx.com/license-guide/ for other information. * $ */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include <devctl.h> #include <errno.h> #include <sys/asoundlib.h> //***************************************************************************** /* *INDENT-OFF* */ #ifdef __USAGE %C [Options] Options: -a<cardno> Card number -n<output_id> Ducking output ID to monitor -l Use legacy status events #endif /* *INDENT-ON* */ //***************************************************************************** static void audiomgmt_cb ( snd_ctl_t *hdl, void *private_data, int cmd) { int status, i, j; const char *ducking_output = private_data; switch (cmd) { case SND_CTL_READ_AUDIOMGMT_CHG: /* deprecated - Use SND_CTL_READ_AUDIOMGMT_STATUS_CHG */ { snd_ducking_status_t *info = NULL; snd_ducking_type_status_t *active_type = NULL; if ((status = snd_ctl_ducking_read(hdl, ducking_output, &info )) != EOK) { printf("Failed to read ducking info - %s\n", snd_strerror(status)); return; } printf("\nActive audio types = %d\n", info->ntypes); /* The active_types structure is variable in size based on the number of pids it references, so we must * walk the active_type member of the info structure using the SND_DUCKING_STATUS_NEXT_TYPE() marco */ for (i = 0, active_type = info->active_types; i < info->ntypes; i++, active_type = SND_DUCKING_STATUS_NEXT_TYPE(active_type)) { printf("Audio Type %s, Priority %d\n", active_type->name, active_type->prio); printf("\tPids (%d): ", active_type->npids); for (j = 0; j < active_type->npids; j++) { printf("%d ", active_type->pids[j]); } printf("\n"); } /* snd_ctl_ducking_read() will allocate the info buffer, so we must free it */ free(info); break; } case SND_CTL_READ_AUDIOMGMT_STATUS_CHG: { snd_ducking_priority_status_t *info = NULL; if ((status = snd_ctl_ducking_status_read(hdl, ducking_output, &info )) != EOK) { printf("Failed to read ducking info - %s\n", snd_strerror(status)); return; } printf("Active Subchns (%d):\n", info->nsubchns); /* The priority status structure is variable in size based on the number of subchns it references, so we must * walk the entries member of the info structure using the SND_DUCKING_STATUS_NEXT_ENTRY() marco */ for (i = 0; i < info->nsubchns; i++) { printf("\tPriority: %d\n", info->subchns[i].prio); printf("\tPid: %d\n", info->subchns[i].pid); printf("\tAudio Type: %s\n", info->subchns[i].name); printf("\tState: "); if (info->subchns[i].state & SND_PCM_DUCKING_STATE_FORCED_ACTIVE) printf("FORCED_ACTIVE "); else printf("ACTIVE "); if (info->subchns[i].state & SND_PCM_DUCKING_STATE_DUCKED) printf("| DUCKED "); if (info->subchns[i].state & SND_PCM_DUCKING_STATE_HARD_SUSPENDED) printf("| HARD_SUSPENDED "); if (info->subchns[i].state & SND_PCM_DUCKING_STATE_SOFT_SUSPENDED) printf("| SOFT_SUSPENDED "); if (info->subchns[i].state & SND_PCM_DUCKING_STATE_PAUSED) printf("| PAUSED "); if (info->subchns[i].state & (SND_PCM_DUCKING_STATE_MUTE_BY_HIGHER|SND_PCM_DUCKING_STATE_MUTE_BY_SAME)) printf("| MUTED "); if (info->subchns[i].ducked_by & (SND_PCM_DUCKED_BY_SAME_PRIO|SND_PCM_DUCKED_BY_HIGHER_PRIO)) { printf("\n\tDucked by: "); if (info->subchns[i].ducked_by & SND_PCM_DUCKED_BY_SAME_PRIO) printf("SAME PRIORITY "); else if (info->subchns[i].ducked_by & SND_PCM_DUCKED_BY_HIGHER_PRIO) printf("HIGHER PRIORITY "); if (info->subchns[i].ducked_by & SND_PCM_DUCKED_BY_NONTRANSIENT) printf("| NON-TRANSIENT"); else printf("| TRANSIENT"); } printf("\n\n"); } printf("\n"); /* snd_ctl_ducking_status_read() will allocate the info buffer, so we must free it */ free(info); break; } default: break; } } int main (int argc, char *argv[]) { int c; int legacy = 0; fd_set rfds; int card = 0, ctl_fd; snd_ctl_t *handle; snd_ctl_callbacks_t callbacks; snd_ctl_filter_t filter; char *ducking_output = NULL; optind = 1; while ((c = getopt(argc, argv, "a:n:l")) != EOF) { switch (c) { case 'a': card = strtol (optarg, &optarg, 0); break; case 'n': ducking_output = optarg; break; case 'l': legacy = 1; break; default: break; } } if (ducking_output == NULL) { printf("Ducking output not provided\n"); return 1; } if (snd_ctl_open(&handle, card) != EOK) { printf("Failed to open control device on card %d\n", card); return 1; } ctl_fd = snd_ctl_file_descriptor(handle); memset(&callbacks, 0, sizeof (callbacks)); callbacks.private_data = ducking_output; callbacks.audiomgmt = &audiomgmt_cb; /* Enable audio management status events */ if (legacy) filter.enable = SND_CTL_EVENT_MASK(SND_CTL_READ_AUDIOMGMT_CHG); else filter.enable = SND_CTL_EVENT_MASK(SND_CTL_READ_AUDIOMGMT_STATUS_CHG); snd_ctl_set_filter(handle, &filter); FD_ZERO(&rfds); while (1) { FD_SET(ctl_fd, &rfds); if (select(ctl_fd + 1, &rfds, NULL, NULL, NULL) == -1) { printf("Select failed - %s\n", strerror(errno)); return 1; } if (FD_ISSET(ctl_fd, &rfds)) { snd_ctl_read(handle, &callbacks); } } snd_ctl_close (handle); return 0; } #if defined(__QNXNTO__) && defined(__USESRCVERSION) #include <sys/srcversion.h> __SRCVERSION("$URL$ $Rev$") #endif