source: roaraudio/libroar/notify.c @ 4305:214fe3e67d09

Last change on this file since 4305:214fe3e67d09 was 4305:214fe3e67d09, checked in by phi, 14 years ago

implemented most of the notify logic

File size: 5.7 KB
Line 
1//notify.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38struct roar_subscriber {
39 uint32_t flags;
40 uint32_t event;
41 int emitter;
42 int target;
43 int target_type;
44 void (*cb)(struct roar_event * event, void * userdata);
45 void * userdata;
46 size_t refc;
47 unsigned int hash;
48// struct roar_subscriber * prev;
49 struct roar_subscriber * next;
50};
51
52struct roar_notify_core {
53 size_t refc;
54 size_t listc;
55 struct roar_subscriber ** lists;
56};
57
58#define _CKRCORE(ret) if ( core == NULL ) { roar_errno = ROAR_ERROR_INVAL; return (ret); }
59#define _CKICORE() _CKRCORE(-1)
60
61static unsigned int _hash_event (struct roar_notify_core * core, struct roar_event * event) {
62 unsigned int hash = 0;
63 unsigned int mask = core->listc - 1;
64
65 hash ^= event->event >>  0;
66 hash ^= event->event >>  8;
67 hash ^= event->event >> 16;
68 hash ^= event->event >> 24;
69
70 return hash & mask;
71}
72
73struct roar_notify_core * roar_notify_core_new(ssize_t lists) {
74 struct roar_notify_core * core = NULL;
75
76 switch (lists) {
77  case   1:
78  case   2:
79  case   4:
80  case   8:
81  case  16:
82  case  32:
83  case  64:
84  case 128:
85  case 256:
86    // they all are ok.
87   break;
88  case  -1:
89    // handle defult:
90    lists = 16;
91   break;
92  default:
93    roar_errno = ROAR_ERROR_INVAL;
94    return NULL;
95   break;
96 }
97
98 if ( (core = roar_mm_malloc(sizeof(struct roar_notify_core))) == NULL ) {
99  return NULL;
100 }
101
102 memset(core, 0, sizeof(struct roar_notify_core));
103
104 core->refc  = 1;
105 core->listc = lists;
106 core->lists = roar_mm_malloc(lists*sizeof(struct roar_subscriber *));
107
108 if ( core->lists == NULL ) {
109  roar_mm_free(core);
110  return NULL;
111 }
112
113 return core;
114}
115
116int roar_notify_core_ref(struct roar_notify_core * core) {
117 _CKICORE();
118
119 core->refc++;
120
121 return 0;
122}
123
124int roar_notify_core_unref(struct roar_notify_core * core) {
125 struct roar_subscriber * cur, * next;
126 size_t i;
127
128 _CKICORE();
129
130 if ( core->refc == 0 ) {
131  ROAR_ERR("roar_notify_core_unref(core=%p): refc is zero, must be greater zero. resolving by setting to one.", core);
132  core->refc = 1;
133 }
134
135 core->refc--;
136
137 if ( core->refc > 0 ) {
138  return 0;
139 }
140
141 for (i = 0; i < core->listc; i++) {
142  cur = core->lists[i];
143  while (cur != NULL) {
144   next = cur->next;
145
146   roar_mm_free(cur);
147
148   cur = next;
149  }
150 }
151
152 roar_mm_free(core->lists);
153 roar_mm_free(core);
154 return 0;
155}
156
157struct roar_subscriber * roar_notify_core_subscribe(struct roar_notify_core * core, struct roar_event * event, void (*cb)(struct roar_event * event, void * userdata), void * userdata) {
158 struct roar_subscriber * subs = NULL;
159 struct roar_subscriber * cur, * old;
160
161 _CKRCORE(NULL);
162
163 if ( event == NULL || cb == NULL ) {
164  roar_errno = ROAR_ERROR_INVAL;
165  return NULL;
166 }
167
168 if ( (subs = roar_mm_malloc(sizeof(struct roar_subscriber))) == NULL ) {
169  return NULL;
170 }
171
172 memset(subs, 0, sizeof(struct roar_subscriber));
173
174 subs->flags       = 0;
175 subs->event       = event->event;
176 subs->emitter     = event->emitter;
177 subs->target      = event->target;
178 subs->target_type = event->target_type;
179 subs->cb          = cb;
180 subs->userdata    = userdata;
181 subs->refc        = 1;
182 subs->hash        = _hash_event(core, event);
183 subs->next        = NULL;
184
185 if ( (cur = core->lists[subs->hash]) == NULL ) {
186  core->lists[subs->hash] = subs;
187 } else {
188  old = cur;
189  while (cur != NULL) {
190   old = cur;
191   cur = cur->next;
192  }
193
194  old->next = subs;
195 }
196
197 return subs;
198}
199
200int roar_notify_core_unsubscribe(struct roar_notify_core * core, struct roar_subscriber * subscriber) {
201 struct roar_subscriber * cur, * old;
202
203 _CKICORE();
204
205 if ( subscriber ) {
206  roar_errno = ROAR_ERROR_INVAL;
207  return -1;
208 }
209
210 if ( (cur = core->lists[subscriber->hash]) == subscriber ) {
211  core->lists[subscriber->hash] = core->lists[subscriber->hash]->next;
212 } else {
213  old = NULL;
214  while (cur != NULL && cur != subscriber ) {
215   old = cur;
216   cur = cur->next;
217  }
218
219  if ( cur != subscriber )
220   return -1;
221
222  old->next = cur->next;
223  roar_mm_free(cur);
224 }
225
226 return 0;
227}
228
229int roar_notify_core_emit(struct roar_notify_core * core, struct roar_event * event) {
230 struct roar_subscriber * cur;
231
232 _CKICORE();
233
234 if ( event ) {
235  roar_errno = ROAR_ERROR_INVAL;
236  return -1;
237 }
238
239 cur = core->lists[_hash_event(core, event)];
240
241 while (cur != NULL) {
242  if ( cur->cb == NULL ) {
243   ROAR_ERR("roar_notify_core_emit(core=%p, event=%p): cur=%p, cb is set NULL, bad.", core, event, cur);
244  } else {
245   cur->cb(event, cur->userdata);
246  }
247  cur = cur->next;
248 }
249
250 return 0;
251}
252
253//ll
Note: See TracBrowser for help on using the repository browser.