Blame src/control/hcontrol.c

Packit 4a16fb
/**
Packit 4a16fb
 * \file control/hcontrol.c
Packit 4a16fb
 * \brief HCTL Interface - High Level CTL
Packit 4a16fb
 * \author Jaroslav Kysela <perex@perex.cz>
Packit 4a16fb
 * \author Abramo Bagnara <abramo@alsa-project.org>
Packit 4a16fb
 * \date 2000
Packit 4a16fb
 *
Packit 4a16fb
 * HCTL interface is designed to access preloaded and sorted primitive controls.
Packit 4a16fb
 * Callbacks may be used for event handling.
Packit 4a16fb
 * See \ref hcontrol page for more details.
Packit 4a16fb
 */
Packit 4a16fb
/*
Packit 4a16fb
 *  Control Interface - high level API
Packit 4a16fb
 *  Copyright (c) 2000 by Jaroslav Kysela <perex@perex.cz>
Packit 4a16fb
 *  Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org>
Packit 4a16fb
 *
Packit 4a16fb
 *
Packit 4a16fb
 *   This library is free software; you can redistribute it and/or modify
Packit 4a16fb
 *   it under the terms of the GNU Lesser General Public License as
Packit 4a16fb
 *   published by the Free Software Foundation; either version 2.1 of
Packit 4a16fb
 *   the License, or (at your option) any later version.
Packit 4a16fb
 *
Packit 4a16fb
 *   This program is distributed in the hope that it will be useful,
Packit 4a16fb
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 4a16fb
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 4a16fb
 *   GNU Lesser General Public License for more details.
Packit 4a16fb
 *
Packit 4a16fb
 *   You should have received a copy of the GNU Lesser General Public
Packit 4a16fb
 *   License along with this library; if not, write to the Free Software
Packit 4a16fb
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit 4a16fb
 *
Packit 4a16fb
 */
Packit 4a16fb
Packit 4a16fb
/*! \page hcontrol High level control interface
Packit 4a16fb
Packit 4a16fb

High level control interface is designed to access preloaded and sorted primitive controls.

Packit 4a16fb
Packit 4a16fb
\section hcontrol_general_overview General overview
Packit 4a16fb
Packit 4a16fb

High level control interface caches the accesses to primitive controls

Packit 4a16fb
to reduce overhead accessing the real controls in kernel drivers.
Packit 4a16fb
Packit 4a16fb
*/
Packit 4a16fb
Packit 4a16fb
#include <stdio.h>
Packit 4a16fb
#include <stdlib.h>
Packit 4a16fb
#include <unistd.h>
Packit 4a16fb
#include <string.h>
Packit 4a16fb
#include <fcntl.h>
Packit 4a16fb
#include <sys/ioctl.h>
Packit 4a16fb
#include "control_local.h"
Packit 4a16fb
#ifdef HAVE_LIBPTHREAD
Packit 4a16fb
#include <pthread.h>
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
#ifndef DOC_HIDDEN
Packit 4a16fb
#define NOT_FOUND 1000000000
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
static int snd_hctl_compare_default(const snd_hctl_elem_t *c1,
Packit 4a16fb
				    const snd_hctl_elem_t *c2);
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Opens an HCTL
Packit 4a16fb
 * \param hctlp Returned HCTL handle
Packit 4a16fb
 * \param name ASCII identifier of the underlying CTL handle
Packit 4a16fb
 * \param mode Open mode (see #SND_CTL_NONBLOCK, #SND_CTL_ASYNC)
Packit 4a16fb
 * \return 0 on success otherwise a negative error code
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_open(snd_hctl_t **hctlp, const char *name, int mode)
Packit 4a16fb
{
Packit 4a16fb
	snd_ctl_t *ctl;
Packit 4a16fb
	int err;
Packit 4a16fb
	
Packit 4a16fb
	if ((err = snd_ctl_open(&ctl, name, mode)) < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	err = snd_hctl_open_ctl(hctlp, ctl);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		snd_ctl_close(ctl);
Packit 4a16fb
	return err;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Opens an HCTL
Packit 4a16fb
 * \param hctlp Returned HCTL handle
Packit 4a16fb
 * \param ctl underlying CTL handle
Packit 4a16fb
 * \return 0 on success otherwise a negative error code
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_open_ctl(snd_hctl_t **hctlp, snd_ctl_t *ctl)
Packit 4a16fb
{
Packit 4a16fb
	snd_hctl_t *hctl;
Packit 4a16fb
Packit 4a16fb
	assert(hctlp);
Packit 4a16fb
	*hctlp = NULL;
Packit 4a16fb
	if ((hctl = (snd_hctl_t *)calloc(1, sizeof(snd_hctl_t))) == NULL)
Packit 4a16fb
		return -ENOMEM;
Packit 4a16fb
	INIT_LIST_HEAD(&hctl->elems);
Packit 4a16fb
	hctl->ctl = ctl;
Packit 4a16fb
	*hctlp = hctl;
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief close HCTL handle
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \return 0 on success otherwise a negative error code
Packit 4a16fb
 *
Packit 4a16fb
 * Closes the specified HCTL handle and frees all associated
Packit 4a16fb
 * resources.
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_close(snd_hctl_t *hctl)
Packit 4a16fb
{
Packit 4a16fb
	int err;
Packit 4a16fb
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	err = snd_ctl_close(hctl->ctl);
Packit 4a16fb
	snd_hctl_free(hctl);
Packit 4a16fb
	free(hctl);
Packit 4a16fb
	return err;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief get identifier of HCTL handle
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \return ascii identifier of HCTL handle
Packit 4a16fb
 *
Packit 4a16fb
 * Returns the ASCII identifier of given HCTL handle. It's the same
Packit 4a16fb
 * identifier specified in snd_hctl_open().
Packit 4a16fb
 */
Packit 4a16fb
const char *snd_hctl_name(snd_hctl_t *hctl)
Packit 4a16fb
{
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	return snd_ctl_name(hctl->ctl);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief set nonblock mode
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \param nonblock 0 = block, 1 = nonblock mode
Packit 4a16fb
 * \return 0 on success otherwise a negative error code
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_nonblock(snd_hctl_t *hctl, int nonblock)
Packit 4a16fb
{
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	return snd_ctl_nonblock(hctl->ctl, nonblock);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief set async mode
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \param sig Signal to raise: < 0 disable, 0 default (SIGIO)
Packit 4a16fb
 * \param pid Process ID to signal: 0 current
Packit 4a16fb
 * \return 0 on success otherwise a negative error code
Packit 4a16fb
 *
Packit 4a16fb
 * A signal is raised when a change happens.
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_async(snd_hctl_t *hctl, int sig, pid_t pid)
Packit 4a16fb
{
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	return snd_ctl_async(hctl->ctl, sig, pid);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief get count of poll descriptors for HCTL handle
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \return count of poll descriptors
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_poll_descriptors_count(snd_hctl_t *hctl)
Packit 4a16fb
{
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	return snd_ctl_poll_descriptors_count(hctl->ctl);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief get poll descriptors
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \param pfds array of poll descriptors
Packit 4a16fb
 * \param space space in the poll descriptor array
Packit 4a16fb
 * \return count of filled descriptors
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_poll_descriptors(snd_hctl_t *hctl, struct pollfd *pfds, unsigned int space)
Packit 4a16fb
{
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	return snd_ctl_poll_descriptors(hctl->ctl, pfds, space);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief get returned events from poll descriptors
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \param pfds array of poll descriptors
Packit 4a16fb
 * \param nfds count of poll descriptors
Packit 4a16fb
 * \param revents returned events
Packit 4a16fb
 * \return zero if success, otherwise a negative error code
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_poll_descriptors_revents(snd_hctl_t *hctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
Packit 4a16fb
{
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	return snd_ctl_poll_descriptors_revents(hctl->ctl, pfds, nfds, revents);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int snd_hctl_throw_event(snd_hctl_t *hctl, unsigned int mask,
Packit 4a16fb
			 snd_hctl_elem_t *elem)
Packit 4a16fb
{
Packit 4a16fb
	if (hctl->callback)
Packit 4a16fb
		return hctl->callback(hctl, mask, elem);
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int snd_hctl_elem_throw_event(snd_hctl_elem_t *elem,
Packit 4a16fb
			      unsigned int mask)
Packit 4a16fb
{
Packit 4a16fb
	if (elem->callback)
Packit 4a16fb
		return elem->callback(elem, mask);
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int snd_hctl_compare_mixer_priority_lookup(const char **name, const char * const *names, int coef)
Packit 4a16fb
{
Packit 4a16fb
	int res;
Packit 4a16fb
Packit 4a16fb
	for (res = 0; *names; names++, res += coef) {
Packit 4a16fb
		if (!strncmp(*name, *names, strlen(*names))) {
Packit 4a16fb
			*name += strlen(*names);
Packit 4a16fb
			if (**name == ' ')
Packit 4a16fb
				(*name)++;
Packit 4a16fb
			return res+1;
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	return NOT_FOUND;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int get_compare_weight(const snd_ctl_elem_id_t *id)
Packit 4a16fb
{
Packit 4a16fb
	static const char *const names[] = {
Packit 4a16fb
		"Master",
Packit 4a16fb
		"Hardware Master",
Packit 4a16fb
		"Headphone",
Packit 4a16fb
		"Tone Control",
Packit 4a16fb
		"3D Control",
Packit 4a16fb
		"PCM",
Packit 4a16fb
		"Front",
Packit 4a16fb
		"Surround",
Packit 4a16fb
		"Center",
Packit 4a16fb
		"LFE",
Packit 4a16fb
		"Synth",
Packit 4a16fb
		"FM",
Packit 4a16fb
		"Wave",
Packit 4a16fb
		"Music",
Packit 4a16fb
		"DSP",
Packit 4a16fb
		"Line",
Packit 4a16fb
		"CD",
Packit 4a16fb
		"Mic",
Packit 4a16fb
		"Phone",
Packit 4a16fb
		"Video",
Packit 4a16fb
		"Zoom Video",
Packit 4a16fb
		"PC Speaker",
Packit 4a16fb
		"Aux",
Packit 4a16fb
		"Mono",
Packit 4a16fb
		"ADC",
Packit 4a16fb
		"Capture Source",
Packit 4a16fb
		"Capture",
Packit 4a16fb
		"Playback",
Packit 4a16fb
		"Loopback",
Packit 4a16fb
		"Analog Loopback",
Packit 4a16fb
		"Digital Loopback",
Packit 4a16fb
		"I2S",
Packit 4a16fb
		"IEC958",
Packit 4a16fb
		NULL
Packit 4a16fb
	};
Packit 4a16fb
	static const char *const names1[] = {
Packit 4a16fb
		"Switch",
Packit 4a16fb
		"Volume",
Packit 4a16fb
		"Playback",
Packit 4a16fb
		"Capture",
Packit 4a16fb
		"Bypass",
Packit 4a16fb
		"Mono",
Packit 4a16fb
		"Front",
Packit 4a16fb
		"Rear",
Packit 4a16fb
		"Pan",
Packit 4a16fb
		"Output",
Packit 4a16fb
		"-",
Packit 4a16fb
		NULL
Packit 4a16fb
	};
Packit 4a16fb
	static const char *const names2[] = {
Packit 4a16fb
		"Switch",
Packit 4a16fb
		"Volume",
Packit 4a16fb
		"Bypass",
Packit 4a16fb
		"Depth",
Packit 4a16fb
		"Wide",
Packit 4a16fb
		"Space",
Packit 4a16fb
		"Level",
Packit 4a16fb
		"Center",
Packit 4a16fb
		NULL
Packit 4a16fb
	};
Packit 4a16fb
	const char *name = (char *)id->name, *name1;
Packit 4a16fb
	int res, res1;
Packit 4a16fb
	
Packit 4a16fb
	if ((res = snd_hctl_compare_mixer_priority_lookup((const char **)&name, names, 1000000)) == NOT_FOUND)
Packit 4a16fb
		return NOT_FOUND;
Packit 4a16fb
	if (*name == '\0')
Packit 4a16fb
		return res;
Packit 4a16fb
	for (name1 = name; *name1 != '\0'; name1++);
Packit 4a16fb
	for (name1--; name1 != name && *name1 != ' '; name1--);
Packit 4a16fb
	while (name1 != name && *name1 == ' ')
Packit 4a16fb
		name1--;
Packit 4a16fb
	if (name1 != name) {
Packit 4a16fb
		for (; name1 != name && *name1 != ' '; name1--);
Packit 4a16fb
		name = name1;
Packit 4a16fb
		if ((res1 = snd_hctl_compare_mixer_priority_lookup((const char **)&name, names1, 1000)) == NOT_FOUND)
Packit 4a16fb
			return res;
Packit 4a16fb
		res += res1;
Packit 4a16fb
	} else {
Packit 4a16fb
		name = name1;
Packit 4a16fb
	}
Packit 4a16fb
	if ((res1 = snd_hctl_compare_mixer_priority_lookup((const char **)&name, names2, 1)) == NOT_FOUND)
Packit 4a16fb
		return res;
Packit 4a16fb
	return res + res1;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int _snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id, int *dir)
Packit 4a16fb
{
Packit 4a16fb
	unsigned int l, u;
Packit 4a16fb
	snd_hctl_elem_t el;
Packit 4a16fb
	int c = 0;
Packit 4a16fb
	int idx = -1;
Packit 4a16fb
	assert(hctl && id);
Packit 4a16fb
	assert(hctl->compare);
Packit 4a16fb
	el.id = *id;
Packit 4a16fb
	el.compare_weight = get_compare_weight(id);
Packit 4a16fb
	l = 0;
Packit 4a16fb
	u = hctl->count;
Packit 4a16fb
	while (l < u) {
Packit 4a16fb
		idx = (l + u) / 2;
Packit 4a16fb
		c = hctl->compare(&el, hctl->pelems[idx]);
Packit 4a16fb
		if (c < 0)
Packit 4a16fb
			u = idx;
Packit 4a16fb
		else if (c > 0)
Packit 4a16fb
			l = idx + 1;
Packit 4a16fb
		else
Packit 4a16fb
			break;
Packit 4a16fb
	}
Packit 4a16fb
	*dir = c;
Packit 4a16fb
	return idx;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int snd_hctl_elem_add(snd_hctl_t *hctl, snd_hctl_elem_t *elem)
Packit 4a16fb
{
Packit 4a16fb
	int dir;
Packit 4a16fb
	int idx; 
Packit 4a16fb
	elem->compare_weight = get_compare_weight(&elem->id);
Packit 4a16fb
	if (hctl->count == hctl->alloc) {
Packit 4a16fb
		snd_hctl_elem_t **h;
Packit 4a16fb
		hctl->alloc += 32;
Packit 4a16fb
		h = realloc(hctl->pelems, sizeof(*h) * hctl->alloc);
Packit 4a16fb
		if (!h) {
Packit 4a16fb
			hctl->alloc -= 32;
Packit 4a16fb
			return -ENOMEM;
Packit 4a16fb
		}
Packit 4a16fb
		hctl->pelems = h;
Packit 4a16fb
	}
Packit 4a16fb
	if (hctl->count == 0) {
Packit 4a16fb
		list_add_tail(&elem->list, &hctl->elems);
Packit 4a16fb
		hctl->pelems[0] = elem;
Packit 4a16fb
	} else {
Packit 4a16fb
		idx = _snd_hctl_find_elem(hctl, &elem->id, &dir;;
Packit 4a16fb
		assert(dir != 0);
Packit 4a16fb
		if (dir > 0) {
Packit 4a16fb
			list_add(&elem->list, &hctl->pelems[idx]->list);
Packit 4a16fb
			idx++;
Packit 4a16fb
		} else {
Packit 4a16fb
			list_add_tail(&elem->list, &hctl->pelems[idx]->list);
Packit 4a16fb
		}
Packit 4a16fb
		memmove(hctl->pelems + idx + 1,
Packit 4a16fb
			hctl->pelems + idx,
Packit 4a16fb
			(hctl->count - idx) * sizeof(snd_hctl_elem_t *));
Packit 4a16fb
		hctl->pelems[idx] = elem;
Packit 4a16fb
	}
Packit 4a16fb
	hctl->count++;
Packit 4a16fb
	return snd_hctl_throw_event(hctl, SNDRV_CTL_EVENT_MASK_ADD, elem);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static void snd_hctl_elem_remove(snd_hctl_t *hctl, unsigned int idx)
Packit 4a16fb
{
Packit 4a16fb
	snd_hctl_elem_t *elem = hctl->pelems[idx];
Packit 4a16fb
	unsigned int m;
Packit 4a16fb
	snd_hctl_elem_throw_event(elem, SNDRV_CTL_EVENT_MASK_REMOVE);
Packit 4a16fb
	list_del(&elem->list);
Packit 4a16fb
	free(elem);
Packit 4a16fb
	hctl->count--;
Packit 4a16fb
	m = hctl->count - idx;
Packit 4a16fb
	if (m > 0)
Packit 4a16fb
		memmove(hctl->pelems + idx,
Packit 4a16fb
			hctl->pelems + idx + 1,
Packit 4a16fb
			m * sizeof(snd_hctl_elem_t *));
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief free HCTL loaded elements
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \return 0 on success otherwise a negative error code
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_free(snd_hctl_t *hctl)
Packit 4a16fb
{
Packit 4a16fb
	while (hctl->count > 0)
Packit 4a16fb
		snd_hctl_elem_remove(hctl, hctl->count - 1);
Packit 4a16fb
	free(hctl->pelems);
Packit 4a16fb
	hctl->pelems = 0;
Packit 4a16fb
	hctl->alloc = 0;
Packit 4a16fb
	INIT_LIST_HEAD(&hctl->elems);
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static snd_hctl_t *compare_hctl;
Packit 4a16fb
static int hctl_compare(const void *a, const void *b) {
Packit 4a16fb
	return compare_hctl->compare(*(const snd_hctl_elem_t * const *) a,
Packit 4a16fb
			     *(const snd_hctl_elem_t * const *) b);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static void snd_hctl_sort(snd_hctl_t *hctl)
Packit 4a16fb
{
Packit 4a16fb
	unsigned int k;
Packit 4a16fb
#ifdef HAVE_LIBPTHREAD
Packit 4a16fb
	static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	assert(hctl->compare);
Packit 4a16fb
	INIT_LIST_HEAD(&hctl->elems);
Packit 4a16fb
Packit 4a16fb
#ifdef HAVE_LIBPTHREAD
Packit 4a16fb
	pthread_mutex_lock(&sync_lock);
Packit 4a16fb
#endif
Packit 4a16fb
	compare_hctl = hctl;
Packit 4a16fb
	qsort(hctl->pelems, hctl->count, sizeof(*hctl->pelems), hctl_compare);
Packit 4a16fb
#ifdef HAVE_LIBPTHREAD
Packit 4a16fb
	pthread_mutex_unlock(&sync_lock);
Packit 4a16fb
#endif
Packit 4a16fb
	for (k = 0; k < hctl->count; k++)
Packit 4a16fb
		list_add_tail(&hctl->pelems[k]->list, &hctl->elems);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Change HCTL compare function and reorder elements
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \param compare Element compare function
Packit 4a16fb
 * \return 0 on success otherwise a negative error code
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_set_compare(snd_hctl_t *hctl, snd_hctl_compare_t compare)
Packit 4a16fb
{
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	hctl->compare = compare == NULL ? snd_hctl_compare_default : compare;
Packit 4a16fb
	snd_hctl_sort(hctl);
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief A "don't care" fast compare functions that may be used with #snd_hctl_set_compare
Packit 4a16fb
 * \param c1 First HCTL element
Packit 4a16fb
 * \param c2 Second HCTL element
Packit 4a16fb
 * \return -1 if c1 < c2, 0 if c1 == c2, 1 if c1 > c2
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_compare_fast(const snd_hctl_elem_t *c1,
Packit 4a16fb
			  const snd_hctl_elem_t *c2)
Packit 4a16fb
{
Packit 4a16fb
	return c1->id.numid - c2->id.numid;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int snd_hctl_compare_default(const snd_hctl_elem_t *c1,
Packit 4a16fb
				    const snd_hctl_elem_t *c2)
Packit 4a16fb
{
Packit 4a16fb
	int res, d;
Packit 4a16fb
Packit 4a16fb
	d = c1->id.iface - c2->id.iface;
Packit 4a16fb
	if (d != 0)
Packit 4a16fb
		return d;
Packit 4a16fb
	if (c1->id.iface == SNDRV_CTL_ELEM_IFACE_MIXER) {
Packit 4a16fb
		d = c1->compare_weight - c2->compare_weight;
Packit 4a16fb
		if (d != 0)
Packit 4a16fb
			return d;
Packit 4a16fb
	}
Packit 4a16fb
	d = c1->id.device - c2->id.device;
Packit 4a16fb
	if (d != 0)
Packit 4a16fb
		return d;
Packit 4a16fb
	d = c1->id.subdevice - c2->id.subdevice;
Packit 4a16fb
	if (d != 0)
Packit 4a16fb
		return d;
Packit 4a16fb
	res = strcmp((const char *)c1->id.name, (const char *)c2->id.name);
Packit 4a16fb
	if (res != 0)
Packit 4a16fb
		return res;
Packit 4a16fb
	return c1->id.index - c2->id.index;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief get first element for an HCTL
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \return pointer to first element
Packit 4a16fb
 */
Packit 4a16fb
snd_hctl_elem_t *snd_hctl_first_elem(snd_hctl_t *hctl)
Packit 4a16fb
{
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	if (list_empty(&hctl->elems))
Packit 4a16fb
		return NULL;
Packit 4a16fb
	return list_entry(hctl->elems.next, snd_hctl_elem_t, list);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief get last element for an HCTL
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \return pointer to last element
Packit 4a16fb
 */
Packit 4a16fb
snd_hctl_elem_t *snd_hctl_last_elem(snd_hctl_t *hctl)
Packit 4a16fb
{
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	if (list_empty(&hctl->elems))
Packit 4a16fb
		return NULL;
Packit 4a16fb
	return list_entry(hctl->elems.prev, snd_hctl_elem_t, list);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief get next HCTL element
Packit 4a16fb
 * \param elem HCTL element
Packit 4a16fb
 * \return pointer to next element
Packit 4a16fb
 */
Packit 4a16fb
snd_hctl_elem_t *snd_hctl_elem_next(snd_hctl_elem_t *elem)
Packit 4a16fb
{
Packit 4a16fb
	assert(elem);
Packit 4a16fb
	if (elem->list.next == &elem->hctl->elems)
Packit 4a16fb
		return NULL;
Packit 4a16fb
	return list_entry(elem->list.next, snd_hctl_elem_t, list);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief get previous HCTL element
Packit 4a16fb
 * \param elem HCTL element
Packit 4a16fb
 * \return pointer to previous element
Packit 4a16fb
 */
Packit 4a16fb
snd_hctl_elem_t *snd_hctl_elem_prev(snd_hctl_elem_t *elem)
Packit 4a16fb
{
Packit 4a16fb
	assert(elem);
Packit 4a16fb
	if (elem->list.prev == &elem->hctl->elems)
Packit 4a16fb
		return NULL;
Packit 4a16fb
	return list_entry(elem->list.prev, snd_hctl_elem_t, list);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Search an HCTL element
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \param id Element identifier
Packit 4a16fb
 * \return pointer to found HCTL element or NULL if it does not exists
Packit 4a16fb
 */
Packit 4a16fb
snd_hctl_elem_t *snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id)
Packit 4a16fb
{
Packit 4a16fb
	int dir;
Packit 4a16fb
	int res = _snd_hctl_find_elem(hctl, id, &dir;;
Packit 4a16fb
	if (res < 0 || dir != 0)
Packit 4a16fb
		return NULL;
Packit 4a16fb
	return hctl->pelems[res];
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Load an HCTL with all elements and sort them
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \return 0 on success otherwise a negative error code
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_load(snd_hctl_t *hctl)
Packit 4a16fb
{
Packit 4a16fb
	snd_ctl_elem_list_t list;
Packit 4a16fb
	int err = 0;
Packit 4a16fb
	unsigned int idx;
Packit 4a16fb
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	assert(hctl->ctl);
Packit 4a16fb
	assert(hctl->count == 0);
Packit 4a16fb
	assert(list_empty(&hctl->elems));
Packit 4a16fb
	memset(&list, 0, sizeof(list));
Packit 4a16fb
	if ((err = snd_ctl_elem_list(hctl->ctl, &list)) < 0)
Packit 4a16fb
		goto _end;
Packit 4a16fb
	while (list.count != list.used) {
Packit 4a16fb
		err = snd_ctl_elem_list_alloc_space(&list, list.count);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			goto _end;
Packit 4a16fb
		if ((err = snd_ctl_elem_list(hctl->ctl, &list)) < 0)
Packit 4a16fb
			goto _end;
Packit 4a16fb
	}
Packit 4a16fb
	if (hctl->alloc < list.count) {
Packit 4a16fb
		hctl->alloc = list.count;
Packit 4a16fb
		free(hctl->pelems);
Packit 4a16fb
		hctl->pelems = malloc(hctl->alloc * sizeof(*hctl->pelems));
Packit 4a16fb
		if (!hctl->pelems) {
Packit 4a16fb
			err = -ENOMEM;
Packit 4a16fb
			goto _end;
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	for (idx = 0; idx < list.count; idx++) {
Packit 4a16fb
		snd_hctl_elem_t *elem;
Packit 4a16fb
		elem = calloc(1, sizeof(snd_hctl_elem_t));
Packit 4a16fb
		if (elem == NULL) {
Packit 4a16fb
			snd_hctl_free(hctl);
Packit 4a16fb
			err = -ENOMEM;
Packit 4a16fb
			goto _end;
Packit 4a16fb
		}
Packit 4a16fb
		elem->id = list.pids[idx];
Packit 4a16fb
		elem->hctl = hctl;
Packit 4a16fb
		elem->compare_weight = get_compare_weight(&elem->id);
Packit 4a16fb
		hctl->pelems[idx] = elem;
Packit 4a16fb
		list_add_tail(&elem->list, &hctl->elems);
Packit 4a16fb
		hctl->count++;
Packit 4a16fb
	}
Packit 4a16fb
	if (!hctl->compare)
Packit 4a16fb
		hctl->compare = snd_hctl_compare_default;
Packit 4a16fb
	snd_hctl_sort(hctl);
Packit 4a16fb
	for (idx = 0; idx < hctl->count; idx++) {
Packit 4a16fb
		int res = snd_hctl_throw_event(hctl, SNDRV_CTL_EVENT_MASK_ADD,
Packit 4a16fb
					       hctl->pelems[idx]);
Packit 4a16fb
		if (res < 0)
Packit 4a16fb
			return res;
Packit 4a16fb
	}
Packit 4a16fb
	err = snd_ctl_subscribe_events(hctl->ctl, 1);
Packit 4a16fb
 _end:
Packit 4a16fb
	free(list.pids);
Packit 4a16fb
	return err;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Set callback function for an HCTL
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \param callback callback function
Packit 4a16fb
 */
Packit 4a16fb
void snd_hctl_set_callback(snd_hctl_t *hctl, snd_hctl_callback_t callback)
Packit 4a16fb
{
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	hctl->callback = callback;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Set callback private value for an HCTL
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \param callback_private callback private value
Packit 4a16fb
 */
Packit 4a16fb
void snd_hctl_set_callback_private(snd_hctl_t *hctl, void *callback_private)
Packit 4a16fb
{
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	hctl->callback_private = callback_private;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get callback private value for an HCTL
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \return callback private value
Packit 4a16fb
 */
Packit 4a16fb
void *snd_hctl_get_callback_private(snd_hctl_t *hctl)
Packit 4a16fb
{
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	return hctl->callback_private;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get number of loaded elements for an HCTL
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \return elements count
Packit 4a16fb
 */
Packit 4a16fb
unsigned int snd_hctl_get_count(snd_hctl_t *hctl)
Packit 4a16fb
{
Packit 4a16fb
	return hctl->count;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Wait for a HCTL to become ready (i.e. at least one event pending)
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \param timeout maximum time in milliseconds to wait
Packit 4a16fb
 * \return a positive value on success otherwise a negative error code
Packit 4a16fb
 * \retval 0 timeout occurred
Packit 4a16fb
 * \retval 1 an event is pending
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_wait(snd_hctl_t *hctl, int timeout)
Packit 4a16fb
{
Packit 4a16fb
	struct pollfd *pfd;
Packit 4a16fb
	unsigned short *revents;
Packit 4a16fb
	int i, npfds, pollio, err, err_poll;
Packit 4a16fb
	
Packit 4a16fb
	npfds = snd_hctl_poll_descriptors_count(hctl);
Packit 4a16fb
	if (npfds <= 0 || npfds >= 16) {
Packit 4a16fb
		SNDERR("Invalid poll_fds %d\n", npfds);
Packit 4a16fb
		return -EIO;
Packit 4a16fb
	}
Packit 4a16fb
	pfd = alloca(sizeof(*pfd) * npfds);
Packit 4a16fb
	revents = alloca(sizeof(*revents) * npfds);
Packit 4a16fb
	err = snd_hctl_poll_descriptors(hctl, pfd, npfds);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	if (err != npfds) {
Packit 4a16fb
		SNDMSG("invalid poll descriptors %d\n", err);
Packit 4a16fb
		return -EIO;
Packit 4a16fb
	}
Packit 4a16fb
	do {
Packit 4a16fb
		pollio = 0;
Packit 4a16fb
		err_poll = poll(pfd, npfds, timeout);
Packit 4a16fb
		if (err_poll < 0) {
Packit 4a16fb
			if (errno == EINTR && !CTLINABORT(hctl->ctl))
Packit 4a16fb
				continue;
Packit 4a16fb
			return -errno;
Packit 4a16fb
		}
Packit 4a16fb
		if (! err_poll)
Packit 4a16fb
			break;
Packit 4a16fb
		err = snd_hctl_poll_descriptors_revents(hctl, pfd, npfds, revents);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return err;
Packit 4a16fb
		for (i = 0; i < npfds; i++) {
Packit 4a16fb
			if (revents[i] & (POLLERR | POLLNVAL))
Packit 4a16fb
				return -EIO;
Packit 4a16fb
			if ((revents[i] & (POLLIN | POLLOUT)) == 0)
Packit 4a16fb
				continue;
Packit 4a16fb
			pollio++;
Packit 4a16fb
		}
Packit 4a16fb
	} while (! pollio);
Packit 4a16fb
	return err_poll > 0 ? 1 : 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get a ctl handle associated to the given hctl handle
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \return a ctl handle otherwise NULL
Packit 4a16fb
 */
Packit 4a16fb
snd_ctl_t *snd_hctl_ctl(snd_hctl_t *hctl)
Packit 4a16fb
{
Packit 4a16fb
	return hctl->ctl;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int snd_hctl_handle_event(snd_hctl_t *hctl, snd_ctl_event_t *event)
Packit 4a16fb
{
Packit 4a16fb
	snd_hctl_elem_t *elem;
Packit 4a16fb
	int res;
Packit 4a16fb
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	assert(hctl->ctl);
Packit 4a16fb
	switch (event->type) {
Packit 4a16fb
	case SND_CTL_EVENT_ELEM:
Packit 4a16fb
		break;
Packit 4a16fb
	default:
Packit 4a16fb
		return 0;
Packit 4a16fb
	}
Packit 4a16fb
	if (event->data.elem.mask == SNDRV_CTL_EVENT_MASK_REMOVE) {
Packit 4a16fb
		int dir;
Packit 4a16fb
		res = _snd_hctl_find_elem(hctl, &event->data.elem.id, &dir;;
Packit 4a16fb
		if (res < 0 || dir != 0)
Packit 4a16fb
			return -ENOENT;
Packit 4a16fb
		snd_hctl_elem_remove(hctl, (unsigned int) res);
Packit 4a16fb
		return 0;
Packit 4a16fb
	}
Packit 4a16fb
	if (event->data.elem.mask & SNDRV_CTL_EVENT_MASK_ADD) {
Packit 4a16fb
		elem = calloc(1, sizeof(snd_hctl_elem_t));
Packit 4a16fb
		if (elem == NULL)
Packit 4a16fb
			return -ENOMEM;
Packit 4a16fb
		elem->id = event->data.elem.id;
Packit 4a16fb
		elem->hctl = hctl;
Packit 4a16fb
		res = snd_hctl_elem_add(hctl, elem);
Packit 4a16fb
		if (res < 0)
Packit 4a16fb
			return res;
Packit 4a16fb
	}
Packit 4a16fb
	if (event->data.elem.mask & (SNDRV_CTL_EVENT_MASK_VALUE |
Packit 4a16fb
				     SNDRV_CTL_EVENT_MASK_INFO)) {
Packit 4a16fb
		elem = snd_hctl_find_elem(hctl, &event->data.elem.id);
Packit 4a16fb
		if (!elem)
Packit 4a16fb
			return -ENOENT;
Packit 4a16fb
		res = snd_hctl_elem_throw_event(elem, event->data.elem.mask &
Packit 4a16fb
						(SNDRV_CTL_EVENT_MASK_VALUE |
Packit 4a16fb
						 SNDRV_CTL_EVENT_MASK_INFO));
Packit 4a16fb
		if (res < 0)
Packit 4a16fb
			return res;
Packit 4a16fb
	}
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Handle pending HCTL events invoking callbacks
Packit 4a16fb
 * \param hctl HCTL handle
Packit 4a16fb
 * \return 0 otherwise a negative error code on failure
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_handle_events(snd_hctl_t *hctl)
Packit 4a16fb
{
Packit 4a16fb
	snd_ctl_event_t event;
Packit 4a16fb
	int res;
Packit 4a16fb
	unsigned int count = 0;
Packit 4a16fb
	
Packit 4a16fb
	assert(hctl);
Packit 4a16fb
	assert(hctl->ctl);
Packit 4a16fb
	while ((res = snd_ctl_read(hctl->ctl, &event)) != 0 &&
Packit 4a16fb
	       res != -EAGAIN) {
Packit 4a16fb
		if (res < 0)
Packit 4a16fb
			return res;
Packit 4a16fb
		res = snd_hctl_handle_event(hctl, &event);
Packit 4a16fb
		if (res < 0)
Packit 4a16fb
			return res;
Packit 4a16fb
		count++;
Packit 4a16fb
	}
Packit 4a16fb
	return count;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get information for an HCTL element
Packit 4a16fb
 * \param elem HCTL element
Packit 4a16fb
 * \param info HCTL element information
Packit 4a16fb
 * \return 0 otherwise a negative error code on failure
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_elem_info(snd_hctl_elem_t *elem, snd_ctl_elem_info_t *info)
Packit 4a16fb
{
Packit 4a16fb
	assert(elem);
Packit 4a16fb
	assert(elem->hctl);
Packit 4a16fb
	assert(info);
Packit 4a16fb
	info->id = elem->id;
Packit 4a16fb
	return snd_ctl_elem_info(elem->hctl->ctl, info);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get value for an HCTL element
Packit 4a16fb
 * \param elem HCTL element
Packit 4a16fb
 * \param value HCTL element value
Packit 4a16fb
 * \return 0 otherwise a negative error code on failure
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_elem_read(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value)
Packit 4a16fb
{
Packit 4a16fb
	assert(elem);
Packit 4a16fb
	assert(elem->hctl);
Packit 4a16fb
	assert(value);
Packit 4a16fb
	value->id = elem->id;
Packit 4a16fb
	return snd_ctl_elem_read(elem->hctl->ctl, value);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Set value for an HCTL element
Packit 4a16fb
 * \param elem HCTL element
Packit 4a16fb
 * \param value HCTL element value
Packit 4a16fb
 * \retval 0 on success
Packit 4a16fb
 * \retval >1 on success when value was changed
Packit 4a16fb
 * \retval <0 a negative error code on failure
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value)
Packit 4a16fb
{
Packit 4a16fb
	assert(elem);
Packit 4a16fb
	assert(elem->hctl);
Packit 4a16fb
	assert(value);
Packit 4a16fb
	value->id = elem->id;
Packit 4a16fb
	return snd_ctl_elem_write(elem->hctl->ctl, value);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get TLV value for an HCTL element
Packit 4a16fb
 * \param elem HCTL element
Packit 4a16fb
 * \param tlv TLV array for value
Packit 4a16fb
 * \param tlv_size size of TLV array in bytes
Packit 4a16fb
 * \return 0 otherwise a negative error code on failure
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_elem_tlv_read(snd_hctl_elem_t *elem, unsigned int *tlv, unsigned int tlv_size)
Packit 4a16fb
{
Packit 4a16fb
	assert(elem);
Packit 4a16fb
	assert(tlv);
Packit 4a16fb
	assert(tlv_size >= 12);
Packit 4a16fb
	return snd_ctl_elem_tlv_read(elem->hctl->ctl, &elem->id, tlv, tlv_size);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Set TLV value for an HCTL element
Packit 4a16fb
 * \param elem HCTL element
Packit 4a16fb
 * \param tlv TLV array for value
Packit 4a16fb
 * \retval 0 on success
Packit 4a16fb
 * \retval >1 on success when value was changed
Packit 4a16fb
 * \retval <0 a negative error code on failure
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_elem_tlv_write(snd_hctl_elem_t *elem, const unsigned int *tlv)
Packit 4a16fb
{
Packit 4a16fb
	assert(elem);
Packit 4a16fb
	assert(tlv);
Packit 4a16fb
	assert(tlv[SNDRV_CTL_TLVO_LEN] >= 4);
Packit 4a16fb
	return snd_ctl_elem_tlv_write(elem->hctl->ctl, &elem->id, tlv);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Set TLV value for an HCTL element
Packit 4a16fb
 * \param elem HCTL element
Packit 4a16fb
 * \param tlv TLV array for value
Packit 4a16fb
 * \retval 0 on success
Packit 4a16fb
 * \retval >1 on success when value was changed
Packit 4a16fb
 * \retval <0 a negative error code on failure
Packit 4a16fb
 */
Packit 4a16fb
int snd_hctl_elem_tlv_command(snd_hctl_elem_t *elem, const unsigned int *tlv)
Packit 4a16fb
{
Packit 4a16fb
	assert(elem);
Packit 4a16fb
	assert(tlv);
Packit 4a16fb
	assert(tlv[SNDRV_CTL_TLVO_LEN] >= 4);
Packit 4a16fb
	return snd_ctl_elem_tlv_command(elem->hctl->ctl, &elem->id, tlv);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get HCTL handle for an HCTL element
Packit 4a16fb
 * \param elem HCTL element
Packit 4a16fb
 * \return HCTL handle
Packit 4a16fb
 */
Packit 4a16fb
snd_hctl_t *snd_hctl_elem_get_hctl(snd_hctl_elem_t *elem)
Packit 4a16fb
{
Packit 4a16fb
	assert(elem);
Packit 4a16fb
	return elem->hctl;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get CTL element identifier of a CTL element id/value
Packit 4a16fb
 * \param obj CTL element id/value
Packit 4a16fb
 * \param ptr Pointer to returned CTL element identifier
Packit 4a16fb
 */
Packit 4a16fb
void snd_hctl_elem_get_id(const snd_hctl_elem_t *obj, snd_ctl_elem_id_t *ptr)
Packit 4a16fb
{
Packit 4a16fb
	assert(obj && ptr);
Packit 4a16fb
	*ptr = obj->id;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get element numeric identifier of a CTL element id/value
Packit 4a16fb
 * \param obj CTL element id/value
Packit 4a16fb
 * \return element numeric identifier
Packit 4a16fb
 */
Packit 4a16fb
unsigned int snd_hctl_elem_get_numid(const snd_hctl_elem_t *obj)
Packit 4a16fb
{
Packit 4a16fb
	assert(obj);
Packit 4a16fb
	return obj->id.numid;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get interface part of CTL element identifier of a CTL element id/value
Packit 4a16fb
 * \param obj CTL element id/value
Packit 4a16fb
 * \return interface part of element identifier
Packit 4a16fb
 */
Packit 4a16fb
snd_ctl_elem_iface_t snd_hctl_elem_get_interface(const snd_hctl_elem_t *obj)
Packit 4a16fb
{
Packit 4a16fb
	assert(obj);
Packit 4a16fb
	return obj->id.iface;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get device part of CTL element identifier of a CTL element id/value
Packit 4a16fb
 * \param obj CTL element id/value
Packit 4a16fb
 * \return device part of element identifier
Packit 4a16fb
 */
Packit 4a16fb
unsigned int snd_hctl_elem_get_device(const snd_hctl_elem_t *obj)
Packit 4a16fb
{
Packit 4a16fb
	assert(obj);
Packit 4a16fb
	return obj->id.device;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get subdevice part of CTL element identifier of a CTL element id/value
Packit 4a16fb
 * \param obj CTL element id/value
Packit 4a16fb
 * \return subdevice part of element identifier
Packit 4a16fb
 */
Packit 4a16fb
unsigned int snd_hctl_elem_get_subdevice(const snd_hctl_elem_t *obj)
Packit 4a16fb
{
Packit 4a16fb
	assert(obj);
Packit 4a16fb
	return obj->id.subdevice;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get name part of CTL element identifier of a CTL element id/value
Packit 4a16fb
 * \param obj CTL element id/value
Packit 4a16fb
 * \return name part of element identifier
Packit 4a16fb
 */
Packit 4a16fb
const char *snd_hctl_elem_get_name(const snd_hctl_elem_t *obj)
Packit 4a16fb
{
Packit 4a16fb
	assert(obj);
Packit 4a16fb
	return (const char *)obj->id.name;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get index part of CTL element identifier of a CTL element id/value
Packit 4a16fb
 * \param obj CTL element id/value
Packit 4a16fb
 * \return index part of element identifier
Packit 4a16fb
 */
Packit 4a16fb
unsigned int snd_hctl_elem_get_index(const snd_hctl_elem_t *obj)
Packit 4a16fb
{
Packit 4a16fb
	assert(obj);
Packit 4a16fb
	return obj->id.index;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Set callback function for an HCTL element
Packit 4a16fb
 * \param obj HCTL element
Packit 4a16fb
 * \param val callback function
Packit 4a16fb
 */
Packit 4a16fb
void snd_hctl_elem_set_callback(snd_hctl_elem_t *obj, snd_hctl_elem_callback_t val)
Packit 4a16fb
{
Packit 4a16fb
	assert(obj);
Packit 4a16fb
	obj->callback = val;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Set callback private value for an HCTL element
Packit 4a16fb
 * \param obj HCTL element
Packit 4a16fb
 * \param val callback private value
Packit 4a16fb
 */
Packit 4a16fb
void snd_hctl_elem_set_callback_private(snd_hctl_elem_t *obj, void * val)
Packit 4a16fb
{
Packit 4a16fb
	assert(obj);
Packit 4a16fb
	obj->callback_private = val;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/**
Packit 4a16fb
 * \brief Get callback private value for an HCTL element
Packit 4a16fb
 * \param obj HCTL element
Packit 4a16fb
 * \return callback private value
Packit 4a16fb
 */
Packit 4a16fb
void * snd_hctl_elem_get_callback_private(const snd_hctl_elem_t *obj)
Packit 4a16fb
{
Packit 4a16fb
	assert(obj);
Packit 4a16fb
	return obj->callback_private;
Packit 4a16fb
}
Packit 4a16fb