3 #include "glib-mainloop.h"
10 struct pa_glib_mainloop
*mainloop
;
13 void (*callback
) (struct pa_mainloop_api
*m
, struct pa_io_event
*e
, int fd
, enum pa_io_event_flags f
, void *userdata
);
15 void (*destroy_callback
) (struct pa_mainloop_api
*m
, struct pa_io_event
*e
, void *userdata
);
16 struct pa_io_event
*next
, *prev
;
19 struct pa_time_event
{
20 struct pa_glib_mainloop
*mainloop
;
23 struct timeval timeval
;
24 void (*callback
) (struct pa_mainloop_api
*m
, struct pa_time_event
*e
, const struct timeval
*tv
, void *userdata
);
26 void (*destroy_callback
) (struct pa_mainloop_api
*m
, struct pa_time_event
*e
, void *userdata
);
27 struct pa_time_event
*next
, *prev
;
30 struct pa_defer_event
{
31 struct pa_glib_mainloop
*mainloop
;
34 void (*callback
) (struct pa_mainloop_api
*m
, struct pa_defer_event
*e
, void *userdata
);
36 void (*destroy_callback
) (struct pa_mainloop_api
*m
, struct pa_defer_event
*e
, void *userdata
);
37 struct pa_defer_event
*next
, *prev
;
40 struct pa_glib_mainloop
{
41 GMainLoop
*glib_mainloop
;
42 struct pa_mainloop_api api
;
43 GSource
*cleanup_source
;
44 struct pa_io_event
*io_events
, *dead_io_events
;
45 struct pa_time_event
*time_events
, *dead_time_events
;
46 struct pa_defer_event
*defer_events
, *dead_defer_events
;
49 static void schedule_free_dead_events(struct pa_glib_mainloop
*g
);
51 static gboolean
glib_source_prepare(GSource
*source
, gint
*timeout
) {
55 static gboolean
glib_source_check(GSource
*source
) {
56 struct pa_io_event
*e
= (struct pa_io_event
*) source
;
58 return !!e
->pollfd
.revents
;
61 static gboolean
glib_source_dispatch(GSource
*source
, GSourceFunc callback
, gpointer user_data
) {
62 struct pa_io_event
*e
= (struct pa_io_event
*) source
;
65 if (e
->pollfd
.revents
) {
67 (e
->pollfd
.revents
? G_IO_IN
: PA_IO_EVENT_INPUT
) |
68 (e
->pollfd
.revents
? G_IO_OUT
: PA_IO_EVENT_OUTPUT
) |
69 (e
->pollfd
.revents
? G_IO_HUP
: PA_IO_EVENT_HANGUP
) |
70 (e
->pollfd
.revents
? G_IO_ERR
: PA_IO_EVENT_ERROR
);
71 e
->pollfd
.revents
= 0;
74 e
->callback(&e
->mainloop
->api
, e
, e
->fd
, f
, e
->userdata
);
80 static void glib_io_enable(struct pa_io_event
*e
, enum pa_io_event_flags f
);
82 static struct pa_io_event
* glib_io_new(struct pa_mainloop_api
*m
, int fd
, enum pa_io_event_flags f
, void (*callback
) (struct pa_mainloop_api
*m
, struct pa_io_event
*e
, int fd
, enum pa_io_event_flags f
, void *userdata
), void *userdata
) {
83 struct pa_io_event
*e
;
84 struct pa_glib_mainloop
*g
;
86 GSourceFuncs io_source_funcs
= {
87 prepare
: glib_source_prepare
,
88 check
: glib_source_check
,
89 dispatch
: glib_source_dispatch
,
91 closure_callback
: NULL
,
92 closure_marshal
: NULL
,
95 assert(m
&& m
->userdata
&& fd
>= 0 && callback
);
98 e
= (struct pa_io_event
*) g_source_new(&io_source_funcs
, sizeof(struct pa_io_event
));
100 e
->mainloop
= m
->userdata
;
103 e
->callback
= callback
;
104 e
->userdata
= userdata
;
105 e
->destroy_callback
= NULL
;
108 e
->pollfd
.events
= e
->pollfd
.revents
= 0;
110 g_source_attach(&e
->source
, g_main_loop_get_context(g
->glib_mainloop
));
112 glib_io_enable(e
, f
);
114 e
->next
= g
->io_events
;
115 if (e
->next
) e
->next
->prev
= e
;
122 static void glib_io_enable(struct pa_io_event
*e
, enum pa_io_event_flags f
) {
124 assert(e
&& !e
->dead
);
126 o
= e
->pollfd
.events
;
127 e
->pollfd
.events
= (f
& PA_IO_EVENT_INPUT
? G_IO_IN
: 0) | (f
& PA_IO_EVENT_OUTPUT
? G_IO_OUT
: 0) | G_IO_HUP
| G_IO_ERR
;
129 if (!o
&& e
->pollfd
.events
)
130 g_source_add_poll(&e
->source
, &e
->pollfd
);
131 else if (o
&& !e
->pollfd
.events
)
132 g_source_remove_poll(&e
->source
, &e
->pollfd
);
135 static void glib_io_free(struct pa_io_event
*e
) {
136 assert(e
&& !e
->dead
);
138 g_source_destroy(&e
->source
);
141 e
->prev
->next
= e
->next
;
143 e
->mainloop
->io_events
= e
->next
;
146 e
->next
->prev
= e
->prev
;
148 if ((e
->next
= e
->mainloop
->dead_io_events
))
151 e
->mainloop
->dead_io_events
= e
;
155 schedule_free_dead_events(e
->mainloop
);
158 static void glib_io_set_destroy(struct pa_io_event
*e
, void (*callback
)(struct pa_mainloop_api
*m
, struct pa_io_event
*e
, void *userdata
)) {
160 e
->destroy_callback
= callback
;
165 static void glib_time_restart(struct pa_time_event
*e
, const struct timeval
*tv
);
167 static struct pa_time_event
* glib_time_new(struct pa_mainloop_api
*m
, const struct timeval
*tv
, void (*callback
) (struct pa_mainloop_api
*m
, struct pa_time_event
*e
, const struct timeval
*tv
, void *userdata
), void *userdata
) {
168 struct pa_glib_mainloop
*g
;
169 struct pa_time_event
*e
;
171 assert(m
&& m
->userdata
&& tv
&& callback
);
174 e
= pa_xmalloc(sizeof(struct pa_time_event
));
177 e
->callback
= callback
;
178 e
->userdata
= userdata
;
179 e
->destroy_callback
= NULL
;
182 glib_time_restart(e
, tv
);
184 e
->next
= g
->time_events
;
185 if (e
->next
) e
->next
->prev
= e
;
192 static guint
msec_diff(const struct timeval
*a
, const struct timeval
*b
) {
196 if (a
->tv_sec
< b
->tv_sec
)
199 if (a
->tv_sec
== b
->tv_sec
&& a
->tv_sec
<= b
->tv_sec
)
202 r
= (a
->tv_sec
-b
->tv_sec
)*1000;
204 if (a
->tv_usec
>= b
->tv_usec
)
205 r
+= (a
->tv_usec
- b
->tv_usec
) / 1000;
207 r
-= (b
->tv_usec
- a
->tv_usec
) / 1000;
212 static gboolean
time_cb(gpointer data
) {
213 struct pa_time_event
* e
= data
;
214 assert(e
&& e
->mainloop
&& e
->source
);
216 g_source_unref(e
->source
);
219 e
->callback(&e
->mainloop
->api
, e
, &e
->timeval
, e
->userdata
);
223 static void glib_time_restart(struct pa_time_event
*e
, const struct timeval
*tv
) {
225 assert(e
&& e
->mainloop
);
227 gettimeofday(&now
, NULL
);
229 g_source_destroy(e
->source
);
230 g_source_unref(e
->source
);
235 e
->source
= g_timeout_source_new(msec_diff(tv
, &now
));
237 g_source_set_callback(e
->source
, time_cb
, e
, NULL
);
238 g_source_attach(e
->source
, g_main_loop_get_context(e
->mainloop
->glib_mainloop
));
243 static void glib_time_free(struct pa_time_event
*e
) {
244 assert(e
&& e
->mainloop
);
247 g_source_destroy(e
->source
);
248 g_source_unref(e
->source
);
253 e
->prev
->next
= e
->next
;
255 e
->mainloop
->time_events
= e
->next
;
258 e
->next
->prev
= e
->prev
;
260 if ((e
->next
= e
->mainloop
->dead_time_events
))
263 e
->mainloop
->dead_time_events
= e
;
267 schedule_free_dead_events(e
->mainloop
);
270 static void glib_time_set_destroy(struct pa_time_event
*e
, void (*callback
)(struct pa_mainloop_api
*m
, struct pa_time_event
*e
, void *userdata
)) {
272 e
->destroy_callback
= callback
;
275 /* Deferred sources */
277 static void glib_defer_enable(struct pa_defer_event
*e
, int b
);
279 static struct pa_defer_event
* glib_defer_new(struct pa_mainloop_api
*m
, void (*callback
) (struct pa_mainloop_api
*m
, struct pa_defer_event
*e
, void *userdata
), void *userdata
) {
280 struct pa_defer_event
*e
;
281 struct pa_glib_mainloop
*g
;
283 assert(m
&& m
->userdata
&& callback
);
286 e
= pa_xmalloc(sizeof(struct pa_defer_event
));
289 e
->callback
= callback
;
290 e
->userdata
= userdata
;
291 e
->destroy_callback
= NULL
;
294 glib_defer_enable(e
, 1);
296 e
->next
= g
->defer_events
;
297 if (e
->next
) e
->next
->prev
= e
;
303 static gboolean
idle_cb(gpointer data
) {
304 struct pa_defer_event
* e
= data
;
305 assert(e
&& e
->mainloop
&& e
->source
);
307 e
->callback(&e
->mainloop
->api
, e
, e
->userdata
);
311 static void glib_defer_enable(struct pa_defer_event
*e
, int b
) {
312 assert(e
&& e
->mainloop
);
314 if (e
->source
&& !b
) {
315 g_source_destroy(e
->source
);
316 g_source_unref(e
->source
);
318 } else if (!e
->source
&& b
) {
319 e
->source
= g_idle_source_new();
321 g_source_set_callback(e
->source
, idle_cb
, e
, NULL
);
322 g_source_attach(e
->source
, g_main_loop_get_context(e
->mainloop
->glib_mainloop
));
323 g_source_set_priority(e
->source
, G_PRIORITY_HIGH_IDLE
);
327 static void glib_defer_free(struct pa_defer_event
*e
) {
328 assert(e
&& e
->mainloop
);
331 g_source_destroy(e
->source
);
332 g_source_unref(e
->source
);
337 e
->prev
->next
= e
->next
;
339 e
->mainloop
->defer_events
= e
->next
;
342 e
->next
->prev
= e
->prev
;
344 if ((e
->next
= e
->mainloop
->dead_defer_events
))
347 e
->mainloop
->dead_defer_events
= e
;
351 schedule_free_dead_events(e
->mainloop
);
354 static void glib_defer_set_destroy(struct pa_defer_event
*e
, void (*callback
)(struct pa_mainloop_api
*m
, struct pa_defer_event
*e
, void *userdata
)) {
356 e
->destroy_callback
= callback
;
361 static void glib_quit(struct pa_mainloop_api
*a
, int retval
) {
362 struct pa_glib_mainloop
*g
;
363 assert(a
&& a
->userdata
);
366 g_main_loop_quit(g
->glib_mainloop
);
369 static const struct pa_mainloop_api vtable
= {
373 io_enable
: glib_io_enable
,
374 io_free
: glib_io_free
,
375 io_set_destroy
: glib_io_set_destroy
,
377 time_new
: glib_time_new
,
378 time_restart
: glib_time_restart
,
379 time_free
: glib_time_free
,
380 time_set_destroy
: glib_time_set_destroy
,
382 defer_new
: glib_defer_new
,
383 defer_enable
: glib_defer_enable
,
384 defer_free
: glib_defer_free
,
385 defer_set_destroy
: glib_defer_set_destroy
,
390 struct pa_glib_mainloop
*pa_glib_mainloop_new(GMainLoop
*ml
) {
391 struct pa_glib_mainloop
*g
;
394 g
= pa_xmalloc(sizeof(struct pa_glib_mainloop
));
395 g
->glib_mainloop
= g_main_loop_ref(ml
);
399 g
->io_events
= g
->dead_io_events
= NULL
;
400 g
->time_events
= g
->dead_time_events
= NULL
;
401 g
->defer_events
= g
->dead_defer_events
= NULL
;
403 g
->cleanup_source
= NULL
;
407 static void free_io_events(struct pa_io_event
*e
) {
409 struct pa_io_event
*r
= e
;
412 if (r
->pollfd
.events
)
413 g_source_remove_poll(&r
->source
, &r
->pollfd
);
416 g_source_destroy(&r
->source
);
418 if (r
->destroy_callback
)
419 r
->destroy_callback(&r
->mainloop
->api
, r
, r
->userdata
);
421 g_source_unref(&r
->source
);
425 static void free_time_events(struct pa_time_event
*e
) {
427 struct pa_time_event
*r
= e
;
431 g_source_destroy(r
->source
);
432 g_source_unref(r
->source
);
435 if (r
->destroy_callback
)
436 r
->destroy_callback(&r
->mainloop
->api
, r
, r
->userdata
);
442 static void free_defer_events(struct pa_defer_event
*e
) {
444 struct pa_defer_event
*r
= e
;
448 g_source_destroy(r
->source
);
449 g_source_unref(r
->source
);
452 if (r
->destroy_callback
)
453 r
->destroy_callback(&r
->mainloop
->api
, r
, r
->userdata
);
459 void pa_glib_mainloop_free(struct pa_glib_mainloop
* g
) {
462 free_io_events(g
->io_events
);
463 free_io_events(g
->dead_io_events
);
464 free_defer_events(g
->defer_events
);
465 free_defer_events(g
->dead_defer_events
);
466 free_time_events(g
->time_events
);
467 free_time_events(g
->dead_time_events
);
469 g_main_loop_unref(g
->glib_mainloop
);
473 struct pa_mainloop_api
* pa_glib_mainloop_get_api(struct pa_glib_mainloop
*g
) {
478 static gboolean
free_dead_events(gpointer p
) {
479 struct pa_glib_mainloop
*g
= p
;
482 free_io_events(g
->dead_io_events
);
483 free_defer_events(g
->dead_defer_events
);
484 free_time_events(g
->dead_time_events
);
486 g_source_destroy(g
->cleanup_source
);
487 g_source_unref(g
->cleanup_source
);
488 g
->cleanup_source
= NULL
;
493 static void schedule_free_dead_events(struct pa_glib_mainloop
*g
) {
494 assert(g
&& g
->glib_mainloop
);
496 if (g
->cleanup_source
)
499 g
->cleanup_source
= g_idle_source_new();
500 assert(g
->cleanup_source
);
501 g_source_set_callback(g
->cleanup_source
, free_dead_events
, g
, NULL
);
502 g_source_attach(g
->cleanup_source
, g_main_loop_get_context(g
->glib_mainloop
));