Use ptrdiff types for databuffer offset/length handling
[openal-soft.git] / OpenAL32 / alDatabuffer.c
blobc9283250315ec7b341490c9ffc8f9be2b5e85acf
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <assert.h>
26 #include "alMain.h"
27 #include "AL/al.h"
28 #include "AL/alc.h"
29 #include "AL/alext.h"
30 #include "alError.h"
31 #include "alDatabuffer.h"
32 #include "alThunk.h"
35 DECL_VERIFIER(Databuffer, ALdatabuffer, databuffer)
38 * alGenDatabuffersEXT(ALsizei n, ALuint *puiBuffers)
40 * Generates n AL Databuffers, and stores the Databuffers Names in the array pointed to by puiBuffers
42 ALvoid ALAPIENTRY alGenDatabuffersEXT(ALsizei n,ALuint *puiBuffers)
44 ALCcontext *Context;
45 ALsizei i=0;
47 Context = GetContextSuspended();
48 if(!Context) return;
50 /* Check that we are actually generation some Databuffers */
51 if(n > 0)
53 ALCdevice *device = Context->Device;
55 /* Check the pointer is valid (and points to enough memory to store
56 * Databuffer Names) */
57 if(!IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint)))
59 ALdatabuffer **list = &device->DatabufferList;
60 while(*list)
61 list = &(*list)->next;
63 /* Create all the new Databuffers */
64 while(i < n)
66 *list = calloc(1, sizeof(ALdatabuffer));
67 if(!(*list))
69 alDeleteDatabuffersEXT(i, puiBuffers);
70 alSetError(Context, AL_OUT_OF_MEMORY);
71 break;
74 puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
75 (*list)->databuffer = puiBuffers[i];
76 (*list)->state = UNMAPPED;
77 device->DatabufferCount++;
78 i++;
80 list = &(*list)->next;
83 else
84 alSetError(Context, AL_INVALID_VALUE);
87 ProcessContext(Context);
91 * alDatabeleteBuffersEXT(ALsizei n, ALuint *puiBuffers)
93 * Deletes the n AL Databuffers pointed to by puiBuffers
95 ALvoid ALAPIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *puiBuffers)
97 ALCcontext *Context;
98 ALdatabuffer *ALBuf;
99 ALsizei i;
100 ALboolean bFailed = AL_FALSE;
102 Context = GetContextSuspended();
103 if(!Context) return;
105 /* Check we are actually Deleting some Databuffers */
106 if(n >= 0)
108 ALCdevice *device = Context->Device;
110 /* Check that all the databuffers are valid and can actually be
111 * deleted */
112 for(i = 0;i < n;i++)
114 if(!puiBuffers[i])
115 continue;
117 /* Check for valid Buffer ID */
118 if((ALBuf=VerifyDatabuffer(device->DatabufferList, puiBuffers[i])) != NULL)
120 if(ALBuf->state != UNMAPPED)
122 /* Databuffer still in use, cannot be deleted */
123 alSetError(Context, AL_INVALID_OPERATION);
124 bFailed = AL_TRUE;
125 break;
128 else
130 /* Invalid Databuffer */
131 alSetError(Context, AL_INVALID_NAME);
132 bFailed = AL_TRUE;
133 break;
137 /* If all the Databuffers were valid (and unmapped), then we can
138 * delete them */
139 if(!bFailed)
141 for(i = 0;i < n;i++)
143 if((ALBuf=VerifyDatabuffer(device->DatabufferList, puiBuffers[i])) != NULL)
145 ALdatabuffer **list = &device->DatabufferList;
147 while(*list && *list != ALBuf)
148 list = &(*list)->next;
150 if(*list)
151 *list = (*list)->next;
153 if(ALBuf == Context->SampleSource)
154 Context->SampleSource = NULL;
155 if(ALBuf == Context->SampleSink)
156 Context->SampleSink = NULL;
158 // Release the memory used to store audio data
159 free(ALBuf->data);
161 // Release buffer structure
162 ALTHUNK_REMOVEENTRY(puiBuffers[i]);
163 memset(ALBuf, 0, sizeof(ALdatabuffer));
164 device->DatabufferCount--;
165 free(ALBuf);
170 else
171 alSetError(Context, AL_INVALID_VALUE);
173 ProcessContext(Context);
177 * alIsDatabufferEXT(ALuint uiBuffer)
179 * Checks if ulBuffer is a valid Databuffer Name
181 ALboolean ALAPIENTRY alIsDatabufferEXT(ALuint uiBuffer)
183 ALCcontext *Context;
184 ALboolean result = AL_TRUE;
185 ALCdevice *device;
187 Context = GetContextSuspended();
188 if(!Context) return AL_FALSE;
190 device = Context->Device;
191 if(uiBuffer)
192 result = (VerifyDatabuffer(device->DatabufferList, uiBuffer) ?
193 AL_TRUE : AL_FALSE);
195 ProcessContext(Context);
197 return result;
201 * alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
203 * Fill databuffer with data
205 ALvoid ALAPIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizeiptrEXT size,ALenum usage)
207 ALCcontext *Context;
208 ALdatabuffer *ALBuf;
209 ALCdevice *Device;
210 ALvoid *temp;
212 Context = GetContextSuspended();
213 if(!Context) return;
215 Device = Context->Device;
216 if((ALBuf=VerifyDatabuffer(Device->DatabufferList, buffer)) != NULL)
218 if(ALBuf->state == UNMAPPED)
220 if(usage == AL_STREAM_WRITE_EXT || usage == AL_STREAM_READ_EXT ||
221 usage == AL_STREAM_COPY_EXT || usage == AL_STATIC_WRITE_EXT ||
222 usage == AL_STATIC_READ_EXT || usage == AL_STATIC_COPY_EXT ||
223 usage == AL_DYNAMIC_WRITE_EXT || usage == AL_DYNAMIC_READ_EXT ||
224 usage == AL_DYNAMIC_COPY_EXT)
226 if(size >= 0)
228 /* (Re)allocate data */
229 temp = realloc(ALBuf->data, size);
230 if(temp)
232 ALBuf->data = temp;
233 ALBuf->size = size;
234 ALBuf->usage = usage;
235 if(data)
236 memcpy(ALBuf->data, data, size);
238 else
239 alSetError(Context, AL_OUT_OF_MEMORY);
241 else
242 alSetError(Context, AL_INVALID_VALUE);
244 else
245 alSetError(Context, AL_INVALID_ENUM);
247 else
248 alSetError(Context, AL_INVALID_OPERATION);
250 else
251 alSetError(Context, AL_INVALID_NAME);
253 ProcessContext(Context);
256 ALvoid ALAPIENTRY alDatabufferSubDataEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, const ALvoid *data)
258 ALCcontext *pContext;
259 ALdatabuffer *pBuffer;
260 ALCdevice *Device;
262 pContext = GetContextSuspended();
263 if(!pContext) return;
265 Device = pContext->Device;
266 if((pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
268 if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
270 if(pBuffer->state == UNMAPPED)
271 memcpy(pBuffer->data+start, data, length);
272 else
273 alSetError(pContext, AL_INVALID_OPERATION);
275 else
276 alSetError(pContext, AL_INVALID_VALUE);
278 else
279 alSetError(pContext, AL_INVALID_NAME);
281 ProcessContext(pContext);
284 ALvoid ALAPIENTRY alGetDatabufferSubDataEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALvoid *data)
286 ALCcontext *pContext;
287 ALdatabuffer *pBuffer;
288 ALCdevice *Device;
290 pContext = GetContextSuspended();
291 if(!pContext) return;
293 Device = pContext->Device;
294 if((pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
296 if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
298 if(pBuffer->state == UNMAPPED)
299 memcpy(data, pBuffer->data+start, length);
300 else
301 alSetError(pContext, AL_INVALID_OPERATION);
303 else
304 alSetError(pContext, AL_INVALID_VALUE);
306 else
307 alSetError(pContext, AL_INVALID_NAME);
309 ProcessContext(pContext);
313 ALvoid ALAPIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue)
315 ALCcontext *pContext;
316 ALCdevice *Device;
318 (void)flValue;
320 pContext = GetContextSuspended();
321 if(!pContext) return;
323 Device = pContext->Device;
324 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
326 switch(eParam)
328 default:
329 alSetError(pContext, AL_INVALID_ENUM);
330 break;
333 else
334 alSetError(pContext, AL_INVALID_NAME);
336 ProcessContext(pContext);
339 ALvoid ALAPIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues)
341 ALCcontext *pContext;
342 ALCdevice *Device;
344 (void)flValues;
346 pContext = GetContextSuspended();
347 if(!pContext) return;
349 Device = pContext->Device;
350 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
352 switch(eParam)
354 default:
355 alSetError(pContext, AL_INVALID_ENUM);
356 break;
359 else
360 alSetError(pContext, AL_INVALID_NAME);
362 ProcessContext(pContext);
366 ALvoid ALAPIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue)
368 ALCcontext *pContext;
369 ALCdevice *Device;
371 (void)lValue;
373 pContext = GetContextSuspended();
374 if(!pContext) return;
376 Device = pContext->Device;
377 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
379 switch(eParam)
381 default:
382 alSetError(pContext, AL_INVALID_ENUM);
383 break;
386 else
387 alSetError(pContext, AL_INVALID_NAME);
389 ProcessContext(pContext);
392 ALvoid ALAPIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues)
394 ALCcontext *pContext;
395 ALCdevice *Device;
397 (void)plValues;
399 pContext = GetContextSuspended();
400 if(!pContext) return;
402 Device = pContext->Device;
403 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
405 switch(eParam)
407 default:
408 alSetError(pContext, AL_INVALID_ENUM);
409 break;
412 else
413 alSetError(pContext, AL_INVALID_NAME);
415 ProcessContext(pContext);
419 ALvoid ALAPIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue)
421 ALCcontext *pContext;
422 ALCdevice *Device;
424 pContext = GetContextSuspended();
425 if(!pContext) return;
427 if(pflValue)
429 Device = pContext->Device;
430 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
432 switch(eParam)
434 default:
435 alSetError(pContext, AL_INVALID_ENUM);
436 break;
439 else
440 alSetError(pContext, AL_INVALID_NAME);
442 else
443 alSetError(pContext, AL_INVALID_VALUE);
445 ProcessContext(pContext);
448 ALvoid ALAPIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues)
450 ALCcontext *pContext;
451 ALCdevice *Device;
453 pContext = GetContextSuspended();
454 if(!pContext) return;
456 if(pflValues)
458 Device = pContext->Device;
459 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
461 switch(eParam)
463 default:
464 alSetError(pContext, AL_INVALID_ENUM);
465 break;
468 else
469 alSetError(pContext, AL_INVALID_NAME);
471 else
472 alSetError(pContext, AL_INVALID_VALUE);
474 ProcessContext(pContext);
477 ALvoid ALAPIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue)
479 ALCcontext *pContext;
480 ALdatabuffer *pBuffer;
481 ALCdevice *Device;
483 pContext = GetContextSuspended();
484 if(!pContext) return;
486 if(plValue)
488 Device = pContext->Device;
489 if((pBuffer=VerifyDatabuffer(Device->DatabufferList, buffer)) != NULL)
491 switch(eParam)
493 case AL_SIZE:
494 *plValue = pBuffer->size;
495 break;
497 default:
498 alSetError(pContext, AL_INVALID_ENUM);
499 break;
502 else
503 alSetError(pContext, AL_INVALID_NAME);
505 else
506 alSetError(pContext, AL_INVALID_VALUE);
508 ProcessContext(pContext);
511 ALvoid ALAPIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues)
513 ALCcontext *pContext;
514 ALCdevice *Device;
516 pContext = GetContextSuspended();
517 if(!pContext) return;
519 if(plValues)
521 Device = pContext->Device;
522 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
524 switch (eParam)
526 case AL_SIZE:
527 alGetDatabufferiEXT(buffer, eParam, plValues);
528 break;
530 default:
531 alSetError(pContext, AL_INVALID_ENUM);
532 break;
535 else
536 alSetError(pContext, AL_INVALID_NAME);
538 else
539 alSetError(pContext, AL_INVALID_VALUE);
541 ProcessContext(pContext);
545 ALvoid ALAPIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer)
547 ALCcontext *pContext;
548 ALdatabuffer *pBuffer = NULL;
549 ALCdevice *Device;
551 pContext = GetContextSuspended();
552 if(!pContext) return;
554 Device = pContext->Device;
555 if(uiBuffer == 0 ||
556 (pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
558 if(target == AL_SAMPLE_SOURCE_EXT)
559 pContext->SampleSource = pBuffer;
560 else if(target == AL_SAMPLE_SINK_EXT)
561 pContext->SampleSink = pBuffer;
562 else
563 alSetError(pContext, AL_INVALID_VALUE);
565 else
566 alSetError(pContext, AL_INVALID_NAME);
568 ProcessContext(pContext);
572 ALvoid* ALAPIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALenum access)
574 ALCcontext *pContext;
575 ALdatabuffer *pBuffer;
576 ALvoid *ret = NULL;
577 ALCdevice *Device;
579 pContext = GetContextSuspended();
580 if(!pContext) return NULL;
582 Device = pContext->Device;
583 if((pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
585 if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
587 if(access == AL_READ_ONLY_EXT || access == AL_WRITE_ONLY_EXT ||
588 access == AL_READ_WRITE_EXT)
590 if(pBuffer->state == UNMAPPED)
592 ret = pBuffer->data + start;
593 pBuffer->state = MAPPED;
595 else
596 alSetError(pContext, AL_INVALID_OPERATION);
598 else
599 alSetError(pContext, AL_INVALID_ENUM);
601 else
602 alSetError(pContext, AL_INVALID_VALUE);
604 else
605 alSetError(pContext, AL_INVALID_NAME);
607 ProcessContext(pContext);
609 return ret;
612 ALvoid ALAPIENTRY alUnmapDatabufferEXT(ALuint uiBuffer)
614 ALCcontext *pContext;
615 ALdatabuffer *pBuffer;
616 ALCdevice *Device;
618 pContext = GetContextSuspended();
619 if(!pContext) return;
621 Device = pContext->Device;
622 if((pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
624 if(pBuffer->state == MAPPED)
625 pBuffer->state = UNMAPPED;
626 else
627 alSetError(pContext, AL_INVALID_OPERATION);
629 else
630 alSetError(pContext, AL_INVALID_NAME);
632 ProcessContext(pContext);
637 * ReleaseALDatabuffers()
639 * INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
641 ALvoid ReleaseALDatabuffers(ALCdevice *device)
643 ALdatabuffer *ALBuffer;
644 ALdatabuffer *ALBufferTemp;
646 ALBuffer = device->DatabufferList;
647 while(ALBuffer)
649 // Release sample data
650 free(ALBuffer->data);
652 // Release Buffer structure
653 ALBufferTemp = ALBuffer;
654 ALBuffer = ALBuffer->next;
655 memset(ALBufferTemp, 0, sizeof(ALdatabuffer));
656 free(ALBufferTemp);
658 device->DatabufferList = NULL;
659 device->DatabufferCount = 0;