Changed control to use events mask. Added subscribe ioctl

This commit is contained in:
Abramo Bagnara 2001-02-13 21:29:30 +00:00
parent fa51799255
commit 3e97ef3ea0
14 changed files with 225 additions and 205 deletions

View file

@ -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;
}

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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,

View file

@ -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;
}