Branch data Line data Source code
1 : : /***
2 : : This file is part of PulseAudio.
3 : :
4 : : Copyright 2004-2006 Lennart Poettering
5 : :
6 : : PulseAudio 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.1 of the License,
9 : : or (at your option) any later version.
10 : :
11 : : PulseAudio 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 Lesser General Public License
17 : : along with PulseAudio; 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 <pulse/xmalloc.h>
27 : : #include <pulse/timeval.h>
28 : :
29 : : #include <pulsecore/core-util.h>
30 : : #include <pulsecore/log.h>
31 : : #include <pulsecore/llist.h>
32 : :
33 : : #include <glib.h>
34 : : #include "glib-mainloop.h"
35 : :
36 : : struct pa_io_event {
37 : : pa_glib_mainloop *mainloop;
38 : : int dead;
39 : :
40 : : GPollFD poll_fd;
41 : : int poll_fd_added;
42 : :
43 : : pa_io_event_cb_t callback;
44 : : void *userdata;
45 : : pa_io_event_destroy_cb_t destroy_callback;
46 : :
47 : : PA_LLIST_FIELDS(pa_io_event);
48 : : };
49 : :
50 : : struct pa_time_event {
51 : : pa_glib_mainloop *mainloop;
52 : : int dead;
53 : :
54 : : int enabled;
55 : : struct timeval timeval;
56 : :
57 : : pa_time_event_cb_t callback;
58 : : void *userdata;
59 : : pa_time_event_destroy_cb_t destroy_callback;
60 : :
61 : : PA_LLIST_FIELDS(pa_time_event);
62 : : };
63 : :
64 : : struct pa_defer_event {
65 : : pa_glib_mainloop *mainloop;
66 : : int dead;
67 : :
68 : : int enabled;
69 : :
70 : : pa_defer_event_cb_t callback;
71 : : void *userdata;
72 : : pa_defer_event_destroy_cb_t destroy_callback;
73 : :
74 : : PA_LLIST_FIELDS(pa_defer_event);
75 : : };
76 : :
77 : : struct pa_glib_mainloop {
78 : : GSource source;
79 : :
80 : : pa_mainloop_api api;
81 : : GMainContext *context;
82 : :
83 : : PA_LLIST_HEAD(pa_io_event, io_events);
84 : : PA_LLIST_HEAD(pa_time_event, time_events);
85 : : PA_LLIST_HEAD(pa_defer_event, defer_events);
86 : :
87 : : int n_enabled_defer_events, n_enabled_time_events;
88 : : int io_events_please_scan, time_events_please_scan, defer_events_please_scan;
89 : :
90 : : pa_time_event *cached_next_time_event;
91 : : };
92 : :
93 : 1 : static void cleanup_io_events(pa_glib_mainloop *g, int force) {
94 : : pa_io_event *e;
95 : :
96 : 1 : e = g->io_events;
97 [ + + ]: 2 : while (e) {
98 : 1 : pa_io_event *n = e->next;
99 : :
100 [ - + ][ # # ]: 1 : if (!force && g->io_events_please_scan <= 0)
101 : : break;
102 : :
103 [ - + ][ # # ]: 1 : if (force || e->dead) {
104 [ - + ][ - + ]: 1 : PA_LLIST_REMOVE(pa_io_event, g->io_events, e);
[ - + ][ - + ]
105 : :
106 [ + - ]: 1 : if (e->dead) {
107 [ - + ][ - + ]: 1 : g_assert(g->io_events_please_scan > 0);
108 : 1 : g->io_events_please_scan--;
109 : : }
110 : :
111 [ - + ]: 1 : if (e->poll_fd_added)
112 : 0 : g_source_remove_poll(&g->source, &e->poll_fd);
113 : :
114 [ - + ]: 1 : if (e->destroy_callback)
115 : 0 : e->destroy_callback(&g->api, e, e->userdata);
116 : :
117 : 1 : pa_xfree(e);
118 : : }
119 : :
120 : 1 : e = n;
121 : : }
122 : :
123 [ - + ][ - + ]: 1 : g_assert(g->io_events_please_scan == 0);
124 : 1 : }
125 : :
126 : 1 : static void cleanup_time_events(pa_glib_mainloop *g, int force) {
127 : : pa_time_event *e;
128 : :
129 : 1 : e = g->time_events;
130 [ + + ]: 2 : while (e) {
131 : 1 : pa_time_event *n = e->next;
132 : :
133 [ - + ][ # # ]: 1 : if (!force && g->time_events_please_scan <= 0)
134 : : break;
135 : :
136 [ - + ][ # # ]: 1 : if (force || e->dead) {
137 [ - + ][ - + ]: 1 : PA_LLIST_REMOVE(pa_time_event, g->time_events, e);
[ - + ][ - + ]
138 : :
139 [ + - ]: 1 : if (e->dead) {
140 [ - + ][ - + ]: 1 : g_assert(g->time_events_please_scan > 0);
141 : 1 : g->time_events_please_scan--;
142 : : }
143 : :
144 [ - + ][ # # ]: 1 : if (!e->dead && e->enabled) {
145 [ # # ][ # # ]: 0 : g_assert(g->n_enabled_time_events > 0);
146 : 0 : g->n_enabled_time_events--;
147 : : }
148 : :
149 [ - + ]: 1 : if (e->destroy_callback)
150 : 0 : e->destroy_callback(&g->api, e, e->userdata);
151 : :
152 : 1 : pa_xfree(e);
153 : : }
154 : :
155 : 1 : e = n;
156 : : }
157 : :
158 [ - + ][ - + ]: 1 : g_assert(g->time_events_please_scan == 0);
159 : 1 : }
160 : :
161 : 1 : static void cleanup_defer_events(pa_glib_mainloop *g, int force) {
162 : : pa_defer_event *e;
163 : :
164 : 1 : e = g->defer_events;
165 [ + + ]: 2 : while (e) {
166 : 1 : pa_defer_event *n = e->next;
167 : :
168 [ - + ][ # # ]: 1 : if (!force && g->defer_events_please_scan <= 0)
169 : : break;
170 : :
171 [ - + ][ # # ]: 1 : if (force || e->dead) {
172 [ - + ][ - + ]: 1 : PA_LLIST_REMOVE(pa_defer_event, g->defer_events, e);
[ - + ][ - + ]
173 : :
174 [ + - ]: 1 : if (e->dead) {
175 [ - + ][ - + ]: 1 : g_assert(g->defer_events_please_scan > 0);
176 : 1 : g->defer_events_please_scan--;
177 : : }
178 : :
179 [ - + ][ # # ]: 1 : if (!e->dead && e->enabled) {
180 [ # # ][ # # ]: 0 : g_assert(g->n_enabled_defer_events > 0);
181 : 0 : g->n_enabled_defer_events--;
182 : : }
183 : :
184 [ - + ]: 1 : if (e->destroy_callback)
185 : 0 : e->destroy_callback(&g->api, e, e->userdata);
186 : :
187 : 1 : pa_xfree(e);
188 : : }
189 : :
190 : 1 : e = n;
191 : : }
192 : :
193 [ - + ][ - + ]: 1 : g_assert(g->defer_events_please_scan == 0);
194 : 1 : }
195 : :
196 : : static gushort map_flags_to_glib(pa_io_event_flags_t flags) {
197 [ # # ][ # # ]: 1 : return (gushort)
[ # # ][ - + ]
[ + - ][ + - ]
198 : 1 : ((flags & PA_IO_EVENT_INPUT ? G_IO_IN : 0) |
199 : 1 : (flags & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) |
200 : : (flags & PA_IO_EVENT_ERROR ? G_IO_ERR : 0) |
201 : 1 : (flags & PA_IO_EVENT_HANGUP ? G_IO_HUP : 0));
202 : : }
203 : :
204 : : static pa_io_event_flags_t map_flags_from_glib(gushort flags) {
205 : 0 : return
206 : 0 : (flags & G_IO_IN ? PA_IO_EVENT_INPUT : 0) |
207 [ # # ]: 0 : (flags & G_IO_OUT ? PA_IO_EVENT_OUTPUT : 0) |
208 : 0 : (flags & G_IO_ERR ? PA_IO_EVENT_ERROR : 0) |
209 [ # # ]: 0 : (flags & G_IO_HUP ? PA_IO_EVENT_HANGUP : 0);
210 : : }
211 : :
212 : 1 : static pa_io_event* glib_io_new(
213 : : pa_mainloop_api*m,
214 : : int fd,
215 : : pa_io_event_flags_t f,
216 : : pa_io_event_cb_t cb,
217 : : void *userdata) {
218 : :
219 : : pa_io_event *e;
220 : : pa_glib_mainloop *g;
221 : :
222 [ - + ][ - + ]: 1 : g_assert(m);
223 [ - + ][ - + ]: 1 : g_assert(m->userdata);
224 [ - + ][ - + ]: 1 : g_assert(fd >= 0);
225 [ - + ][ - + ]: 1 : g_assert(cb);
226 : :
227 : 1 : g = m->userdata;
228 : :
229 : 1 : e = pa_xnew(pa_io_event, 1);
230 : 1 : e->mainloop = g;
231 : 1 : e->dead = 0;
232 : :
233 : 1 : e->poll_fd.fd = fd;
234 : 1 : e->poll_fd.events = map_flags_to_glib(f);
235 : 1 : e->poll_fd.revents = 0;
236 : :
237 : 1 : e->callback = cb;
238 : 1 : e->userdata = userdata;
239 : 1 : e->destroy_callback = NULL;
240 : :
241 [ - + ][ - + ]: 1 : PA_LLIST_PREPEND(pa_io_event, g->io_events, e);
242 : :
243 : 1 : g_source_add_poll(&g->source, &e->poll_fd);
244 : 1 : e->poll_fd_added = 1;
245 : :
246 : 1 : return e;
247 : : }
248 : :
249 : 0 : static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) {
250 [ # # ][ # # ]: 0 : g_assert(e);
251 [ # # ][ # # ]: 0 : g_assert(!e->dead);
252 : :
253 : 0 : e->poll_fd.events = map_flags_to_glib(f);
254 : 0 : }
255 : :
256 : 1 : static void glib_io_free(pa_io_event*e) {
257 [ - + ][ - + ]: 1 : g_assert(e);
258 [ - + ][ - + ]: 1 : g_assert(!e->dead);
259 : :
260 : 1 : e->dead = 1;
261 : 1 : e->mainloop->io_events_please_scan++;
262 : :
263 [ + - ]: 1 : if (e->poll_fd_added) {
264 : 1 : g_source_remove_poll(&e->mainloop->source, &e->poll_fd);
265 : 1 : e->poll_fd_added = 0;
266 : : }
267 : 1 : }
268 : :
269 : 0 : static void glib_io_set_destroy(pa_io_event*e, pa_io_event_destroy_cb_t cb) {
270 [ # # ][ # # ]: 0 : g_assert(e);
271 [ # # ][ # # ]: 0 : g_assert(!e->dead);
272 : :
273 : 0 : e->destroy_callback = cb;
274 : 0 : }
275 : :
276 : : /* Time sources */
277 : :
278 : 1 : static pa_time_event* glib_time_new(
279 : : pa_mainloop_api*m,
280 : : const struct timeval *tv,
281 : : pa_time_event_cb_t cb,
282 : : void *userdata) {
283 : :
284 : : pa_glib_mainloop *g;
285 : : pa_time_event *e;
286 : :
287 [ - + ][ - + ]: 1 : g_assert(m);
288 [ - + ][ - + ]: 1 : g_assert(m->userdata);
289 [ - + ][ - + ]: 1 : g_assert(cb);
290 : :
291 : 1 : g = m->userdata;
292 : :
293 : 1 : e = pa_xnew(pa_time_event, 1);
294 : 1 : e->mainloop = g;
295 : 1 : e->dead = 0;
296 : :
297 [ + - ]: 1 : if ((e->enabled = !!tv)) {
298 : 1 : e->timeval = *tv;
299 : 1 : g->n_enabled_time_events++;
300 : :
301 [ - + ]: 1 : if (g->cached_next_time_event) {
302 [ # # ][ # # ]: 0 : g_assert(g->cached_next_time_event->enabled);
303 : :
304 [ # # ]: 0 : if (pa_timeval_cmp(tv, &g->cached_next_time_event->timeval) < 0)
305 : 0 : g->cached_next_time_event = e;
306 : : }
307 : : }
308 : :
309 : 1 : e->callback = cb;
310 : 1 : e->userdata = userdata;
311 : 1 : e->destroy_callback = NULL;
312 : :
313 [ - + ][ - + ]: 1 : PA_LLIST_PREPEND(pa_time_event, g->time_events, e);
314 : :
315 : 1 : return e;
316 : : }
317 : :
318 : 1 : static void glib_time_restart(pa_time_event*e, const struct timeval *tv) {
319 [ - + ][ - + ]: 1 : g_assert(e);
320 [ - + ][ - + ]: 1 : g_assert(!e->dead);
321 : :
322 [ + - ]: 1 : if (e->enabled && !tv) {
323 [ - + ][ - + ]: 1 : g_assert(e->mainloop->n_enabled_time_events > 0);
324 : 1 : e->mainloop->n_enabled_time_events--;
325 [ # # ]: 0 : } else if (!e->enabled && tv)
326 : 0 : e->mainloop->n_enabled_time_events++;
327 : :
328 [ - + ]: 1 : if ((e->enabled = !!tv))
329 : 0 : e->timeval = *tv;
330 : :
331 [ + - ][ - + ]: 1 : if (e->mainloop->cached_next_time_event && e->enabled) {
332 [ # # ][ # # ]: 0 : g_assert(e->mainloop->cached_next_time_event->enabled);
333 : :
334 [ # # ]: 0 : if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0)
335 : 0 : e->mainloop->cached_next_time_event = e;
336 [ + - ]: 1 : } else if (e->mainloop->cached_next_time_event == e)
337 : 1 : e->mainloop->cached_next_time_event = NULL;
338 : 1 : }
339 : :
340 : 1 : static void glib_time_free(pa_time_event *e) {
341 [ - + ][ - + ]: 1 : g_assert(e);
342 [ - + ][ - + ]: 1 : g_assert(!e->dead);
343 : :
344 : 1 : e->dead = 1;
345 : 1 : e->mainloop->time_events_please_scan++;
346 : :
347 [ - + ]: 1 : if (e->enabled)
348 : 0 : e->mainloop->n_enabled_time_events--;
349 : :
350 [ - + ]: 1 : if (e->mainloop->cached_next_time_event == e)
351 : 0 : e->mainloop->cached_next_time_event = NULL;
352 : 1 : }
353 : :
354 : 0 : static void glib_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t cb) {
355 [ # # ][ # # ]: 0 : g_assert(e);
356 [ # # ][ # # ]: 0 : g_assert(!e->dead);
357 : :
358 : 0 : e->destroy_callback = cb;
359 : 0 : }
360 : :
361 : : /* Deferred sources */
362 : :
363 : 1 : static pa_defer_event* glib_defer_new(
364 : : pa_mainloop_api*m,
365 : : pa_defer_event_cb_t cb,
366 : : void *userdata) {
367 : :
368 : : pa_defer_event *e;
369 : : pa_glib_mainloop *g;
370 : :
371 [ - + ][ - + ]: 1 : g_assert(m);
372 [ - + ][ - + ]: 1 : g_assert(m->userdata);
373 [ - + ][ - + ]: 1 : g_assert(cb);
374 : :
375 : 1 : g = m->userdata;
376 : :
377 : 1 : e = pa_xnew(pa_defer_event, 1);
378 : 1 : e->mainloop = g;
379 : 1 : e->dead = 0;
380 : :
381 : 1 : e->enabled = 1;
382 : 1 : g->n_enabled_defer_events++;
383 : :
384 : 1 : e->callback = cb;
385 : 1 : e->userdata = userdata;
386 : 1 : e->destroy_callback = NULL;
387 : :
388 [ - + ][ - + ]: 1 : PA_LLIST_PREPEND(pa_defer_event, g->defer_events, e);
389 : 1 : return e;
390 : : }
391 : :
392 : 1 : static void glib_defer_enable(pa_defer_event *e, int b) {
393 [ - + ][ - + ]: 1 : g_assert(e);
394 [ - + ][ - + ]: 1 : g_assert(!e->dead);
395 : :
396 [ + - ]: 1 : if (e->enabled && !b) {
397 [ - + ][ - + ]: 1 : g_assert(e->mainloop->n_enabled_defer_events > 0);
398 : 1 : e->mainloop->n_enabled_defer_events--;
399 [ # # ]: 0 : } else if (!e->enabled && b)
400 : 0 : e->mainloop->n_enabled_defer_events++;
401 : :
402 : 1 : e->enabled = b;
403 : 1 : }
404 : :
405 : 1 : static void glib_defer_free(pa_defer_event *e) {
406 [ - + ][ - + ]: 1 : g_assert(e);
407 [ - + ][ - + ]: 1 : g_assert(!e->dead);
408 : :
409 : 1 : e->dead = 1;
410 : 1 : e->mainloop->defer_events_please_scan++;
411 : :
412 [ - + ]: 1 : if (e->enabled) {
413 [ # # ][ # # ]: 0 : g_assert(e->mainloop->n_enabled_defer_events > 0);
414 : 0 : e->mainloop->n_enabled_defer_events--;
415 : : }
416 : 1 : }
417 : :
418 : 0 : static void glib_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t cb) {
419 [ # # ][ # # ]: 0 : g_assert(e);
420 [ # # ][ # # ]: 0 : g_assert(!e->dead);
421 : :
422 : 0 : e->destroy_callback = cb;
423 : 0 : }
424 : :
425 : : /* quit() */
426 : :
427 : 0 : static void glib_quit(pa_mainloop_api*a, int retval) {
428 : :
429 : 0 : g_warning("quit() ignored");
430 : :
431 : : /* NOOP */
432 : 0 : }
433 : :
434 : 2 : static pa_time_event* find_next_time_event(pa_glib_mainloop *g) {
435 : 2 : pa_time_event *t, *n = NULL;
436 [ - + ][ - + ]: 2 : g_assert(g);
437 : :
438 [ + + ]: 2 : if (g->cached_next_time_event)
439 : 1 : return g->cached_next_time_event;
440 : :
441 [ + + ]: 2 : for (t = g->time_events; t; t = t->next) {
442 : :
443 [ + - ][ - + ]: 1 : if (t->dead || !t->enabled)
444 : 0 : continue;
445 : :
446 [ - + ][ # # ]: 1 : if (!n || pa_timeval_cmp(&t->timeval, &n->timeval) < 0) {
447 : 1 : n = t;
448 : :
449 : : /* Shortcut for tv = { 0, 0 } */
450 [ + - ]: 1 : if (n->timeval.tv_sec <= 0)
451 : : break;
452 : : }
453 : : }
454 : :
455 : 1 : g->cached_next_time_event = n;
456 : 2 : return n;
457 : : }
458 : :
459 : : static void scan_dead(pa_glib_mainloop *g) {
460 [ - + ][ - + ]: 2 : g_assert(g);
461 : :
462 [ - + ]: 2 : if (g->io_events_please_scan)
463 : 0 : cleanup_io_events(g, 0);
464 : :
465 [ - + ]: 2 : if (g->time_events_please_scan)
466 : 0 : cleanup_time_events(g, 0);
467 : :
468 [ - + ]: 2 : if (g->defer_events_please_scan)
469 : 0 : cleanup_defer_events(g, 0);
470 : : }
471 : :
472 : 2 : static gboolean prepare_func(GSource *source, gint *timeout) {
473 : 2 : pa_glib_mainloop *g = (pa_glib_mainloop*) source;
474 : :
475 [ - + ][ - + ]: 2 : g_assert(g);
476 [ - + ][ - + ]: 2 : g_assert(timeout);
477 : :
478 : : scan_dead(g);
479 : :
480 [ + + ]: 2 : if (g->n_enabled_defer_events) {
481 : 1 : *timeout = 0;
482 : 1 : return TRUE;
483 [ + - ]: 1 : } else if (g->n_enabled_time_events) {
484 : : pa_time_event *t;
485 : : GTimeVal now;
486 : : struct timeval tvnow;
487 : : pa_usec_t usec;
488 : :
489 : 1 : t = find_next_time_event(g);
490 [ - + ][ - + ]: 1 : g_assert(t);
491 : :
492 : 1 : g_get_current_time(&now);
493 : 1 : tvnow.tv_sec = now.tv_sec;
494 : 1 : tvnow.tv_usec = now.tv_usec;
495 : :
496 [ + - ]: 1 : if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) {
497 : 1 : *timeout = 0;
498 : 1 : return TRUE;
499 : : }
500 : 0 : usec = pa_timeval_diff(&t->timeval, &tvnow);
501 : 0 : *timeout = (gint) (usec / 1000);
502 : : } else
503 : 2 : *timeout = -1;
504 : :
505 : : return FALSE;
506 : : }
507 : 0 : static gboolean check_func(GSource *source) {
508 : 0 : pa_glib_mainloop *g = (pa_glib_mainloop*) source;
509 : : pa_io_event *e;
510 : :
511 [ # # ][ # # ]: 0 : g_assert(g);
512 : :
513 [ # # ]: 0 : if (g->n_enabled_defer_events)
514 : : return TRUE;
515 [ # # ]: 0 : else if (g->n_enabled_time_events) {
516 : : pa_time_event *t;
517 : : GTimeVal now;
518 : : struct timeval tvnow;
519 : :
520 : 0 : t = find_next_time_event(g);
521 [ # # ][ # # ]: 0 : g_assert(t);
522 : :
523 : 0 : g_get_current_time(&now);
524 : 0 : tvnow.tv_sec = now.tv_sec;
525 : 0 : tvnow.tv_usec = now.tv_usec;
526 : :
527 [ # # ]: 0 : if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0)
528 : : return TRUE;
529 : : }
530 : :
531 [ # # ]: 0 : for (e = g->io_events; e; e = e->next)
532 [ # # ][ # # ]: 0 : if (!e->dead && e->poll_fd.revents != 0)
533 : : return TRUE;
534 : :
535 : : return FALSE;
536 : : }
537 : :
538 : 2 : static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer userdata) {
539 : 2 : pa_glib_mainloop *g = (pa_glib_mainloop*) source;
540 : : pa_io_event *e;
541 : :
542 [ - + ][ - + ]: 2 : g_assert(g);
543 : :
544 [ + + ]: 2 : if (g->n_enabled_defer_events) {
545 : : pa_defer_event *d;
546 : :
547 [ + - ]: 1 : for (d = g->defer_events; d; d = d->next) {
548 [ + - ][ - + ]: 1 : if (d->dead || !d->enabled)
549 : 0 : continue;
550 : :
551 : : break;
552 : : }
553 : :
554 [ - + ][ - + ]: 1 : g_assert(d);
555 : :
556 : 1 : d->callback(&g->api, d, d->userdata);
557 : 1 : return TRUE;
558 : : }
559 : :
560 [ + - ]: 1 : if (g->n_enabled_time_events) {
561 : : GTimeVal now;
562 : : struct timeval tvnow;
563 : : pa_time_event *t;
564 : :
565 : 1 : t = find_next_time_event(g);
566 [ - + ][ - + ]: 1 : g_assert(t);
567 : :
568 : 1 : g_get_current_time(&now);
569 : 1 : tvnow.tv_sec = now.tv_sec;
570 : 1 : tvnow.tv_usec = now.tv_usec;
571 : :
572 [ + - ]: 1 : if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) {
573 : :
574 : : /* Disable time event */
575 : 1 : glib_time_restart(t, NULL);
576 : :
577 : 1 : t->callback(&g->api, t, &t->timeval, t->userdata);
578 : 1 : return TRUE;
579 : : }
580 : : }
581 : :
582 [ # # ]: 2 : for (e = g->io_events; e; e = e->next)
583 [ # # ][ # # ]: 0 : if (!e->dead && e->poll_fd.revents != 0) {
584 : 0 : e->callback(&g->api, e, e->poll_fd.fd, map_flags_from_glib(e->poll_fd.revents), e->userdata);
585 : 0 : e->poll_fd.revents = 0;
586 : 0 : return TRUE;
587 : : }
588 : :
589 : : return FALSE;
590 : : }
591 : :
592 : : static const pa_mainloop_api vtable = {
593 : : .userdata = NULL,
594 : :
595 : : .io_new = glib_io_new,
596 : : .io_enable = glib_io_enable,
597 : : .io_free = glib_io_free,
598 : : .io_set_destroy= glib_io_set_destroy,
599 : :
600 : : .time_new = glib_time_new,
601 : : .time_restart = glib_time_restart,
602 : : .time_free = glib_time_free,
603 : : .time_set_destroy = glib_time_set_destroy,
604 : :
605 : : .defer_new = glib_defer_new,
606 : : .defer_enable = glib_defer_enable,
607 : : .defer_free = glib_defer_free,
608 : : .defer_set_destroy = glib_defer_set_destroy,
609 : :
610 : : .quit = glib_quit,
611 : : };
612 : :
613 : 1 : pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) {
614 : : pa_glib_mainloop *g;
615 : :
616 : : static GSourceFuncs source_funcs = {
617 : : prepare_func,
618 : : check_func,
619 : : dispatch_func,
620 : : NULL,
621 : : NULL,
622 : : NULL
623 : : };
624 : :
625 : 1 : g = (pa_glib_mainloop*) g_source_new(&source_funcs, sizeof(pa_glib_mainloop));
626 [ + - ]: 1 : g_main_context_ref(g->context = c ? c : g_main_context_default());
627 : :
628 : 1 : g->api = vtable;
629 : 1 : g->api.userdata = g;
630 : :
631 : 1 : PA_LLIST_HEAD_INIT(pa_io_event, g->io_events);
632 : 1 : PA_LLIST_HEAD_INIT(pa_time_event, g->time_events);
633 : 1 : PA_LLIST_HEAD_INIT(pa_defer_event, g->defer_events);
634 : :
635 : 1 : g->n_enabled_defer_events = g->n_enabled_time_events = 0;
636 : 1 : g->io_events_please_scan = g->time_events_please_scan = g->defer_events_please_scan = 0;
637 : :
638 : 1 : g->cached_next_time_event = NULL;
639 : :
640 : 1 : g_source_attach(&g->source, g->context);
641 : 1 : g_source_set_can_recurse(&g->source, FALSE);
642 : :
643 : 1 : return g;
644 : : }
645 : :
646 : 1 : void pa_glib_mainloop_free(pa_glib_mainloop* g) {
647 [ - + ][ - + ]: 1 : g_assert(g);
648 : :
649 : 1 : cleanup_io_events(g, 1);
650 : 1 : cleanup_defer_events(g, 1);
651 : 1 : cleanup_time_events(g, 1);
652 : :
653 : 1 : g_main_context_unref(g->context);
654 : 1 : g_source_destroy(&g->source);
655 : 1 : g_source_unref(&g->source);
656 : 1 : }
657 : :
658 : 1 : pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g) {
659 [ - + ][ - + ]: 1 : g_assert(g);
660 : :
661 : 1 : return &g->api;
662 : : }
|