Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/openal-0.0.8/src/al_bpool.c @ 17

Last change on this file since 17 was 17, checked in by landauf, 16 years ago

added openal

File size: 6.4 KB
Line 
1#include "al_siteconfig.h"
2
3#include <stdlib.h>
4
5#include "al_bpool.h"
6#include "al_debug.h"
7
8#include "alc/alc_context.h"
9#include "alc/alc_speaker.h"
10
11#define AL_FIRST_BUFFER_ID  0x8000
12#define MINBUFFERS          20
13
14#ifndef elementsof
15#define elementsof(a) ((sizeof(a)) / (sizeof *(a)))
16#endif
17
18/*
19 * _alBufferInit( AL_buffer *buf, ALuint bid )
20 *
21 * Initializes AL_buffer *buf to defaults, set its id to bid.
22 */
23static void _alBufferInit( AL_buffer *buf, ALuint bid );
24
25/*
26 * bpool_resize( bpool_t *bpool, size_t newsize )
27 *
28 * increase size of buffer pool object (bpool) until it can contain up to
29 * newsize objects.  Return AL_TRUE if resize operation was successful,
30 * AL_FALSE otherwise.
31 */
32ALboolean bpool_resize( bpool_t *bpool, size_t newsize ) {
33        void *temp;
34        unsigned int i;
35
36        if(newsize < 1) {
37                newsize = 1;
38        }
39
40        if(bpool->size >= newsize) {
41                return AL_TRUE; /* no resize needed */
42        }
43
44        /*
45         * Resize buffer pool
46         */
47        temp = realloc(bpool->pool, newsize * sizeof *bpool->pool);
48        if(temp == NULL) {
49                return AL_FALSE; /* could not realloc */
50        }
51
52        bpool->pool = temp;
53
54        for(i = bpool->size; i < newsize; i++) {
55                bpool->pool[i].inuse = AL_FALSE;
56        }
57
58        /*
59         * resize the sid <-> index map.
60         */
61        temp = realloc(bpool->map, newsize * sizeof *bpool->map);
62        if(temp == NULL) {
63                return AL_FALSE;
64        }
65        bpool->map = temp;
66
67        for(i = bpool->size; i < newsize; i++) {
68                bpool->map[i] = 0;
69        }
70
71        bpool->size = newsize;
72
73        return AL_TRUE;
74}
75
76/*
77 * bpool_alloc( bpool_t *bpool )
78 *
79 * allocates a buffer pool node from bpool, returns index or -1
80 * on error.
81 */
82int bpool_alloc( bpool_t *bpool ) {
83        ALuint size = 0;
84        int bindex = 0;
85
86        bindex = bpool_first_free_index( bpool );
87        if(bindex == -1)  {
88                size = bpool->size + bpool->size / 2;
89
90                if(size < MINBUFFERS) {
91                        size = MINBUFFERS;
92                }
93
94                if(bpool_resize(bpool, size) == AL_FALSE) {
95                        return -1;
96                }
97
98                bindex = bpool_first_free_index(bpool);
99        }
100
101        bpool->pool[bindex].inuse = AL_TRUE;
102        bpool->map[bindex]        = bpool_next_bid();
103
104        _alBufferInit(&bpool->pool[bindex].data, bpool->map[bindex]);
105
106        return bpool->map[bindex];
107}
108
109/*
110 * bpool_index( bpool_t *bpool, ALuint bindex )
111 *
112 * retrieve a buffer pool node from a buffer pool ( bpool ), with index
113 * bindex.  Returns NULL if bindex is not a valid index into the bpool.
114 *
115 * NOTE: bindex is *not* a buffer name (bid).  It is a value returned from
116 * a successful call to bpool_alloc.
117 */
118AL_buffer *bpool_index( bpool_t *bpool, ALuint bid ) {
119        int bindex;
120
121        bindex = bpool_bid_to_index( bpool, bid );
122        if(bindex < 0) {
123                return NULL;
124        }
125
126        if(bindex >= (int) bpool->size) {
127                return NULL;
128        }
129
130        return &bpool->pool[bindex].data;
131}
132
133/*
134 * bpool_first_free_index( bpool_t *bpool )
135 *
136 * returns index of first unused buffer pool node in bpool.
137 */
138int bpool_first_free_index( bpool_t *bpool ) {
139        ALuint i;
140
141        for( i = 0; i < bpool->size; i++ ) {
142                if(bpool->pool[i].inuse == AL_FALSE) {
143                        return i;
144                }
145        }
146
147        return -1;
148}
149
150/*
151 * bpool_dealloc( bpool_t *bpool, ALuint bid, void (*freer_func)(void *) )
152 *
153 * finalizes a single buffer pool node, named by bid.  Returns AL_TRUE if the
154 * buffer pool node was valid, in use, and was finalized.  Returns AL_FALSE if
155 * the buffer pool node was invalid, not in use, or any other error occured.
156 */
157ALboolean bpool_dealloc( bpool_t *bpool, ALuint bid,
158                                void (*freer_func)(void *) ) {
159        AL_buffer *src;
160        int bindex;
161
162        bindex = bpool_bid_to_index( bpool, bid );
163        if(bindex < 0) {
164                /* invalid bid */
165                _alDebug(ALD_MAXIMUS, __FILE__, __LINE__,
166                        "bid %d is a bad index", bid);
167
168                return AL_FALSE;
169        }
170
171        if(bindex >= (int) bpool->size) {
172                return AL_FALSE;
173        }
174
175        src = bpool_index(bpool, bid);
176        if(src == NULL) {
177                _alDebug(ALD_MAXIMUS, __FILE__, __LINE__,
178                        "bid %d is a bad index", bid);
179                return AL_FALSE;
180        }
181
182        if(bpool->pool[bindex].inuse == AL_FALSE) {
183                /* already deleted */
184                return AL_FALSE;
185        }
186
187        _alDebug(ALD_MEM, __FILE__, __LINE__, "freer_func'ing %d", bid);
188
189        freer_func(src);
190
191        bpool->pool[bindex].inuse = AL_FALSE;
192        bpool->map[bindex] = 0;
193
194        return AL_TRUE;
195}
196
197/*
198 * bpool_free( bpool_t *bpool, void (*freer_func)(void *) )
199 *
200 * dealloc all buffer pool nodes in a buffer pool object, using freer_func to
201 * finalize each node.
202 */
203void bpool_free( bpool_t *bpool, void (*freer_func)(void *) ) {
204        ALuint bid;
205        unsigned int i;
206
207        for(i = 0; i < bpool->size; i++) {
208                if(bpool->pool[i].inuse == AL_TRUE) {
209                        bid = bpool->map[i];
210
211                        bpool_dealloc(bpool, bid, freer_func);
212                }
213        }
214
215        free( bpool->pool );
216        bpool->pool = NULL;
217
218        free( bpool->map );
219        bpool->map = NULL;
220
221        bpool->size = 0;
222
223        /* let the caller free bpool itself */
224        return;
225}
226
227/*
228 * bpool_init( bpool_t *bpool )
229 *
230 * initializes buffer pool object (bpool).
231 */
232void bpool_init( bpool_t *bpool ) {
233        bpool->size = 0;
234        bpool->pool = NULL;
235        bpool->map  = NULL;
236
237        return;
238}
239
240/*
241 * bpool_bid_to_index( bpool_t *bpool, ALuint bid )
242 *
243 * converts an AL_buffer name (bid) to buffer pool node index suitable
244 * for passing to bpool_index.  Returns -1 if bid does not name a buffer id
245 * within bpool.
246 *
247 * FIXME: use binary search.
248 */
249int bpool_bid_to_index( bpool_t *bpool, ALuint bid ) {
250        unsigned int i;
251
252        if ( bid > 0 ) {
253                for(i = 0; i < bpool->size; i++) {
254                        if(bpool->map[i] == bid) {
255                                return i;
256                        }
257                }
258        }
259
260        return -1;
261}
262
263/*
264 * bpool_next_bid( void )
265 *
266 * return next suitable AL_buffer name (bid) suitable for using in
267 * al calls ( alBufferData( bid, ... ), etc ).  These should be sequential
268 * and unique.
269 */
270ALuint bpool_next_bid( void ) {
271        static ALuint id = AL_FIRST_BUFFER_ID;
272
273        return ++id;
274}
275
276/*
277 * _alBufferInit( AL_buffer *buf, ALuint bid )
278 *
279 * Allocate and initialize a new buffer.  Probably shouldn't
280 * be called directly but from add_bufnod (which subsequently
281 * adds it to the pool data structure, which maintains these
282 * things)
283 *
284 * assumes locked buffers
285 */
286static void _alBufferInit( AL_buffer *buf, ALuint bid ) {
287        ALuint i;
288
289        if( buf == NULL ) {
290                return;
291        }
292
293        buf->num_buffers = _alcDCGetNumSpeakers();
294
295        for(i = 0; i < elementsof(buf->orig_buffers); i++) {
296                buf->orig_buffers[i] = NULL;
297        }
298
299        buf->bid            = bid;
300        buf->flags          = ALB_NONE;
301        buf->streampos      = 0;
302        buf->appendpos      = 0;
303
304        buf->format         = canon_format;
305        buf->frequency      = canon_speed;
306        buf->size           = 0;
307
308        buf->callback                = NULL;
309        buf->destroy_source_callback = NULL;
310        buf->destroy_buffer_callback = NULL;
311
312        buf->queue_list.sids    = NULL;
313        buf->queue_list.size    = 0;
314        buf->queue_list.items   = 0;
315
316        buf->current_list.sids    = NULL;
317        buf->current_list.size    = 0;
318        buf->current_list.items   = 0;
319
320        return;
321}
Note: See TracBrowser for help on using the repository browser.