gpointer tag;
void *buf;
unsigned int buf_len;
+ GList *entries;
} CtlCardSource;
enum ctl_card_prop_type {
generate_error(error, errno);
}
+static void handle_elem_event(CtlCardSource *src, struct snd_ctl_event *ev)
+{
+ ALSACtlCard *self = src->self;
+ GList *entry;
+
+ // Maintain local cache for addition of element.
+ if (ev->data.elem.mask & SNDRV_CTL_EVENT_MASK_ADD) {
+ ALSACtlElemId *elem_id =
+ g_boxed_copy(ALSACTL_TYPE_ELEM_ID, &ev->data.elem.id);
+ src->entries = g_list_append(src->entries, (gpointer)elem_id);
+ }
+
+ for (entry = src->entries; entry != NULL; entry = entry->next) {
+ ALSACtlElemId *elem_id = (ALSACtlElemId *)entry->data;
+
+ if (ev->data.elem.id.numid == elem_id->numid) {
+ ALSACtlEventMaskFlag mask;
+
+ if (ev->data.elem.mask != SNDRV_CTL_EVENT_MASK_REMOVE)
+ mask = ev->data.elem.mask;
+ else
+ mask = ALSACTL_EVENT_MASK_FLAG_REMOVE;
+
+ g_signal_emit(self,
+ ctl_card_sigs[CTL_CARD_SIG_HANDLE_ELEM_EVENT], 0,
+ elem_id, mask);
+
+ // Maintain local cache for removal of element.
+ if (ev->data.elem.mask == SNDRV_CTL_EVENT_MASK_REMOVE) {
+ src->entries = g_list_delete_link(src->entries, entry);
+ g_boxed_free(ALSACTL_TYPE_ELEM_ID, elem_id);
+ }
+
+ break;
+ }
+ }
+}
+
static gboolean ctl_card_prepare_src(GSource *src, gint *timeout)
{
*timeout = 500;
ev = src->buf;
while (len >= sizeof(*ev)) {
- // TODO: handle the event.
+ if (ev->type == SNDRV_CTL_EVENT_ELEM)
+ handle_elem_event(src, ev);
len -= sizeof(*ev);
++ev;
{
CtlCardSource *src = (CtlCardSource *)gsrc;
ALSACtlCardPrivate *priv = alsactl_card_get_instance_private(src->self);
+ GList *entry;
// Unsubscribe events.
if (g_atomic_int_dec_and_test(&priv->subscribers)) {
ioctl(priv->fd, SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS, &subscribe);
}
+ for (entry = src->entries; entry != NULL; entry = entry->next) {
+ ALSACtlElemId *elem_id = (ALSACtlElemId *)entry->data;
+ g_boxed_free(ALSACTL_TYPE_ELEM_ID, elem_id);
+ }
+ g_list_free(src->entries);
+
g_free(src->buf);
g_object_unref(src->self);
}
src->buf = buf;
src->buf_len = page_size;
+ alsactl_card_get_elem_id_list(self, &src->entries, error);
+ if (*error != NULL) {
+ g_source_unref(*gsrc);
+ return;
+ }
+
// Subscribe any event.
{
int subscribe = 1;