source: roaraudio/libroarpulse/mainloop.c @ 3468:c2bff8bedf7c

Last change on this file since 3468:c2bff8bedf7c was 3468:c2bff8bedf7c, checked in by phi, 14 years ago

wrote io event API

File size: 6.7 KB
Line 
1//mainloop.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
5 *  The code (may) include prototypes and comments (and maybe
6 *  other code fragements) from libpulse*. They are mostly copyrighted by:
7 *  Lennart Poettering <poettering@users.sourceforge.net> and
8 *  Pierre Ossman <drzeus@drzeus.cx>
9 *
10 *  This file is part of libroarpulse a part of RoarAudio,
11 *  a cross-platform sound system for both, home and professional use.
12 *  See README for details.
13 *
14 *  This file is free software; you can redistribute it and/or modify
15 *  it under the terms of the GNU General Public License version 3
16 *  as published by the Free Software Foundation.
17 *
18 *  RoarAudio is distributed in the hope that it will be useful,
19 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 *  GNU General Public License for more details.
22 *
23 *  You should have received a copy of the GNU General Public License
24 *  along with this software; see the file COPYING.  If not, write to
25 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26 *
27 *  NOTE for everyone want's to change something and send patches:
28 *  read README and HACKING! There a addition information on
29 *  the license of this document you need to read before you send
30 *  any patches.
31 *
32 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
33 *  or libpulse*:
34 *  The libs libroaresd, libroararts and libroarpulse link this libroar
35 *  and are therefore GPL. Because of this it may be illigal to use
36 *  them with any software that uses libesd, libartsc or libpulse*.
37 */
38
39#include <libroarpulse/libroarpulse.h>
40
41#define MAX_IO_EVENTS    8
42
43struct pa_io_event {
44 int used;
45 pa_mainloop_api *api;
46 int fd;
47 pa_io_event_flags_t events;
48 pa_io_event_cb_t cb;
49 void *userdata;
50 pa_io_event_destroy_cb_t destroy;
51};
52
53struct pa_mainloop {
54 pa_mainloop_api api;
55 pa_poll_func    poll_func;
56 void          * poll_userdata;
57 int             quit;
58 int             quitval;
59 pa_io_event     io_event[MAX_IO_EVENTS];
60};
61
62// IO EVENTS:
63static void _roar_pa_io_enable(pa_io_event* e, pa_io_event_flags_t events);
64
65/** Create a new IO event source object */
66static pa_io_event* _roar_pa_io_new(pa_mainloop_api*a, int fd,
67                                    pa_io_event_flags_t events, pa_io_event_cb_t cb, void *userdata) {
68 pa_mainloop * mainloop = a->userdata;
69 pa_io_event * ret = NULL;
70 int i;
71
72 for (i = 0; i < MAX_IO_EVENTS; i++) {
73  if ( mainloop->io_event[i].used == 0 ) {
74   ret = &(mainloop->io_event[i]);
75  }
76 }
77
78 if ( ret == NULL )
79  return NULL;
80
81 ret->used = 1;
82
83 ret->api      = a;
84 ret->fd       = fd;
85 ret->cb       = cb;
86 ret->userdata = userdata;
87
88 // Callbacks:
89 ret->destroy  = NULL;
90
91 _roar_pa_io_enable(ret, events);
92
93 return ret;
94}
95/** Enable or disable IO events on this object */
96static void _roar_pa_io_enable(pa_io_event* e, pa_io_event_flags_t events) {
97 if ( e == NULL )
98  return;
99
100 e->events = events;
101}
102
103/** Free a IO event source object */
104static void _roar_pa_io_free(pa_io_event* e) {
105 if ( e == NULL )
106  return;
107
108 if ( e->destroy != NULL )
109  e->destroy(e->api, e, e->userdata);
110
111 e->used = 0;
112}
113/** Set a function that is called when the IO event source is destroyed. Use this to free the userdata argument if required */
114static void _roar_pa_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t cb) {
115 if ( e == NULL )
116  return;
117
118 e->destroy = cb;
119}
120
121
122
123// API:
124
125/** Allocate a new main loop object */
126pa_mainloop *pa_mainloop_new(void) {
127 pa_mainloop * m = roar_mm_malloc(sizeof(pa_mainloop));
128
129 if ( m == NULL )
130  return NULL;
131
132 memset(m, 0, sizeof(pa_mainloop));
133
134 m->api.userdata       = m;
135 m->api.io_new         = _roar_pa_io_new;
136 m->api.io_enable      = _roar_pa_io_enable;
137 m->api.io_free        = _roar_pa_io_free;
138 m->api.io_set_destroy = _roar_pa_io_set_destroy;
139
140 return m;
141}
142
143/** Free a main loop object */
144void pa_mainloop_free(pa_mainloop* m) {
145 if ( m == NULL )
146  return;
147
148 roar_mm_free(m);
149}
150
151/** Prepare for a single iteration of the main loop. Returns a negative value
152on error or exit request. timeout specifies a maximum timeout for the subsequent
153poll, or -1 for blocking behaviour. .*/
154int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
155 if ( m == NULL )
156  return -1;
157
158 m->quit = 1;
159
160 if ( m->quit )
161  return -2;
162
163 return -1;
164}
165
166/** Execute the previously prepared poll. Returns a negative value on error.*/
167int pa_mainloop_poll(pa_mainloop *m) {
168 if ( m == NULL )
169  return -1;
170
171 if ( m->quit )
172  return -2;
173
174 return -1;
175}
176
177/** Dispatch timeout, io and deferred events from the previously executed poll. Returns
178a negative value on error. On success returns the number of source dispatched. */
179int pa_mainloop_dispatch(pa_mainloop *m) {
180 if ( m == NULL )
181  return -1;
182
183 if ( m->quit )
184  return -2;
185
186 return -1;
187}
188
189/** Return the return value as specified with the main loop's quit() routine. */
190int pa_mainloop_get_retval(pa_mainloop *m) {
191 if ( m == NULL )
192  return -1;
193
194 return m->quitval;
195}
196
197/** Run a single iteration of the main loop. This is a convenience function
198for pa_mainloop_prepare(), pa_mainloop_poll() and pa_mainloop_dispatch().
199Returns a negative value on error or exit request. If block is nonzero,
200block for events if none are queued. Optionally return the return value as
201specified with the main loop's quit() routine in the integer variable retval points
202to. On success returns the number of sources dispatched in this iteration. */
203int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) {
204 int r;
205
206 if ( m == NULL )
207  return -1;
208
209 r = pa_mainloop_prepare(m, block ? -1 : 0);
210
211 if ( r > 0 )
212  r = pa_mainloop_poll(m);
213
214 if ( r > 0 )
215  r = pa_mainloop_dispatch(m);
216
217 if ( r == -2 && retval != NULL ) {
218  *retval = m->quitval;
219 }
220
221 return r;
222}
223
224/** Run unlimited iterations of the main loop object until the main loop's quit() routine is called. */
225int pa_mainloop_run(pa_mainloop *m, int *retval) {
226 int r = 1;
227
228 if ( m == NULL )
229  return -1;
230
231 while (!(m->quit) && r > 0) {
232  r = pa_mainloop_iterate(m, 1, retval);
233 }
234
235 if ( r == -2 )
236  return 1;
237
238 if ( r < 0 )
239  return -1;
240
241 return 0;
242}
243
244/** Return the abstract main loop abstraction layer vtable for this main loop. */
245pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) {
246 if ( m == NULL )
247  return NULL;
248
249 return &(m->api);
250}
251
252/** Shutdown the main loop */
253void pa_mainloop_quit(pa_mainloop *m, int r) {
254 if ( m == NULL )
255  return;
256
257 m->quitval = r;
258 m->quit    = 1;
259}
260
261/** Interrupt a running poll (for threaded systems) */
262void pa_mainloop_wakeup(pa_mainloop *m);
263
264/** Change the poll() implementation */
265void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
266 if ( m == NULL )
267  return;
268
269 m->poll_func     = poll_func;
270 m->poll_userdata = userdata;
271}
272
273//ll
Note: See TracBrowser for help on using the repository browser.