Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

added openal

File size: 8.5 KB
Line 
1/* -*- mode: C; tab-width:8; c-basic-offset:8 -*-
2 * vi:set ts=8:
3 *
4 * al_queue.c
5 *
6 * Stuff related to the management and use of buffer queue.
7 *
8 * FIXME: clean this mess up
9 */
10
11#include "al_siteconfig.h"
12
13#include <AL/al.h>
14#include <stdlib.h>
15#include <string.h>
16
17#include "al_config.h"
18#include "al_buffer.h"
19#include "al_debug.h"
20#include "al_error.h"
21#include "al_main.h"
22#include "al_source.h"
23#include "al_queue.h"
24#include "al_types.h"
25#include "al_mixer.h"
26
27#include "alc/alc_context.h"
28
29/*
30 * alSourceQueueBuffers( ALuint sid, ALsizei numBuffers, ALuint *bids )
31 *
32 * Queue bids[0..numBuffers-1] to the source named sid, setting
33 * AL_INVALID_VALUE if numBuffers < 0, or AL_INVALID_NAME if either sid or and
34 * bid in bids[0..numBuffers-1] is not a valid buffer.
35 */
36void alSourceQueueBuffers( ALuint sid, ALsizei numBuffers, const ALuint *bids ) {
37        AL_source *src;
38        ALsizei i;
39
40        if( numBuffers == 0) {
41                /* with n == 0, we NOP */
42                return;
43        }
44
45        if( numBuffers < 0) {
46                _alDebug(ALD_SOURCE, __FILE__, __LINE__,
47                      "alSourceQueueBuffers: illegal n value %d\n", numBuffers );
48
49                _alcDCLockContext();
50                _alDCSetError( AL_INVALID_VALUE );
51                _alcDCUnlockContext();
52
53                return;
54        }
55
56        _alLockMixBuf();
57        SOURCELOCK();
58
59        src = _alDCGetSource( sid );
60        if( src == NULL ) {
61                _alDCSetError( AL_INVALID_NAME );
62
63                _alDebug(ALD_SOURCE, __FILE__, __LINE__,
64                      "alSourceQueueBuffers: invalid sid %d\n", sid );
65
66                SOURCEUNLOCK();
67                _alUnlockMixBuf();
68
69                return;
70        }
71
72        _alLockBuffer();
73
74        /* make sure that bids are valid */
75        for( i = 0; i < numBuffers; i++ ) {
76                if( _alIsBuffer( bids[i] ) == AL_FALSE ) {
77                        /*
78                         * we have an invalid bid.  bid 0 is okay but the
79                         * rest are not.
80                         */
81                        if( bids[i] != 0 ) {
82                                _alUnlockBuffer();
83
84                                _alDCSetError( AL_INVALID_NAME );
85
86                                SOURCEUNLOCK();
87                                _alUnlockMixBuf();
88
89                                return;
90                        }
91                }
92        }
93
94        /* now, append the bids */
95        for( i = 0; i < numBuffers; i++ ) {
96                if( bids[i] != 0 ) {
97                        /*
98                         * only append non-0 bids, because we don't
99                         * need them anyway.
100                         */
101                        _alSourceQueueAppend( src, bids[i] );
102                }
103        }
104
105        /* we're done */
106
107        _alUnlockBuffer();
108        SOURCEUNLOCK();
109        _alUnlockMixBuf();
110
111        return;
112}
113
114/*
115 * _alSourceQueueGetCurrentState( AL_source *src )
116 *
117 * Returns the current AL_sourcestate of the current queue entry for AL_source
118 * *src.
119 *
120 * assumes locked sources
121 */
122AL_sourcestate *_alSourceQueueGetCurrentState( AL_source *src )
123{
124        int rind = src->bid_queue.read_index;
125
126        /*
127         * This assert means we're querying a value with the read
128         * index beyond our size.
129         *
130         * Well, like a dumbass I made looping source queue specific.  Now I'm
131         * paying the price.  Okay, return return return.
132         */
133        /* assert( rind < src->bid_queue.size ); */
134
135        if(rind >= src->bid_queue.size)
136        {
137                return NULL;
138        }
139
140        return &src->bid_queue.queuestate[rind];
141}
142
143/*
144 * _alSourceQueueInit( AL_source *src )
145 *
146 * Initialize an AL_source queue.
147 *
148 * assumes locked context
149 */
150void _alSourceQueueInit( AL_source *src ) {
151        src->bid_queue.queue       = NULL;
152        src->bid_queue.queuestate  = NULL;
153        src->bid_queue.size        = 0;
154
155        _alSourceQueueClear( src );
156
157        return;
158}
159
160/*
161 * _alSourceQueueClear( AL_source *src )
162 *
163 * Clears a source's queue, removing all entries.
164 *
165 * assumes locked context
166 */
167void _alSourceQueueClear( AL_source *src ) {
168        ALuint bid;
169        int i;
170
171        for(i = 0; i < src->bid_queue.size; i++) {
172                bid = src->bid_queue.queue[i];
173
174                if(bid != 0) {
175                        /* bid 0 is a special name */
176                        _alBidRemoveQueueRef(bid, src->sid);
177                }
178        }
179
180        src->bid_queue.read_index  = 0;
181        src->bid_queue.write_index = 0;
182        src->bid_queue.size        = 0;
183
184        _alSourceQueueAppend(src, 0);
185
186        return;
187}
188
189/*
190 * _alSourceQueueAppend( AL_source *src, ALuint bid )
191 *
192 * Append bid to source's queue.
193 *
194 * assumes locked context
195 */
196void _alSourceQueueAppend( AL_source *src, ALuint bid ) {
197        int size    = src->bid_queue.size;
198        int newsize = size + 1;
199        int windex  = src->bid_queue.write_index;
200        void *temp;
201
202        if(src->bid_queue.size > 0) {
203                if(src->bid_queue.queue[windex] == 0) {
204                        /*
205                         * special case.  bid == 0 is the "no bid"
206                         * bid, which means that it's just a place
207                         * holder to allow buffer specific source
208                         * parameters to be set.
209                         *
210                         * Don't bother to resize, just overwrite.
211                         */
212                        src->bid_queue.queue[windex] = bid;
213
214                        return;
215                }
216        }
217
218        temp = realloc(src->bid_queue.queue,
219                       newsize * sizeof *src->bid_queue.queue);
220        if(temp == NULL) {
221                return;
222        }
223        src->bid_queue.queue = temp;
224        src->bid_queue.queue[size] = 0;
225
226        temp = realloc(src->bid_queue.queuestate,
227                       newsize * sizeof *src->bid_queue.queuestate);
228        if(temp == NULL) {
229                return;
230        }
231        src->bid_queue.queuestate = temp;
232
233        /*
234         * If this is a "real" append operation, ie not bid == NONE,
235         * then increment the write index so that buffer specific
236         * source setting operations take place.
237         */
238        if(bid != 0) {
239                windex++;
240                src->bid_queue.write_index++;
241        }
242
243        /*
244         * Initialize sourcestate flags.
245         */
246        _alSourceStateInit(&src->bid_queue.queuestate[windex]);
247
248        /*
249         * Set bid and new size.
250         */
251        src->bid_queue.queue[windex] = bid;
252        src->bid_queue.size = newsize;
253
254
255        return;
256}
257
258
259/*
260 * _alSourceQueueHead( AL_source *src, ALuint bid )
261 *
262 * Truncates a source's queue with a single entry of bid.
263 *
264 * assumes locked context
265 */
266void _alSourceQueueHead( AL_source *src, ALuint bid ) {
267        _alSourceQueueClear( src );
268
269        src->bid_queue.queue[0]    = bid;
270        src->bid_queue.write_index = 0;
271        src->bid_queue.read_index  = 0;
272        src->bid_queue.size        = 1;
273
274        return;
275}
276
277/*
278 * alSourceUnqueueBuffers( ALuint sid, ALsizei n, ALuint *bids )
279 *
280 * Unqueues first occurance of each bid in bids[0..n-1] from source named sid.
281 */
282void alSourceUnqueueBuffers( ALuint sid, ALsizei n, ALuint *bids ) {
283        _alLockMixBuf();
284        _alcDCLockContext();
285
286        _alSourceUnqueueBuffers( sid, n, bids );
287
288        _alcDCUnlockContext();
289        _alUnlockMixBuf();
290
291        return;
292}
293
294/*
295 * _alSourceStateInit( AL_sourcestate *srcstate )
296 *
297 * Initialize an AL_sourcestate object to the default settings.
298 */
299void _alSourceStateInit( AL_sourcestate *srcstate ) {
300        srcstate->flags = ALQ_NONE;
301
302        return;
303}
304
305/*
306 * _alSourceUnqueueBuffers( ALuint sid, ALsizei n, ALuint *bids )
307 *
308 * Non locking version of alSourceUnqueueBuffers.
309 *
310 * assumes locked context
311 */
312void _alSourceUnqueueBuffers(ALuint sid, ALsizei n, ALuint *bids ) {
313        AL_source *src;
314        ALuint *tempqueue;
315        AL_sourcestate *tempstate;
316        int newsize;
317        int i;
318
319        if(n == 0) {
320                /* legal nop */
321                return;
322        }
323
324        if(n < 0) {
325                /* bad n */
326                _alDCSetError( AL_INVALID_VALUE );
327
328                _alDebug(ALD_SOURCE, __FILE__, __LINE__,
329                        "alSourceUnqueueBuffers: invalid numBuffers %d", n );
330
331                return;
332        }
333
334        src = _alDCGetSource( sid );
335        if(src == NULL) {
336                _alDCSetError(AL_INVALID_NAME);
337                return;
338        }
339
340        if(n > src->bid_queue.read_index) {
341                /* User has requested too many buffers unqueued */
342                _alDCSetError( AL_INVALID_VALUE );
343
344                _alDebug(ALD_SOURCE, __FILE__, __LINE__,
345                        "alSourceUnqueueBuffers: invalid numBuffers %d", n );
346
347                return;
348        }
349
350        /* make sure queue is valid */
351        for( i = 0; i < n; i++ )
352        {
353                if(!_alIsBuffer(src->bid_queue.queue[i]))
354                {
355                        _alDCSetError( AL_INVALID_NAME );
356                        _alDebug(ALD_SOURCE, __FILE__, __LINE__,
357                                "alSourceUnqueueBuffers: invalid buffer name %d",
358                                n );
359
360                        return;
361                }
362        }
363
364        /* copy queue into bids */
365        newsize = src->bid_queue.size - n;
366
367        for( i = 0; i < n; i++ )
368        {
369                _alBidRemoveQueueRef( src->bid_queue.queue[i], src->sid );
370                _alBidRemoveCurrentRef( src->bid_queue.queue[i], src->sid );
371        }
372
373        /* resize */
374        tempqueue = malloc(newsize * sizeof *tempqueue);
375        tempstate = malloc(newsize * sizeof *tempstate);
376
377        assert( tempqueue );
378        assert( tempstate );
379
380        if((tempqueue == NULL) || (tempstate == NULL))
381        {
382                /*
383                 * since newsize is less than our current size,
384                 * we really shouldn't bomb out here, but should
385                 * instead just set the deleted bids to 0 or something[
386                 */
387                _alDCSetError(AL_OUT_OF_MEMORY);
388                _alDebug(ALD_SOURCE, __FILE__, __LINE__,
389                        "alSourceUnqueueBuffers: unable to allocate memory" );
390
391                return;
392        }
393
394        /* okay, we've succedded, so copy the bids for return */
395        memcpy( bids, src->bid_queue.queue, n * sizeof *bids );
396
397        /* copy the new queue and state */
398        memcpy( tempqueue,
399                &src->bid_queue.queue[n], newsize * sizeof *tempqueue );
400        memcpy( tempstate,
401                &src->bid_queue.queuestate[n], newsize * sizeof *tempstate );
402
403        /*
404         * read_index now points to the wrong bid, so subtract by
405         * old size - newsize.
406         */
407        src->bid_queue.read_index -= (src->bid_queue.size - newsize);
408
409        /*
410         * write_indesx too
411         */
412        src->bid_queue.write_index -= (src->bid_queue.size - newsize);
413
414        free( src->bid_queue.queue );
415        free( src->bid_queue.queuestate );
416
417        src->bid_queue.queue      = tempqueue;
418        src->bid_queue.queuestate = tempstate;
419        src->bid_queue.size       = newsize;
420
421        return;
422}
Note: See TracBrowser for help on using the repository browser.