audiomgmt_monitor.c example

This is a sample application shows how to get the current active audio types.

You can use the following options to run the program:

/*
 * $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

#endif
/* *INDENT-ON* */
//*****************************************************************************

void audiomgmt_cb ( snd_ctl_t *hdl, void *private_data, int cmd)
{
	int status, i, j;
	const char *ducking_output = private_data;
	snd_ducking_status_t *info = NULL;
	snd_ducking_type_status_t *active_type = NULL;


	switch (cmd)
	{
		case SND_CTL_READ_AUDIOMGMT_CHG:
			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 struture 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;
		default:
			break;
	}
}

int main (int argc, char *argv[])
{
	int c;
	fd_set rfds;
	int card = 0, ctl_fd;
	snd_ctl_t *handle;
	snd_ctl_callbacks_t callbacks;
	char *ducking_output = NULL;

	optind = 1;
	while ((c = getopt(argc, argv, "a:n:")) != EOF)
	{
		switch (c)
		{
			case 'a':
				card = strtol (optarg, &optarg, 0);
				break;
			case 'n':
				ducking_output = optarg;
				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;

	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;