Blame src/mixer/mixer.c

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

Mixer interface is designed to access the abstracted mixer controls.

Packit Service db8eaa
This is an abstraction layer over the hcontrol layer.
Packit Service db8eaa
Packit Service db8eaa
\section mixer_general_overview General overview
Packit Service db8eaa
Packit Service db8eaa
*/
Packit Service db8eaa
Packit Service db8eaa
#include <stdio.h>
Packit Service db8eaa
#include <stdlib.h>
Packit Service db8eaa
#include <unistd.h>
Packit Service db8eaa
#include <string.h>
Packit Service db8eaa
#include <fcntl.h>
Packit Service db8eaa
#include <sys/ioctl.h>
Packit Service db8eaa
#include "mixer_local.h"
Packit Service db8eaa
Packit Service db8eaa
#ifndef DOC_HIDDEN
Packit Service db8eaa
typedef struct _snd_mixer_slave {
Packit Service db8eaa
	snd_hctl_t *hctl;
Packit Service db8eaa
	struct list_head list;
Packit Service db8eaa
} snd_mixer_slave_t;
Packit Service db8eaa
Packit Service db8eaa
#endif
Packit Service db8eaa
Packit Service db8eaa
static int snd_mixer_compare_default(const snd_mixer_elem_t *c1,
Packit Service db8eaa
				     const snd_mixer_elem_t *c2);
Packit Service db8eaa
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Opens an empty mixer
Packit Service db8eaa
 * \param mixerp Returned mixer handle
Packit Service db8eaa
 * \param mode Open mode
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_open(snd_mixer_t **mixerp, int mode ATTRIBUTE_UNUSED)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_mixer_t *mixer;
Packit Service db8eaa
	assert(mixerp);
Packit Service db8eaa
	mixer = calloc(1, sizeof(*mixer));
Packit Service db8eaa
	if (mixer == NULL)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	INIT_LIST_HEAD(&mixer->slaves);
Packit Service db8eaa
	INIT_LIST_HEAD(&mixer->classes);
Packit Service db8eaa
	INIT_LIST_HEAD(&mixer->elems);
Packit Service db8eaa
	mixer->compare = snd_mixer_compare_default;
Packit Service db8eaa
	*mixerp = mixer;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Attach an HCTL element to a mixer element
Packit Service db8eaa
 * \param melem Mixer element
Packit Service db8eaa
 * \param helem HCTL element
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * For use by mixer element class specific code.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_elem_attach(snd_mixer_elem_t *melem,
Packit Service db8eaa
			  snd_hctl_elem_t *helem)
Packit Service db8eaa
{
Packit Service db8eaa
	bag_t *bag = snd_hctl_elem_get_callback_private(helem);
Packit Service db8eaa
	int err;
Packit Service db8eaa
	err = bag_add(bag, melem);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return err;
Packit Service db8eaa
	return bag_add(&melem->helems, helem);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Detach an HCTL element from a mixer element
Packit Service db8eaa
 * \param melem Mixer element
Packit Service db8eaa
 * \param helem HCTL element
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * For use by mixer element class specific code.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_elem_detach(snd_mixer_elem_t *melem,
Packit Service db8eaa
			  snd_hctl_elem_t *helem)
Packit Service db8eaa
{
Packit Service db8eaa
	bag_t *bag = snd_hctl_elem_get_callback_private(helem);
Packit Service db8eaa
	int err;
Packit Service db8eaa
	err = bag_del(bag, melem);
Packit Service db8eaa
	assert(err >= 0);
Packit Service db8eaa
	err = bag_del(&melem->helems, helem);
Packit Service db8eaa
	assert(err >= 0);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Return true if a mixer element does not contain any HCTL elements
Packit Service db8eaa
 * \param melem Mixer element
Packit Service db8eaa
 * \return 0 if not empty, 1 if empty
Packit Service db8eaa
 *
Packit Service db8eaa
 * For use by mixer element class specific code.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_elem_empty(snd_mixer_elem_t *melem)
Packit Service db8eaa
{
Packit Service db8eaa
	return bag_empty(&melem->helems);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int hctl_elem_event_handler(snd_hctl_elem_t *helem,
Packit Service db8eaa
				   unsigned int mask)
Packit Service db8eaa
{
Packit Service db8eaa
	bag_t *bag = snd_hctl_elem_get_callback_private(helem);
Packit Service db8eaa
	if (mask == SND_CTL_EVENT_MASK_REMOVE) {
Packit Service db8eaa
		int res = 0;
Packit Service db8eaa
		int err;
Packit Service db8eaa
		bag_iterator_t i, n;
Packit Service db8eaa
		bag_for_each_safe(i, n, bag) {
Packit Service db8eaa
			snd_mixer_elem_t *melem = bag_iterator_entry(i);
Packit Service db8eaa
			snd_mixer_class_t *class = melem->class;
Packit Service db8eaa
			err = class->event(class, mask, helem, melem);
Packit Service db8eaa
			if (err < 0)
Packit Service db8eaa
				res = err;
Packit Service db8eaa
		}
Packit Service db8eaa
		assert(bag_empty(bag));
Packit Service db8eaa
		bag_free(bag);
Packit Service db8eaa
		return res;
Packit Service db8eaa
	}
Packit Service db8eaa
	if (mask & (SND_CTL_EVENT_MASK_VALUE | SND_CTL_EVENT_MASK_INFO)) {
Packit Service db8eaa
		int err = 0;
Packit Service db8eaa
		bag_iterator_t i, n;
Packit Service db8eaa
		bag_for_each_safe(i, n, bag) {
Packit Service db8eaa
			snd_mixer_elem_t *melem = bag_iterator_entry(i);
Packit Service db8eaa
			snd_mixer_class_t *class = melem->class;
Packit Service db8eaa
			err = class->event(class, mask, helem, melem);
Packit Service db8eaa
			if (err < 0)
Packit Service db8eaa
				return err;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int hctl_event_handler(snd_hctl_t *hctl, unsigned int mask,
Packit Service db8eaa
			      snd_hctl_elem_t *elem)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_mixer_t *mixer = snd_hctl_get_callback_private(hctl);
Packit Service db8eaa
	int res = 0;
Packit Service db8eaa
	if (mask & SND_CTL_EVENT_MASK_ADD) {
Packit Service db8eaa
		struct list_head *pos;
Packit Service db8eaa
		bag_t *bag;
Packit Service db8eaa
		int err = bag_new(&bag;;
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
		snd_hctl_elem_set_callback(elem, hctl_elem_event_handler);
Packit Service db8eaa
		snd_hctl_elem_set_callback_private(elem, bag);
Packit Service db8eaa
		list_for_each(pos, &mixer->classes) {
Packit Service db8eaa
			snd_mixer_class_t *c;
Packit Service db8eaa
			c = list_entry(pos, snd_mixer_class_t, list);
Packit Service db8eaa
			err = c->event(c, mask, elem, NULL);
Packit Service db8eaa
			if (err < 0)
Packit Service db8eaa
				res = err;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
	return res;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Attach an HCTL specified with the CTL device name to an opened mixer
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \param name HCTL name (see #snd_hctl_open)
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_attach(snd_mixer_t *mixer, const char *name)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_hctl_t *hctl;
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	err = snd_hctl_open(&hctl, name, 0);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return err;
Packit Service db8eaa
	err = snd_mixer_attach_hctl(mixer, hctl);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return err;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Attach an HCTL to an opened mixer
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \param hctl the HCTL to be attached
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * Upon error, this function closes the given hctl handle automatically.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_attach_hctl(snd_mixer_t *mixer, snd_hctl_t *hctl)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_mixer_slave_t *slave;
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	assert(hctl);
Packit Service db8eaa
	slave = calloc(1, sizeof(*slave));
Packit Service db8eaa
	if (slave == NULL) {
Packit Service db8eaa
		snd_hctl_close(hctl);
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	}
Packit Service db8eaa
	err = snd_hctl_nonblock(hctl, 1);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		snd_hctl_close(hctl);
Packit Service db8eaa
		free(slave);
Packit Service db8eaa
		return err;
Packit Service db8eaa
	}
Packit Service db8eaa
	snd_hctl_set_callback(hctl, hctl_event_handler);
Packit Service db8eaa
	snd_hctl_set_callback_private(hctl, mixer);
Packit Service db8eaa
	slave->hctl = hctl;
Packit Service db8eaa
	list_add_tail(&slave->list, &mixer->slaves);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Detach a previously attached HCTL to an opened mixer freeing all related resources
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \param name HCTL previously attached
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_detach(snd_mixer_t *mixer, const char *name)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	list_for_each(pos, &mixer->slaves) {
Packit Service db8eaa
		snd_mixer_slave_t *s;
Packit Service db8eaa
		s = list_entry(pos, snd_mixer_slave_t, list);
Packit Service db8eaa
		if (strcmp(name, snd_hctl_name(s->hctl)) == 0) {
Packit Service db8eaa
			snd_hctl_close(s->hctl);
Packit Service db8eaa
			list_del(pos);
Packit Service db8eaa
			free(s);
Packit Service db8eaa
			return 0;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
	return -ENOENT;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Detach a previously attached HCTL to an opened mixer freeing all related resources
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \param hctl HCTL previously attached
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * Note: The hctl handle is not closed!
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_detach_hctl(snd_mixer_t *mixer, snd_hctl_t *hctl)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	list_for_each(pos, &mixer->slaves) {
Packit Service db8eaa
		snd_mixer_slave_t *s;
Packit Service db8eaa
		s = list_entry(pos, snd_mixer_slave_t, list);
Packit Service db8eaa
		if (hctl == s->hctl) {
Packit Service db8eaa
			list_del(pos);
Packit Service db8eaa
			free(s);
Packit Service db8eaa
			return 0;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
	return -ENOENT;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Obtain a HCTL pointer associated to given name
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \param name HCTL previously attached
Packit Service db8eaa
 * \param hctl HCTL pointer
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_get_hctl(snd_mixer_t *mixer, const char *name, snd_hctl_t **hctl)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	list_for_each(pos, &mixer->slaves) {
Packit Service db8eaa
		snd_mixer_slave_t *s;
Packit Service db8eaa
		s = list_entry(pos, snd_mixer_slave_t, list);
Packit Service db8eaa
		if (strcmp(name, snd_hctl_name(s->hctl)) == 0) {
Packit Service db8eaa
			*hctl = s->hctl;
Packit Service db8eaa
			return 0;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
	return -ENOENT;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int snd_mixer_throw_event(snd_mixer_t *mixer, unsigned int mask,
Packit Service db8eaa
			  snd_mixer_elem_t *elem)
Packit Service db8eaa
{
Packit Service db8eaa
	mixer->events++;
Packit Service db8eaa
	if (mixer->callback)
Packit Service db8eaa
		return mixer->callback(mixer, mask, elem);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem, unsigned int mask)
Packit Service db8eaa
{
Packit Service db8eaa
	elem->class->mixer->events++;
Packit Service db8eaa
	if (elem->callback)
Packit Service db8eaa
		return elem->callback(elem, mask);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int _snd_mixer_find_elem(snd_mixer_t *mixer, snd_mixer_elem_t *elem, int *dir)
Packit Service db8eaa
{
Packit Service db8eaa
	unsigned int l, u;
Packit Service db8eaa
	int c = 0;
Packit Service db8eaa
	int idx = -1;
Packit Service db8eaa
	assert(mixer && elem);
Packit Service db8eaa
	assert(mixer->compare);
Packit Service db8eaa
	l = 0;
Packit Service db8eaa
	u = mixer->count;
Packit Service db8eaa
	while (l < u) {
Packit Service db8eaa
		idx = (l + u) / 2;
Packit Service db8eaa
		c = mixer->compare(elem, mixer->pelems[idx]);
Packit Service db8eaa
		if (c < 0)
Packit Service db8eaa
			u = idx;
Packit Service db8eaa
		else if (c > 0)
Packit Service db8eaa
			l = idx + 1;
Packit Service db8eaa
		else
Packit Service db8eaa
			break;
Packit Service db8eaa
	}
Packit Service db8eaa
	*dir = c;
Packit Service db8eaa
	return idx;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Get private data associated to give mixer element
Packit Service db8eaa
 * \param elem Mixer element
Packit Service db8eaa
 * \return private data
Packit Service db8eaa
 *
Packit Service db8eaa
 * For use by mixer element class specific code.
Packit Service db8eaa
 */
Packit Service db8eaa
void *snd_mixer_elem_get_private(const snd_mixer_elem_t *elem)
Packit Service db8eaa
{
Packit Service db8eaa
	return elem->private_data;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Allocate a new mixer element
Packit Service db8eaa
 * \param elem Returned mixer element
Packit Service db8eaa
 * \param type Mixer element type
Packit Service db8eaa
 * \param compare_weight Mixer element compare weight
Packit Service db8eaa
 * \param private_data Private data
Packit Service db8eaa
 * \param private_free Private data free callback
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * For use by mixer element class specific code.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_elem_new(snd_mixer_elem_t **elem,
Packit Service db8eaa
		       snd_mixer_elem_type_t type,
Packit Service db8eaa
		       int compare_weight,
Packit Service db8eaa
		       void *private_data,
Packit Service db8eaa
		       void (*private_free)(snd_mixer_elem_t *elem))
Packit Service db8eaa
{
Packit Service db8eaa
	snd_mixer_elem_t *melem = calloc(1, sizeof(*melem));
Packit Service db8eaa
	if (melem == NULL)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	melem->type = type;
Packit Service db8eaa
	melem->compare_weight = compare_weight;
Packit Service db8eaa
	melem->private_data = private_data;
Packit Service db8eaa
	melem->private_free = private_free;
Packit Service db8eaa
	INIT_LIST_HEAD(&melem->helems);
Packit Service db8eaa
	*elem = melem;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Add an element for a registered mixer element class
Packit Service db8eaa
 * \param elem Mixer element
Packit Service db8eaa
 * \param class Mixer element class
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * For use by mixer element class specific code.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_elem_add(snd_mixer_elem_t *elem, snd_mixer_class_t *class)
Packit Service db8eaa
{
Packit Service db8eaa
	int dir, idx;
Packit Service db8eaa
	snd_mixer_t *mixer = class->mixer;
Packit Service db8eaa
	elem->class = class;
Packit Service db8eaa
Packit Service db8eaa
	if (mixer->count == mixer->alloc) {
Packit Service db8eaa
		snd_mixer_elem_t **m;
Packit Service db8eaa
		mixer->alloc += 32;
Packit Service db8eaa
		m = realloc(mixer->pelems, sizeof(*m) * mixer->alloc);
Packit Service db8eaa
		if (!m) {
Packit Service db8eaa
			mixer->alloc -= 32;
Packit Service db8eaa
			return -ENOMEM;
Packit Service db8eaa
		}
Packit Service db8eaa
		mixer->pelems = m;
Packit Service db8eaa
	}
Packit Service db8eaa
	if (mixer->count == 0) {
Packit Service db8eaa
		list_add_tail(&elem->list, &mixer->elems);
Packit Service db8eaa
		mixer->pelems[0] = elem;
Packit Service db8eaa
	} else {
Packit Service db8eaa
		idx = _snd_mixer_find_elem(mixer, elem, &dir;;
Packit Service db8eaa
		assert(dir != 0);
Packit Service db8eaa
		if (dir > 0) {
Packit Service db8eaa
			list_add(&elem->list, &mixer->pelems[idx]->list);
Packit Service db8eaa
			idx++;
Packit Service db8eaa
		} else {
Packit Service db8eaa
			list_add_tail(&elem->list, &mixer->pelems[idx]->list);
Packit Service db8eaa
		}
Packit Service db8eaa
		memmove(mixer->pelems + idx + 1,
Packit Service db8eaa
			mixer->pelems + idx,
Packit Service db8eaa
			(mixer->count - idx) * sizeof(snd_mixer_elem_t *));
Packit Service db8eaa
		mixer->pelems[idx] = elem;
Packit Service db8eaa
	}
Packit Service db8eaa
	mixer->count++;
Packit Service db8eaa
	return snd_mixer_throw_event(mixer, SND_CTL_EVENT_MASK_ADD, elem);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Remove a mixer element
Packit Service db8eaa
 * \param elem Mixer element
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * For use by mixer element class specific code.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_elem_remove(snd_mixer_elem_t *elem)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_mixer_t *mixer = elem->class->mixer;
Packit Service db8eaa
	bag_iterator_t i, n;
Packit Service db8eaa
	int err, idx, dir;
Packit Service db8eaa
	unsigned int m;
Packit Service db8eaa
	assert(elem);
Packit Service db8eaa
	assert(mixer->count);
Packit Service db8eaa
	idx = _snd_mixer_find_elem(mixer, elem, &dir;;
Packit Service db8eaa
	if (dir != 0)
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	bag_for_each_safe(i, n, &elem->helems) {
Packit Service db8eaa
		snd_hctl_elem_t *helem = bag_iterator_entry(i);
Packit Service db8eaa
		snd_mixer_elem_detach(elem, helem);
Packit Service db8eaa
	}
Packit Service db8eaa
	err = snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_REMOVE);
Packit Service db8eaa
	list_del(&elem->list);
Packit Service db8eaa
	snd_mixer_elem_free(elem);
Packit Service db8eaa
	mixer->count--;
Packit Service db8eaa
	m = mixer->count - idx;
Packit Service db8eaa
	if (m > 0)
Packit Service db8eaa
		memmove(mixer->pelems + idx,
Packit Service db8eaa
			mixer->pelems + idx + 1,
Packit Service db8eaa
			m * sizeof(snd_mixer_elem_t *));
Packit Service db8eaa
	return err;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Free a mixer element
Packit Service db8eaa
 * \param elem Mixer element
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * For use by mixer element class specific code.
Packit Service db8eaa
 */
Packit Service db8eaa
void snd_mixer_elem_free(snd_mixer_elem_t *elem)
Packit Service db8eaa
{
Packit Service db8eaa
	if (elem->private_free)
Packit Service db8eaa
		elem->private_free(elem);
Packit Service db8eaa
	free(elem);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Mixer element informations are changed
Packit Service db8eaa
 * \param elem Mixer element
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * For use by mixer element class specific code.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_elem_info(snd_mixer_elem_t *elem)
Packit Service db8eaa
{
Packit Service db8eaa
	return snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_INFO);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Mixer element values is changed
Packit Service db8eaa
 * \param elem Mixer element
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * For use by mixer element class specific code.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_elem_value(snd_mixer_elem_t *elem)
Packit Service db8eaa
{
Packit Service db8eaa
	return snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_VALUE);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Register mixer element class
Packit Service db8eaa
 * \param class Mixer element class
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * For use by mixer element class specific code.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_class_register(snd_mixer_class_t *class, snd_mixer_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	class->mixer = mixer;
Packit Service db8eaa
	list_add_tail(&class->list, &mixer->classes);
Packit Service db8eaa
	if (!class->event)
Packit Service db8eaa
		return 0;
Packit Service db8eaa
	list_for_each(pos, &mixer->slaves) {
Packit Service db8eaa
		int err;
Packit Service db8eaa
		snd_mixer_slave_t *slave;
Packit Service db8eaa
		snd_hctl_elem_t *elem;
Packit Service db8eaa
		slave = list_entry(pos, snd_mixer_slave_t, list);
Packit Service db8eaa
		elem = snd_hctl_first_elem(slave->hctl);
Packit Service db8eaa
		while (elem) {
Packit Service db8eaa
			err = class->event(class, SND_CTL_EVENT_MASK_ADD, elem, NULL);
Packit Service db8eaa
			if (err < 0)
Packit Service db8eaa
				return err;
Packit Service db8eaa
			elem = snd_hctl_elem_next(elem);
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Unregister mixer element class and remove all its elements
Packit Service db8eaa
 * \param class Mixer element class
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * Note that the class structure is also deallocated!
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_class_unregister(snd_mixer_class_t *class)
Packit Service db8eaa
{
Packit Service db8eaa
	unsigned int k;
Packit Service db8eaa
	snd_mixer_elem_t *e;
Packit Service db8eaa
	snd_mixer_t *mixer = class->mixer;
Packit Service db8eaa
	for (k = mixer->count; k > 0; k--) {
Packit Service db8eaa
		e = mixer->pelems[k-1];
Packit Service db8eaa
		if (e->class == class)
Packit Service db8eaa
			snd_mixer_elem_remove(e);
Packit Service db8eaa
	}
Packit Service db8eaa
	if (class->private_free)
Packit Service db8eaa
		class->private_free(class);
Packit Service db8eaa
	list_del(&class->list);
Packit Service db8eaa
	free(class);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Load a mixer elements
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_load(snd_mixer_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	list_for_each(pos, &mixer->slaves) {
Packit Service db8eaa
		int err;
Packit Service db8eaa
		snd_mixer_slave_t *s;
Packit Service db8eaa
		s = list_entry(pos, snd_mixer_slave_t, list);
Packit Service db8eaa
		err = snd_hctl_load(s->hctl);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
	}
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Unload all mixer elements and free all related resources
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 */
Packit Service db8eaa
void snd_mixer_free(snd_mixer_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	list_for_each(pos, &mixer->slaves) {
Packit Service db8eaa
		snd_mixer_slave_t *s;
Packit Service db8eaa
		s = list_entry(pos, snd_mixer_slave_t, list);
Packit Service db8eaa
		snd_hctl_free(s->hctl);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Close a mixer and free all related resources
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_close(snd_mixer_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	int res = 0;
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	while (!list_empty(&mixer->classes)) {
Packit Service db8eaa
		snd_mixer_class_t *c;
Packit Service db8eaa
		c = list_entry(mixer->classes.next, snd_mixer_class_t, list);
Packit Service db8eaa
		snd_mixer_class_unregister(c);
Packit Service db8eaa
	}
Packit Service db8eaa
	assert(list_empty(&mixer->elems));
Packit Service db8eaa
	assert(mixer->count == 0);
Packit Service db8eaa
	free(mixer->pelems);
Packit Service db8eaa
	mixer->pelems = NULL;
Packit Service db8eaa
	while (!list_empty(&mixer->slaves)) {
Packit Service db8eaa
		int err;
Packit Service db8eaa
		snd_mixer_slave_t *s;
Packit Service db8eaa
		s = list_entry(mixer->slaves.next, snd_mixer_slave_t, list);
Packit Service db8eaa
		err = snd_hctl_close(s->hctl);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			res = err;
Packit Service db8eaa
		list_del(&s->list);
Packit Service db8eaa
		free(s);
Packit Service db8eaa
	}
Packit Service db8eaa
	free(mixer);
Packit Service db8eaa
	return res;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int snd_mixer_compare_default(const snd_mixer_elem_t *c1,
Packit Service db8eaa
				     const snd_mixer_elem_t *c2)
Packit Service db8eaa
{
Packit Service db8eaa
	int d = c1->compare_weight - c2->compare_weight;
Packit Service db8eaa
	if (d)
Packit Service db8eaa
		return d;
Packit Service db8eaa
	assert(c1->class && c1->class->compare);
Packit Service db8eaa
	assert(c2->class && c2->class->compare);
Packit Service db8eaa
	assert(c1->class == c2->class);
Packit Service db8eaa
	return c1->class->compare(c1, c2);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int mixer_compare(const void *a, const void *b)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_mixer_t *mixer;
Packit Service db8eaa
Packit Service db8eaa
	mixer = (*((const snd_mixer_elem_t * const *)a))->class->mixer;
Packit Service db8eaa
	return mixer->compare(*(const snd_mixer_elem_t * const *)a, *(const snd_mixer_elem_t * const *)b);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int snd_mixer_sort(snd_mixer_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	unsigned int k;
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	assert(mixer->compare);
Packit Service db8eaa
	INIT_LIST_HEAD(&mixer->elems);
Packit Service db8eaa
	qsort(mixer->pelems, mixer->count, sizeof(snd_mixer_elem_t *), mixer_compare);
Packit Service db8eaa
	for (k = 0; k < mixer->count; k++)
Packit Service db8eaa
		list_add_tail(&mixer->pelems[k]->list, &mixer->elems);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Change mixer compare function and reorder elements
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \param compare Element compare function
Packit Service db8eaa
 * \return 0 on success otherwise a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_set_compare(snd_mixer_t *mixer, snd_mixer_compare_t compare)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_mixer_compare_t compare_old;
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	compare_old = mixer->compare;
Packit Service db8eaa
	mixer->compare = compare == NULL ? snd_mixer_compare_default : compare;
Packit Service db8eaa
	if ((err = snd_mixer_sort(mixer)) < 0) {
Packit Service db8eaa
		mixer->compare = compare_old;
Packit Service db8eaa
		return err;
Packit Service db8eaa
	}
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief get count of poll descriptors for mixer handle
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \return count of poll descriptors
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_poll_descriptors_count(snd_mixer_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	unsigned int c = 0;
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	list_for_each(pos, &mixer->slaves) {
Packit Service db8eaa
		snd_mixer_slave_t *s;
Packit Service db8eaa
		int n;
Packit Service db8eaa
		s = list_entry(pos, snd_mixer_slave_t, list);
Packit Service db8eaa
		n = snd_hctl_poll_descriptors_count(s->hctl);
Packit Service db8eaa
		if (n < 0)
Packit Service db8eaa
			return n;
Packit Service db8eaa
		c += n;
Packit Service db8eaa
	}
Packit Service db8eaa
	return c;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief get poll descriptors
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \param pfds array of poll descriptors
Packit Service db8eaa
 * \param space space in the poll descriptor array
Packit Service db8eaa
 * \return count of filled descriptors
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_poll_descriptors(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int space)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	unsigned int count = 0;
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	list_for_each(pos, &mixer->slaves) {
Packit Service db8eaa
		snd_mixer_slave_t *s;
Packit Service db8eaa
		int n;
Packit Service db8eaa
		s = list_entry(pos, snd_mixer_slave_t, list);
Packit Service db8eaa
		n = snd_hctl_poll_descriptors(s->hctl, pfds, space);
Packit Service db8eaa
		if (n < 0)
Packit Service db8eaa
			return n;
Packit Service db8eaa
		if (space >= (unsigned int) n) {
Packit Service db8eaa
			count += n;
Packit Service db8eaa
			space -= n;
Packit Service db8eaa
			pfds += n;
Packit Service db8eaa
		} else
Packit Service db8eaa
			space = 0;
Packit Service db8eaa
	}
Packit Service db8eaa
	return count;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief get returned events from poll descriptors
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \param pfds array of poll descriptors
Packit Service db8eaa
 * \param nfds count of poll descriptors
Packit Service db8eaa
 * \param revents returned events
Packit Service db8eaa
 * \return zero if success, otherwise a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
Packit Service db8eaa
{
Packit Service db8eaa
	unsigned int idx;
Packit Service db8eaa
	unsigned short res;
Packit Service db8eaa
        assert(mixer && pfds && revents);
Packit Service db8eaa
	if (nfds == 0)
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	res = 0;
Packit Service db8eaa
	for (idx = 0; idx < nfds; idx++, pfds++)
Packit Service db8eaa
		res |= pfds->revents & (POLLIN|POLLERR|POLLNVAL);
Packit Service db8eaa
	*revents = res;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Wait for a mixer to become ready (i.e. at least one event pending)
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \param timeout maximum time in milliseconds to wait
Packit Service db8eaa
 * \return 0 otherwise a negative error code on failure
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_wait(snd_mixer_t *mixer, int timeout)
Packit Service db8eaa
{
Packit Service db8eaa
	struct pollfd spfds[16];
Packit Service db8eaa
	struct pollfd *pfds = spfds;
Packit Service db8eaa
	int err;
Packit Service db8eaa
	int count;
Packit Service db8eaa
	count = snd_mixer_poll_descriptors(mixer, pfds, sizeof(spfds) / sizeof(spfds[0]));
Packit Service db8eaa
	if (count < 0)
Packit Service db8eaa
		return count;
Packit Service db8eaa
	if ((unsigned int) count > sizeof(spfds) / sizeof(spfds[0])) {
Packit Service db8eaa
		pfds = alloca(count * sizeof(*pfds));
Packit Service db8eaa
		if (!pfds)
Packit Service db8eaa
			return -ENOMEM;
Packit Service db8eaa
		err = snd_mixer_poll_descriptors(mixer, pfds, 
Packit Service db8eaa
						 (unsigned int) count);
Packit Service db8eaa
		assert(err == count);
Packit Service db8eaa
	}
Packit Service db8eaa
	err = poll(pfds, (unsigned int) count, timeout);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return -errno;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief get first element for a mixer
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \return pointer to first element
Packit Service db8eaa
 */
Packit Service db8eaa
snd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	if (list_empty(&mixer->elems))
Packit Service db8eaa
		return NULL;
Packit Service db8eaa
	return list_entry(mixer->elems.next, snd_mixer_elem_t, list);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief get last element for a mixer
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \return pointer to last element
Packit Service db8eaa
 */
Packit Service db8eaa
snd_mixer_elem_t *snd_mixer_last_elem(snd_mixer_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	if (list_empty(&mixer->elems))
Packit Service db8eaa
		return NULL;
Packit Service db8eaa
	return list_entry(mixer->elems.prev, snd_mixer_elem_t, list);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief get next mixer element
Packit Service db8eaa
 * \param elem mixer element
Packit Service db8eaa
 * \return pointer to next element
Packit Service db8eaa
 */
Packit Service db8eaa
snd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(elem);
Packit Service db8eaa
	if (elem->list.next == &elem->class->mixer->elems)
Packit Service db8eaa
		return NULL;
Packit Service db8eaa
	return list_entry(elem->list.next, snd_mixer_elem_t, list);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief get previous mixer element
Packit Service db8eaa
 * \param elem mixer element
Packit Service db8eaa
 * \return pointer to previous element
Packit Service db8eaa
 */
Packit Service db8eaa
snd_mixer_elem_t *snd_mixer_elem_prev(snd_mixer_elem_t *elem)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(elem);
Packit Service db8eaa
	if (elem->list.prev == &elem->class->mixer->elems)
Packit Service db8eaa
		return NULL;
Packit Service db8eaa
	return list_entry(elem->list.prev, snd_mixer_elem_t, list);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Handle pending mixer events invoking callbacks
Packit Service db8eaa
 * \param mixer Mixer handle
Packit Service db8eaa
 * \return Number of events that occured on success, otherwise a negative error code on failure
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_handle_events(snd_mixer_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	mixer->events = 0;
Packit Service db8eaa
	list_for_each(pos, &mixer->slaves) {
Packit Service db8eaa
		int err;
Packit Service db8eaa
		snd_mixer_slave_t *s;
Packit Service db8eaa
		s = list_entry(pos, snd_mixer_slave_t, list);
Packit Service db8eaa
		err = snd_hctl_handle_events(s->hctl);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
	}
Packit Service db8eaa
	return mixer->events;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Set callback function for a mixer
Packit Service db8eaa
 * \param obj mixer handle
Packit Service db8eaa
 * \param val callback function
Packit Service db8eaa
 */
Packit Service db8eaa
void snd_mixer_set_callback(snd_mixer_t *obj, snd_mixer_callback_t val)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(obj);
Packit Service db8eaa
	obj->callback = val;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Set callback private value for a mixer
Packit Service db8eaa
 * \param mixer mixer handle
Packit Service db8eaa
 * \param val callback private value
Packit Service db8eaa
 */
Packit Service db8eaa
void snd_mixer_set_callback_private(snd_mixer_t *mixer, void * val)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	mixer->callback_private = val;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Get callback private value for a mixer
Packit Service db8eaa
 * \param mixer mixer handle
Packit Service db8eaa
 * \return callback private value
Packit Service db8eaa
 */
Packit Service db8eaa
void * snd_mixer_get_callback_private(const snd_mixer_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	return mixer->callback_private;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Get elements count for a mixer
Packit Service db8eaa
 * \param mixer mixer handle
Packit Service db8eaa
 * \return elements count
Packit Service db8eaa
 */
Packit Service db8eaa
unsigned int snd_mixer_get_count(const snd_mixer_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	return mixer->count;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Set callback function for a mixer element
Packit Service db8eaa
 * \param mixer mixer element
Packit Service db8eaa
 * \param val callback function
Packit Service db8eaa
 */
Packit Service db8eaa
void snd_mixer_elem_set_callback(snd_mixer_elem_t *mixer, snd_mixer_elem_callback_t val)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	mixer->callback = val;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Set callback private value for a mixer element
Packit Service db8eaa
 * \param mixer mixer element
Packit Service db8eaa
 * \param val callback private value
Packit Service db8eaa
 */
Packit Service db8eaa
void snd_mixer_elem_set_callback_private(snd_mixer_elem_t *mixer, void * val)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	mixer->callback_private = val;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Get callback private value for a mixer element
Packit Service db8eaa
 * \param mixer mixer element
Packit Service db8eaa
 * \return callback private value
Packit Service db8eaa
 */
Packit Service db8eaa
void * snd_mixer_elem_get_callback_private(const snd_mixer_elem_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	return mixer->callback_private;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Get type for a mixer element
Packit Service db8eaa
 * \param mixer mixer element
Packit Service db8eaa
 * \return mixer element type
Packit Service db8eaa
 */
Packit Service db8eaa
snd_mixer_elem_type_t snd_mixer_elem_get_type(const snd_mixer_elem_t *mixer)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(mixer);
Packit Service db8eaa
	return mixer->type;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief get size of #snd_mixer_class_t
Packit Service db8eaa
 * \return size in bytes
Packit Service db8eaa
 */
Packit Service db8eaa
size_t snd_mixer_class_sizeof()
Packit Service db8eaa
{
Packit Service db8eaa
	return sizeof(snd_mixer_class_t);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief allocate an invalid #snd_mixer_class_t using standard malloc
Packit Service db8eaa
 * \param ptr returned pointer
Packit Service db8eaa
 * \return 0 on success otherwise negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_class_malloc(snd_mixer_class_t **ptr)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(ptr);
Packit Service db8eaa
	*ptr = calloc(1, sizeof(snd_mixer_class_t));
Packit Service db8eaa
	if (!*ptr)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief frees a previously allocated #snd_mixer_class_t
Packit Service db8eaa
 * \param obj pointer to object to free
Packit Service db8eaa
 */
Packit Service db8eaa
void snd_mixer_class_free(snd_mixer_class_t *obj)
Packit Service db8eaa
{
Packit Service db8eaa
	if (obj->private_free)
Packit Service db8eaa
		obj->private_free(obj);
Packit Service db8eaa
	free(obj);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief copy one #snd_mixer_class_t to another
Packit Service db8eaa
 * \param dst pointer to destination
Packit Service db8eaa
 * \param src pointer to source
Packit Service db8eaa
 */
Packit Service db8eaa
void snd_mixer_class_copy(snd_mixer_class_t *dst, const snd_mixer_class_t *src)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(dst && src);
Packit Service db8eaa
	*dst = *src;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Get a mixer associated to given mixer class
Packit Service db8eaa
 * \param obj Mixer simple class identifier
Packit Service db8eaa
 * \return mixer pointer
Packit Service db8eaa
 */
Packit Service db8eaa
snd_mixer_t *snd_mixer_class_get_mixer(const snd_mixer_class_t *obj)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(obj);
Packit Service db8eaa
	return obj->mixer;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Get mixer event callback associated to given mixer class
Packit Service db8eaa
 * \param obj Mixer simple class identifier
Packit Service db8eaa
 * \return event callback pointer
Packit Service db8eaa
 */
Packit Service db8eaa
snd_mixer_event_t snd_mixer_class_get_event(const snd_mixer_class_t *obj)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(obj);
Packit Service db8eaa
	return obj->event;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Get mixer private data associated to given mixer class
Packit Service db8eaa
 * \param obj Mixer simple class identifier
Packit Service db8eaa
 * \return event callback pointer
Packit Service db8eaa
 */
Packit Service db8eaa
void *snd_mixer_class_get_private(const snd_mixer_class_t *obj)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(obj);
Packit Service db8eaa
	return obj->private_data;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Get mixer compare callback associated to given mixer class
Packit Service db8eaa
 * \param obj Mixer simple class identifier
Packit Service db8eaa
 * \return event callback pointer
Packit Service db8eaa
 */
Packit Service db8eaa
snd_mixer_compare_t snd_mixer_class_get_compare(const snd_mixer_class_t *obj)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(obj);
Packit Service db8eaa
	return obj->compare;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Set mixer event callback to given mixer class
Packit Service db8eaa
 * \param obj Mixer simple class identifier
Packit Service db8eaa
 * \param event Event callback
Packit Service db8eaa
 * \return zero if success, otherwise a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_class_set_event(snd_mixer_class_t *obj, snd_mixer_event_t event)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(obj);
Packit Service db8eaa
	obj->event = event;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Set mixer private data to given mixer class
Packit Service db8eaa
 * \param obj Mixer simple class identifier
Packit Service db8eaa
 * \param private_data class private data
Packit Service db8eaa
 * \return zero if success, otherwise a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_class_set_private(snd_mixer_class_t *obj, void *private_data)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(obj);
Packit Service db8eaa
	obj->private_data = private_data;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Set mixer private data free callback to given mixer class
Packit Service db8eaa
 * \param obj Mixer simple class identifier
Packit Service db8eaa
 * \param private_free Mixer class private data free callback
Packit Service db8eaa
 * \return zero if success, otherwise a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_class_set_private_free(snd_mixer_class_t *obj, void (*private_free)(snd_mixer_class_t *))
Packit Service db8eaa
{
Packit Service db8eaa
	assert(obj);
Packit Service db8eaa
	obj->private_free = private_free;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Set mixer compare callback to given mixer class
Packit Service db8eaa
 * \param obj Mixer simple class identifier
Packit Service db8eaa
 * \param compare the compare callback to be used
Packit Service db8eaa
 * \return zero if success, otherwise a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_mixer_class_set_compare(snd_mixer_class_t *obj, snd_mixer_compare_t compare)
Packit Service db8eaa
{
Packit Service db8eaa
	assert(obj);
Packit Service db8eaa
	obj->compare = compare;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}