]> code.delx.au - pulseaudio/blob - polyp/subscribe.c
d3b97de7e5de6e3f2d2e84ed7f3d71deef0f379b
[pulseaudio] / polyp / subscribe.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU 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.
10
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.
15
16 You should have received a copy of the GNU 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
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <assert.h>
28
29 #include "queue.h"
30 #include "subscribe.h"
31 #include "xmalloc.h"
32 #include "log.h"
33
34 struct pa_subscription {
35 struct pa_core *core;
36 int dead;
37 void (*callback)(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
38 void *userdata;
39 enum pa_subscription_mask mask;
40
41 struct pa_subscription *prev, *next;
42 };
43
44 struct pa_subscription_event {
45 enum pa_subscription_event_type type;
46 uint32_t index;
47 };
48
49 static void sched_event(struct pa_core *c);
50
51 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) {
52 struct pa_subscription *s;
53 assert(c);
54
55 s = pa_xmalloc(sizeof(struct pa_subscription));
56 s->core = c;
57 s->dead = 0;
58 s->callback = callback;
59 s->userdata = userdata;
60 s->mask = m;
61
62 if ((s->next = c->subscriptions))
63 s->next->prev = s;
64 s->prev = NULL;
65 c->subscriptions = s;
66 return s;
67 }
68
69 void pa_subscription_free(struct pa_subscription*s) {
70 assert(s && !s->dead);
71 s->dead = 1;
72 sched_event(s->core);
73 }
74
75 static void free_item(struct pa_subscription *s) {
76 assert(s && s->core);
77
78 if (s->prev)
79 s->prev->next = s->next;
80 else
81 s->core->subscriptions = s->next;
82
83 if (s->next)
84 s->next->prev = s->prev;
85
86 pa_xfree(s);
87 }
88
89 void pa_subscription_free_all(struct pa_core *c) {
90 struct pa_subscription_event *e;
91 assert(c);
92
93 while (c->subscriptions)
94 free_item(c->subscriptions);
95
96 if (c->subscription_event_queue) {
97 while ((e = pa_queue_pop(c->subscription_event_queue)))
98 pa_xfree(e);
99
100 pa_queue_free(c->subscription_event_queue, NULL, NULL);
101 c->subscription_event_queue = NULL;
102 }
103
104 if (c->subscription_defer_event) {
105 c->mainloop->defer_free(c->subscription_defer_event);
106 c->subscription_defer_event = NULL;
107 }
108 }
109
110 /*static void dump_event(struct pa_subscription_event*e) {
111 switch (e->type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
112 case PA_SUBSCRIPTION_EVENT_SINK:
113 pa_log(__FILE__": SINK_EVENT");
114 break;
115 case PA_SUBSCRIPTION_EVENT_SOURCE:
116 pa_log(__FILE__": SOURCE_EVENT");
117 break;
118 case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
119 pa_log(__FILE__": SINK_INPUT_EVENT");
120 break;
121 case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT:
122 pa_log(__FILE__": SOURCE_OUTPUT_EVENT");
123 break;
124 case PA_SUBSCRIPTION_EVENT_MODULE:
125 pa_log(__FILE__": MODULE_EVENT");
126 break;
127 case PA_SUBSCRIPTION_EVENT_CLIENT:
128 pa_log(__FILE__": CLIENT_EVENT");
129 break;
130 default:
131 pa_log(__FILE__": OTHER");
132 break;
133 }
134
135 switch (e->type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) {
136 case PA_SUBSCRIPTION_EVENT_NEW:
137 pa_log(__FILE__": NEW");
138 break;
139 case PA_SUBSCRIPTION_EVENT_CHANGE:
140 pa_log(__FILE__": CHANGE");
141 break;
142 case PA_SUBSCRIPTION_EVENT_REMOVE:
143 pa_log(__FILE__": REMOVE");
144 break;
145 default:
146 pa_log(__FILE__": OTHER");
147 break;
148 }
149
150 pa_log(__FILE__": %u\n", e->index);
151 }*/
152
153 static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) {
154 struct pa_core *c = userdata;
155 struct pa_subscription *s;
156 assert(c && c->subscription_defer_event == e && c->mainloop == m);
157
158 c->mainloop->defer_enable(c->subscription_defer_event, 0);
159
160
161 /* Dispatch queued events */
162
163 if (c->subscription_event_queue) {
164 struct pa_subscription_event *e;
165
166 while ((e = pa_queue_pop(c->subscription_event_queue))) {
167 struct pa_subscription *s;
168
169 for (s = c->subscriptions; s; s = s->next) {
170
171 if (!s->dead && pa_subscription_match_flags(s->mask, e->type))
172 s->callback(c, e->type, e->index, s->userdata);
173 }
174
175 pa_xfree(e);
176 }
177 }
178
179 /* Remove dead subscriptions */
180
181 s = c->subscriptions;
182 while (s) {
183 struct pa_subscription *n = s->next;
184 if (s->dead)
185 free_item(s);
186 s = n;
187 }
188 }
189
190 static void sched_event(struct pa_core *c) {
191 assert(c);
192
193 if (!c->subscription_defer_event) {
194 c->subscription_defer_event = c->mainloop->defer_new(c->mainloop, defer_cb, c);
195 assert(c->subscription_defer_event);
196 }
197
198 c->mainloop->defer_enable(c->subscription_defer_event, 1);
199 }
200
201
202 void pa_subscription_post(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index) {
203 struct pa_subscription_event *e;
204 assert(c);
205
206 e = pa_xmalloc(sizeof(struct pa_subscription_event));
207 e->type = t;
208 e->index = index;
209
210 if (!c->subscription_event_queue) {
211 c->subscription_event_queue = pa_queue_new();
212 assert(c->subscription_event_queue);
213 }
214
215 pa_queue_push(c->subscription_event_queue, e);
216 sched_event(c);
217 }
218
219