4 This file is part of polypaudio.
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
30 #include "core-subscribe.h"
34 /* The subscription subsystem may be used to be notified whenever an
35 * entity (sink, source, ...) is created or deleted. Modules may
36 * register a callback function that is called whenever an event
37 * matching a subscription mask happens. The execution of the callback
38 * function is postponed to the next main loop iteration, i.e. is not
39 * called from within the stack frame the entity was created in. */
41 struct pa_subscription {
44 void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata);
46 pa_subscription_mask_t mask;
48 pa_subscription *prev, *next;
51 struct pa_subscription_event {
52 pa_subscription_event_type_t type;
56 static void sched_event(pa_core *c);
58 /* Allocate a new subscription object for the given subscription mask. Use the specified callback function and user data */
59 pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata) {
63 s = pa_xmalloc(sizeof(pa_subscription));
66 s->callback = callback;
67 s->userdata = userdata;
70 if ((s->next = c->subscriptions))
77 /* Free a subscription object, effectively marking it for deletion */
78 void pa_subscription_free(pa_subscription*s) {
79 assert(s && !s->dead);
84 static void free_item(pa_subscription *s) {
88 s->prev->next = s->next;
90 s->core->subscriptions = s->next;
93 s->next->prev = s->prev;
98 /* Free all subscription objects */
99 void pa_subscription_free_all(pa_core *c) {
100 pa_subscription_event *e;
103 while (c->subscriptions)
104 free_item(c->subscriptions);
106 if (c->subscription_event_queue) {
107 while ((e = pa_queue_pop(c->subscription_event_queue)))
110 pa_queue_free(c->subscription_event_queue, NULL, NULL);
111 c->subscription_event_queue = NULL;
114 if (c->subscription_defer_event) {
115 c->mainloop->defer_free(c->subscription_defer_event);
116 c->subscription_defer_event = NULL;
120 /*static void dump_event(pa_subscription_event*e) {
121 switch (e->type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
122 case PA_SUBSCRIPTION_EVENT_SINK:
123 pa_log(__FILE__": SINK_EVENT");
125 case PA_SUBSCRIPTION_EVENT_SOURCE:
126 pa_log(__FILE__": SOURCE_EVENT");
128 case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
129 pa_log(__FILE__": SINK_INPUT_EVENT");
131 case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT:
132 pa_log(__FILE__": SOURCE_OUTPUT_EVENT");
134 case PA_SUBSCRIPTION_EVENT_MODULE:
135 pa_log(__FILE__": MODULE_EVENT");
137 case PA_SUBSCRIPTION_EVENT_CLIENT:
138 pa_log(__FILE__": CLIENT_EVENT");
141 pa_log(__FILE__": OTHER");
145 switch (e->type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) {
146 case PA_SUBSCRIPTION_EVENT_NEW:
147 pa_log(__FILE__": NEW");
149 case PA_SUBSCRIPTION_EVENT_CHANGE:
150 pa_log(__FILE__": CHANGE");
152 case PA_SUBSCRIPTION_EVENT_REMOVE:
153 pa_log(__FILE__": REMOVE");
156 pa_log(__FILE__": OTHER");
160 pa_log(__FILE__": %u\n", e->index);
163 /* Deferred callback for dispatching subscirption events */
164 static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) {
165 pa_core *c = userdata;
167 assert(c && c->subscription_defer_event == de && c->mainloop == m);
169 c->mainloop->defer_enable(c->subscription_defer_event, 0);
172 /* Dispatch queued events */
174 if (c->subscription_event_queue) {
175 pa_subscription_event *e;
177 while ((e = pa_queue_pop(c->subscription_event_queue))) {
179 for (s = c->subscriptions; s; s = s->next) {
181 if (!s->dead && pa_subscription_match_flags(s->mask, e->type))
182 s->callback(c, e->type, e->index, s->userdata);
189 /* Remove dead subscriptions */
191 s = c->subscriptions;
193 pa_subscription *n = s->next;
200 /* Schedule an mainloop event so that a pending subscription event is dispatched */
201 static void sched_event(pa_core *c) {
204 if (!c->subscription_defer_event) {
205 c->subscription_defer_event = c->mainloop->defer_new(c->mainloop, defer_cb, c);
206 assert(c->subscription_defer_event);
209 c->mainloop->defer_enable(c->subscription_defer_event, 1);
212 /* Append a new subscription event to the subscription event queue and schedule a main loop event */
213 void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t index) {
214 pa_subscription_event *e;
217 e = pa_xmalloc(sizeof(pa_subscription_event));
221 if (!c->subscription_event_queue) {
222 c->subscription_event_queue = pa_queue_new();
223 assert(c->subscription_event_queue);
226 pa_queue_push(c->subscription_event_queue, e);