mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
Changed control to use events mask. Added subscribe ioctl
This commit is contained in:
parent
fa51799255
commit
3e97ef3ea0
14 changed files with 225 additions and 205 deletions
|
|
@ -572,8 +572,11 @@ int ctl_shm_cmd(client_t *client)
|
|||
case SND_CTL_IOCTL_ASYNC:
|
||||
ctrl->result = snd_ctl_async(ctl, ctrl->u.async.sig, ctrl->u.async.pid);
|
||||
break;
|
||||
case SNDRV_CTL_IOCTL_INFO:
|
||||
ctrl->result = snd_ctl_card_info(ctl, &ctrl->u.hw_info);
|
||||
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
|
||||
ctrl->result = snd_ctl_subscribe_events(ctl, ctrl->u.subscribe_events);
|
||||
break;
|
||||
case SNDRV_CTL_IOCTL_CARD_INFO:
|
||||
ctrl->result = snd_ctl_card_info(ctl, &ctrl->u.card_info);
|
||||
break;
|
||||
case SNDRV_CTL_IOCTL_ELEM_LIST:
|
||||
{
|
||||
|
|
|
|||
|
|
@ -95,7 +95,8 @@ typedef struct {
|
|||
pid_t pid;
|
||||
} async;
|
||||
int device;
|
||||
snd_ctl_card_info_t hw_info;
|
||||
int subscribe_events;
|
||||
snd_ctl_card_info_t card_info;
|
||||
snd_ctl_elem_list_t element_list;
|
||||
snd_ctl_elem_info_t element_info;
|
||||
snd_ctl_elem_value_t element_read;
|
||||
|
|
|
|||
|
|
@ -112,13 +112,14 @@ typedef enum sndrv_ctl_event_type snd_ctl_event_type_t;
|
|||
#define SND_CTL_ELEM_IFACE_SEQUENCER ((snd_ctl_elem_iface_t) SNDRV_CTL_ELEM_IFACE_SEQUENCER)
|
||||
#define SND_CTL_ELEM_IFACE_LAST ((snd_ctl_elem_iface_t) SNDRV_CTL_ELEM_IFACE_LAST)
|
||||
|
||||
#define SND_CTL_EVENT_REBUILD ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_REBUILD)
|
||||
#define SND_CTL_EVENT_VALUE ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_VALUE)
|
||||
#define SND_CTL_EVENT_INFO ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_INFO)
|
||||
#define SND_CTL_EVENT_ADD ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_ADD)
|
||||
#define SND_CTL_EVENT_REMOVE ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_REMOVE)
|
||||
#define SND_CTL_EVENT_ELEM ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_ELEM)
|
||||
#define SND_CTL_EVENT_LAST ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_LAST)
|
||||
|
||||
#define SND_CTL_EVENT_MASK_ADD SNDRV_CTL_EVENT_MASK_ADD
|
||||
#define SND_CTL_EVENT_MASK_INFO SNDRV_CTL_EVENT_MASK_INFO
|
||||
#define SND_CTL_EVENT_MASK_VALUE SNDRV_CTL_EVENT_MASK_VALUE
|
||||
#define SND_CTL_EVENT_MASK_REMOVE SNDRV_CTL_EVENT_MASK_REMOVE
|
||||
|
||||
enum _snd_ctl_type {
|
||||
SND_CTL_TYPE_HW,
|
||||
SND_CTL_TYPE_SHM,
|
||||
|
|
@ -160,6 +161,7 @@ int snd_ctl_close(snd_ctl_t *ctl);
|
|||
int snd_ctl_nonblock(snd_ctl_t *ctl, int nonblock);
|
||||
int snd_ctl_async(snd_ctl_t *ctl, int sig, pid_t pid);
|
||||
int snd_ctl_poll_descriptors(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int space);
|
||||
int snd_ctl_subscribe_events(snd_ctl_t *ctl, int subscribe);
|
||||
int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info);
|
||||
int snd_ctl_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t * list);
|
||||
int snd_ctl_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info);
|
||||
|
|
@ -184,6 +186,15 @@ const char *snd_ctl_elem_type_name(snd_ctl_elem_type_t type);
|
|||
const char *snd_ctl_elem_iface_name(snd_ctl_elem_iface_t iface);
|
||||
const char *snd_ctl_event_type_name(snd_ctl_event_type_t type);
|
||||
|
||||
unsigned int snd_ctl_event_elem_get_mask(const snd_ctl_event_t *obj);
|
||||
unsigned int snd_ctl_event_elem_get_numid(const snd_ctl_event_t *obj);
|
||||
void snd_ctl_event_elem_get_id(const snd_ctl_event_t *obj, snd_ctl_elem_id_t *ptr);
|
||||
snd_ctl_elem_iface_t snd_ctl_event_elem_get_interface(const snd_ctl_event_t *obj);
|
||||
unsigned int snd_ctl_event_elem_get_device(const snd_ctl_event_t *obj);
|
||||
unsigned int snd_ctl_event_elem_get_subdevice(const snd_ctl_event_t *obj);
|
||||
const char *snd_ctl_event_elem_get_name(const snd_ctl_event_t *obj);
|
||||
unsigned int snd_ctl_event_elem_get_index(const snd_ctl_event_t *obj);
|
||||
|
||||
int snd_ctl_elem_list_alloc_space(snd_ctl_elem_list_t *obj, unsigned int entries);
|
||||
void snd_ctl_elem_list_free_space(snd_ctl_elem_list_t *obj);
|
||||
|
||||
|
|
@ -206,10 +217,10 @@ extern "C" {
|
|||
typedef int (*snd_hctl_compare_t)(const snd_hctl_elem_t *e1,
|
||||
const snd_hctl_elem_t *e2);
|
||||
typedef int (*snd_hctl_callback_t)(snd_hctl_t *hctl,
|
||||
snd_ctl_event_type_t event,
|
||||
unsigned int mask,
|
||||
snd_hctl_elem_t *elem);
|
||||
typedef int (*snd_hctl_elem_callback_t)(snd_hctl_elem_t *elem,
|
||||
snd_ctl_event_type_t event);
|
||||
unsigned int mask);
|
||||
|
||||
int snd_hctl_open(snd_hctl_t **hctl, const char *name);
|
||||
int snd_hctl_close(snd_hctl_t *hctl);
|
||||
|
|
|
|||
|
|
@ -62,20 +62,6 @@ void snd_ctl_event_copy(snd_ctl_event_t *dst, const snd_ctl_event_t *src);
|
|||
|
||||
snd_ctl_event_type_t snd_ctl_event_get_type(const snd_ctl_event_t *obj);
|
||||
|
||||
unsigned int snd_ctl_event_get_numid(const snd_ctl_event_t *obj);
|
||||
|
||||
void snd_ctl_event_get_id(const snd_ctl_event_t *obj, snd_ctl_elem_id_t *ptr);
|
||||
|
||||
snd_ctl_elem_iface_t snd_ctl_event_get_interface(const snd_ctl_event_t *obj);
|
||||
|
||||
unsigned int snd_ctl_event_get_device(const snd_ctl_event_t *obj);
|
||||
|
||||
unsigned int snd_ctl_event_get_subdevice(const snd_ctl_event_t *obj);
|
||||
|
||||
const char *snd_ctl_event_get_name(const snd_ctl_event_t *obj);
|
||||
|
||||
unsigned int snd_ctl_event_get_index(const snd_ctl_event_t *obj);
|
||||
|
||||
size_t snd_ctl_elem_list_sizeof();
|
||||
#define snd_ctl_elem_list_alloca(ptr) ({ assert(ptr); *ptr = (snd_ctl_elem_list_t *) alloca(snd_ctl_elem_list_sizeof()); memset(*ptr, 0, snd_ctl_elem_list_sizeof()); 0; })
|
||||
int snd_ctl_elem_list_malloc(snd_ctl_elem_list_t **ptr);
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ typedef struct _snd_mixer_class snd_mixer_class_t;
|
|||
typedef struct _snd_mixer_info snd_mixer_info_t;
|
||||
typedef struct _snd_mixer_elem snd_mixer_elem_t;
|
||||
typedef int (*snd_mixer_callback_t)(snd_mixer_t *ctl,
|
||||
snd_ctl_event_type_t event,
|
||||
unsigned int mask,
|
||||
snd_mixer_elem_t *elem);
|
||||
typedef int (*snd_mixer_elem_callback_t)(snd_mixer_elem_t *elem,
|
||||
snd_ctl_event_type_t event);
|
||||
unsigned int mask);
|
||||
typedef int (*snd_mixer_compare_t)(const snd_mixer_elem_t *e1,
|
||||
const snd_mixer_elem_t *e2);
|
||||
|
||||
|
|
|
|||
|
|
@ -84,10 +84,16 @@ int snd_ctl_poll_descriptors(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int s
|
|||
return 1;
|
||||
}
|
||||
|
||||
int snd_ctl_subscribe_events(snd_ctl_t *ctl, int subscribe)
|
||||
{
|
||||
assert(ctl);
|
||||
return ctl->ops->subscribe_events(ctl, subscribe);
|
||||
}
|
||||
|
||||
int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info)
|
||||
{
|
||||
assert(ctl && info);
|
||||
return ctl->ops->hw_info(ctl, info);
|
||||
return ctl->ops->card_info(ctl, info);
|
||||
}
|
||||
|
||||
int snd_ctl_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t *list)
|
||||
|
|
@ -280,11 +286,7 @@ const char *snd_ctl_elem_iface_names[] = {
|
|||
};
|
||||
|
||||
const char *snd_ctl_event_type_names[] = {
|
||||
EVENT(REBUILD),
|
||||
EVENT(VALUE),
|
||||
EVENT(INFO),
|
||||
EVENT(ADD),
|
||||
EVENT(REMOVE),
|
||||
EVENT(ELEM),
|
||||
};
|
||||
|
||||
const char *snd_ctl_elem_type_name(snd_ctl_elem_type_t type)
|
||||
|
|
@ -323,3 +325,60 @@ void snd_ctl_elem_list_free_space(snd_ctl_elem_list_t *obj)
|
|||
free(obj->pids);
|
||||
obj->pids = NULL;
|
||||
}
|
||||
|
||||
unsigned int snd_ctl_event_elem_get_mask(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type == SND_CTL_EVENT_ELEM);
|
||||
return obj->data.elem.mask;
|
||||
}
|
||||
|
||||
unsigned int snd_ctl_event_elem_get_numid(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type == SND_CTL_EVENT_ELEM);
|
||||
return obj->data.elem.id.numid;
|
||||
}
|
||||
|
||||
void snd_ctl_event_elem_get_id(const snd_ctl_event_t *obj, snd_ctl_elem_id_t *ptr)
|
||||
{
|
||||
assert(obj && ptr);
|
||||
assert(obj->type == SND_CTL_EVENT_ELEM);
|
||||
*ptr = obj->data.elem.id;
|
||||
}
|
||||
|
||||
snd_ctl_elem_iface_t snd_ctl_event_elem_get_interface(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type == SND_CTL_EVENT_ELEM);
|
||||
return snd_int_to_enum(obj->data.elem.id.iface);
|
||||
}
|
||||
|
||||
unsigned int snd_ctl_event_elem_get_device(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type == SND_CTL_EVENT_ELEM);
|
||||
return obj->data.elem.id.device;
|
||||
}
|
||||
|
||||
unsigned int snd_ctl_event_elem_get_subdevice(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type == SND_CTL_EVENT_ELEM);
|
||||
return obj->data.elem.id.subdevice;
|
||||
}
|
||||
|
||||
const char *snd_ctl_event_elem_get_name(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type == SND_CTL_EVENT_ELEM);
|
||||
return obj->data.elem.id.name;
|
||||
}
|
||||
|
||||
unsigned int snd_ctl_event_elem_get_index(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type == SND_CTL_EVENT_ELEM);
|
||||
return obj->data.elem.id.index;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -111,10 +111,21 @@ static int snd_ctl_hw_poll_descriptor(snd_ctl_t *handle)
|
|||
return hw->fd;
|
||||
}
|
||||
|
||||
static int snd_ctl_hw_hw_info(snd_ctl_t *handle, snd_ctl_card_info_t *info)
|
||||
static int snd_ctl_hw_subscribe_events(snd_ctl_t *handle, int subscribe)
|
||||
{
|
||||
snd_ctl_hw_t *hw = handle->private_data;
|
||||
if (ioctl(hw->fd, SNDRV_CTL_IOCTL_INFO, info) < 0)
|
||||
if (ioctl(hw->fd, SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS, &subscribe) < 0) {
|
||||
SYSERR("SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS failed");
|
||||
return -errno;
|
||||
}
|
||||
return subscribe;
|
||||
}
|
||||
|
||||
static int snd_ctl_hw_card_info(snd_ctl_t *handle, snd_ctl_card_info_t *info)
|
||||
{
|
||||
snd_ctl_hw_t *hw = handle->private_data;
|
||||
if (ioctl(hw->fd, SNDRV_CTL_IOCTL_CARD_INFO, info) < 0)
|
||||
SYSERR("SNDRV_CTL_IOCTL_CARD_INFO failed");
|
||||
return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -230,7 +241,8 @@ snd_ctl_ops_t snd_ctl_hw_ops = {
|
|||
nonblock: snd_ctl_hw_nonblock,
|
||||
async: snd_ctl_hw_async,
|
||||
poll_descriptor: snd_ctl_hw_poll_descriptor,
|
||||
hw_info: snd_ctl_hw_hw_info,
|
||||
subscribe_events: snd_ctl_hw_subscribe_events,
|
||||
card_info: snd_ctl_hw_card_info,
|
||||
element_list: snd_ctl_hw_elem_list,
|
||||
element_info: snd_ctl_hw_elem_info,
|
||||
element_read: snd_ctl_hw_elem_read,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ typedef struct _snd_ctl_ops {
|
|||
int (*nonblock)(snd_ctl_t *handle, int nonblock);
|
||||
int (*async)(snd_ctl_t *handle, int sig, pid_t pid);
|
||||
int (*poll_descriptor)(snd_ctl_t *handle);
|
||||
int (*hw_info)(snd_ctl_t *handle, snd_ctl_card_info_t *info);
|
||||
int (*subscribe_events)(snd_ctl_t *handle, int subscribe);
|
||||
int (*card_info)(snd_ctl_t *handle, snd_ctl_card_info_t *info);
|
||||
int (*element_list)(snd_ctl_t *handle, snd_ctl_elem_list_t *list);
|
||||
int (*element_info)(snd_ctl_t *handle, snd_ctl_elem_info_t *info);
|
||||
int (*element_read)(snd_ctl_t *handle, snd_ctl_elem_value_t *control);
|
||||
|
|
|
|||
|
|
@ -222,55 +222,6 @@ snd_ctl_event_type_t snd_ctl_event_get_type(const snd_ctl_event_t *obj)
|
|||
return snd_int_to_enum(obj->type);
|
||||
}
|
||||
|
||||
unsigned int snd_ctl_event_get_numid(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type != SNDRV_CTL_EVENT_REBUILD);
|
||||
return obj->data.id.numid;
|
||||
}
|
||||
|
||||
void snd_ctl_event_get_id(const snd_ctl_event_t *obj, snd_ctl_elem_id_t *ptr)
|
||||
{
|
||||
assert(obj && ptr);
|
||||
assert(obj->type != SNDRV_CTL_EVENT_REBUILD);
|
||||
*ptr = obj->data.id;
|
||||
}
|
||||
|
||||
snd_ctl_elem_iface_t snd_ctl_event_get_interface(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type != SNDRV_CTL_EVENT_REBUILD);
|
||||
return snd_int_to_enum(obj->data.id.iface);
|
||||
}
|
||||
|
||||
unsigned int snd_ctl_event_get_device(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type != SNDRV_CTL_EVENT_REBUILD);
|
||||
return obj->data.id.device;
|
||||
}
|
||||
|
||||
unsigned int snd_ctl_event_get_subdevice(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type != SNDRV_CTL_EVENT_REBUILD);
|
||||
return obj->data.id.subdevice;
|
||||
}
|
||||
|
||||
const char *snd_ctl_event_get_name(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type != SNDRV_CTL_EVENT_REBUILD);
|
||||
return obj->data.id.name;
|
||||
}
|
||||
|
||||
unsigned int snd_ctl_event_get_index(const snd_ctl_event_t *obj)
|
||||
{
|
||||
assert(obj);
|
||||
assert(obj->type != SNDRV_CTL_EVENT_REBUILD);
|
||||
return obj->data.id.index;
|
||||
}
|
||||
|
||||
size_t snd_ctl_elem_list_sizeof()
|
||||
{
|
||||
return sizeof(snd_ctl_elem_list_t);
|
||||
|
|
|
|||
|
|
@ -122,17 +122,26 @@ static int snd_ctl_shm_poll_descriptor(snd_ctl_t *ctl)
|
|||
return fd;
|
||||
}
|
||||
|
||||
static int snd_ctl_shm_hw_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info)
|
||||
static int snd_ctl_shm_subscribe_events(snd_ctl_t *ctl, int subscribe)
|
||||
{
|
||||
snd_ctl_shm_t *shm = ctl->private_data;
|
||||
volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
|
||||
ctrl->cmd = SND_CTL_IOCTL_POLL_DESCRIPTOR;
|
||||
ctrl->u.subscribe_events = subscribe;
|
||||
return snd_ctl_shm_action(ctl);
|
||||
}
|
||||
|
||||
static int snd_ctl_shm_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info)
|
||||
{
|
||||
snd_ctl_shm_t *shm = ctl->private_data;
|
||||
volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
|
||||
int err;
|
||||
// ctrl->u.hw_info = *info;
|
||||
ctrl->cmd = SNDRV_CTL_IOCTL_INFO;
|
||||
// ctrl->u.card_info = *info;
|
||||
ctrl->cmd = SNDRV_CTL_IOCTL_CARD_INFO;
|
||||
err = snd_ctl_shm_action(ctl);
|
||||
if (err < 0)
|
||||
return err;
|
||||
*info = ctrl->u.hw_info;
|
||||
*info = ctrl->u.card_info;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -334,7 +343,8 @@ snd_ctl_ops_t snd_ctl_shm_ops = {
|
|||
nonblock: snd_ctl_shm_nonblock,
|
||||
async: snd_ctl_shm_async,
|
||||
poll_descriptor: snd_ctl_shm_poll_descriptor,
|
||||
hw_info: snd_ctl_shm_hw_info,
|
||||
subscribe_events: snd_ctl_shm_subscribe_events,
|
||||
card_info: snd_ctl_shm_card_info,
|
||||
element_list: snd_ctl_shm_elem_list,
|
||||
element_info: snd_ctl_shm_elem_info,
|
||||
element_read: snd_ctl_shm_elem_read,
|
||||
|
|
|
|||
|
|
@ -89,42 +89,19 @@ int snd_hctl_poll_descriptors(snd_hctl_t *hctl, struct pollfd *pfds, unsigned in
|
|||
return snd_ctl_poll_descriptors(hctl->ctl, pfds, space);
|
||||
}
|
||||
|
||||
static int _snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id, int *dir)
|
||||
{
|
||||
unsigned int l, u;
|
||||
int c = 0;
|
||||
int idx = -1;
|
||||
assert(hctl && id);
|
||||
assert(hctl->compare);
|
||||
l = 0;
|
||||
u = hctl->count;
|
||||
while (l < u) {
|
||||
idx = (l + u) / 2;
|
||||
c = hctl->compare((snd_hctl_elem_t *) id, hctl->pelems[idx]);
|
||||
if (c < 0)
|
||||
u = idx;
|
||||
else if (c > 0)
|
||||
l = idx + 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
*dir = c;
|
||||
return idx;
|
||||
}
|
||||
|
||||
int snd_hctl_throw_event(snd_hctl_t *hctl, snd_ctl_event_type_t event,
|
||||
int snd_hctl_throw_event(snd_hctl_t *hctl, unsigned int mask,
|
||||
snd_hctl_elem_t *elem)
|
||||
{
|
||||
if (hctl->callback)
|
||||
return hctl->callback(hctl, event, elem);
|
||||
return hctl->callback(hctl, mask, elem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_hctl_elem_throw_event(snd_hctl_elem_t *elem,
|
||||
snd_ctl_event_type_t event)
|
||||
unsigned int mask)
|
||||
{
|
||||
if (elem->callback)
|
||||
return elem->callback(elem, event);
|
||||
return elem->callback(elem, mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -207,6 +184,32 @@ static int get_compare_weight(const char *name)
|
|||
return res + res1;
|
||||
}
|
||||
|
||||
static int _snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id, int *dir)
|
||||
{
|
||||
unsigned int l, u;
|
||||
snd_hctl_elem_t el;
|
||||
int c = 0;
|
||||
int idx = -1;
|
||||
assert(hctl && id);
|
||||
assert(hctl->compare);
|
||||
el.id = *id;
|
||||
el.compare_weight = get_compare_weight(id->name);
|
||||
l = 0;
|
||||
u = hctl->count;
|
||||
while (l < u) {
|
||||
idx = (l + u) / 2;
|
||||
c = hctl->compare(&el, hctl->pelems[idx]);
|
||||
if (c < 0)
|
||||
u = idx;
|
||||
else if (c > 0)
|
||||
l = idx + 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
*dir = c;
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int snd_hctl_elem_add(snd_hctl_t *hctl, snd_hctl_elem_t *elem)
|
||||
{
|
||||
int dir;
|
||||
|
|
@ -241,14 +244,14 @@ static int snd_hctl_elem_add(snd_hctl_t *hctl, snd_hctl_elem_t *elem)
|
|||
hctl->pelems[idx] = elem;
|
||||
}
|
||||
hctl->count++;
|
||||
return snd_hctl_throw_event(hctl, SND_CTL_EVENT_ADD, elem);
|
||||
return snd_hctl_throw_event(hctl, SNDRV_CTL_EVENT_MASK_ADD, elem);
|
||||
}
|
||||
|
||||
static void snd_hctl_elem_remove(snd_hctl_t *hctl, unsigned int idx)
|
||||
{
|
||||
snd_hctl_elem_t *elem = hctl->pelems[idx];
|
||||
unsigned int m;
|
||||
snd_hctl_elem_throw_event(elem, SND_CTL_EVENT_REMOVE);
|
||||
snd_hctl_elem_throw_event(elem, SNDRV_CTL_EVENT_MASK_REMOVE);
|
||||
list_del(&elem->list);
|
||||
free(elem);
|
||||
hctl->count--;
|
||||
|
|
@ -408,11 +411,12 @@ int snd_hctl_load(snd_hctl_t *hctl)
|
|||
hctl->compare = snd_hctl_compare_default;
|
||||
snd_hctl_sort(hctl);
|
||||
for (idx = 0; idx < hctl->count; idx++) {
|
||||
int res = snd_hctl_throw_event(hctl, SND_CTL_EVENT_ADD,
|
||||
int res = snd_hctl_throw_event(hctl, SNDRV_CTL_EVENT_MASK_ADD,
|
||||
hctl->pelems[idx]);
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
err = snd_ctl_subscribe_events(hctl->ctl, 1);
|
||||
_end:
|
||||
if (list.pids)
|
||||
free(list.pids);
|
||||
|
|
@ -462,46 +466,41 @@ int snd_hctl_handle_event(snd_hctl_t *hctl, snd_ctl_event_t *event)
|
|||
assert(hctl);
|
||||
assert(hctl->ctl);
|
||||
switch (event->type) {
|
||||
case SND_CTL_EVENT_REMOVE:
|
||||
{
|
||||
case SND_CTL_EVENT_ELEM:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
if (event->data.elem.mask == SNDRV_CTL_EVENT_MASK_REMOVE) {
|
||||
int dir;
|
||||
res = _snd_hctl_find_elem(hctl, &event->data.id, &dir);
|
||||
res = _snd_hctl_find_elem(hctl, &event->data.elem.id, &dir);
|
||||
assert(res >= 0 && dir == 0);
|
||||
if (res < 0 || dir != 0)
|
||||
return -ENOENT;
|
||||
snd_hctl_elem_remove(hctl, res);
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
case SND_CTL_EVENT_VALUE:
|
||||
case SND_CTL_EVENT_INFO:
|
||||
elem = snd_hctl_find_elem(hctl, &event->data.id);
|
||||
assert(elem);
|
||||
if (!elem)
|
||||
return -ENOENT;
|
||||
return snd_hctl_elem_throw_event(elem, event->type);
|
||||
case SND_CTL_EVENT_ADD:
|
||||
if (event->data.elem.mask & SNDRV_CTL_EVENT_MASK_ADD) {
|
||||
elem = calloc(1, sizeof(snd_hctl_elem_t));
|
||||
if (elem == NULL)
|
||||
return -ENOMEM;
|
||||
elem->id = event->data.id;
|
||||
elem->id = event->data.elem.id;
|
||||
elem->hctl = hctl;
|
||||
res = snd_hctl_elem_add(hctl, elem);
|
||||
if (res < 0)
|
||||
return res;
|
||||
break;
|
||||
case SND_CTL_EVENT_REBUILD:
|
||||
snd_hctl_free(hctl);
|
||||
res = snd_hctl_load(hctl);
|
||||
}
|
||||
if (event->data.elem.mask & (SNDRV_CTL_EVENT_MASK_VALUE |
|
||||
SNDRV_CTL_EVENT_MASK_INFO)) {
|
||||
elem = snd_hctl_find_elem(hctl, &event->data.elem.id);
|
||||
assert(elem);
|
||||
if (!elem)
|
||||
return -ENOENT;
|
||||
res = snd_hctl_elem_throw_event(elem, event->data.elem.mask &
|
||||
(SNDRV_CTL_EVENT_MASK_VALUE |
|
||||
SNDRV_CTL_EVENT_MASK_INFO));
|
||||
if (res < 0)
|
||||
return res;
|
||||
#if 0
|
||||
/* I don't think this have to be passed to higher level */
|
||||
return hctl_event(hctl, event->type, NULL);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,56 +87,44 @@ int snd_mixer_elem_empty(snd_mixer_elem_t *melem)
|
|||
}
|
||||
|
||||
static int hctl_elem_event_handler(snd_hctl_elem_t *helem,
|
||||
snd_ctl_event_type_t event)
|
||||
unsigned int mask)
|
||||
{
|
||||
bag_t *bag = snd_hctl_elem_get_callback_private(helem);
|
||||
int res = 0;
|
||||
switch (event) {
|
||||
case SND_CTL_EVENT_VALUE:
|
||||
case SND_CTL_EVENT_INFO:
|
||||
{
|
||||
int err = 0;
|
||||
bag_iterator_t i;
|
||||
bag_for_each(i, bag) {
|
||||
snd_mixer_elem_t *melem = bag_iterator_entry(i);
|
||||
snd_mixer_class_t *class = melem->class;
|
||||
err = class->event(class, event, helem, melem);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SND_CTL_EVENT_REMOVE:
|
||||
{
|
||||
if (mask == SND_CTL_EVENT_MASK_REMOVE) {
|
||||
int res = 0;
|
||||
int err;
|
||||
bag_iterator_t i, n;
|
||||
bag_for_each_safe(i, n, bag) {
|
||||
snd_mixer_elem_t *melem = bag_iterator_entry(i);
|
||||
snd_mixer_class_t *class = melem->class;
|
||||
err = class->event(class, event, helem, melem);
|
||||
err = class->event(class, mask, helem, melem);
|
||||
if (err < 0)
|
||||
res = err;
|
||||
}
|
||||
assert(bag_empty(bag));
|
||||
bag_free(bag);
|
||||
break;
|
||||
|
||||
return res;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
if (mask & (SND_CTL_EVENT_MASK_VALUE | SND_CTL_EVENT_MASK_INFO)) {
|
||||
int err = 0;
|
||||
bag_iterator_t i;
|
||||
bag_for_each(i, bag) {
|
||||
snd_mixer_elem_t *melem = bag_iterator_entry(i);
|
||||
snd_mixer_class_t *class = melem->class;
|
||||
err = class->event(class, mask, helem, melem);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hctl_event_handler(snd_hctl_t *hctl, snd_ctl_event_type_t event,
|
||||
static int hctl_event_handler(snd_hctl_t *hctl, unsigned int mask,
|
||||
snd_hctl_elem_t *elem)
|
||||
{
|
||||
snd_mixer_t *mixer = snd_hctl_get_callback_private(hctl);
|
||||
int res = 0;
|
||||
switch (event) {
|
||||
case SND_CTL_EVENT_ADD:
|
||||
{
|
||||
if (mask & SND_CTL_EVENT_MASK_ADD) {
|
||||
struct list_head *pos;
|
||||
bag_t *bag;
|
||||
int err = bag_new(&bag);
|
||||
|
|
@ -147,15 +135,10 @@ static int hctl_event_handler(snd_hctl_t *hctl, snd_ctl_event_type_t event,
|
|||
list_for_each(pos, &mixer->classes) {
|
||||
snd_mixer_class_t *c;
|
||||
c = list_entry(pos, snd_mixer_class_t, list);
|
||||
err = c->event(c, event, elem, NULL);
|
||||
err = c->event(c, mask, elem, NULL);
|
||||
if (err < 0)
|
||||
res = err;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -203,21 +186,20 @@ int snd_mixer_detach(snd_mixer_t *mixer, const char *name)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
int snd_mixer_throw_event(snd_mixer_t *mixer, snd_ctl_event_type_t event,
|
||||
int snd_mixer_throw_event(snd_mixer_t *mixer, unsigned int mask,
|
||||
snd_mixer_elem_t *elem)
|
||||
{
|
||||
mixer->events++;
|
||||
if (mixer->callback)
|
||||
return mixer->callback(mixer, event, elem);
|
||||
return mixer->callback(mixer, mask, elem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem,
|
||||
snd_ctl_event_type_t event)
|
||||
int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem, unsigned int mask)
|
||||
{
|
||||
elem->class->mixer->events++;
|
||||
if (elem->callback)
|
||||
return elem->callback(elem, event);
|
||||
return elem->callback(elem, mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -278,7 +260,7 @@ int snd_mixer_elem_add(snd_mixer_elem_t *elem, snd_mixer_class_t *class)
|
|||
mixer->pelems[idx] = elem;
|
||||
}
|
||||
mixer->count++;
|
||||
return snd_mixer_throw_event(mixer, SND_CTL_EVENT_ADD, elem);
|
||||
return snd_mixer_throw_event(mixer, SND_CTL_EVENT_MASK_ADD, elem);
|
||||
}
|
||||
|
||||
int snd_mixer_elem_remove(snd_mixer_elem_t *elem)
|
||||
|
|
@ -296,7 +278,7 @@ int snd_mixer_elem_remove(snd_mixer_elem_t *elem)
|
|||
snd_hctl_elem_t *helem = bag_iterator_entry(i);
|
||||
snd_mixer_elem_detach(elem, helem);
|
||||
}
|
||||
err = snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_REMOVE);
|
||||
err = snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_REMOVE);
|
||||
list_del(&elem->list);
|
||||
if (elem->private_free)
|
||||
elem->private_free(elem);
|
||||
|
|
@ -312,7 +294,7 @@ int snd_mixer_elem_remove(snd_mixer_elem_t *elem)
|
|||
|
||||
int snd_mixer_elem_change(snd_mixer_elem_t *elem)
|
||||
{
|
||||
return snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_INFO);
|
||||
return snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_INFO);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -330,7 +312,7 @@ int snd_mixer_class_register(snd_mixer_class_t *class, snd_mixer_t *mixer)
|
|||
slave = list_entry(pos, snd_mixer_slave_t, list);
|
||||
elem = snd_hctl_first_elem(slave->hctl);
|
||||
while (elem) {
|
||||
err = class->event(class, SND_CTL_EVENT_ADD, elem, NULL);
|
||||
err = class->event(class, SND_CTL_EVENT_MASK_ADD, elem, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
elem = snd_hctl_elem_next(elem);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ typedef struct list_head *bag_iterator_t;
|
|||
struct _snd_mixer_class {
|
||||
struct list_head list;
|
||||
snd_mixer_t *mixer;
|
||||
int (*event)(snd_mixer_class_t *class, snd_ctl_event_type_t event,
|
||||
int (*event)(snd_mixer_class_t *class, unsigned int mask,
|
||||
snd_hctl_elem_t *helem, snd_mixer_elem_t *melem);
|
||||
void *private_data;
|
||||
void (*private_free)(snd_mixer_class_t *class);
|
||||
|
|
@ -111,8 +111,7 @@ struct _snd_mixer_selem_value {
|
|||
int snd_mixer_class_register(snd_mixer_class_t *class, snd_mixer_t *mixer);
|
||||
int snd_mixer_add_elem(snd_mixer_t *mixer, snd_mixer_elem_t *elem);
|
||||
int snd_mixer_remove_elem(snd_mixer_t *mixer, snd_mixer_elem_t *elem);
|
||||
int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem,
|
||||
snd_ctl_event_type_t event);
|
||||
int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem, unsigned int mask);
|
||||
int snd_mixer_elem_add(snd_mixer_elem_t *elem, snd_mixer_class_t *class);
|
||||
int snd_mixer_elem_remove(snd_mixer_elem_t *elem);
|
||||
int snd_mixer_elem_change(snd_mixer_elem_t *elem);
|
||||
|
|
|
|||
|
|
@ -787,21 +787,27 @@ int simple_event_info(snd_mixer_elem_t *melem)
|
|||
return snd_mixer_elem_change(melem);
|
||||
}
|
||||
|
||||
int simple_event(snd_mixer_class_t *class, snd_ctl_event_type_t event,
|
||||
int simple_event(snd_mixer_class_t *class, unsigned int mask,
|
||||
snd_hctl_elem_t *helem, snd_mixer_elem_t *melem)
|
||||
{
|
||||
switch (event) {
|
||||
case SND_CTL_EVENT_ADD:
|
||||
return simple_event_add(class, helem);
|
||||
case SND_CTL_EVENT_INFO:
|
||||
return simple_event_info(melem);
|
||||
case SND_CTL_EVENT_VALUE:
|
||||
return snd_mixer_elem_throw_event(melem, event);
|
||||
case SND_CTL_EVENT_REMOVE:
|
||||
int err;
|
||||
if (mask == SND_CTL_EVENT_MASK_REMOVE)
|
||||
return simple_event_remove(helem, melem);
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
if (mask & SND_CTL_EVENT_MASK_ADD) {
|
||||
err = simple_event_add(class, helem);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (mask & SND_CTL_EVENT_MASK_INFO) {
|
||||
err = simple_event_info(melem);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (mask & SND_CTL_EVENT_MASK_VALUE) {
|
||||
/* FIXME */
|
||||
err = snd_mixer_elem_throw_event(melem, mask);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue