1d5ac70f0Sopenharmony_ci/** 2d5ac70f0Sopenharmony_ci * \file mixer/mixer.c 3d5ac70f0Sopenharmony_ci * \brief Mixer Interface 4d5ac70f0Sopenharmony_ci * \author Jaroslav Kysela <perex@perex.cz> 5d5ac70f0Sopenharmony_ci * \author Abramo Bagnara <abramo@alsa-project.org> 6d5ac70f0Sopenharmony_ci * \date 2001 7d5ac70f0Sopenharmony_ci * 8d5ac70f0Sopenharmony_ci * Mixer interface is designed to access mixer elements. 9d5ac70f0Sopenharmony_ci * Callbacks may be used for event handling. 10d5ac70f0Sopenharmony_ci */ 11d5ac70f0Sopenharmony_ci/* 12d5ac70f0Sopenharmony_ci * Mixer Interface - main file 13d5ac70f0Sopenharmony_ci * Copyright (c) 1998/1999/2000 by Jaroslav Kysela <perex@perex.cz> 14d5ac70f0Sopenharmony_ci * Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org> 15d5ac70f0Sopenharmony_ci * 16d5ac70f0Sopenharmony_ci * 17d5ac70f0Sopenharmony_ci * This library is free software; you can redistribute it and/or modify 18d5ac70f0Sopenharmony_ci * it under the terms of the GNU Lesser General Public License as 19d5ac70f0Sopenharmony_ci * published by the Free Software Foundation; either version 2.1 of 20d5ac70f0Sopenharmony_ci * the License, or (at your option) any later version. 21d5ac70f0Sopenharmony_ci * 22d5ac70f0Sopenharmony_ci * This program is distributed in the hope that it will be useful, 23d5ac70f0Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 24d5ac70f0Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25d5ac70f0Sopenharmony_ci * GNU Lesser General Public License for more details. 26d5ac70f0Sopenharmony_ci * 27d5ac70f0Sopenharmony_ci * You should have received a copy of the GNU Lesser General Public 28d5ac70f0Sopenharmony_ci * License along with this library; if not, write to the Free Software 29d5ac70f0Sopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 30d5ac70f0Sopenharmony_ci * 31d5ac70f0Sopenharmony_ci */ 32d5ac70f0Sopenharmony_ci 33d5ac70f0Sopenharmony_ci/*! \page mixer Mixer interface 34d5ac70f0Sopenharmony_ci 35d5ac70f0Sopenharmony_ci<P>Mixer interface is designed to access the abstracted mixer controls. 36d5ac70f0Sopenharmony_ciThis is an abstraction layer over the hcontrol layer. 37d5ac70f0Sopenharmony_ci 38d5ac70f0Sopenharmony_ci\section mixer_general_overview General overview 39d5ac70f0Sopenharmony_ci 40d5ac70f0Sopenharmony_ci*/ 41d5ac70f0Sopenharmony_ci 42d5ac70f0Sopenharmony_ci#include "mixer_local.h" 43d5ac70f0Sopenharmony_ci#include <stdio.h> 44d5ac70f0Sopenharmony_ci#include <stdlib.h> 45d5ac70f0Sopenharmony_ci#include <unistd.h> 46d5ac70f0Sopenharmony_ci#include <string.h> 47d5ac70f0Sopenharmony_ci#include <fcntl.h> 48d5ac70f0Sopenharmony_ci#include <sys/ioctl.h> 49d5ac70f0Sopenharmony_ci 50d5ac70f0Sopenharmony_ci#ifndef DOC_HIDDEN 51d5ac70f0Sopenharmony_citypedef struct _snd_mixer_slave { 52d5ac70f0Sopenharmony_ci snd_hctl_t *hctl; 53d5ac70f0Sopenharmony_ci struct list_head list; 54d5ac70f0Sopenharmony_ci} snd_mixer_slave_t; 55d5ac70f0Sopenharmony_ci 56d5ac70f0Sopenharmony_ci#endif 57d5ac70f0Sopenharmony_ci 58d5ac70f0Sopenharmony_cistatic int snd_mixer_compare_default(const snd_mixer_elem_t *c1, 59d5ac70f0Sopenharmony_ci const snd_mixer_elem_t *c2); 60d5ac70f0Sopenharmony_ci 61d5ac70f0Sopenharmony_ci 62d5ac70f0Sopenharmony_ci/** 63d5ac70f0Sopenharmony_ci * \brief Opens an empty mixer 64d5ac70f0Sopenharmony_ci * \param mixerp Returned mixer handle 65d5ac70f0Sopenharmony_ci * \param mode Open mode 66d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 67d5ac70f0Sopenharmony_ci */ 68d5ac70f0Sopenharmony_ciint snd_mixer_open(snd_mixer_t **mixerp, int mode ATTRIBUTE_UNUSED) 69d5ac70f0Sopenharmony_ci{ 70d5ac70f0Sopenharmony_ci snd_mixer_t *mixer; 71d5ac70f0Sopenharmony_ci assert(mixerp); 72d5ac70f0Sopenharmony_ci mixer = calloc(1, sizeof(*mixer)); 73d5ac70f0Sopenharmony_ci if (mixer == NULL) 74d5ac70f0Sopenharmony_ci return -ENOMEM; 75d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&mixer->slaves); 76d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&mixer->classes); 77d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&mixer->elems); 78d5ac70f0Sopenharmony_ci mixer->compare = snd_mixer_compare_default; 79d5ac70f0Sopenharmony_ci *mixerp = mixer; 80d5ac70f0Sopenharmony_ci return 0; 81d5ac70f0Sopenharmony_ci} 82d5ac70f0Sopenharmony_ci 83d5ac70f0Sopenharmony_ci/** 84d5ac70f0Sopenharmony_ci * \brief Attach an HCTL element to a mixer element 85d5ac70f0Sopenharmony_ci * \param melem Mixer element 86d5ac70f0Sopenharmony_ci * \param helem HCTL element 87d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 88d5ac70f0Sopenharmony_ci * 89d5ac70f0Sopenharmony_ci * For use by mixer element class specific code. 90d5ac70f0Sopenharmony_ci * 91d5ac70f0Sopenharmony_ci * The implementation of mixer class typically calls it at #SND_CTL_EVENT_MASK_ADD event. Once 92d5ac70f0Sopenharmony_ci * attaching, the implementation should make sure to detach it by call of #snd_mixer_elem_detach() 93d5ac70f0Sopenharmony_ci * at #SND_CTL_EVENT_MASK_REMOVE event. Unless detaching, mixer API internal hits assertion due 94d5ac70f0Sopenharmony_ci * to unsatisfied postcondition after the event. 95d5ac70f0Sopenharmony_ci */ 96d5ac70f0Sopenharmony_ciint snd_mixer_elem_attach(snd_mixer_elem_t *melem, 97d5ac70f0Sopenharmony_ci snd_hctl_elem_t *helem) 98d5ac70f0Sopenharmony_ci{ 99d5ac70f0Sopenharmony_ci bag_t *bag = snd_hctl_elem_get_callback_private(helem); 100d5ac70f0Sopenharmony_ci int err; 101d5ac70f0Sopenharmony_ci err = bag_add(bag, melem); 102d5ac70f0Sopenharmony_ci if (err < 0) 103d5ac70f0Sopenharmony_ci return err; 104d5ac70f0Sopenharmony_ci return bag_add(&melem->helems, helem); 105d5ac70f0Sopenharmony_ci} 106d5ac70f0Sopenharmony_ci 107d5ac70f0Sopenharmony_ci/** 108d5ac70f0Sopenharmony_ci * \brief Detach an HCTL element from a mixer element 109d5ac70f0Sopenharmony_ci * \param melem Mixer element 110d5ac70f0Sopenharmony_ci * \param helem HCTL element 111d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 112d5ac70f0Sopenharmony_ci * 113d5ac70f0Sopenharmony_ci * For use by mixer element class specific code. 114d5ac70f0Sopenharmony_ci * 115d5ac70f0Sopenharmony_ci * The implementation of mixer class typically calls it at #SND_CTL_EVENT_MASK_REMOVE event for 116d5ac70f0Sopenharmony_ci * attached mixer element at #SND_CTL_EVENT_MASK_ADD. Unless detaching, mixer API internal hits 117d5ac70f0Sopenharmony_ci * assertion due to unsatisfied postcondition after the event. 118d5ac70f0Sopenharmony_ci */ 119d5ac70f0Sopenharmony_ciint snd_mixer_elem_detach(snd_mixer_elem_t *melem, 120d5ac70f0Sopenharmony_ci snd_hctl_elem_t *helem) 121d5ac70f0Sopenharmony_ci{ 122d5ac70f0Sopenharmony_ci bag_t *bag = snd_hctl_elem_get_callback_private(helem); 123d5ac70f0Sopenharmony_ci int err; 124d5ac70f0Sopenharmony_ci err = bag_del(bag, melem); 125d5ac70f0Sopenharmony_ci assert(err >= 0); 126d5ac70f0Sopenharmony_ci err = bag_del(&melem->helems, helem); 127d5ac70f0Sopenharmony_ci assert(err >= 0); 128d5ac70f0Sopenharmony_ci return 0; 129d5ac70f0Sopenharmony_ci} 130d5ac70f0Sopenharmony_ci 131d5ac70f0Sopenharmony_ci/** 132d5ac70f0Sopenharmony_ci * \brief Return true if a mixer element does not contain any HCTL elements 133d5ac70f0Sopenharmony_ci * \param melem Mixer element 134d5ac70f0Sopenharmony_ci * \return 0 if not empty, 1 if empty 135d5ac70f0Sopenharmony_ci * 136d5ac70f0Sopenharmony_ci * For use by mixer element class specific code. 137d5ac70f0Sopenharmony_ci */ 138d5ac70f0Sopenharmony_ciint snd_mixer_elem_empty(snd_mixer_elem_t *melem) 139d5ac70f0Sopenharmony_ci{ 140d5ac70f0Sopenharmony_ci return bag_empty(&melem->helems); 141d5ac70f0Sopenharmony_ci} 142d5ac70f0Sopenharmony_ci 143d5ac70f0Sopenharmony_cistatic int hctl_elem_event_handler(snd_hctl_elem_t *helem, 144d5ac70f0Sopenharmony_ci unsigned int mask) 145d5ac70f0Sopenharmony_ci{ 146d5ac70f0Sopenharmony_ci bag_t *bag = snd_hctl_elem_get_callback_private(helem); 147d5ac70f0Sopenharmony_ci if (mask == SND_CTL_EVENT_MASK_REMOVE) { 148d5ac70f0Sopenharmony_ci int res = 0; 149d5ac70f0Sopenharmony_ci int err; 150d5ac70f0Sopenharmony_ci bag_iterator_t i, n; 151d5ac70f0Sopenharmony_ci bag_for_each_safe(i, n, bag) { 152d5ac70f0Sopenharmony_ci snd_mixer_elem_t *melem = bag_iterator_entry(i); 153d5ac70f0Sopenharmony_ci snd_mixer_class_t *class = melem->class; 154d5ac70f0Sopenharmony_ci err = class->event(class, mask, helem, melem); 155d5ac70f0Sopenharmony_ci if (err < 0) 156d5ac70f0Sopenharmony_ci res = err; 157d5ac70f0Sopenharmony_ci } 158d5ac70f0Sopenharmony_ci // NOTE: Unsatisfied postcondition. Typically, some of registerd implementation of 159d5ac70f0Sopenharmony_ci // mixer class forget to detach mixer element from hcontrol element which has been 160d5ac70f0Sopenharmony_ci // attached at ADD event. 161d5ac70f0Sopenharmony_ci assert(bag_empty(bag)); 162d5ac70f0Sopenharmony_ci bag_free(bag); 163d5ac70f0Sopenharmony_ci return res; 164d5ac70f0Sopenharmony_ci } 165d5ac70f0Sopenharmony_ci if (mask & (SND_CTL_EVENT_MASK_VALUE | SND_CTL_EVENT_MASK_INFO)) { 166d5ac70f0Sopenharmony_ci int err = 0; 167d5ac70f0Sopenharmony_ci bag_iterator_t i, n; 168d5ac70f0Sopenharmony_ci bag_for_each_safe(i, n, bag) { 169d5ac70f0Sopenharmony_ci snd_mixer_elem_t *melem = bag_iterator_entry(i); 170d5ac70f0Sopenharmony_ci snd_mixer_class_t *class = melem->class; 171d5ac70f0Sopenharmony_ci err = class->event(class, mask, helem, melem); 172d5ac70f0Sopenharmony_ci if (err < 0) 173d5ac70f0Sopenharmony_ci return err; 174d5ac70f0Sopenharmony_ci } 175d5ac70f0Sopenharmony_ci } 176d5ac70f0Sopenharmony_ci return 0; 177d5ac70f0Sopenharmony_ci} 178d5ac70f0Sopenharmony_ci 179d5ac70f0Sopenharmony_cistatic int hctl_event_handler(snd_hctl_t *hctl, unsigned int mask, 180d5ac70f0Sopenharmony_ci snd_hctl_elem_t *elem) 181d5ac70f0Sopenharmony_ci{ 182d5ac70f0Sopenharmony_ci snd_mixer_t *mixer = snd_hctl_get_callback_private(hctl); 183d5ac70f0Sopenharmony_ci int res = 0; 184d5ac70f0Sopenharmony_ci if (mask & SND_CTL_EVENT_MASK_ADD) { 185d5ac70f0Sopenharmony_ci struct list_head *pos; 186d5ac70f0Sopenharmony_ci bag_t *bag; 187d5ac70f0Sopenharmony_ci int err = bag_new(&bag); 188d5ac70f0Sopenharmony_ci if (err < 0) 189d5ac70f0Sopenharmony_ci return err; 190d5ac70f0Sopenharmony_ci snd_hctl_elem_set_callback(elem, hctl_elem_event_handler); 191d5ac70f0Sopenharmony_ci snd_hctl_elem_set_callback_private(elem, bag); 192d5ac70f0Sopenharmony_ci list_for_each(pos, &mixer->classes) { 193d5ac70f0Sopenharmony_ci snd_mixer_class_t *c; 194d5ac70f0Sopenharmony_ci c = list_entry(pos, snd_mixer_class_t, list); 195d5ac70f0Sopenharmony_ci err = c->event(c, mask, elem, NULL); 196d5ac70f0Sopenharmony_ci if (err < 0) 197d5ac70f0Sopenharmony_ci res = err; 198d5ac70f0Sopenharmony_ci } 199d5ac70f0Sopenharmony_ci } 200d5ac70f0Sopenharmony_ci return res; 201d5ac70f0Sopenharmony_ci} 202d5ac70f0Sopenharmony_ci 203d5ac70f0Sopenharmony_ci 204d5ac70f0Sopenharmony_ci/** 205d5ac70f0Sopenharmony_ci * \brief Attach an HCTL specified with the CTL device name to an opened mixer 206d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 207d5ac70f0Sopenharmony_ci * \param name HCTL name (see #snd_hctl_open) 208d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 209d5ac70f0Sopenharmony_ci */ 210d5ac70f0Sopenharmony_ciint snd_mixer_attach(snd_mixer_t *mixer, const char *name) 211d5ac70f0Sopenharmony_ci{ 212d5ac70f0Sopenharmony_ci snd_hctl_t *hctl; 213d5ac70f0Sopenharmony_ci int err; 214d5ac70f0Sopenharmony_ci 215d5ac70f0Sopenharmony_ci err = snd_hctl_open(&hctl, name, 0); 216d5ac70f0Sopenharmony_ci if (err < 0) 217d5ac70f0Sopenharmony_ci return err; 218d5ac70f0Sopenharmony_ci err = snd_mixer_attach_hctl(mixer, hctl); 219d5ac70f0Sopenharmony_ci if (err < 0) 220d5ac70f0Sopenharmony_ci return err; 221d5ac70f0Sopenharmony_ci return 0; 222d5ac70f0Sopenharmony_ci} 223d5ac70f0Sopenharmony_ci 224d5ac70f0Sopenharmony_ci/** 225d5ac70f0Sopenharmony_ci * \brief Attach an HCTL to an opened mixer 226d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 227d5ac70f0Sopenharmony_ci * \param hctl the HCTL to be attached 228d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 229d5ac70f0Sopenharmony_ci * 230d5ac70f0Sopenharmony_ci * Upon error, this function closes the given hctl handle automatically. 231d5ac70f0Sopenharmony_ci */ 232d5ac70f0Sopenharmony_ciint snd_mixer_attach_hctl(snd_mixer_t *mixer, snd_hctl_t *hctl) 233d5ac70f0Sopenharmony_ci{ 234d5ac70f0Sopenharmony_ci snd_mixer_slave_t *slave; 235d5ac70f0Sopenharmony_ci int err; 236d5ac70f0Sopenharmony_ci 237d5ac70f0Sopenharmony_ci assert(hctl); 238d5ac70f0Sopenharmony_ci slave = calloc(1, sizeof(*slave)); 239d5ac70f0Sopenharmony_ci if (slave == NULL) { 240d5ac70f0Sopenharmony_ci snd_hctl_close(hctl); 241d5ac70f0Sopenharmony_ci return -ENOMEM; 242d5ac70f0Sopenharmony_ci } 243d5ac70f0Sopenharmony_ci err = snd_hctl_nonblock(hctl, 1); 244d5ac70f0Sopenharmony_ci if (err < 0) { 245d5ac70f0Sopenharmony_ci snd_hctl_close(hctl); 246d5ac70f0Sopenharmony_ci free(slave); 247d5ac70f0Sopenharmony_ci return err; 248d5ac70f0Sopenharmony_ci } 249d5ac70f0Sopenharmony_ci snd_hctl_set_callback(hctl, hctl_event_handler); 250d5ac70f0Sopenharmony_ci snd_hctl_set_callback_private(hctl, mixer); 251d5ac70f0Sopenharmony_ci slave->hctl = hctl; 252d5ac70f0Sopenharmony_ci list_add_tail(&slave->list, &mixer->slaves); 253d5ac70f0Sopenharmony_ci return 0; 254d5ac70f0Sopenharmony_ci} 255d5ac70f0Sopenharmony_ci 256d5ac70f0Sopenharmony_ci/** 257d5ac70f0Sopenharmony_ci * \brief Detach a previously attached HCTL to an opened mixer freeing all related resources 258d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 259d5ac70f0Sopenharmony_ci * \param name HCTL previously attached 260d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 261d5ac70f0Sopenharmony_ci */ 262d5ac70f0Sopenharmony_ciint snd_mixer_detach(snd_mixer_t *mixer, const char *name) 263d5ac70f0Sopenharmony_ci{ 264d5ac70f0Sopenharmony_ci struct list_head *pos; 265d5ac70f0Sopenharmony_ci list_for_each(pos, &mixer->slaves) { 266d5ac70f0Sopenharmony_ci snd_mixer_slave_t *s; 267d5ac70f0Sopenharmony_ci s = list_entry(pos, snd_mixer_slave_t, list); 268d5ac70f0Sopenharmony_ci if (strcmp(name, snd_hctl_name(s->hctl)) == 0) { 269d5ac70f0Sopenharmony_ci snd_hctl_close(s->hctl); 270d5ac70f0Sopenharmony_ci list_del(pos); 271d5ac70f0Sopenharmony_ci free(s); 272d5ac70f0Sopenharmony_ci return 0; 273d5ac70f0Sopenharmony_ci } 274d5ac70f0Sopenharmony_ci } 275d5ac70f0Sopenharmony_ci return -ENOENT; 276d5ac70f0Sopenharmony_ci} 277d5ac70f0Sopenharmony_ci 278d5ac70f0Sopenharmony_ci/** 279d5ac70f0Sopenharmony_ci * \brief Detach a previously attached HCTL to an opened mixer freeing all related resources 280d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 281d5ac70f0Sopenharmony_ci * \param hctl HCTL previously attached 282d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 283d5ac70f0Sopenharmony_ci * 284d5ac70f0Sopenharmony_ci * Note: The hctl handle is not closed! 285d5ac70f0Sopenharmony_ci */ 286d5ac70f0Sopenharmony_ciint snd_mixer_detach_hctl(snd_mixer_t *mixer, snd_hctl_t *hctl) 287d5ac70f0Sopenharmony_ci{ 288d5ac70f0Sopenharmony_ci struct list_head *pos; 289d5ac70f0Sopenharmony_ci list_for_each(pos, &mixer->slaves) { 290d5ac70f0Sopenharmony_ci snd_mixer_slave_t *s; 291d5ac70f0Sopenharmony_ci s = list_entry(pos, snd_mixer_slave_t, list); 292d5ac70f0Sopenharmony_ci if (hctl == s->hctl) { 293d5ac70f0Sopenharmony_ci list_del(pos); 294d5ac70f0Sopenharmony_ci free(s); 295d5ac70f0Sopenharmony_ci return 0; 296d5ac70f0Sopenharmony_ci } 297d5ac70f0Sopenharmony_ci } 298d5ac70f0Sopenharmony_ci return -ENOENT; 299d5ac70f0Sopenharmony_ci} 300d5ac70f0Sopenharmony_ci 301d5ac70f0Sopenharmony_ci/** 302d5ac70f0Sopenharmony_ci * \brief Obtain a HCTL pointer associated to given name 303d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 304d5ac70f0Sopenharmony_ci * \param name HCTL previously attached 305d5ac70f0Sopenharmony_ci * \param hctl HCTL pointer 306d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 307d5ac70f0Sopenharmony_ci */ 308d5ac70f0Sopenharmony_ciint snd_mixer_get_hctl(snd_mixer_t *mixer, const char *name, snd_hctl_t **hctl) 309d5ac70f0Sopenharmony_ci{ 310d5ac70f0Sopenharmony_ci struct list_head *pos; 311d5ac70f0Sopenharmony_ci list_for_each(pos, &mixer->slaves) { 312d5ac70f0Sopenharmony_ci snd_mixer_slave_t *s; 313d5ac70f0Sopenharmony_ci s = list_entry(pos, snd_mixer_slave_t, list); 314d5ac70f0Sopenharmony_ci if (strcmp(name, snd_hctl_name(s->hctl)) == 0) { 315d5ac70f0Sopenharmony_ci *hctl = s->hctl; 316d5ac70f0Sopenharmony_ci return 0; 317d5ac70f0Sopenharmony_ci } 318d5ac70f0Sopenharmony_ci } 319d5ac70f0Sopenharmony_ci return -ENOENT; 320d5ac70f0Sopenharmony_ci} 321d5ac70f0Sopenharmony_ci 322d5ac70f0Sopenharmony_cistatic int snd_mixer_throw_event(snd_mixer_t *mixer, unsigned int mask, 323d5ac70f0Sopenharmony_ci snd_mixer_elem_t *elem) 324d5ac70f0Sopenharmony_ci{ 325d5ac70f0Sopenharmony_ci mixer->events++; 326d5ac70f0Sopenharmony_ci if (mixer->callback) 327d5ac70f0Sopenharmony_ci return mixer->callback(mixer, mask, elem); 328d5ac70f0Sopenharmony_ci return 0; 329d5ac70f0Sopenharmony_ci} 330d5ac70f0Sopenharmony_ci 331d5ac70f0Sopenharmony_cistatic int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem, unsigned int mask) 332d5ac70f0Sopenharmony_ci{ 333d5ac70f0Sopenharmony_ci elem->class->mixer->events++; 334d5ac70f0Sopenharmony_ci if (elem->callback) 335d5ac70f0Sopenharmony_ci return elem->callback(elem, mask); 336d5ac70f0Sopenharmony_ci return 0; 337d5ac70f0Sopenharmony_ci} 338d5ac70f0Sopenharmony_ci 339d5ac70f0Sopenharmony_cistatic int _snd_mixer_find_elem(snd_mixer_t *mixer, snd_mixer_elem_t *elem, int *dir) 340d5ac70f0Sopenharmony_ci{ 341d5ac70f0Sopenharmony_ci unsigned int l, u; 342d5ac70f0Sopenharmony_ci int c = 0; 343d5ac70f0Sopenharmony_ci int idx = -1; 344d5ac70f0Sopenharmony_ci assert(mixer && elem); 345d5ac70f0Sopenharmony_ci assert(mixer->compare); 346d5ac70f0Sopenharmony_ci l = 0; 347d5ac70f0Sopenharmony_ci u = mixer->count; 348d5ac70f0Sopenharmony_ci while (l < u) { 349d5ac70f0Sopenharmony_ci idx = (l + u) / 2; 350d5ac70f0Sopenharmony_ci c = mixer->compare(elem, mixer->pelems[idx]); 351d5ac70f0Sopenharmony_ci if (c < 0) 352d5ac70f0Sopenharmony_ci u = idx; 353d5ac70f0Sopenharmony_ci else if (c > 0) 354d5ac70f0Sopenharmony_ci l = idx + 1; 355d5ac70f0Sopenharmony_ci else 356d5ac70f0Sopenharmony_ci break; 357d5ac70f0Sopenharmony_ci } 358d5ac70f0Sopenharmony_ci *dir = c; 359d5ac70f0Sopenharmony_ci return idx; 360d5ac70f0Sopenharmony_ci} 361d5ac70f0Sopenharmony_ci 362d5ac70f0Sopenharmony_ci/** 363d5ac70f0Sopenharmony_ci * \brief Get private data associated to give mixer element 364d5ac70f0Sopenharmony_ci * \param elem Mixer element 365d5ac70f0Sopenharmony_ci * \return private data 366d5ac70f0Sopenharmony_ci * 367d5ac70f0Sopenharmony_ci * For use by mixer element class specific code. 368d5ac70f0Sopenharmony_ci */ 369d5ac70f0Sopenharmony_civoid *snd_mixer_elem_get_private(const snd_mixer_elem_t *elem) 370d5ac70f0Sopenharmony_ci{ 371d5ac70f0Sopenharmony_ci return elem->private_data; 372d5ac70f0Sopenharmony_ci} 373d5ac70f0Sopenharmony_ci 374d5ac70f0Sopenharmony_ci/** 375d5ac70f0Sopenharmony_ci * \brief Allocate a new mixer element 376d5ac70f0Sopenharmony_ci * \param elem Returned mixer element 377d5ac70f0Sopenharmony_ci * \param type Mixer element type 378d5ac70f0Sopenharmony_ci * \param compare_weight Mixer element compare weight 379d5ac70f0Sopenharmony_ci * \param private_data Private data 380d5ac70f0Sopenharmony_ci * \param private_free Private data free callback 381d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 382d5ac70f0Sopenharmony_ci * 383d5ac70f0Sopenharmony_ci * For use by mixer element class specific code. 384d5ac70f0Sopenharmony_ci */ 385d5ac70f0Sopenharmony_ciint snd_mixer_elem_new(snd_mixer_elem_t **elem, 386d5ac70f0Sopenharmony_ci snd_mixer_elem_type_t type, 387d5ac70f0Sopenharmony_ci int compare_weight, 388d5ac70f0Sopenharmony_ci void *private_data, 389d5ac70f0Sopenharmony_ci void (*private_free)(snd_mixer_elem_t *elem)) 390d5ac70f0Sopenharmony_ci{ 391d5ac70f0Sopenharmony_ci snd_mixer_elem_t *melem = calloc(1, sizeof(*melem)); 392d5ac70f0Sopenharmony_ci if (melem == NULL) 393d5ac70f0Sopenharmony_ci return -ENOMEM; 394d5ac70f0Sopenharmony_ci melem->type = type; 395d5ac70f0Sopenharmony_ci melem->compare_weight = compare_weight; 396d5ac70f0Sopenharmony_ci melem->private_data = private_data; 397d5ac70f0Sopenharmony_ci melem->private_free = private_free; 398d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&melem->helems); 399d5ac70f0Sopenharmony_ci *elem = melem; 400d5ac70f0Sopenharmony_ci return 0; 401d5ac70f0Sopenharmony_ci} 402d5ac70f0Sopenharmony_ci 403d5ac70f0Sopenharmony_ci/** 404d5ac70f0Sopenharmony_ci * \brief Add an element for a registered mixer element class 405d5ac70f0Sopenharmony_ci * \param elem Mixer element 406d5ac70f0Sopenharmony_ci * \param class Mixer element class 407d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 408d5ac70f0Sopenharmony_ci * 409d5ac70f0Sopenharmony_ci * For use by mixer element class specific code. 410d5ac70f0Sopenharmony_ci */ 411d5ac70f0Sopenharmony_ciint snd_mixer_elem_add(snd_mixer_elem_t *elem, snd_mixer_class_t *class) 412d5ac70f0Sopenharmony_ci{ 413d5ac70f0Sopenharmony_ci int dir, idx; 414d5ac70f0Sopenharmony_ci snd_mixer_t *mixer = class->mixer; 415d5ac70f0Sopenharmony_ci elem->class = class; 416d5ac70f0Sopenharmony_ci 417d5ac70f0Sopenharmony_ci if (mixer->count == mixer->alloc) { 418d5ac70f0Sopenharmony_ci snd_mixer_elem_t **m; 419d5ac70f0Sopenharmony_ci mixer->alloc += 32; 420d5ac70f0Sopenharmony_ci m = realloc(mixer->pelems, sizeof(*m) * mixer->alloc); 421d5ac70f0Sopenharmony_ci if (!m) { 422d5ac70f0Sopenharmony_ci mixer->alloc -= 32; 423d5ac70f0Sopenharmony_ci return -ENOMEM; 424d5ac70f0Sopenharmony_ci } 425d5ac70f0Sopenharmony_ci mixer->pelems = m; 426d5ac70f0Sopenharmony_ci } 427d5ac70f0Sopenharmony_ci if (mixer->count == 0) { 428d5ac70f0Sopenharmony_ci list_add_tail(&elem->list, &mixer->elems); 429d5ac70f0Sopenharmony_ci mixer->pelems[0] = elem; 430d5ac70f0Sopenharmony_ci } else { 431d5ac70f0Sopenharmony_ci idx = _snd_mixer_find_elem(mixer, elem, &dir); 432d5ac70f0Sopenharmony_ci assert(dir != 0); 433d5ac70f0Sopenharmony_ci if (dir > 0) { 434d5ac70f0Sopenharmony_ci list_add(&elem->list, &mixer->pelems[idx]->list); 435d5ac70f0Sopenharmony_ci idx++; 436d5ac70f0Sopenharmony_ci } else { 437d5ac70f0Sopenharmony_ci list_add_tail(&elem->list, &mixer->pelems[idx]->list); 438d5ac70f0Sopenharmony_ci } 439d5ac70f0Sopenharmony_ci memmove(mixer->pelems + idx + 1, 440d5ac70f0Sopenharmony_ci mixer->pelems + idx, 441d5ac70f0Sopenharmony_ci (mixer->count - idx) * sizeof(snd_mixer_elem_t *)); 442d5ac70f0Sopenharmony_ci mixer->pelems[idx] = elem; 443d5ac70f0Sopenharmony_ci } 444d5ac70f0Sopenharmony_ci mixer->count++; 445d5ac70f0Sopenharmony_ci return snd_mixer_throw_event(mixer, SND_CTL_EVENT_MASK_ADD, elem); 446d5ac70f0Sopenharmony_ci} 447d5ac70f0Sopenharmony_ci 448d5ac70f0Sopenharmony_ci/** 449d5ac70f0Sopenharmony_ci * \brief Remove a mixer element 450d5ac70f0Sopenharmony_ci * \param elem Mixer element 451d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 452d5ac70f0Sopenharmony_ci * 453d5ac70f0Sopenharmony_ci * For use by mixer element class specific code. 454d5ac70f0Sopenharmony_ci */ 455d5ac70f0Sopenharmony_ciint snd_mixer_elem_remove(snd_mixer_elem_t *elem) 456d5ac70f0Sopenharmony_ci{ 457d5ac70f0Sopenharmony_ci snd_mixer_t *mixer = elem->class->mixer; 458d5ac70f0Sopenharmony_ci bag_iterator_t i, n; 459d5ac70f0Sopenharmony_ci int err, idx, dir; 460d5ac70f0Sopenharmony_ci unsigned int m; 461d5ac70f0Sopenharmony_ci assert(elem); 462d5ac70f0Sopenharmony_ci assert(mixer->count); 463d5ac70f0Sopenharmony_ci idx = _snd_mixer_find_elem(mixer, elem, &dir); 464d5ac70f0Sopenharmony_ci if (dir != 0) 465d5ac70f0Sopenharmony_ci return -EINVAL; 466d5ac70f0Sopenharmony_ci bag_for_each_safe(i, n, &elem->helems) { 467d5ac70f0Sopenharmony_ci snd_hctl_elem_t *helem = bag_iterator_entry(i); 468d5ac70f0Sopenharmony_ci snd_mixer_elem_detach(elem, helem); 469d5ac70f0Sopenharmony_ci } 470d5ac70f0Sopenharmony_ci err = snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_REMOVE); 471d5ac70f0Sopenharmony_ci list_del(&elem->list); 472d5ac70f0Sopenharmony_ci snd_mixer_elem_free(elem); 473d5ac70f0Sopenharmony_ci mixer->count--; 474d5ac70f0Sopenharmony_ci m = mixer->count - idx; 475d5ac70f0Sopenharmony_ci if (m > 0) 476d5ac70f0Sopenharmony_ci memmove(mixer->pelems + idx, 477d5ac70f0Sopenharmony_ci mixer->pelems + idx + 1, 478d5ac70f0Sopenharmony_ci m * sizeof(snd_mixer_elem_t *)); 479d5ac70f0Sopenharmony_ci return err; 480d5ac70f0Sopenharmony_ci} 481d5ac70f0Sopenharmony_ci 482d5ac70f0Sopenharmony_ci/** 483d5ac70f0Sopenharmony_ci * \brief Free a mixer element 484d5ac70f0Sopenharmony_ci * \param elem Mixer element 485d5ac70f0Sopenharmony_ci * 486d5ac70f0Sopenharmony_ci * For use by mixer element class specific code. 487d5ac70f0Sopenharmony_ci */ 488d5ac70f0Sopenharmony_civoid snd_mixer_elem_free(snd_mixer_elem_t *elem) 489d5ac70f0Sopenharmony_ci{ 490d5ac70f0Sopenharmony_ci if (elem->private_free) 491d5ac70f0Sopenharmony_ci elem->private_free(elem); 492d5ac70f0Sopenharmony_ci free(elem); 493d5ac70f0Sopenharmony_ci} 494d5ac70f0Sopenharmony_ci 495d5ac70f0Sopenharmony_ci/** 496d5ac70f0Sopenharmony_ci * \brief Mixer element informations are changed 497d5ac70f0Sopenharmony_ci * \param elem Mixer element 498d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 499d5ac70f0Sopenharmony_ci * 500d5ac70f0Sopenharmony_ci * For use by mixer element class specific code. 501d5ac70f0Sopenharmony_ci */ 502d5ac70f0Sopenharmony_ciint snd_mixer_elem_info(snd_mixer_elem_t *elem) 503d5ac70f0Sopenharmony_ci{ 504d5ac70f0Sopenharmony_ci return snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_INFO); 505d5ac70f0Sopenharmony_ci} 506d5ac70f0Sopenharmony_ci 507d5ac70f0Sopenharmony_ci/** 508d5ac70f0Sopenharmony_ci * \brief Mixer element values is changed 509d5ac70f0Sopenharmony_ci * \param elem Mixer element 510d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 511d5ac70f0Sopenharmony_ci * 512d5ac70f0Sopenharmony_ci * For use by mixer element class specific code. 513d5ac70f0Sopenharmony_ci */ 514d5ac70f0Sopenharmony_ciint snd_mixer_elem_value(snd_mixer_elem_t *elem) 515d5ac70f0Sopenharmony_ci{ 516d5ac70f0Sopenharmony_ci return snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_VALUE); 517d5ac70f0Sopenharmony_ci} 518d5ac70f0Sopenharmony_ci 519d5ac70f0Sopenharmony_ci/** 520d5ac70f0Sopenharmony_ci * \brief Register mixer element class 521d5ac70f0Sopenharmony_ci * \param class Mixer element class 522d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 523d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 524d5ac70f0Sopenharmony_ci * 525d5ac70f0Sopenharmony_ci * For use by mixer element class specific code. 526d5ac70f0Sopenharmony_ci */ 527d5ac70f0Sopenharmony_ciint snd_mixer_class_register(snd_mixer_class_t *class, snd_mixer_t *mixer) 528d5ac70f0Sopenharmony_ci{ 529d5ac70f0Sopenharmony_ci struct list_head *pos; 530d5ac70f0Sopenharmony_ci class->mixer = mixer; 531d5ac70f0Sopenharmony_ci list_add_tail(&class->list, &mixer->classes); 532d5ac70f0Sopenharmony_ci if (!class->event) 533d5ac70f0Sopenharmony_ci return 0; 534d5ac70f0Sopenharmony_ci list_for_each(pos, &mixer->slaves) { 535d5ac70f0Sopenharmony_ci int err; 536d5ac70f0Sopenharmony_ci snd_mixer_slave_t *slave; 537d5ac70f0Sopenharmony_ci snd_hctl_elem_t *elem; 538d5ac70f0Sopenharmony_ci slave = list_entry(pos, snd_mixer_slave_t, list); 539d5ac70f0Sopenharmony_ci elem = snd_hctl_first_elem(slave->hctl); 540d5ac70f0Sopenharmony_ci while (elem) { 541d5ac70f0Sopenharmony_ci err = class->event(class, SND_CTL_EVENT_MASK_ADD, elem, NULL); 542d5ac70f0Sopenharmony_ci if (err < 0) 543d5ac70f0Sopenharmony_ci return err; 544d5ac70f0Sopenharmony_ci elem = snd_hctl_elem_next(elem); 545d5ac70f0Sopenharmony_ci } 546d5ac70f0Sopenharmony_ci } 547d5ac70f0Sopenharmony_ci return 0; 548d5ac70f0Sopenharmony_ci} 549d5ac70f0Sopenharmony_ci 550d5ac70f0Sopenharmony_ci/** 551d5ac70f0Sopenharmony_ci * \brief Unregister mixer element class and remove all its elements 552d5ac70f0Sopenharmony_ci * \param class Mixer element class 553d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 554d5ac70f0Sopenharmony_ci * 555d5ac70f0Sopenharmony_ci * Note that the class structure is also deallocated! 556d5ac70f0Sopenharmony_ci */ 557d5ac70f0Sopenharmony_ciint snd_mixer_class_unregister(snd_mixer_class_t *class) 558d5ac70f0Sopenharmony_ci{ 559d5ac70f0Sopenharmony_ci unsigned int k; 560d5ac70f0Sopenharmony_ci snd_mixer_elem_t *e; 561d5ac70f0Sopenharmony_ci snd_mixer_t *mixer = class->mixer; 562d5ac70f0Sopenharmony_ci for (k = mixer->count; k > 0; k--) { 563d5ac70f0Sopenharmony_ci e = mixer->pelems[k-1]; 564d5ac70f0Sopenharmony_ci if (e->class == class) 565d5ac70f0Sopenharmony_ci snd_mixer_elem_remove(e); 566d5ac70f0Sopenharmony_ci } 567d5ac70f0Sopenharmony_ci if (class->private_free) 568d5ac70f0Sopenharmony_ci class->private_free(class); 569d5ac70f0Sopenharmony_ci list_del(&class->list); 570d5ac70f0Sopenharmony_ci free(class); 571d5ac70f0Sopenharmony_ci return 0; 572d5ac70f0Sopenharmony_ci} 573d5ac70f0Sopenharmony_ci 574d5ac70f0Sopenharmony_ci/** 575d5ac70f0Sopenharmony_ci * \brief Load a mixer elements 576d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 577d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 578d5ac70f0Sopenharmony_ci */ 579d5ac70f0Sopenharmony_ciint snd_mixer_load(snd_mixer_t *mixer) 580d5ac70f0Sopenharmony_ci{ 581d5ac70f0Sopenharmony_ci struct list_head *pos; 582d5ac70f0Sopenharmony_ci list_for_each(pos, &mixer->slaves) { 583d5ac70f0Sopenharmony_ci int err; 584d5ac70f0Sopenharmony_ci snd_mixer_slave_t *s; 585d5ac70f0Sopenharmony_ci s = list_entry(pos, snd_mixer_slave_t, list); 586d5ac70f0Sopenharmony_ci err = snd_hctl_load(s->hctl); 587d5ac70f0Sopenharmony_ci if (err < 0) 588d5ac70f0Sopenharmony_ci return err; 589d5ac70f0Sopenharmony_ci } 590d5ac70f0Sopenharmony_ci return 0; 591d5ac70f0Sopenharmony_ci} 592d5ac70f0Sopenharmony_ci 593d5ac70f0Sopenharmony_ci/** 594d5ac70f0Sopenharmony_ci * \brief Unload all mixer elements and free all related resources 595d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 596d5ac70f0Sopenharmony_ci */ 597d5ac70f0Sopenharmony_civoid snd_mixer_free(snd_mixer_t *mixer) 598d5ac70f0Sopenharmony_ci{ 599d5ac70f0Sopenharmony_ci struct list_head *pos; 600d5ac70f0Sopenharmony_ci list_for_each(pos, &mixer->slaves) { 601d5ac70f0Sopenharmony_ci snd_mixer_slave_t *s; 602d5ac70f0Sopenharmony_ci s = list_entry(pos, snd_mixer_slave_t, list); 603d5ac70f0Sopenharmony_ci snd_hctl_free(s->hctl); 604d5ac70f0Sopenharmony_ci } 605d5ac70f0Sopenharmony_ci} 606d5ac70f0Sopenharmony_ci 607d5ac70f0Sopenharmony_ci/** 608d5ac70f0Sopenharmony_ci * \brief Close a mixer and free all related resources 609d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 610d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 611d5ac70f0Sopenharmony_ci */ 612d5ac70f0Sopenharmony_ciint snd_mixer_close(snd_mixer_t *mixer) 613d5ac70f0Sopenharmony_ci{ 614d5ac70f0Sopenharmony_ci int res = 0; 615d5ac70f0Sopenharmony_ci assert(mixer); 616d5ac70f0Sopenharmony_ci while (!list_empty(&mixer->classes)) { 617d5ac70f0Sopenharmony_ci snd_mixer_class_t *c; 618d5ac70f0Sopenharmony_ci c = list_entry(mixer->classes.next, snd_mixer_class_t, list); 619d5ac70f0Sopenharmony_ci snd_mixer_class_unregister(c); 620d5ac70f0Sopenharmony_ci } 621d5ac70f0Sopenharmony_ci assert(list_empty(&mixer->elems)); 622d5ac70f0Sopenharmony_ci assert(mixer->count == 0); 623d5ac70f0Sopenharmony_ci free(mixer->pelems); 624d5ac70f0Sopenharmony_ci mixer->pelems = NULL; 625d5ac70f0Sopenharmony_ci while (!list_empty(&mixer->slaves)) { 626d5ac70f0Sopenharmony_ci int err; 627d5ac70f0Sopenharmony_ci snd_mixer_slave_t *s; 628d5ac70f0Sopenharmony_ci s = list_entry(mixer->slaves.next, snd_mixer_slave_t, list); 629d5ac70f0Sopenharmony_ci err = snd_hctl_close(s->hctl); 630d5ac70f0Sopenharmony_ci if (err < 0) 631d5ac70f0Sopenharmony_ci res = err; 632d5ac70f0Sopenharmony_ci list_del(&s->list); 633d5ac70f0Sopenharmony_ci free(s); 634d5ac70f0Sopenharmony_ci } 635d5ac70f0Sopenharmony_ci free(mixer); 636d5ac70f0Sopenharmony_ci return res; 637d5ac70f0Sopenharmony_ci} 638d5ac70f0Sopenharmony_ci 639d5ac70f0Sopenharmony_cistatic int snd_mixer_compare_default(const snd_mixer_elem_t *c1, 640d5ac70f0Sopenharmony_ci const snd_mixer_elem_t *c2) 641d5ac70f0Sopenharmony_ci{ 642d5ac70f0Sopenharmony_ci int d = c1->compare_weight - c2->compare_weight; 643d5ac70f0Sopenharmony_ci if (d) 644d5ac70f0Sopenharmony_ci return d; 645d5ac70f0Sopenharmony_ci assert(c1->class && c1->class->compare); 646d5ac70f0Sopenharmony_ci assert(c2->class && c2->class->compare); 647d5ac70f0Sopenharmony_ci assert(c1->class == c2->class); 648d5ac70f0Sopenharmony_ci return c1->class->compare(c1, c2); 649d5ac70f0Sopenharmony_ci} 650d5ac70f0Sopenharmony_ci 651d5ac70f0Sopenharmony_cistatic int mixer_compare(const void *a, const void *b) 652d5ac70f0Sopenharmony_ci{ 653d5ac70f0Sopenharmony_ci snd_mixer_t *mixer; 654d5ac70f0Sopenharmony_ci 655d5ac70f0Sopenharmony_ci mixer = (*((const snd_mixer_elem_t * const *)a))->class->mixer; 656d5ac70f0Sopenharmony_ci return mixer->compare(*(const snd_mixer_elem_t * const *)a, *(const snd_mixer_elem_t * const *)b); 657d5ac70f0Sopenharmony_ci} 658d5ac70f0Sopenharmony_ci 659d5ac70f0Sopenharmony_cistatic int snd_mixer_sort(snd_mixer_t *mixer) 660d5ac70f0Sopenharmony_ci{ 661d5ac70f0Sopenharmony_ci unsigned int k; 662d5ac70f0Sopenharmony_ci assert(mixer); 663d5ac70f0Sopenharmony_ci assert(mixer->compare); 664d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&mixer->elems); 665d5ac70f0Sopenharmony_ci qsort(mixer->pelems, mixer->count, sizeof(snd_mixer_elem_t *), mixer_compare); 666d5ac70f0Sopenharmony_ci for (k = 0; k < mixer->count; k++) 667d5ac70f0Sopenharmony_ci list_add_tail(&mixer->pelems[k]->list, &mixer->elems); 668d5ac70f0Sopenharmony_ci return 0; 669d5ac70f0Sopenharmony_ci} 670d5ac70f0Sopenharmony_ci 671d5ac70f0Sopenharmony_ci/** 672d5ac70f0Sopenharmony_ci * \brief Change mixer compare function and reorder elements 673d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 674d5ac70f0Sopenharmony_ci * \param compare Element compare function 675d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code 676d5ac70f0Sopenharmony_ci */ 677d5ac70f0Sopenharmony_ciint snd_mixer_set_compare(snd_mixer_t *mixer, snd_mixer_compare_t compare) 678d5ac70f0Sopenharmony_ci{ 679d5ac70f0Sopenharmony_ci snd_mixer_compare_t compare_old; 680d5ac70f0Sopenharmony_ci int err; 681d5ac70f0Sopenharmony_ci 682d5ac70f0Sopenharmony_ci assert(mixer); 683d5ac70f0Sopenharmony_ci compare_old = mixer->compare; 684d5ac70f0Sopenharmony_ci mixer->compare = compare == NULL ? snd_mixer_compare_default : compare; 685d5ac70f0Sopenharmony_ci if ((err = snd_mixer_sort(mixer)) < 0) { 686d5ac70f0Sopenharmony_ci mixer->compare = compare_old; 687d5ac70f0Sopenharmony_ci return err; 688d5ac70f0Sopenharmony_ci } 689d5ac70f0Sopenharmony_ci return 0; 690d5ac70f0Sopenharmony_ci} 691d5ac70f0Sopenharmony_ci 692d5ac70f0Sopenharmony_ci/** 693d5ac70f0Sopenharmony_ci * \brief get count of poll descriptors for mixer handle 694d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 695d5ac70f0Sopenharmony_ci * \return count of poll descriptors 696d5ac70f0Sopenharmony_ci */ 697d5ac70f0Sopenharmony_ciint snd_mixer_poll_descriptors_count(snd_mixer_t *mixer) 698d5ac70f0Sopenharmony_ci{ 699d5ac70f0Sopenharmony_ci struct list_head *pos; 700d5ac70f0Sopenharmony_ci unsigned int c = 0; 701d5ac70f0Sopenharmony_ci assert(mixer); 702d5ac70f0Sopenharmony_ci list_for_each(pos, &mixer->slaves) { 703d5ac70f0Sopenharmony_ci snd_mixer_slave_t *s; 704d5ac70f0Sopenharmony_ci int n; 705d5ac70f0Sopenharmony_ci s = list_entry(pos, snd_mixer_slave_t, list); 706d5ac70f0Sopenharmony_ci n = snd_hctl_poll_descriptors_count(s->hctl); 707d5ac70f0Sopenharmony_ci if (n < 0) 708d5ac70f0Sopenharmony_ci return n; 709d5ac70f0Sopenharmony_ci c += n; 710d5ac70f0Sopenharmony_ci } 711d5ac70f0Sopenharmony_ci return c; 712d5ac70f0Sopenharmony_ci} 713d5ac70f0Sopenharmony_ci 714d5ac70f0Sopenharmony_ci/** 715d5ac70f0Sopenharmony_ci * \brief get poll descriptors 716d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 717d5ac70f0Sopenharmony_ci * \param pfds array of poll descriptors 718d5ac70f0Sopenharmony_ci * \param space space in the poll descriptor array 719d5ac70f0Sopenharmony_ci * \return count of filled descriptors 720d5ac70f0Sopenharmony_ci */ 721d5ac70f0Sopenharmony_ciint snd_mixer_poll_descriptors(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int space) 722d5ac70f0Sopenharmony_ci{ 723d5ac70f0Sopenharmony_ci struct list_head *pos; 724d5ac70f0Sopenharmony_ci unsigned int count = 0; 725d5ac70f0Sopenharmony_ci assert(mixer); 726d5ac70f0Sopenharmony_ci list_for_each(pos, &mixer->slaves) { 727d5ac70f0Sopenharmony_ci snd_mixer_slave_t *s; 728d5ac70f0Sopenharmony_ci int n; 729d5ac70f0Sopenharmony_ci s = list_entry(pos, snd_mixer_slave_t, list); 730d5ac70f0Sopenharmony_ci n = snd_hctl_poll_descriptors(s->hctl, pfds, space); 731d5ac70f0Sopenharmony_ci if (n < 0) 732d5ac70f0Sopenharmony_ci return n; 733d5ac70f0Sopenharmony_ci if (space >= (unsigned int) n) { 734d5ac70f0Sopenharmony_ci count += n; 735d5ac70f0Sopenharmony_ci space -= n; 736d5ac70f0Sopenharmony_ci pfds += n; 737d5ac70f0Sopenharmony_ci } else 738d5ac70f0Sopenharmony_ci space = 0; 739d5ac70f0Sopenharmony_ci } 740d5ac70f0Sopenharmony_ci return count; 741d5ac70f0Sopenharmony_ci} 742d5ac70f0Sopenharmony_ci 743d5ac70f0Sopenharmony_ci/** 744d5ac70f0Sopenharmony_ci * \brief get returned events from poll descriptors 745d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 746d5ac70f0Sopenharmony_ci * \param pfds array of poll descriptors 747d5ac70f0Sopenharmony_ci * \param nfds count of poll descriptors 748d5ac70f0Sopenharmony_ci * \param revents returned events 749d5ac70f0Sopenharmony_ci * \return zero if success, otherwise a negative error code 750d5ac70f0Sopenharmony_ci */ 751d5ac70f0Sopenharmony_ciint snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) 752d5ac70f0Sopenharmony_ci{ 753d5ac70f0Sopenharmony_ci unsigned int idx; 754d5ac70f0Sopenharmony_ci unsigned short res; 755d5ac70f0Sopenharmony_ci assert(mixer && pfds && revents); 756d5ac70f0Sopenharmony_ci if (nfds == 0) 757d5ac70f0Sopenharmony_ci return -EINVAL; 758d5ac70f0Sopenharmony_ci res = 0; 759d5ac70f0Sopenharmony_ci for (idx = 0; idx < nfds; idx++, pfds++) 760d5ac70f0Sopenharmony_ci res |= pfds->revents & (POLLIN|POLLERR|POLLNVAL); 761d5ac70f0Sopenharmony_ci *revents = res; 762d5ac70f0Sopenharmony_ci return 0; 763d5ac70f0Sopenharmony_ci} 764d5ac70f0Sopenharmony_ci 765d5ac70f0Sopenharmony_ci/** 766d5ac70f0Sopenharmony_ci * \brief Wait for a mixer to become ready (i.e. at least one event pending) 767d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 768d5ac70f0Sopenharmony_ci * \param timeout maximum time in milliseconds to wait 769d5ac70f0Sopenharmony_ci * \return 0 otherwise a negative error code on failure 770d5ac70f0Sopenharmony_ci */ 771d5ac70f0Sopenharmony_ciint snd_mixer_wait(snd_mixer_t *mixer, int timeout) 772d5ac70f0Sopenharmony_ci{ 773d5ac70f0Sopenharmony_ci struct pollfd spfds[16]; 774d5ac70f0Sopenharmony_ci struct pollfd *pfds = spfds; 775d5ac70f0Sopenharmony_ci int err; 776d5ac70f0Sopenharmony_ci int count; 777d5ac70f0Sopenharmony_ci count = snd_mixer_poll_descriptors(mixer, pfds, sizeof(spfds) / sizeof(spfds[0])); 778d5ac70f0Sopenharmony_ci if (count < 0) 779d5ac70f0Sopenharmony_ci return count; 780d5ac70f0Sopenharmony_ci if ((unsigned int) count > sizeof(spfds) / sizeof(spfds[0])) { 781d5ac70f0Sopenharmony_ci pfds = alloca(count * sizeof(*pfds)); 782d5ac70f0Sopenharmony_ci if (!pfds) 783d5ac70f0Sopenharmony_ci return -ENOMEM; 784d5ac70f0Sopenharmony_ci err = snd_mixer_poll_descriptors(mixer, pfds, 785d5ac70f0Sopenharmony_ci (unsigned int) count); 786d5ac70f0Sopenharmony_ci assert(err == count); 787d5ac70f0Sopenharmony_ci } 788d5ac70f0Sopenharmony_ci err = poll(pfds, (unsigned int) count, timeout); 789d5ac70f0Sopenharmony_ci if (err < 0) 790d5ac70f0Sopenharmony_ci return -errno; 791d5ac70f0Sopenharmony_ci return 0; 792d5ac70f0Sopenharmony_ci} 793d5ac70f0Sopenharmony_ci 794d5ac70f0Sopenharmony_ci/** 795d5ac70f0Sopenharmony_ci * \brief get first element for a mixer 796d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 797d5ac70f0Sopenharmony_ci * \return pointer to first element 798d5ac70f0Sopenharmony_ci */ 799d5ac70f0Sopenharmony_cisnd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer) 800d5ac70f0Sopenharmony_ci{ 801d5ac70f0Sopenharmony_ci assert(mixer); 802d5ac70f0Sopenharmony_ci if (list_empty(&mixer->elems)) 803d5ac70f0Sopenharmony_ci return NULL; 804d5ac70f0Sopenharmony_ci return list_entry(mixer->elems.next, snd_mixer_elem_t, list); 805d5ac70f0Sopenharmony_ci} 806d5ac70f0Sopenharmony_ci 807d5ac70f0Sopenharmony_ci/** 808d5ac70f0Sopenharmony_ci * \brief get last element for a mixer 809d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 810d5ac70f0Sopenharmony_ci * \return pointer to last element 811d5ac70f0Sopenharmony_ci */ 812d5ac70f0Sopenharmony_cisnd_mixer_elem_t *snd_mixer_last_elem(snd_mixer_t *mixer) 813d5ac70f0Sopenharmony_ci{ 814d5ac70f0Sopenharmony_ci assert(mixer); 815d5ac70f0Sopenharmony_ci if (list_empty(&mixer->elems)) 816d5ac70f0Sopenharmony_ci return NULL; 817d5ac70f0Sopenharmony_ci return list_entry(mixer->elems.prev, snd_mixer_elem_t, list); 818d5ac70f0Sopenharmony_ci} 819d5ac70f0Sopenharmony_ci 820d5ac70f0Sopenharmony_ci/** 821d5ac70f0Sopenharmony_ci * \brief get next mixer element 822d5ac70f0Sopenharmony_ci * \param elem mixer element 823d5ac70f0Sopenharmony_ci * \return pointer to next element 824d5ac70f0Sopenharmony_ci */ 825d5ac70f0Sopenharmony_cisnd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem) 826d5ac70f0Sopenharmony_ci{ 827d5ac70f0Sopenharmony_ci assert(elem); 828d5ac70f0Sopenharmony_ci if (elem->list.next == &elem->class->mixer->elems) 829d5ac70f0Sopenharmony_ci return NULL; 830d5ac70f0Sopenharmony_ci return list_entry(elem->list.next, snd_mixer_elem_t, list); 831d5ac70f0Sopenharmony_ci} 832d5ac70f0Sopenharmony_ci 833d5ac70f0Sopenharmony_ci/** 834d5ac70f0Sopenharmony_ci * \brief get previous mixer element 835d5ac70f0Sopenharmony_ci * \param elem mixer element 836d5ac70f0Sopenharmony_ci * \return pointer to previous element 837d5ac70f0Sopenharmony_ci */ 838d5ac70f0Sopenharmony_cisnd_mixer_elem_t *snd_mixer_elem_prev(snd_mixer_elem_t *elem) 839d5ac70f0Sopenharmony_ci{ 840d5ac70f0Sopenharmony_ci assert(elem); 841d5ac70f0Sopenharmony_ci if (elem->list.prev == &elem->class->mixer->elems) 842d5ac70f0Sopenharmony_ci return NULL; 843d5ac70f0Sopenharmony_ci return list_entry(elem->list.prev, snd_mixer_elem_t, list); 844d5ac70f0Sopenharmony_ci} 845d5ac70f0Sopenharmony_ci 846d5ac70f0Sopenharmony_ci/** 847d5ac70f0Sopenharmony_ci * \brief Handle pending mixer events invoking callbacks 848d5ac70f0Sopenharmony_ci * \param mixer Mixer handle 849d5ac70f0Sopenharmony_ci * \return Number of events that occured on success, otherwise a negative error code on failure 850d5ac70f0Sopenharmony_ci */ 851d5ac70f0Sopenharmony_ciint snd_mixer_handle_events(snd_mixer_t *mixer) 852d5ac70f0Sopenharmony_ci{ 853d5ac70f0Sopenharmony_ci struct list_head *pos; 854d5ac70f0Sopenharmony_ci assert(mixer); 855d5ac70f0Sopenharmony_ci mixer->events = 0; 856d5ac70f0Sopenharmony_ci list_for_each(pos, &mixer->slaves) { 857d5ac70f0Sopenharmony_ci int err; 858d5ac70f0Sopenharmony_ci snd_mixer_slave_t *s; 859d5ac70f0Sopenharmony_ci s = list_entry(pos, snd_mixer_slave_t, list); 860d5ac70f0Sopenharmony_ci err = snd_hctl_handle_events(s->hctl); 861d5ac70f0Sopenharmony_ci if (err < 0) 862d5ac70f0Sopenharmony_ci return err; 863d5ac70f0Sopenharmony_ci } 864d5ac70f0Sopenharmony_ci return mixer->events; 865d5ac70f0Sopenharmony_ci} 866d5ac70f0Sopenharmony_ci 867d5ac70f0Sopenharmony_ci/** 868d5ac70f0Sopenharmony_ci * \brief Set callback function for a mixer 869d5ac70f0Sopenharmony_ci * \param obj mixer handle 870d5ac70f0Sopenharmony_ci * \param val callback function 871d5ac70f0Sopenharmony_ci */ 872d5ac70f0Sopenharmony_civoid snd_mixer_set_callback(snd_mixer_t *obj, snd_mixer_callback_t val) 873d5ac70f0Sopenharmony_ci{ 874d5ac70f0Sopenharmony_ci assert(obj); 875d5ac70f0Sopenharmony_ci obj->callback = val; 876d5ac70f0Sopenharmony_ci} 877d5ac70f0Sopenharmony_ci 878d5ac70f0Sopenharmony_ci/** 879d5ac70f0Sopenharmony_ci * \brief Set callback private value for a mixer 880d5ac70f0Sopenharmony_ci * \param mixer mixer handle 881d5ac70f0Sopenharmony_ci * \param val callback private value 882d5ac70f0Sopenharmony_ci */ 883d5ac70f0Sopenharmony_civoid snd_mixer_set_callback_private(snd_mixer_t *mixer, void * val) 884d5ac70f0Sopenharmony_ci{ 885d5ac70f0Sopenharmony_ci assert(mixer); 886d5ac70f0Sopenharmony_ci mixer->callback_private = val; 887d5ac70f0Sopenharmony_ci} 888d5ac70f0Sopenharmony_ci 889d5ac70f0Sopenharmony_ci/** 890d5ac70f0Sopenharmony_ci * \brief Get callback private value for a mixer 891d5ac70f0Sopenharmony_ci * \param mixer mixer handle 892d5ac70f0Sopenharmony_ci * \return callback private value 893d5ac70f0Sopenharmony_ci */ 894d5ac70f0Sopenharmony_civoid * snd_mixer_get_callback_private(const snd_mixer_t *mixer) 895d5ac70f0Sopenharmony_ci{ 896d5ac70f0Sopenharmony_ci assert(mixer); 897d5ac70f0Sopenharmony_ci return mixer->callback_private; 898d5ac70f0Sopenharmony_ci} 899d5ac70f0Sopenharmony_ci 900d5ac70f0Sopenharmony_ci/** 901d5ac70f0Sopenharmony_ci * \brief Get elements count for a mixer 902d5ac70f0Sopenharmony_ci * \param mixer mixer handle 903d5ac70f0Sopenharmony_ci * \return elements count 904d5ac70f0Sopenharmony_ci */ 905d5ac70f0Sopenharmony_ciunsigned int snd_mixer_get_count(const snd_mixer_t *mixer) 906d5ac70f0Sopenharmony_ci{ 907d5ac70f0Sopenharmony_ci assert(mixer); 908d5ac70f0Sopenharmony_ci return mixer->count; 909d5ac70f0Sopenharmony_ci} 910d5ac70f0Sopenharmony_ci 911d5ac70f0Sopenharmony_ci/** 912d5ac70f0Sopenharmony_ci * \brief Set callback function for a mixer element 913d5ac70f0Sopenharmony_ci * \param mixer mixer element 914d5ac70f0Sopenharmony_ci * \param val callback function 915d5ac70f0Sopenharmony_ci */ 916d5ac70f0Sopenharmony_civoid snd_mixer_elem_set_callback(snd_mixer_elem_t *mixer, snd_mixer_elem_callback_t val) 917d5ac70f0Sopenharmony_ci{ 918d5ac70f0Sopenharmony_ci assert(mixer); 919d5ac70f0Sopenharmony_ci mixer->callback = val; 920d5ac70f0Sopenharmony_ci} 921d5ac70f0Sopenharmony_ci 922d5ac70f0Sopenharmony_ci/** 923d5ac70f0Sopenharmony_ci * \brief Set callback private value for a mixer element 924d5ac70f0Sopenharmony_ci * \param mixer mixer element 925d5ac70f0Sopenharmony_ci * \param val callback private value 926d5ac70f0Sopenharmony_ci */ 927d5ac70f0Sopenharmony_civoid snd_mixer_elem_set_callback_private(snd_mixer_elem_t *mixer, void * val) 928d5ac70f0Sopenharmony_ci{ 929d5ac70f0Sopenharmony_ci assert(mixer); 930d5ac70f0Sopenharmony_ci mixer->callback_private = val; 931d5ac70f0Sopenharmony_ci} 932d5ac70f0Sopenharmony_ci 933d5ac70f0Sopenharmony_ci/** 934d5ac70f0Sopenharmony_ci * \brief Get callback private value for a mixer element 935d5ac70f0Sopenharmony_ci * \param mixer mixer element 936d5ac70f0Sopenharmony_ci * \return callback private value 937d5ac70f0Sopenharmony_ci */ 938d5ac70f0Sopenharmony_civoid * snd_mixer_elem_get_callback_private(const snd_mixer_elem_t *mixer) 939d5ac70f0Sopenharmony_ci{ 940d5ac70f0Sopenharmony_ci assert(mixer); 941d5ac70f0Sopenharmony_ci return mixer->callback_private; 942d5ac70f0Sopenharmony_ci} 943d5ac70f0Sopenharmony_ci 944d5ac70f0Sopenharmony_ci/** 945d5ac70f0Sopenharmony_ci * \brief Get type for a mixer element 946d5ac70f0Sopenharmony_ci * \param mixer mixer element 947d5ac70f0Sopenharmony_ci * \return mixer element type 948d5ac70f0Sopenharmony_ci */ 949d5ac70f0Sopenharmony_cisnd_mixer_elem_type_t snd_mixer_elem_get_type(const snd_mixer_elem_t *mixer) 950d5ac70f0Sopenharmony_ci{ 951d5ac70f0Sopenharmony_ci assert(mixer); 952d5ac70f0Sopenharmony_ci return mixer->type; 953d5ac70f0Sopenharmony_ci} 954d5ac70f0Sopenharmony_ci 955d5ac70f0Sopenharmony_ci 956d5ac70f0Sopenharmony_ci/** 957d5ac70f0Sopenharmony_ci * \brief get size of #snd_mixer_class_t 958d5ac70f0Sopenharmony_ci * \return size in bytes 959d5ac70f0Sopenharmony_ci */ 960d5ac70f0Sopenharmony_cisize_t snd_mixer_class_sizeof() 961d5ac70f0Sopenharmony_ci{ 962d5ac70f0Sopenharmony_ci return sizeof(snd_mixer_class_t); 963d5ac70f0Sopenharmony_ci} 964d5ac70f0Sopenharmony_ci 965d5ac70f0Sopenharmony_ci/** 966d5ac70f0Sopenharmony_ci * \brief allocate an invalid #snd_mixer_class_t using standard malloc 967d5ac70f0Sopenharmony_ci * \param ptr returned pointer 968d5ac70f0Sopenharmony_ci * \return 0 on success otherwise negative error code 969d5ac70f0Sopenharmony_ci */ 970d5ac70f0Sopenharmony_ciint snd_mixer_class_malloc(snd_mixer_class_t **ptr) 971d5ac70f0Sopenharmony_ci{ 972d5ac70f0Sopenharmony_ci assert(ptr); 973d5ac70f0Sopenharmony_ci *ptr = calloc(1, sizeof(snd_mixer_class_t)); 974d5ac70f0Sopenharmony_ci if (!*ptr) 975d5ac70f0Sopenharmony_ci return -ENOMEM; 976d5ac70f0Sopenharmony_ci return 0; 977d5ac70f0Sopenharmony_ci} 978d5ac70f0Sopenharmony_ci 979d5ac70f0Sopenharmony_ci/** 980d5ac70f0Sopenharmony_ci * \brief frees a previously allocated #snd_mixer_class_t 981d5ac70f0Sopenharmony_ci * \param obj pointer to object to free 982d5ac70f0Sopenharmony_ci */ 983d5ac70f0Sopenharmony_civoid snd_mixer_class_free(snd_mixer_class_t *obj) 984d5ac70f0Sopenharmony_ci{ 985d5ac70f0Sopenharmony_ci if (obj->private_free) 986d5ac70f0Sopenharmony_ci obj->private_free(obj); 987d5ac70f0Sopenharmony_ci free(obj); 988d5ac70f0Sopenharmony_ci} 989d5ac70f0Sopenharmony_ci 990d5ac70f0Sopenharmony_ci/** 991d5ac70f0Sopenharmony_ci * \brief copy one #snd_mixer_class_t to another 992d5ac70f0Sopenharmony_ci * \param dst pointer to destination 993d5ac70f0Sopenharmony_ci * \param src pointer to source 994d5ac70f0Sopenharmony_ci */ 995d5ac70f0Sopenharmony_civoid snd_mixer_class_copy(snd_mixer_class_t *dst, const snd_mixer_class_t *src) 996d5ac70f0Sopenharmony_ci{ 997d5ac70f0Sopenharmony_ci assert(dst && src); 998d5ac70f0Sopenharmony_ci *dst = *src; 999d5ac70f0Sopenharmony_ci} 1000d5ac70f0Sopenharmony_ci 1001d5ac70f0Sopenharmony_ci/** 1002d5ac70f0Sopenharmony_ci * \brief Get a mixer associated to given mixer class 1003d5ac70f0Sopenharmony_ci * \param obj Mixer simple class identifier 1004d5ac70f0Sopenharmony_ci * \return mixer pointer 1005d5ac70f0Sopenharmony_ci */ 1006d5ac70f0Sopenharmony_cisnd_mixer_t *snd_mixer_class_get_mixer(const snd_mixer_class_t *obj) 1007d5ac70f0Sopenharmony_ci{ 1008d5ac70f0Sopenharmony_ci assert(obj); 1009d5ac70f0Sopenharmony_ci return obj->mixer; 1010d5ac70f0Sopenharmony_ci} 1011d5ac70f0Sopenharmony_ci 1012d5ac70f0Sopenharmony_ci/** 1013d5ac70f0Sopenharmony_ci * \brief Get mixer event callback associated to given mixer class 1014d5ac70f0Sopenharmony_ci * \param obj Mixer simple class identifier 1015d5ac70f0Sopenharmony_ci * \return event callback pointer 1016d5ac70f0Sopenharmony_ci */ 1017d5ac70f0Sopenharmony_cisnd_mixer_event_t snd_mixer_class_get_event(const snd_mixer_class_t *obj) 1018d5ac70f0Sopenharmony_ci{ 1019d5ac70f0Sopenharmony_ci assert(obj); 1020d5ac70f0Sopenharmony_ci return obj->event; 1021d5ac70f0Sopenharmony_ci} 1022d5ac70f0Sopenharmony_ci 1023d5ac70f0Sopenharmony_ci/** 1024d5ac70f0Sopenharmony_ci * \brief Get mixer private data associated to given mixer class 1025d5ac70f0Sopenharmony_ci * \param obj Mixer simple class identifier 1026d5ac70f0Sopenharmony_ci * \return event callback pointer 1027d5ac70f0Sopenharmony_ci */ 1028d5ac70f0Sopenharmony_civoid *snd_mixer_class_get_private(const snd_mixer_class_t *obj) 1029d5ac70f0Sopenharmony_ci{ 1030d5ac70f0Sopenharmony_ci assert(obj); 1031d5ac70f0Sopenharmony_ci return obj->private_data; 1032d5ac70f0Sopenharmony_ci} 1033d5ac70f0Sopenharmony_ci 1034d5ac70f0Sopenharmony_ci 1035d5ac70f0Sopenharmony_ci/** 1036d5ac70f0Sopenharmony_ci * \brief Get mixer compare callback associated to given mixer class 1037d5ac70f0Sopenharmony_ci * \param obj Mixer simple class identifier 1038d5ac70f0Sopenharmony_ci * \return event callback pointer 1039d5ac70f0Sopenharmony_ci */ 1040d5ac70f0Sopenharmony_cisnd_mixer_compare_t snd_mixer_class_get_compare(const snd_mixer_class_t *obj) 1041d5ac70f0Sopenharmony_ci{ 1042d5ac70f0Sopenharmony_ci assert(obj); 1043d5ac70f0Sopenharmony_ci return obj->compare; 1044d5ac70f0Sopenharmony_ci} 1045d5ac70f0Sopenharmony_ci 1046d5ac70f0Sopenharmony_ci/** 1047d5ac70f0Sopenharmony_ci * \brief Set mixer event callback to given mixer class 1048d5ac70f0Sopenharmony_ci * \param obj Mixer simple class identifier 1049d5ac70f0Sopenharmony_ci * \param event Event callback 1050d5ac70f0Sopenharmony_ci * \return zero if success, otherwise a negative error code 1051d5ac70f0Sopenharmony_ci */ 1052d5ac70f0Sopenharmony_ciint snd_mixer_class_set_event(snd_mixer_class_t *obj, snd_mixer_event_t event) 1053d5ac70f0Sopenharmony_ci{ 1054d5ac70f0Sopenharmony_ci assert(obj); 1055d5ac70f0Sopenharmony_ci obj->event = event; 1056d5ac70f0Sopenharmony_ci return 0; 1057d5ac70f0Sopenharmony_ci} 1058d5ac70f0Sopenharmony_ci 1059d5ac70f0Sopenharmony_ci/** 1060d5ac70f0Sopenharmony_ci * \brief Set mixer private data to given mixer class 1061d5ac70f0Sopenharmony_ci * \param obj Mixer simple class identifier 1062d5ac70f0Sopenharmony_ci * \param private_data class private data 1063d5ac70f0Sopenharmony_ci * \return zero if success, otherwise a negative error code 1064d5ac70f0Sopenharmony_ci */ 1065d5ac70f0Sopenharmony_ciint snd_mixer_class_set_private(snd_mixer_class_t *obj, void *private_data) 1066d5ac70f0Sopenharmony_ci{ 1067d5ac70f0Sopenharmony_ci assert(obj); 1068d5ac70f0Sopenharmony_ci obj->private_data = private_data; 1069d5ac70f0Sopenharmony_ci return 0; 1070d5ac70f0Sopenharmony_ci} 1071d5ac70f0Sopenharmony_ci 1072d5ac70f0Sopenharmony_ci/** 1073d5ac70f0Sopenharmony_ci * \brief Set mixer private data free callback to given mixer class 1074d5ac70f0Sopenharmony_ci * \param obj Mixer simple class identifier 1075d5ac70f0Sopenharmony_ci * \param private_free Mixer class private data free callback 1076d5ac70f0Sopenharmony_ci * \return zero if success, otherwise a negative error code 1077d5ac70f0Sopenharmony_ci */ 1078d5ac70f0Sopenharmony_ciint snd_mixer_class_set_private_free(snd_mixer_class_t *obj, void (*private_free)(snd_mixer_class_t *)) 1079d5ac70f0Sopenharmony_ci{ 1080d5ac70f0Sopenharmony_ci assert(obj); 1081d5ac70f0Sopenharmony_ci obj->private_free = private_free; 1082d5ac70f0Sopenharmony_ci return 0; 1083d5ac70f0Sopenharmony_ci} 1084d5ac70f0Sopenharmony_ci 1085d5ac70f0Sopenharmony_ci/** 1086d5ac70f0Sopenharmony_ci * \brief Set mixer compare callback to given mixer class 1087d5ac70f0Sopenharmony_ci * \param obj Mixer simple class identifier 1088d5ac70f0Sopenharmony_ci * \param compare the compare callback to be used 1089d5ac70f0Sopenharmony_ci * \return zero if success, otherwise a negative error code 1090d5ac70f0Sopenharmony_ci */ 1091d5ac70f0Sopenharmony_ciint snd_mixer_class_set_compare(snd_mixer_class_t *obj, snd_mixer_compare_t compare) 1092d5ac70f0Sopenharmony_ci{ 1093d5ac70f0Sopenharmony_ci assert(obj); 1094d5ac70f0Sopenharmony_ci obj->compare = compare; 1095d5ac70f0Sopenharmony_ci return 0; 1096d5ac70f0Sopenharmony_ci} 1097