]> code.delx.au - pulseaudio/blob - src/pulsecore/hook-list.c
4f8841876e44be5bdf550d6afbfc1eb79fe6a577
[pulseaudio] / src / pulsecore / hook-list.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2006 Lennart Poettering
7
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 USA.
22 ***/
23
24 #include <pulsecore/hook-list.h>
25
26 void pa_hook_init(pa_hook *hook, void *data) {
27 assert(hook);
28
29 PA_LLIST_HEAD_INIT(pa_hook_slot, hook->slots);
30 hook->last = NULL;
31 hook->n_dead = hook->firing = 0;
32 hook->data = data;
33 }
34
35 static void slot_free(pa_hook *hook, pa_hook_slot *slot) {
36 assert(hook);
37 assert(slot);
38
39 if (hook->last == slot)
40 hook->last = slot->prev;
41
42 PA_LLIST_REMOVE(pa_hook_slot, hook->slots, slot);
43
44 pa_xfree(slot);
45 }
46
47 void pa_hook_free(pa_hook *hook) {
48 assert(hook);
49 assert(!hook->firing);
50
51 while (hook->slots)
52 slot_free(hook, hook->slots);
53
54 pa_hook_init(hook, NULL);
55 }
56
57 pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *data) {
58 pa_hook_slot *slot;
59
60 assert(cb);
61
62 slot = pa_xnew(pa_hook_slot, 1);
63 slot->hook = hook;
64 slot->dead = 0;
65 slot->callback = cb;
66 slot->data = data;
67
68 PA_LLIST_INSERT_AFTER(pa_hook_slot, hook->slots, hook->last, slot);
69 hook->last = slot;
70
71 return slot;
72 }
73
74 void pa_hook_slot_free(pa_hook_slot *slot) {
75 assert(slot);
76 assert(!slot->dead);
77
78 if (slot->hook->firing > 0) {
79 slot->dead = 1;
80 slot->hook->n_dead++;
81 } else
82 slot_free(slot->hook, slot);
83 }
84
85 pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data) {
86 pa_hook_slot *slot, *next;
87 pa_hook_result_t result = PA_HOOK_OK;
88
89 assert(hook);
90
91 hook->firing ++;
92
93 for (slot = hook->slots; slot; slot = slot->next) {
94 if (slot->dead)
95 continue;
96
97 if ((result = slot->callback(hook->data, data, slot->data)) != PA_HOOK_OK)
98 break;
99 }
100
101 hook->firing --;
102
103 for (slot = hook->slots; hook->n_dead > 0 && slot; slot = next) {
104 next = slot->next;
105
106 if (slot->dead) {
107 slot_free(hook, slot);
108 hook->n_dead--;
109 }
110 }
111
112 return result;
113 }
114