Blame src/mixer/mixer.c

Packit 4a16fb
/**
Packit 4a16fb
 * \file mixer/mixer.c
Packit 4a16fb
 * \brief Mixer Interface
Packit 4a16fb
 * \author Jaroslav Kysela <perex@perex.cz>
Packit 4a16fb
 * \author Abramo Bagnara <abramo@alsa-project.org>
Packit 4a16fb
 * \date 2001
Packit 4a16fb
 *
Packit 4a16fb
 * Mixer interface is designed to access mixer elements.
Packit 4a16fb
 * Callbacks may be used for event handling.
Packit 4a16fb
 */
Packit 4a16fb
/*
Packit 4a16fb
 *  Mixer Interface - main file
Packit 4a16fb
 *  Copyright (c) 1998/1999/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 mixer Mixer interface
Packit 4a16fb
Packit 4a16fb

Mixer interface is designed to access the abstracted mixer controls.

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