mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-08 13:29:59 -05:00
add subscription subsystem
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@112 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
fc618e9f31
commit
3d374e9f67
11 changed files with 236 additions and 2 deletions
152
polyp/subscribe.c
Normal file
152
polyp/subscribe.c
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "queue.h"
|
||||
#include "subscribe.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
struct pa_subscription {
|
||||
struct pa_core *core;
|
||||
int dead;
|
||||
void (*callback)(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
|
||||
void *userdata;
|
||||
enum pa_subscription_mask mask;
|
||||
|
||||
struct pa_subscription *prev, *next;
|
||||
};
|
||||
|
||||
struct pa_subscription_event {
|
||||
enum pa_subscription_event_type type;
|
||||
uint32_t index;
|
||||
};
|
||||
|
||||
static void sched_event(struct pa_core *c);
|
||||
|
||||
struct pa_subscription* pa_subscription_new(struct pa_core *c, enum pa_subscription_mask m, void (*callback)(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
|
||||
struct pa_subscription *s;
|
||||
assert(c);
|
||||
|
||||
s = pa_xmalloc(sizeof(struct pa_subscription));
|
||||
s->core = c;
|
||||
s->dead = 0;
|
||||
s->callback = callback;
|
||||
s->userdata = userdata;
|
||||
s->mask = m;
|
||||
|
||||
if ((s->next = c->subscriptions))
|
||||
s->next->prev = s;
|
||||
s->prev = NULL;
|
||||
c->subscriptions = s;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pa_subscription_free(struct pa_subscription*s) {
|
||||
assert(s && !s->dead);
|
||||
s->dead = 1;
|
||||
sched_event(s->core);
|
||||
}
|
||||
|
||||
static void free_item(struct pa_subscription *s) {
|
||||
assert(s && s->core);
|
||||
|
||||
if (s->prev)
|
||||
s->prev->next = s->next;
|
||||
else
|
||||
s->core->subscriptions = s->next;
|
||||
|
||||
if (s->next)
|
||||
s->next->prev = s->prev;
|
||||
|
||||
pa_xfree(s);
|
||||
}
|
||||
|
||||
void pa_subscription_free_all(struct pa_core *c) {
|
||||
struct pa_subscription_event *e;
|
||||
assert(c);
|
||||
|
||||
while (c->subscriptions)
|
||||
free_item(c->subscriptions);
|
||||
|
||||
if (c->subscription_event_queue) {
|
||||
while ((e = pa_queue_pop(c->subscription_event_queue)))
|
||||
pa_xfree(e);
|
||||
|
||||
pa_queue_free(c->subscription_event_queue, NULL, NULL);
|
||||
c->subscription_event_queue = NULL;
|
||||
}
|
||||
|
||||
if (c->subscription_defer_event) {
|
||||
c->mainloop->defer_free(c->subscription_defer_event);
|
||||
c->subscription_defer_event = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) {
|
||||
struct pa_core *c = userdata;
|
||||
struct pa_subscription *s;
|
||||
assert(c && c->subscription_defer_event == e && c->mainloop == m);
|
||||
|
||||
c->mainloop->defer_enable(c->subscription_defer_event, 0);
|
||||
|
||||
|
||||
/* Dispatch queued events */
|
||||
|
||||
if (c->subscription_event_queue) {
|
||||
struct pa_subscription_event *e;
|
||||
|
||||
while ((e = pa_queue_pop(c->subscription_event_queue))) {
|
||||
struct pa_subscription *s;
|
||||
|
||||
for (s = c->subscriptions; s; s = s->next) {
|
||||
if (!s->dead && pa_subscription_match_flags(s->mask, e->type))
|
||||
s->callback(c, e->type, e->index, s->userdata);
|
||||
}
|
||||
|
||||
pa_xfree(e);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove dead subscriptions */
|
||||
|
||||
s = c->subscriptions;
|
||||
while (s) {
|
||||
struct pa_subscription *n = s->next;
|
||||
if (s->dead)
|
||||
free_item(s);
|
||||
s = n;
|
||||
}
|
||||
}
|
||||
|
||||
static void sched_event(struct pa_core *c) {
|
||||
assert(c);
|
||||
|
||||
if (!c->subscription_defer_event) {
|
||||
c->subscription_defer_event = c->mainloop->defer_new(c->mainloop, defer_cb, c);
|
||||
assert(c->subscription_defer_event);
|
||||
}
|
||||
|
||||
c->mainloop->defer_enable(c->subscription_defer_event, 1);
|
||||
}
|
||||
|
||||
|
||||
void pa_subscription_post(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index) {
|
||||
struct pa_subscription_event *e;
|
||||
assert(c);
|
||||
|
||||
e = pa_xmalloc(sizeof(struct pa_subscription_event));
|
||||
e->type = t;
|
||||
e->index = index;
|
||||
|
||||
if (!c->subscription_event_queue) {
|
||||
c->subscription_event_queue = pa_queue_new();
|
||||
assert(c->subscription_event_queue);
|
||||
}
|
||||
|
||||
pa_queue_push(c->subscription_event_queue, e);
|
||||
sched_event(c);
|
||||
}
|
||||
|
||||
|
||||
int pa_subscription_match_flags(enum pa_subscription_mask m, enum pa_subscription_event_type t) {
|
||||
return !!(m & (1 >> (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue