Check i64 property ranges before passing them to the int handlers
[openal-soft.git] / OpenAL32 / alSource.c
blob5350ca75eb11b1fa2278c68f9801885caa31865c
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 <math.h>
25 #include <float.h>
27 #include "AL/al.h"
28 #include "AL/alc.h"
29 #include "alMain.h"
30 #include "alError.h"
31 #include "alSource.h"
32 #include "alBuffer.h"
33 #include "alThunk.h"
34 #include "alAuxEffectSlot.h"
37 enum Resampler DefaultResampler = LinearResampler;
38 const ALsizei ResamplerPadding[ResamplerMax] = {
39 0, /* Point */
40 1, /* Linear */
41 2, /* Cubic */
43 const ALsizei ResamplerPrePadding[ResamplerMax] = {
44 0, /* Point */
45 0, /* Linear */
46 1, /* Cubic */
50 static ALvoid InitSourceParams(ALsource *Source);
51 static ALint64 GetSourceOffset(const ALsource *Source);
52 static ALdouble GetSourceSecOffset(const ALsource *Source);
53 static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offsets, ALdouble updateLen);
54 static ALint GetSampleOffset(ALsource *Source);
56 static ALenum SetSourcefv(ALsource *Source, ALCcontext *Context, ALenum name, const ALfloat *values);
57 static ALenum SetSourceiv(ALsource *Source, ALCcontext *Context, ALenum name, const ALint *values);
59 static ALenum GetSourcedv(const ALsource *Source, ALCcontext *Context, ALenum name, ALdouble *values);
60 static ALenum GetSourceiv(const ALsource *Source, ALCcontext *Context, ALenum name, ALint *values);
61 static ALenum GetSourcei64v(const ALsource *Source, ALCcontext *Context, ALenum name, ALint64 *values);
64 #define RETERR(x) do { \
65 alSetError(Context, (x)); \
66 return (x); \
67 } while(0)
69 #define CHECKVAL(x) do { \
70 if(!(x)) \
71 RETERR(AL_INVALID_VALUE); \
72 } while(0)
74 static ALenum SetSourcefv(ALsource *Source, ALCcontext *Context, ALenum name, const ALfloat *values)
76 switch(name)
78 case AL_PITCH:
79 CHECKVAL(*values >= 0.0f);
81 Source->Pitch = *values;
82 Source->NeedsUpdate = AL_TRUE;
83 break;
85 case AL_CONE_INNER_ANGLE:
86 CHECKVAL(*values >= 0.0f && *values <= 360.0f);
88 Source->InnerAngle = *values;
89 Source->NeedsUpdate = AL_TRUE;
90 break;
92 case AL_CONE_OUTER_ANGLE:
93 CHECKVAL(*values >= 0.0f && *values <= 360.0f);
95 Source->OuterAngle = *values;
96 Source->NeedsUpdate = AL_TRUE;
97 break;
99 case AL_GAIN:
100 CHECKVAL(*values >= 0.0f);
102 Source->Gain = *values;
103 Source->NeedsUpdate = AL_TRUE;
104 break;
106 case AL_MAX_DISTANCE:
107 CHECKVAL(*values >= 0.0f);
109 Source->MaxDistance = *values;
110 Source->NeedsUpdate = AL_TRUE;
111 break;
113 case AL_ROLLOFF_FACTOR:
114 CHECKVAL(*values >= 0.0f);
116 Source->RollOffFactor = *values;
117 Source->NeedsUpdate = AL_TRUE;
118 break;
120 case AL_REFERENCE_DISTANCE:
121 CHECKVAL(*values >= 0.0f);
123 Source->RefDistance = *values;
124 Source->NeedsUpdate = AL_TRUE;
125 break;
127 case AL_MIN_GAIN:
128 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
130 Source->MinGain = *values;
131 Source->NeedsUpdate = AL_TRUE;
132 break;
134 case AL_MAX_GAIN:
135 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
137 Source->MaxGain = *values;
138 Source->NeedsUpdate = AL_TRUE;
139 break;
141 case AL_CONE_OUTER_GAIN:
142 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
144 Source->OuterGain = *values;
145 Source->NeedsUpdate = AL_TRUE;
146 break;
148 case AL_CONE_OUTER_GAINHF:
149 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
151 Source->OuterGainHF = *values;
152 Source->NeedsUpdate = AL_TRUE;
153 break;
155 case AL_AIR_ABSORPTION_FACTOR:
156 CHECKVAL(*values >= 0.0f && *values <= 10.0f);
158 Source->AirAbsorptionFactor = *values;
159 Source->NeedsUpdate = AL_TRUE;
160 break;
162 case AL_ROOM_ROLLOFF_FACTOR:
163 CHECKVAL(*values >= 0.0f && *values <= 10.0f);
165 Source->RoomRolloffFactor = *values;
166 Source->NeedsUpdate = AL_TRUE;
167 break;
169 case AL_DOPPLER_FACTOR:
170 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
172 Source->DopplerFactor = *values;
173 Source->NeedsUpdate = AL_TRUE;
174 break;
176 case AL_SEC_OFFSET:
177 case AL_SAMPLE_OFFSET:
178 case AL_BYTE_OFFSET:
179 CHECKVAL(*values >= 0.0f);
181 LockContext(Context);
182 Source->OffsetType = name;
183 Source->Offset = *values;
185 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
186 !Context->DeferUpdates)
188 if(ApplyOffset(Source) == AL_FALSE)
190 UnlockContext(Context);
191 RETERR(AL_INVALID_VALUE);
194 UnlockContext(Context);
195 break;
198 case AL_POSITION:
199 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
201 LockContext(Context);
202 Source->Position[0] = values[0];
203 Source->Position[1] = values[1];
204 Source->Position[2] = values[2];
205 UnlockContext(Context);
206 Source->NeedsUpdate = AL_TRUE;
207 break;
209 case AL_VELOCITY:
210 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
212 LockContext(Context);
213 Source->Velocity[0] = values[0];
214 Source->Velocity[1] = values[1];
215 Source->Velocity[2] = values[2];
216 UnlockContext(Context);
217 Source->NeedsUpdate = AL_TRUE;
218 break;
220 case AL_DIRECTION:
221 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
223 LockContext(Context);
224 Source->Orientation[0] = values[0];
225 Source->Orientation[1] = values[1];
226 Source->Orientation[2] = values[2];
227 UnlockContext(Context);
228 Source->NeedsUpdate = AL_TRUE;
229 break;
232 default:
233 RETERR(AL_INVALID_ENUM);
236 return AL_NO_ERROR;
239 static ALenum SetSourceiv(ALsource *Source, ALCcontext *Context, ALenum name, const ALint *values)
241 ALCdevice *device = Context->Device;
242 ALbuffer *buffer = NULL;
243 ALfilter *filter = NULL;
244 ALeffectslot *slot = NULL;
245 ALbufferlistitem *oldlist;
246 ALfloat fvals[3];
247 ALenum err;
249 switch(name)
251 case AL_SOURCE_RELATIVE:
252 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
254 Source->HeadRelative = (ALboolean)*values;
255 Source->NeedsUpdate = AL_TRUE;
256 break;
258 case AL_LOOPING:
259 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
261 Source->Looping = (ALboolean)*values;
262 break;
264 case AL_BUFFER:
265 CHECKVAL(*values == 0 || (buffer=LookupBuffer(device, *values)) != NULL);
267 LockContext(Context);
268 if(!(Source->state == AL_STOPPED || Source->state == AL_INITIAL))
270 UnlockContext(Context);
271 RETERR(AL_INVALID_OPERATION);
274 Source->BuffersInQueue = 0;
275 Source->BuffersPlayed = 0;
277 if(buffer != NULL)
279 ALbufferlistitem *BufferListItem;
281 /* Source is now Static */
282 Source->SourceType = AL_STATIC;
284 /* Add the selected buffer to a one-item queue */
285 BufferListItem = malloc(sizeof(ALbufferlistitem));
286 BufferListItem->buffer = buffer;
287 BufferListItem->next = NULL;
288 BufferListItem->prev = NULL;
289 IncrementRef(&buffer->ref);
291 oldlist = ExchangePtr((XchgPtr*)&Source->queue, BufferListItem);
292 Source->BuffersInQueue = 1;
294 ReadLock(&buffer->lock);
295 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
296 Source->SampleSize = BytesFromFmt(buffer->FmtType);
297 ReadUnlock(&buffer->lock);
298 if(buffer->FmtChannels == FmtMono)
299 Source->Update = CalcSourceParams;
300 else
301 Source->Update = CalcNonAttnSourceParams;
302 Source->NeedsUpdate = AL_TRUE;
304 else
306 /* Source is now Undetermined */
307 Source->SourceType = AL_UNDETERMINED;
308 oldlist = ExchangePtr((XchgPtr*)&Source->queue, NULL);
311 /* Delete all elements in the previous queue */
312 while(oldlist != NULL)
314 ALbufferlistitem *temp = oldlist;
315 oldlist = temp->next;
317 if(temp->buffer)
318 DecrementRef(&temp->buffer->ref);
319 free(temp);
321 UnlockContext(Context);
322 break;
324 case AL_SOURCE_STATE:
325 /* Query only */
326 RETERR(AL_INVALID_OPERATION);
328 case AL_SEC_OFFSET:
329 case AL_SAMPLE_OFFSET:
330 case AL_BYTE_OFFSET:
331 CHECKVAL(*values >= 0);
333 LockContext(Context);
334 Source->OffsetType = name;
335 Source->Offset = *values;
337 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
338 !Context->DeferUpdates)
340 if(ApplyOffset(Source) == AL_FALSE)
342 UnlockContext(Context);
343 RETERR(AL_INVALID_VALUE);
346 UnlockContext(Context);
347 break;
349 case AL_DIRECT_FILTER:
350 CHECKVAL(*values == 0 || (filter=LookupFilter(device, *values)) != NULL);
352 LockContext(Context);
353 if(!filter)
355 Source->DirectGain = 1.0f;
356 Source->DirectGainHF = 1.0f;
358 else
360 Source->DirectGain = filter->Gain;
361 Source->DirectGainHF = filter->GainHF;
363 UnlockContext(Context);
364 Source->NeedsUpdate = AL_TRUE;
365 break;
367 case AL_DIRECT_FILTER_GAINHF_AUTO:
368 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
370 Source->DryGainHFAuto = *values;
371 Source->NeedsUpdate = AL_TRUE;
372 break;
374 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
375 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
377 Source->WetGainAuto = *values;
378 Source->NeedsUpdate = AL_TRUE;
379 break;
381 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
382 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
384 Source->WetGainHFAuto = *values;
385 Source->NeedsUpdate = AL_TRUE;
386 break;
388 case AL_DIRECT_CHANNELS_SOFT:
389 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
391 Source->DirectChannels = *values;
392 Source->NeedsUpdate = AL_TRUE;
393 break;
395 case AL_DISTANCE_MODEL:
396 CHECKVAL(*values == AL_NONE ||
397 *values == AL_INVERSE_DISTANCE ||
398 *values == AL_INVERSE_DISTANCE_CLAMPED ||
399 *values == AL_LINEAR_DISTANCE ||
400 *values == AL_LINEAR_DISTANCE_CLAMPED ||
401 *values == AL_EXPONENT_DISTANCE ||
402 *values == AL_EXPONENT_DISTANCE_CLAMPED);
404 Source->DistanceModel = *values;
405 if(Context->SourceDistanceModel)
406 Source->NeedsUpdate = AL_TRUE;
407 break;
410 case AL_AUXILIARY_SEND_FILTER:
411 LockContext(Context);
412 if(!((ALuint)values[1] < device->NumAuxSends &&
413 (values[0] == 0 || (slot=LookupEffectSlot(Context, values[0])) != NULL) &&
414 (values[2] == 0 || (filter=LookupFilter(device, values[2])) != NULL)))
416 UnlockContext(Context);
417 RETERR(AL_INVALID_VALUE);
420 /* Add refcount on the new slot, and release the previous slot */
421 if(slot) IncrementRef(&slot->ref);
422 slot = ExchangePtr((XchgPtr*)&Source->Send[values[1]].Slot, slot);
423 if(slot) DecrementRef(&slot->ref);
425 if(!filter)
427 /* Disable filter */
428 Source->Send[values[1]].Gain = 1.0f;
429 Source->Send[values[1]].GainHF = 1.0f;
431 else
433 Source->Send[values[1]].Gain = filter->Gain;
434 Source->Send[values[1]].GainHF = filter->GainHF;
436 Source->NeedsUpdate = AL_TRUE;
437 UnlockContext(Context);
438 break;
441 case AL_MAX_DISTANCE:
442 case AL_ROLLOFF_FACTOR:
443 case AL_CONE_INNER_ANGLE:
444 case AL_CONE_OUTER_ANGLE:
445 case AL_REFERENCE_DISTANCE:
446 fvals[0] = (ALfloat)*values;
447 if((err=SetSourcefv(Source, Context, name, fvals)) != AL_NO_ERROR)
448 return err;
449 break;
451 case AL_POSITION:
452 case AL_VELOCITY:
453 case AL_DIRECTION:
454 fvals[0] = (ALfloat)values[0];
455 fvals[1] = (ALfloat)values[1];
456 fvals[2] = (ALfloat)values[2];
457 if((err=SetSourcefv(Source, Context, name, fvals)) != AL_NO_ERROR)
458 return err;
459 break;
461 default:
462 return AL_INVALID_ENUM;
465 return AL_NO_ERROR;
468 #undef CHECKVAL
471 static ALenum GetSourcedv(const ALsource *Source, ALCcontext *Context, ALenum name, ALdouble *values)
473 ALdouble offsets[2];
474 ALdouble updateLen;
475 ALint ivals[3];
476 ALenum err;
478 switch(name)
480 case AL_MAX_DISTANCE:
481 *values = Source->MaxDistance;
482 break;
484 case AL_ROLLOFF_FACTOR:
485 *values = Source->RollOffFactor;
486 break;
488 case AL_REFERENCE_DISTANCE:
489 *values = Source->RefDistance;
490 break;
492 case AL_CONE_INNER_ANGLE:
493 *values = Source->InnerAngle;
494 break;
496 case AL_CONE_OUTER_ANGLE:
497 *values = Source->OuterAngle;
498 break;
500 case AL_SEC_OFFSET:
501 case AL_SAMPLE_OFFSET:
502 case AL_BYTE_OFFSET:
503 LockContext(Context);
504 updateLen = (ALdouble)Context->Device->UpdateSize /
505 Context->Device->Frequency;
506 GetSourceOffsets(Source, name, offsets, updateLen);
507 UnlockContext(Context);
508 *values = offsets[0];
509 break;
511 case AL_CONE_OUTER_GAINHF:
512 *values = Source->OuterGainHF;
513 break;
515 case AL_AIR_ABSORPTION_FACTOR:
516 *values = Source->AirAbsorptionFactor;
517 break;
519 case AL_ROOM_ROLLOFF_FACTOR:
520 *values = Source->RoomRolloffFactor;
521 break;
523 case AL_DOPPLER_FACTOR:
524 *values = Source->DopplerFactor;
525 break;
527 case AL_SAMPLE_RW_OFFSETS_SOFT:
528 case AL_BYTE_RW_OFFSETS_SOFT:
529 LockContext(Context);
530 updateLen = (ALdouble)Context->Device->UpdateSize /
531 Context->Device->Frequency;
532 GetSourceOffsets(Source, name, values, updateLen);
533 UnlockContext(Context);
534 break;
536 case AL_SEC_OFFSET_LATENCY_SOFT:
537 LockContext(Context);
538 values[0] = GetSourceSecOffset(Source);
539 values[1] = (ALdouble)ALCdevice_GetLatency(Context->Device) /
540 1000000000.0;
541 UnlockContext(Context);
542 break;
544 case AL_POSITION:
545 LockContext(Context);
546 values[0] = Source->Position[0];
547 values[1] = Source->Position[1];
548 values[2] = Source->Position[2];
549 UnlockContext(Context);
550 break;
552 case AL_VELOCITY:
553 LockContext(Context);
554 values[0] = Source->Velocity[0];
555 values[1] = Source->Velocity[1];
556 values[2] = Source->Velocity[2];
557 UnlockContext(Context);
558 break;
560 case AL_DIRECTION:
561 LockContext(Context);
562 values[0] = Source->Orientation[0];
563 values[1] = Source->Orientation[1];
564 values[2] = Source->Orientation[2];
565 UnlockContext(Context);
566 break;
568 case AL_SOURCE_RELATIVE:
569 case AL_LOOPING:
570 case AL_BUFFER:
571 case AL_SOURCE_STATE:
572 case AL_BUFFERS_QUEUED:
573 case AL_BUFFERS_PROCESSED:
574 case AL_SOURCE_TYPE:
575 case AL_DIRECT_FILTER_GAINHF_AUTO:
576 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
577 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
578 case AL_DIRECT_CHANNELS_SOFT:
579 case AL_DISTANCE_MODEL:
580 if((err=GetSourceiv(Source, Context, name, ivals)) != AL_NO_ERROR)
581 return err;
582 *values = (ALdouble)ivals[0];
583 break;
585 default:
586 RETERR(AL_INVALID_ENUM);
589 return AL_NO_ERROR;
592 static ALenum GetSourceiv(const ALsource *Source, ALCcontext *Context, ALenum name, ALint *values)
594 ALbufferlistitem *BufferList;
595 ALdouble dvals[3];
596 ALenum err;
598 switch(name)
600 case AL_SOURCE_RELATIVE:
601 *values = Source->HeadRelative;
602 break;
604 case AL_LOOPING:
605 *values = Source->Looping;
606 break;
608 case AL_BUFFER:
609 LockContext(Context);
610 BufferList = Source->queue;
611 if(Source->SourceType != AL_STATIC)
613 ALuint i = Source->BuffersPlayed;
614 while(i > 0)
616 BufferList = BufferList->next;
617 i--;
620 *values = ((BufferList && BufferList->buffer) ?
621 BufferList->buffer->id : 0);
622 UnlockContext(Context);
623 break;
625 case AL_SOURCE_STATE:
626 *values = Source->state;
627 break;
629 case AL_BUFFERS_QUEUED:
630 *values = Source->BuffersInQueue;
631 break;
633 case AL_BUFFERS_PROCESSED:
634 LockContext(Context);
635 if(Source->Looping || Source->SourceType != AL_STREAMING)
637 /* Buffers on a looping source are in a perpetual state of
638 * PENDING, so don't report any as PROCESSED */
639 *values = 0;
641 else
642 *values = Source->BuffersPlayed;
643 UnlockContext(Context);
644 break;
646 case AL_SOURCE_TYPE:
647 *values = Source->SourceType;
648 break;
650 case AL_DIRECT_FILTER_GAINHF_AUTO:
651 *values = Source->DryGainHFAuto;
652 break;
654 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
655 *values = Source->WetGainAuto;
656 break;
658 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
659 *values = Source->WetGainHFAuto;
660 break;
662 case AL_DIRECT_CHANNELS_SOFT:
663 *values = Source->DirectChannels;
664 break;
666 case AL_DISTANCE_MODEL:
667 *values = Source->DistanceModel;
668 break;
670 case AL_MAX_DISTANCE:
671 case AL_ROLLOFF_FACTOR:
672 case AL_REFERENCE_DISTANCE:
673 case AL_CONE_INNER_ANGLE:
674 case AL_CONE_OUTER_ANGLE:
675 case AL_SEC_OFFSET:
676 case AL_SAMPLE_OFFSET:
677 case AL_BYTE_OFFSET:
678 case AL_DOPPLER_FACTOR:
679 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
680 return err;
681 *values = (ALint)dvals[0];
682 break;
684 case AL_SAMPLE_RW_OFFSETS_SOFT:
685 case AL_BYTE_RW_OFFSETS_SOFT:
686 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
687 return err;
688 values[0] = (ALint)dvals[0];
689 values[1] = (ALint)dvals[0];
690 break;
692 case AL_POSITION:
693 case AL_VELOCITY:
694 case AL_DIRECTION:
695 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
696 return err;
697 values[0] = (ALint)dvals[0];
698 values[1] = (ALint)dvals[1];
699 values[2] = (ALint)dvals[2];
700 break;
702 default:
703 RETERR(AL_INVALID_ENUM);
706 return AL_NO_ERROR;
709 static ALenum GetSourcei64v(const ALsource *Source, ALCcontext *Context, ALenum name, ALint64 *values)
711 ALdouble dvals[3];
712 ALint ivals[3];
713 ALenum err;
715 switch(name)
717 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
718 LockContext(Context);
719 values[0] = GetSourceOffset(Source);
720 values[1] = ALCdevice_GetLatency(Context->Device);
721 UnlockContext(Context);
722 break;
724 case AL_MAX_DISTANCE:
725 case AL_ROLLOFF_FACTOR:
726 case AL_REFERENCE_DISTANCE:
727 case AL_CONE_INNER_ANGLE:
728 case AL_CONE_OUTER_ANGLE:
729 case AL_SEC_OFFSET:
730 case AL_SAMPLE_OFFSET:
731 case AL_BYTE_OFFSET:
732 case AL_DOPPLER_FACTOR:
733 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
734 return err;
735 *values = (ALint64)dvals[0];
736 break;
738 case AL_SAMPLE_RW_OFFSETS_SOFT:
739 case AL_BYTE_RW_OFFSETS_SOFT:
740 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
741 return err;
742 values[0] = (ALint64)dvals[0];
743 values[1] = (ALint64)dvals[0];
744 break;
746 case AL_POSITION:
747 case AL_VELOCITY:
748 case AL_DIRECTION:
749 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
750 return err;
751 values[0] = (ALint64)dvals[0];
752 values[1] = (ALint64)dvals[1];
753 values[2] = (ALint64)dvals[2];
754 break;
756 case AL_SOURCE_RELATIVE:
757 case AL_LOOPING:
758 case AL_BUFFER:
759 case AL_SOURCE_STATE:
760 case AL_BUFFERS_QUEUED:
761 case AL_BUFFERS_PROCESSED:
762 case AL_SOURCE_TYPE:
763 case AL_DIRECT_FILTER_GAINHF_AUTO:
764 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
765 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
766 case AL_DIRECT_CHANNELS_SOFT:
767 case AL_DISTANCE_MODEL:
768 if((err=GetSourceiv(Source, Context, name, ivals)) != AL_NO_ERROR)
769 return err;
770 *values = ivals[0];
771 break;
773 default:
774 RETERR(AL_INVALID_ENUM);
777 return AL_NO_ERROR;
780 #undef RETERR
783 AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
785 ALCcontext *Context;
786 ALsizei cur = 0;
788 Context = GetContextRef();
789 if(!Context) return;
791 al_try
793 ALenum err;
795 CHECK_VALUE(Context, n >= 0);
796 for(cur = 0;cur < n;cur++)
798 ALsource *source = al_calloc(16, sizeof(ALsource));
799 if(!source)
800 al_throwerr(Context, AL_OUT_OF_MEMORY);
801 InitSourceParams(source);
803 err = NewThunkEntry(&source->id);
804 if(err == AL_NO_ERROR)
805 err = InsertUIntMapEntry(&Context->SourceMap, source->id, source);
806 if(err != AL_NO_ERROR)
808 FreeThunkEntry(source->id);
809 memset(source, 0, sizeof(ALsource));
810 al_free(source);
812 al_throwerr(Context, err);
815 sources[cur] = source->id;
818 al_catchany()
820 if(cur > 0)
821 alDeleteSources(cur, sources);
823 al_endtry;
825 ALCcontext_DecRef(Context);
829 AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
831 ALCcontext *Context;
833 Context = GetContextRef();
834 if(!Context) return;
836 al_try
838 ALbufferlistitem *BufferList;
839 ALsource *Source;
840 ALsizei i, j;
842 CHECK_VALUE(Context, n >= 0);
844 /* Check that all Sources are valid */
845 for(i = 0;i < n;i++)
847 if(LookupSource(Context, sources[i]) == NULL)
848 al_throwerr(Context, AL_INVALID_NAME);
851 for(i = 0;i < n;i++)
853 ALsource **srclist, **srclistend;
855 if((Source=RemoveSource(Context, sources[i])) == NULL)
856 continue;
857 FreeThunkEntry(Source->id);
859 LockContext(Context);
860 srclist = Context->ActiveSources;
861 srclistend = srclist + Context->ActiveSourceCount;
862 while(srclist != srclistend)
864 if(*srclist == Source)
866 Context->ActiveSourceCount--;
867 *srclist = *(--srclistend);
868 break;
870 srclist++;
872 UnlockContext(Context);
874 while(Source->queue != NULL)
876 BufferList = Source->queue;
877 Source->queue = BufferList->next;
879 if(BufferList->buffer != NULL)
880 DecrementRef(&BufferList->buffer->ref);
881 free(BufferList);
884 for(j = 0;j < MAX_SENDS;++j)
886 if(Source->Send[j].Slot)
887 DecrementRef(&Source->Send[j].Slot->ref);
888 Source->Send[j].Slot = NULL;
891 memset(Source, 0, sizeof(*Source));
892 al_free(Source);
895 al_endtry;
897 ALCcontext_DecRef(Context);
901 AL_API ALboolean AL_APIENTRY alIsSource(ALuint source)
903 ALCcontext *Context;
904 ALboolean result;
906 Context = GetContextRef();
907 if(!Context) return AL_FALSE;
909 result = (LookupSource(Context, source) ? AL_TRUE : AL_FALSE);
911 ALCcontext_DecRef(Context);
913 return result;
917 AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value)
919 ALCcontext *Context;
920 ALsource *Source;
922 Context = GetContextRef();
923 if(!Context) return;
925 if((Source=LookupSource(Context, source)) == NULL)
926 alSetError(Context, AL_INVALID_NAME);
927 else switch(param)
929 case AL_PITCH:
930 case AL_CONE_INNER_ANGLE:
931 case AL_CONE_OUTER_ANGLE:
932 case AL_GAIN:
933 case AL_MAX_DISTANCE:
934 case AL_ROLLOFF_FACTOR:
935 case AL_REFERENCE_DISTANCE:
936 case AL_MIN_GAIN:
937 case AL_MAX_GAIN:
938 case AL_CONE_OUTER_GAIN:
939 case AL_CONE_OUTER_GAINHF:
940 case AL_AIR_ABSORPTION_FACTOR:
941 case AL_ROOM_ROLLOFF_FACTOR:
942 case AL_DOPPLER_FACTOR:
943 case AL_SEC_OFFSET:
944 case AL_SAMPLE_OFFSET:
945 case AL_BYTE_OFFSET:
946 SetSourcefv(Source, Context, param, &value);
947 break;
949 default:
950 alSetError(Context, AL_INVALID_ENUM);
953 ALCcontext_DecRef(Context);
956 AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
958 ALCcontext *Context;
959 ALsource *Source;
960 ALfloat fvals[3];
962 Context = GetContextRef();
963 if(!Context) return;
965 if((Source=LookupSource(Context, source)) == NULL)
966 alSetError(Context, AL_INVALID_NAME);
967 else switch(param)
969 case AL_POSITION:
970 case AL_VELOCITY:
971 case AL_DIRECTION:
972 fvals[0] = value1;
973 fvals[1] = value2;
974 fvals[2] = value3;
975 SetSourcefv(Source, Context, param, fvals);
976 break;
978 default:
979 alSetError(Context, AL_INVALID_ENUM);
982 ALCcontext_DecRef(Context);
985 AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values)
987 ALCcontext *Context;
988 ALsource *Source;
990 Context = GetContextRef();
991 if(!Context) return;
993 if((Source=LookupSource(Context, source)) == NULL)
994 alSetError(Context, AL_INVALID_NAME);
995 else if(!values)
996 alSetError(Context, AL_INVALID_VALUE);
997 else switch(param)
999 case AL_PITCH:
1000 case AL_CONE_INNER_ANGLE:
1001 case AL_CONE_OUTER_ANGLE:
1002 case AL_GAIN:
1003 case AL_MAX_DISTANCE:
1004 case AL_ROLLOFF_FACTOR:
1005 case AL_REFERENCE_DISTANCE:
1006 case AL_MIN_GAIN:
1007 case AL_MAX_GAIN:
1008 case AL_CONE_OUTER_GAIN:
1009 case AL_CONE_OUTER_GAINHF:
1010 case AL_SEC_OFFSET:
1011 case AL_SAMPLE_OFFSET:
1012 case AL_BYTE_OFFSET:
1013 case AL_AIR_ABSORPTION_FACTOR:
1014 case AL_ROOM_ROLLOFF_FACTOR:
1016 case AL_POSITION:
1017 case AL_VELOCITY:
1018 case AL_DIRECTION:
1019 SetSourcefv(Source, Context, param, values);
1020 break;
1022 default:
1023 alSetError(Context, AL_INVALID_ENUM);
1026 ALCcontext_DecRef(Context);
1030 AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value)
1032 ALCcontext *Context;
1033 ALsource *Source;
1034 ALfloat fval;
1036 Context = GetContextRef();
1037 if(!Context) return;
1039 if((Source=LookupSource(Context, source)) == NULL)
1040 alSetError(Context, AL_INVALID_NAME);
1041 else switch(param)
1043 case AL_PITCH:
1044 case AL_CONE_INNER_ANGLE:
1045 case AL_CONE_OUTER_ANGLE:
1046 case AL_GAIN:
1047 case AL_MAX_DISTANCE:
1048 case AL_ROLLOFF_FACTOR:
1049 case AL_REFERENCE_DISTANCE:
1050 case AL_MIN_GAIN:
1051 case AL_MAX_GAIN:
1052 case AL_CONE_OUTER_GAIN:
1053 case AL_CONE_OUTER_GAINHF:
1054 case AL_AIR_ABSORPTION_FACTOR:
1055 case AL_ROOM_ROLLOFF_FACTOR:
1056 case AL_DOPPLER_FACTOR:
1057 case AL_SEC_OFFSET:
1058 case AL_SAMPLE_OFFSET:
1059 case AL_BYTE_OFFSET:
1060 fval = value;
1061 SetSourcefv(Source, Context, param, &fval);
1062 break;
1064 default:
1065 alSetError(Context, AL_INVALID_ENUM);
1068 ALCcontext_DecRef(Context);
1071 AL_API ALvoid AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3)
1073 ALCcontext *Context;
1074 ALsource *Source;
1075 ALfloat fvals[3];
1077 Context = GetContextRef();
1078 if(!Context) return;
1080 if((Source=LookupSource(Context, source)) == NULL)
1081 alSetError(Context, AL_INVALID_NAME);
1082 else switch(param)
1084 case AL_POSITION:
1085 case AL_VELOCITY:
1086 case AL_DIRECTION:
1087 fvals[0] = value1;
1088 fvals[1] = value2;
1089 fvals[2] = value3;
1090 SetSourcefv(Source, Context, param, fvals);
1091 break;
1093 default:
1094 alSetError(Context, AL_INVALID_ENUM);
1097 ALCcontext_DecRef(Context);
1100 AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values)
1102 ALCcontext *Context;
1103 ALsource *Source;
1104 ALfloat fvals[3];
1106 Context = GetContextRef();
1107 if(!Context) return;
1109 if((Source=LookupSource(Context, source)) == NULL)
1110 alSetError(Context, AL_INVALID_NAME);
1111 else if(!values)
1112 alSetError(Context, AL_INVALID_VALUE);
1113 else switch(param)
1115 case AL_PITCH:
1116 case AL_CONE_INNER_ANGLE:
1117 case AL_CONE_OUTER_ANGLE:
1118 case AL_GAIN:
1119 case AL_MAX_DISTANCE:
1120 case AL_ROLLOFF_FACTOR:
1121 case AL_REFERENCE_DISTANCE:
1122 case AL_MIN_GAIN:
1123 case AL_MAX_GAIN:
1124 case AL_CONE_OUTER_GAIN:
1125 case AL_CONE_OUTER_GAINHF:
1126 case AL_SEC_OFFSET:
1127 case AL_SAMPLE_OFFSET:
1128 case AL_BYTE_OFFSET:
1129 case AL_AIR_ABSORPTION_FACTOR:
1130 case AL_ROOM_ROLLOFF_FACTOR:
1131 fvals[0] = values[0];
1132 SetSourcefv(Source, Context, param, fvals);
1133 break;
1135 case AL_POSITION:
1136 case AL_VELOCITY:
1137 case AL_DIRECTION:
1138 fvals[0] = values[0];
1139 fvals[1] = values[1];
1140 fvals[2] = values[2];
1141 SetSourcefv(Source, Context, param, fvals);
1142 break;
1144 default:
1145 alSetError(Context, AL_INVALID_ENUM);
1148 ALCcontext_DecRef(Context);
1152 AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value)
1154 ALCcontext *Context;
1155 ALsource *Source;
1157 Context = GetContextRef();
1158 if(!Context) return;
1160 if((Source=LookupSource(Context, source)) == NULL)
1161 alSetError(Context, AL_INVALID_NAME);
1162 else switch(param)
1164 case AL_MAX_DISTANCE:
1165 case AL_ROLLOFF_FACTOR:
1166 case AL_CONE_INNER_ANGLE:
1167 case AL_CONE_OUTER_ANGLE:
1168 case AL_REFERENCE_DISTANCE:
1169 case AL_SOURCE_RELATIVE:
1170 case AL_LOOPING:
1171 case AL_BUFFER:
1172 case AL_SOURCE_STATE:
1173 case AL_SEC_OFFSET:
1174 case AL_SAMPLE_OFFSET:
1175 case AL_BYTE_OFFSET:
1176 case AL_DIRECT_FILTER:
1177 case AL_DIRECT_FILTER_GAINHF_AUTO:
1178 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1179 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1180 case AL_DIRECT_CHANNELS_SOFT:
1181 case AL_DISTANCE_MODEL:
1182 SetSourceiv(Source, Context, param, &value);
1183 break;
1185 default:
1186 alSetError(Context, AL_INVALID_ENUM);
1189 ALCcontext_DecRef(Context);
1192 AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3)
1194 ALCcontext *Context;
1195 ALsource *Source;
1196 ALint ivals[3];
1198 Context = GetContextRef();
1199 if(!Context) return;
1201 if((Source=LookupSource(Context, source)) == NULL)
1202 alSetError(Context, AL_INVALID_NAME);
1203 else switch(param)
1205 case AL_POSITION:
1206 case AL_VELOCITY:
1207 case AL_DIRECTION:
1208 case AL_AUXILIARY_SEND_FILTER:
1209 ivals[0] = value1;
1210 ivals[1] = value2;
1211 ivals[2] = value3;
1212 SetSourceiv(Source, Context, param, ivals);
1213 break;
1215 default:
1216 alSetError(Context, AL_INVALID_ENUM);
1219 ALCcontext_DecRef(Context);
1222 AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values)
1224 ALCcontext *Context;
1225 ALsource *Source;
1227 Context = GetContextRef();
1228 if(!Context) return;
1230 if((Source=LookupSource(Context, source)) == NULL)
1231 alSetError(Context, AL_INVALID_NAME);
1232 else if(!values)
1233 alSetError(Context, AL_INVALID_VALUE);
1234 else switch(param)
1236 case AL_SOURCE_RELATIVE:
1237 case AL_CONE_INNER_ANGLE:
1238 case AL_CONE_OUTER_ANGLE:
1239 case AL_LOOPING:
1240 case AL_BUFFER:
1241 case AL_SOURCE_STATE:
1242 case AL_SEC_OFFSET:
1243 case AL_SAMPLE_OFFSET:
1244 case AL_BYTE_OFFSET:
1245 case AL_MAX_DISTANCE:
1246 case AL_ROLLOFF_FACTOR:
1247 case AL_REFERENCE_DISTANCE:
1248 case AL_DIRECT_FILTER:
1249 case AL_DIRECT_FILTER_GAINHF_AUTO:
1250 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1251 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1252 case AL_DISTANCE_MODEL:
1253 case AL_DIRECT_CHANNELS_SOFT:
1255 case AL_POSITION:
1256 case AL_VELOCITY:
1257 case AL_DIRECTION:
1258 case AL_AUXILIARY_SEND_FILTER:
1259 SetSourceiv(Source, Context, param, values);
1260 break;
1262 default:
1263 alSetError(Context, AL_INVALID_ENUM);
1266 ALCcontext_DecRef(Context);
1270 AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value)
1272 ALCcontext *Context;
1273 ALsource *Source;
1275 Context = GetContextRef();
1276 if(!Context) return;
1278 if((Source=LookupSource(Context, source)) == NULL)
1279 alSetError(Context, AL_INVALID_NAME);
1280 else switch(param)
1282 case AL_MAX_DISTANCE:
1283 case AL_ROLLOFF_FACTOR:
1284 case AL_CONE_INNER_ANGLE:
1285 case AL_CONE_OUTER_ANGLE:
1286 case AL_REFERENCE_DISTANCE:
1287 case AL_SOURCE_RELATIVE:
1288 case AL_LOOPING:
1289 case AL_SOURCE_STATE:
1290 case AL_SEC_OFFSET:
1291 case AL_SAMPLE_OFFSET:
1292 case AL_BYTE_OFFSET:
1293 case AL_DIRECT_FILTER_GAINHF_AUTO:
1294 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1295 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1296 case AL_DIRECT_CHANNELS_SOFT:
1297 case AL_DISTANCE_MODEL:
1298 if(!(value <= INT_MAX && value >= INT_MIN))
1299 alSetError(Context, AL_INVALID_VALUE);
1300 else
1302 ALint ival = value;
1303 SetSourceiv(Source, Context, param, &ival);
1305 break;
1307 case AL_BUFFER:
1308 case AL_DIRECT_FILTER:
1309 if(!(value <= UINT_MAX && value >= 0))
1310 alSetError(Context, AL_INVALID_VALUE);
1311 else
1313 ALint ival = value;
1314 SetSourceiv(Source, Context, param, &ival);
1316 break;
1318 default:
1319 alSetError(Context, AL_INVALID_ENUM);
1322 ALCcontext_DecRef(Context);
1325 AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3)
1327 ALCcontext *Context;
1328 ALsource *Source;
1330 Context = GetContextRef();
1331 if(!Context) return;
1333 if((Source=LookupSource(Context, source)) == NULL)
1334 alSetError(Context, AL_INVALID_NAME);
1335 else switch(param)
1337 case AL_POSITION:
1338 case AL_VELOCITY:
1339 case AL_DIRECTION:
1340 if(!(value1 <= INT_MAX && value1 >= INT_MIN &&
1341 value2 <= INT_MAX && value2 >= INT_MIN &&
1342 value3 <= INT_MAX && value3 >= INT_MIN))
1343 alSetError(Context, AL_INVALID_VALUE);
1344 else
1346 ALint ivals[3] = { value1, value2, value3 };
1347 SetSourceiv(Source, Context, param, ivals);
1349 break;
1351 case AL_AUXILIARY_SEND_FILTER:
1352 if(!(value1 <= UINT_MAX && value1 >= 0 &&
1353 value2 <= UINT_MAX && value2 >= 0 &&
1354 value3 <= UINT_MAX && value3 >= 0))
1355 alSetError(Context, AL_INVALID_VALUE);
1356 else
1358 ALint ivals[3] = { value1, value2, value3 };
1359 SetSourceiv(Source, Context, param, ivals);
1361 break;
1363 default:
1364 alSetError(Context, AL_INVALID_ENUM);
1367 ALCcontext_DecRef(Context);
1370 AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values)
1372 ALCcontext *Context;
1373 ALsource *Source;
1375 Context = GetContextRef();
1376 if(!Context) return;
1378 if((Source=LookupSource(Context, source)) == NULL)
1379 alSetError(Context, AL_INVALID_NAME);
1380 else if(!values)
1381 alSetError(Context, AL_INVALID_VALUE);
1382 else switch(param)
1384 case AL_SOURCE_RELATIVE:
1385 case AL_CONE_INNER_ANGLE:
1386 case AL_CONE_OUTER_ANGLE:
1387 case AL_LOOPING:
1388 case AL_SOURCE_STATE:
1389 case AL_SEC_OFFSET:
1390 case AL_SAMPLE_OFFSET:
1391 case AL_BYTE_OFFSET:
1392 case AL_MAX_DISTANCE:
1393 case AL_ROLLOFF_FACTOR:
1394 case AL_REFERENCE_DISTANCE:
1395 case AL_DIRECT_FILTER_GAINHF_AUTO:
1396 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1397 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1398 case AL_DISTANCE_MODEL:
1399 case AL_DIRECT_CHANNELS_SOFT:
1400 if(!(values[0] <= INT_MAX && values[0] >= INT_MIN))
1401 alSetError(Context, AL_INVALID_VALUE);
1402 else
1404 ALint ival = values[0];
1405 SetSourceiv(Source, Context, param, &ival);
1407 break;
1409 case AL_BUFFER:
1410 case AL_DIRECT_FILTER:
1411 if(!(values[0] <= UINT_MAX && values[0] >= 0))
1412 alSetError(Context, AL_INVALID_VALUE);
1413 else
1415 ALint ival = values[0];
1416 SetSourceiv(Source, Context, param, &ival);
1418 break;
1420 case AL_POSITION:
1421 case AL_VELOCITY:
1422 case AL_DIRECTION:
1423 if(!(values[0] <= INT_MAX && values[0] >= INT_MIN &&
1424 values[1] <= INT_MAX && values[1] >= INT_MIN &&
1425 values[2] <= INT_MAX && values[2] >= INT_MIN))
1426 alSetError(Context, AL_INVALID_VALUE);
1427 else
1429 ALint ivals[3] = { values[0], values[1], values[2] };
1430 SetSourceiv(Source, Context, param, ivals);
1432 break;
1434 case AL_AUXILIARY_SEND_FILTER:
1435 if(!(values[0] <= UINT_MAX && values[0] >= 0 &&
1436 values[1] <= UINT_MAX && values[1] >= 0 &&
1437 values[2] <= UINT_MAX && values[2] >= 0))
1438 alSetError(Context, AL_INVALID_VALUE);
1439 else
1441 ALint ivals[3] = { values[0], values[1], values[2] };
1442 SetSourceiv(Source, Context, param, ivals);
1444 break;
1446 default:
1447 alSetError(Context, AL_INVALID_ENUM);
1450 ALCcontext_DecRef(Context);
1454 AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value)
1456 ALCcontext *Context;
1457 ALsource *Source;
1458 ALdouble dval;
1460 Context = GetContextRef();
1461 if(!Context) return;
1463 if((Source=LookupSource(Context, source)) == NULL)
1464 alSetError(Context, AL_INVALID_NAME);
1465 else if(!value)
1466 alSetError(Context, AL_INVALID_VALUE);
1467 else switch(param)
1469 case AL_PITCH:
1470 case AL_GAIN:
1471 case AL_MIN_GAIN:
1472 case AL_MAX_GAIN:
1473 case AL_MAX_DISTANCE:
1474 case AL_ROLLOFF_FACTOR:
1475 case AL_CONE_OUTER_GAIN:
1476 case AL_CONE_OUTER_GAINHF:
1477 case AL_SEC_OFFSET:
1478 case AL_SAMPLE_OFFSET:
1479 case AL_BYTE_OFFSET:
1480 case AL_CONE_INNER_ANGLE:
1481 case AL_CONE_OUTER_ANGLE:
1482 case AL_REFERENCE_DISTANCE:
1483 case AL_AIR_ABSORPTION_FACTOR:
1484 case AL_ROOM_ROLLOFF_FACTOR:
1485 case AL_DOPPLER_FACTOR:
1486 if(GetSourcedv(Source, Context, param, &dval) == AL_NO_ERROR)
1487 *value = (ALfloat)dval;
1488 break;
1490 default:
1491 alSetError(Context, AL_INVALID_ENUM);
1494 ALCcontext_DecRef(Context);
1498 AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
1500 ALCcontext *Context;
1501 ALsource *Source;
1502 ALdouble dvals[3];
1504 Context = GetContextRef();
1505 if(!Context) return;
1507 if((Source=LookupSource(Context, source)) == NULL)
1508 alSetError(Context, AL_INVALID_NAME);
1509 else if(!(value1 && value2 && value3))
1510 alSetError(Context, AL_INVALID_VALUE);
1511 else switch(param)
1513 case AL_POSITION:
1514 case AL_VELOCITY:
1515 case AL_DIRECTION:
1516 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1518 *value1 = (ALfloat)dvals[0];
1519 *value2 = (ALfloat)dvals[1];
1520 *value3 = (ALfloat)dvals[2];
1522 break;
1524 default:
1525 alSetError(Context, AL_INVALID_ENUM);
1528 ALCcontext_DecRef(Context);
1532 AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values)
1534 ALCcontext *Context;
1535 ALsource *Source;
1536 ALdouble dvals[2];
1538 switch(param)
1540 case AL_PITCH:
1541 case AL_GAIN:
1542 case AL_MIN_GAIN:
1543 case AL_MAX_GAIN:
1544 case AL_MAX_DISTANCE:
1545 case AL_ROLLOFF_FACTOR:
1546 case AL_DOPPLER_FACTOR:
1547 case AL_CONE_OUTER_GAIN:
1548 case AL_SEC_OFFSET:
1549 case AL_SAMPLE_OFFSET:
1550 case AL_BYTE_OFFSET:
1551 case AL_CONE_INNER_ANGLE:
1552 case AL_CONE_OUTER_ANGLE:
1553 case AL_REFERENCE_DISTANCE:
1554 case AL_CONE_OUTER_GAINHF:
1555 case AL_AIR_ABSORPTION_FACTOR:
1556 case AL_ROOM_ROLLOFF_FACTOR:
1557 alGetSourcef(source, param, values);
1558 return;
1560 case AL_POSITION:
1561 case AL_VELOCITY:
1562 case AL_DIRECTION:
1563 alGetSource3f(source, param, values+0, values+1, values+2);
1564 return;
1567 Context = GetContextRef();
1568 if(!Context) return;
1570 if((Source=LookupSource(Context, source)) == NULL)
1571 alSetError(Context, AL_INVALID_NAME);
1572 else if(!values)
1573 alSetError(Context, AL_INVALID_VALUE);
1574 else switch(param)
1576 case AL_SAMPLE_RW_OFFSETS_SOFT:
1577 case AL_BYTE_RW_OFFSETS_SOFT:
1578 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1580 values[0] = (ALfloat)dvals[0];
1581 values[1] = (ALfloat)dvals[1];
1583 break;
1585 default:
1586 alSetError(Context, AL_INVALID_ENUM);
1589 ALCcontext_DecRef(Context);
1593 AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value)
1595 ALCcontext *Context;
1596 ALsource *Source;
1598 Context = GetContextRef();
1599 if(!Context) return;
1601 if((Source=LookupSource(Context, source)) == NULL)
1602 alSetError(Context, AL_INVALID_NAME);
1603 else if(!value)
1604 alSetError(Context, AL_INVALID_VALUE);
1605 else switch(param)
1607 case AL_PITCH:
1608 case AL_GAIN:
1609 case AL_MIN_GAIN:
1610 case AL_MAX_GAIN:
1611 case AL_MAX_DISTANCE:
1612 case AL_ROLLOFF_FACTOR:
1613 case AL_CONE_OUTER_GAIN:
1614 case AL_CONE_OUTER_GAINHF:
1615 case AL_SEC_OFFSET:
1616 case AL_SAMPLE_OFFSET:
1617 case AL_BYTE_OFFSET:
1618 case AL_CONE_INNER_ANGLE:
1619 case AL_CONE_OUTER_ANGLE:
1620 case AL_REFERENCE_DISTANCE:
1621 case AL_AIR_ABSORPTION_FACTOR:
1622 case AL_ROOM_ROLLOFF_FACTOR:
1623 case AL_DOPPLER_FACTOR:
1624 GetSourcedv(Source, Context, param, value);
1625 break;
1627 default:
1628 alSetError(Context, AL_INVALID_ENUM);
1631 ALCcontext_DecRef(Context);
1634 AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3)
1636 ALCcontext *Context;
1637 ALsource *Source;
1638 ALdouble dvals[3];
1640 Context = GetContextRef();
1641 if(!Context) return;
1643 if((Source=LookupSource(Context, source)) == NULL)
1644 alSetError(Context, AL_INVALID_NAME);
1645 else if(!(value1 && value2 && value3))
1646 alSetError(Context, AL_INVALID_VALUE);
1647 else switch(param)
1649 case AL_POSITION:
1650 case AL_VELOCITY:
1651 case AL_DIRECTION:
1652 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1654 *value1 = dvals[0];
1655 *value2 = dvals[1];
1656 *value3 = dvals[2];
1658 break;
1660 default:
1661 alSetError(Context, AL_INVALID_ENUM);
1664 ALCcontext_DecRef(Context);
1667 AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values)
1669 ALCcontext *Context;
1670 ALsource *Source;
1672 Context = GetContextRef();
1673 if(!Context) return;
1675 if((Source=LookupSource(Context, source)) == NULL)
1676 alSetError(Context, AL_INVALID_NAME);
1677 else if(!values)
1678 alSetError(Context, AL_INVALID_VALUE);
1679 else switch(param)
1681 case AL_PITCH:
1682 case AL_GAIN:
1683 case AL_MIN_GAIN:
1684 case AL_MAX_GAIN:
1685 case AL_MAX_DISTANCE:
1686 case AL_ROLLOFF_FACTOR:
1687 case AL_DOPPLER_FACTOR:
1688 case AL_CONE_OUTER_GAIN:
1689 case AL_SEC_OFFSET:
1690 case AL_SAMPLE_OFFSET:
1691 case AL_BYTE_OFFSET:
1692 case AL_CONE_INNER_ANGLE:
1693 case AL_CONE_OUTER_ANGLE:
1694 case AL_REFERENCE_DISTANCE:
1695 case AL_CONE_OUTER_GAINHF:
1696 case AL_AIR_ABSORPTION_FACTOR:
1697 case AL_ROOM_ROLLOFF_FACTOR:
1699 case AL_SAMPLE_RW_OFFSETS_SOFT:
1700 case AL_BYTE_RW_OFFSETS_SOFT:
1701 case AL_SEC_OFFSET_LATENCY_SOFT:
1703 case AL_POSITION:
1704 case AL_VELOCITY:
1705 case AL_DIRECTION:
1706 GetSourcedv(Source, Context, param, values);
1707 break;
1709 default:
1710 alSetError(Context, AL_INVALID_ENUM);
1713 ALCcontext_DecRef(Context);
1717 AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value)
1719 ALCcontext *Context;
1720 ALsource *Source;
1722 Context = GetContextRef();
1723 if(!Context) return;
1725 if((Source=LookupSource(Context, source)) == NULL)
1726 alSetError(Context, AL_INVALID_NAME);
1727 else if(!value)
1728 alSetError(Context, AL_INVALID_VALUE);
1729 else switch(param)
1731 case AL_MAX_DISTANCE:
1732 case AL_ROLLOFF_FACTOR:
1733 case AL_REFERENCE_DISTANCE:
1734 case AL_SOURCE_RELATIVE:
1735 case AL_CONE_INNER_ANGLE:
1736 case AL_CONE_OUTER_ANGLE:
1737 case AL_LOOPING:
1738 case AL_BUFFER:
1739 case AL_SOURCE_STATE:
1740 case AL_BUFFERS_QUEUED:
1741 case AL_BUFFERS_PROCESSED:
1742 case AL_SOURCE_TYPE:
1743 case AL_SEC_OFFSET:
1744 case AL_SAMPLE_OFFSET:
1745 case AL_BYTE_OFFSET:
1746 case AL_DIRECT_FILTER_GAINHF_AUTO:
1747 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1748 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1749 case AL_DOPPLER_FACTOR:
1750 case AL_DIRECT_CHANNELS_SOFT:
1751 case AL_DISTANCE_MODEL:
1752 GetSourceiv(Source, Context, param, value);
1753 break;
1755 default:
1756 alSetError(Context, AL_INVALID_ENUM);
1759 ALCcontext_DecRef(Context);
1763 AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3)
1765 ALCcontext *Context;
1766 ALsource *Source;
1767 ALint ivals[3];
1769 Context = GetContextRef();
1770 if(!Context) return;
1772 if((Source=LookupSource(Context, source)) == NULL)
1773 alSetError(Context, AL_INVALID_NAME);
1774 else if(!(value1 && value2 && value3))
1775 alSetError(Context, AL_INVALID_VALUE);
1776 else switch(param)
1778 case AL_POSITION:
1779 case AL_VELOCITY:
1780 case AL_DIRECTION:
1781 if(GetSourceiv(Source, Context, param, ivals) == AL_NO_ERROR)
1783 *value1 = ivals[0];
1784 *value2 = ivals[1];
1785 *value3 = ivals[2];
1787 break;
1789 default:
1790 alSetError(Context, AL_INVALID_ENUM);
1793 ALCcontext_DecRef(Context);
1797 AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values)
1799 ALCcontext *Context;
1800 ALsource *Source;
1802 Context = GetContextRef();
1803 if(!Context) return;
1805 if((Source=LookupSource(Context, source)) == NULL)
1806 alSetError(Context, AL_INVALID_NAME);
1807 else if(!values)
1808 alSetError(Context, AL_INVALID_VALUE);
1809 else switch(param)
1811 case AL_SOURCE_RELATIVE:
1812 case AL_CONE_INNER_ANGLE:
1813 case AL_CONE_OUTER_ANGLE:
1814 case AL_LOOPING:
1815 case AL_BUFFER:
1816 case AL_SOURCE_STATE:
1817 case AL_BUFFERS_QUEUED:
1818 case AL_BUFFERS_PROCESSED:
1819 case AL_SEC_OFFSET:
1820 case AL_SAMPLE_OFFSET:
1821 case AL_BYTE_OFFSET:
1822 case AL_MAX_DISTANCE:
1823 case AL_ROLLOFF_FACTOR:
1824 case AL_DOPPLER_FACTOR:
1825 case AL_REFERENCE_DISTANCE:
1826 case AL_SOURCE_TYPE:
1827 case AL_DIRECT_FILTER:
1828 case AL_DIRECT_FILTER_GAINHF_AUTO:
1829 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1830 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1831 case AL_DISTANCE_MODEL:
1832 case AL_DIRECT_CHANNELS_SOFT:
1834 case AL_SAMPLE_RW_OFFSETS_SOFT:
1835 case AL_BYTE_RW_OFFSETS_SOFT:
1837 case AL_POSITION:
1838 case AL_VELOCITY:
1839 case AL_DIRECTION:
1840 GetSourceiv(Source, Context, param, values);
1841 break;
1843 default:
1844 alSetError(Context, AL_INVALID_ENUM);
1847 ALCcontext_DecRef(Context);
1851 AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value)
1853 ALCcontext *Context;
1854 ALsource *Source;
1856 Context = GetContextRef();
1857 if(!Context) return;
1859 if((Source=LookupSource(Context, source)) == NULL)
1860 alSetError(Context, AL_INVALID_NAME);
1861 else if(!value)
1862 alSetError(Context, AL_INVALID_VALUE);
1863 else switch(param)
1865 case AL_MAX_DISTANCE:
1866 case AL_ROLLOFF_FACTOR:
1867 case AL_REFERENCE_DISTANCE:
1868 case AL_SOURCE_RELATIVE:
1869 case AL_CONE_INNER_ANGLE:
1870 case AL_CONE_OUTER_ANGLE:
1871 case AL_LOOPING:
1872 case AL_BUFFER:
1873 case AL_SOURCE_STATE:
1874 case AL_BUFFERS_QUEUED:
1875 case AL_BUFFERS_PROCESSED:
1876 case AL_SOURCE_TYPE:
1877 case AL_SEC_OFFSET:
1878 case AL_SAMPLE_OFFSET:
1879 case AL_BYTE_OFFSET:
1880 case AL_DIRECT_FILTER_GAINHF_AUTO:
1881 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1882 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1883 case AL_DOPPLER_FACTOR:
1884 case AL_DIRECT_CHANNELS_SOFT:
1885 case AL_DISTANCE_MODEL:
1886 GetSourcei64v(Source, Context, param, value);
1887 break;
1889 default:
1890 alSetError(Context, AL_INVALID_ENUM);
1893 ALCcontext_DecRef(Context);
1896 AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3)
1898 ALCcontext *Context;
1899 ALsource *Source;
1900 ALint64 i64vals[3];
1902 Context = GetContextRef();
1903 if(!Context) return;
1905 if((Source=LookupSource(Context, source)) == NULL)
1906 alSetError(Context, AL_INVALID_NAME);
1907 else if(!(value1 && value2 && value3))
1908 alSetError(Context, AL_INVALID_VALUE);
1909 else switch(param)
1911 case AL_POSITION:
1912 case AL_VELOCITY:
1913 case AL_DIRECTION:
1914 if(GetSourcei64v(Source, Context, param, i64vals) == AL_NO_ERROR)
1916 *value1 = i64vals[0];
1917 *value2 = i64vals[1];
1918 *value3 = i64vals[2];
1920 break;
1922 default:
1923 alSetError(Context, AL_INVALID_ENUM);
1926 ALCcontext_DecRef(Context);
1929 AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values)
1931 ALCcontext *Context;
1932 ALsource *Source;
1934 Context = GetContextRef();
1935 if(!Context) return;
1937 if((Source=LookupSource(Context, source)) == NULL)
1938 alSetError(Context, AL_INVALID_NAME);
1939 else if(!values)
1940 alSetError(Context, AL_INVALID_VALUE);
1941 else switch(param)
1943 case AL_MAX_DISTANCE:
1944 case AL_ROLLOFF_FACTOR:
1945 case AL_REFERENCE_DISTANCE:
1946 case AL_SOURCE_RELATIVE:
1947 case AL_CONE_INNER_ANGLE:
1948 case AL_CONE_OUTER_ANGLE:
1949 case AL_LOOPING:
1950 case AL_BUFFER:
1951 case AL_SOURCE_STATE:
1952 case AL_BUFFERS_QUEUED:
1953 case AL_BUFFERS_PROCESSED:
1954 case AL_SOURCE_TYPE:
1955 case AL_SEC_OFFSET:
1956 case AL_SAMPLE_OFFSET:
1957 case AL_BYTE_OFFSET:
1958 case AL_DIRECT_FILTER_GAINHF_AUTO:
1959 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1960 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1961 case AL_DOPPLER_FACTOR:
1962 case AL_DIRECT_CHANNELS_SOFT:
1963 case AL_DISTANCE_MODEL:
1965 case AL_SAMPLE_RW_OFFSETS_SOFT:
1966 case AL_BYTE_RW_OFFSETS_SOFT:
1967 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
1969 case AL_POSITION:
1970 case AL_VELOCITY:
1971 case AL_DIRECTION:
1972 GetSourcei64v(Source, Context, param, values);
1973 break;
1975 default:
1976 alSetError(Context, AL_INVALID_ENUM);
1979 ALCcontext_DecRef(Context);
1983 AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint source)
1985 alSourcePlayv(1, &source);
1987 AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
1989 ALCcontext *Context;
1990 ALsource *Source;
1991 ALsizei i;
1993 Context = GetContextRef();
1994 if(!Context) return;
1996 al_try
1998 CHECK_VALUE(Context, n >= 0);
1999 for(i = 0;i < n;i++)
2001 if(!LookupSource(Context, sources[i]))
2002 al_throwerr(Context, AL_INVALID_NAME);
2005 LockContext(Context);
2006 while(Context->MaxActiveSources-Context->ActiveSourceCount < n)
2008 void *temp = NULL;
2009 ALsizei newcount;
2011 newcount = Context->MaxActiveSources << 1;
2012 if(newcount > 0)
2013 temp = realloc(Context->ActiveSources,
2014 sizeof(*Context->ActiveSources) * newcount);
2015 if(!temp)
2017 UnlockContext(Context);
2018 al_throwerr(Context, AL_OUT_OF_MEMORY);
2021 Context->ActiveSources = temp;
2022 Context->MaxActiveSources = newcount;
2025 for(i = 0;i < n;i++)
2027 Source = LookupSource(Context, sources[i]);
2028 if(Context->DeferUpdates) Source->new_state = AL_PLAYING;
2029 else SetSourceState(Source, Context, AL_PLAYING);
2031 UnlockContext(Context);
2033 al_endtry;
2035 ALCcontext_DecRef(Context);
2038 AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source)
2040 alSourcePausev(1, &source);
2042 AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
2044 ALCcontext *Context;
2045 ALsource *Source;
2046 ALsizei i;
2048 Context = GetContextRef();
2049 if(!Context) return;
2051 al_try
2053 CHECK_VALUE(Context, n >= 0);
2054 for(i = 0;i < n;i++)
2056 if(!LookupSource(Context, sources[i]))
2057 al_throwerr(Context, AL_INVALID_NAME);
2060 LockContext(Context);
2061 for(i = 0;i < n;i++)
2063 Source = LookupSource(Context, sources[i]);
2064 if(Context->DeferUpdates) Source->new_state = AL_PAUSED;
2065 else SetSourceState(Source, Context, AL_PAUSED);
2067 UnlockContext(Context);
2069 al_endtry;
2071 ALCcontext_DecRef(Context);
2074 AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source)
2076 alSourceStopv(1, &source);
2078 AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
2080 ALCcontext *Context;
2081 ALsource *Source;
2082 ALsizei i;
2084 Context = GetContextRef();
2085 if(!Context) return;
2087 al_try
2089 CHECK_VALUE(Context, n >= 0);
2090 for(i = 0;i < n;i++)
2092 if(!LookupSource(Context, sources[i]))
2093 al_throwerr(Context, AL_INVALID_NAME);
2096 LockContext(Context);
2097 for(i = 0;i < n;i++)
2099 Source = LookupSource(Context, sources[i]);
2100 Source->new_state = AL_NONE;
2101 SetSourceState(Source, Context, AL_STOPPED);
2103 UnlockContext(Context);
2105 al_endtry;
2107 ALCcontext_DecRef(Context);
2110 AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source)
2112 alSourceRewindv(1, &source);
2114 AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
2116 ALCcontext *Context;
2117 ALsource *Source;
2118 ALsizei i;
2120 Context = GetContextRef();
2121 if(!Context) return;
2123 al_try
2125 CHECK_VALUE(Context, n >= 0);
2126 for(i = 0;i < n;i++)
2128 if(!LookupSource(Context, sources[i]))
2129 al_throwerr(Context, AL_INVALID_NAME);
2132 LockContext(Context);
2133 for(i = 0;i < n;i++)
2135 Source = LookupSource(Context, sources[i]);
2136 Source->new_state = AL_NONE;
2137 SetSourceState(Source, Context, AL_INITIAL);
2139 UnlockContext(Context);
2141 al_endtry;
2143 ALCcontext_DecRef(Context);
2147 AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers)
2149 ALCcontext *Context;
2150 ALsource *Source;
2151 ALsizei i;
2152 ALbufferlistitem *BufferListStart = NULL;
2153 ALbufferlistitem *BufferList;
2154 ALbuffer *BufferFmt;
2156 if(nb == 0)
2157 return;
2159 Context = GetContextRef();
2160 if(!Context) return;
2162 al_try
2164 ALCdevice *device = Context->Device;
2166 CHECK_VALUE(Context, nb >= 0);
2168 if((Source=LookupSource(Context, source)) == NULL)
2169 al_throwerr(Context, AL_INVALID_NAME);
2171 LockContext(Context);
2172 if(Source->SourceType == AL_STATIC)
2174 UnlockContext(Context);
2175 /* Can't queue on a Static Source */
2176 al_throwerr(Context, AL_INVALID_OPERATION);
2179 BufferFmt = NULL;
2181 /* Check for a valid Buffer, for its frequency and format */
2182 BufferList = Source->queue;
2183 while(BufferList)
2185 if(BufferList->buffer)
2187 BufferFmt = BufferList->buffer;
2188 break;
2190 BufferList = BufferList->next;
2193 for(i = 0;i < nb;i++)
2195 ALbuffer *buffer = NULL;
2196 if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
2198 UnlockContext(Context);
2199 al_throwerr(Context, AL_INVALID_NAME);
2202 if(!BufferListStart)
2204 BufferListStart = malloc(sizeof(ALbufferlistitem));
2205 BufferListStart->buffer = buffer;
2206 BufferListStart->next = NULL;
2207 BufferListStart->prev = NULL;
2208 BufferList = BufferListStart;
2210 else
2212 BufferList->next = malloc(sizeof(ALbufferlistitem));
2213 BufferList->next->buffer = buffer;
2214 BufferList->next->next = NULL;
2215 BufferList->next->prev = BufferList;
2216 BufferList = BufferList->next;
2218 if(!buffer) continue;
2219 IncrementRef(&buffer->ref);
2221 ReadLock(&buffer->lock);
2222 if(BufferFmt == NULL)
2224 BufferFmt = buffer;
2226 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
2227 Source->SampleSize = BytesFromFmt(buffer->FmtType);
2228 if(buffer->FmtChannels == FmtMono)
2229 Source->Update = CalcSourceParams;
2230 else
2231 Source->Update = CalcNonAttnSourceParams;
2233 Source->NeedsUpdate = AL_TRUE;
2235 else if(BufferFmt->Frequency != buffer->Frequency ||
2236 BufferFmt->OriginalChannels != buffer->OriginalChannels ||
2237 BufferFmt->OriginalType != buffer->OriginalType)
2239 ReadUnlock(&buffer->lock);
2240 UnlockContext(Context);
2241 al_throwerr(Context, AL_INVALID_OPERATION);
2243 ReadUnlock(&buffer->lock);
2246 /* Source is now streaming */
2247 Source->SourceType = AL_STREAMING;
2249 if(Source->queue == NULL)
2250 Source->queue = BufferListStart;
2251 else
2253 /* Append to the end of the queue */
2254 BufferList = Source->queue;
2255 while(BufferList->next != NULL)
2256 BufferList = BufferList->next;
2258 BufferListStart->prev = BufferList;
2259 BufferList->next = BufferListStart;
2262 Source->BuffersInQueue += nb;
2264 UnlockContext(Context);
2266 al_catchany()
2268 while(BufferListStart)
2270 BufferList = BufferListStart;
2271 BufferListStart = BufferList->next;
2273 if(BufferList->buffer)
2274 DecrementRef(&BufferList->buffer->ref);
2275 free(BufferList);
2278 al_endtry;
2280 ALCcontext_DecRef(Context);
2283 AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers)
2285 ALCcontext *Context;
2286 ALsource *Source;
2287 ALsizei i;
2288 ALbufferlistitem *BufferList;
2290 if(nb == 0)
2291 return;
2293 Context = GetContextRef();
2294 if(!Context) return;
2296 al_try
2298 CHECK_VALUE(Context, nb >= 0);
2300 if((Source=LookupSource(Context, source)) == NULL)
2301 al_throwerr(Context, AL_INVALID_NAME);
2303 LockContext(Context);
2304 if(Source->Looping || Source->SourceType != AL_STREAMING ||
2305 (ALuint)nb > Source->BuffersPlayed)
2307 UnlockContext(Context);
2308 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2309 al_throwerr(Context, AL_INVALID_VALUE);
2312 for(i = 0;i < nb;i++)
2314 BufferList = Source->queue;
2315 Source->queue = BufferList->next;
2316 Source->BuffersInQueue--;
2317 Source->BuffersPlayed--;
2319 if(BufferList->buffer)
2321 buffers[i] = BufferList->buffer->id;
2322 DecrementRef(&BufferList->buffer->ref);
2324 else
2325 buffers[i] = 0;
2327 free(BufferList);
2329 if(Source->queue)
2330 Source->queue->prev = NULL;
2331 UnlockContext(Context);
2333 al_endtry;
2335 ALCcontext_DecRef(Context);
2339 static ALvoid InitSourceParams(ALsource *Source)
2341 ALuint i;
2343 Source->InnerAngle = 360.0f;
2344 Source->OuterAngle = 360.0f;
2345 Source->Pitch = 1.0f;
2346 Source->Position[0] = 0.0f;
2347 Source->Position[1] = 0.0f;
2348 Source->Position[2] = 0.0f;
2349 Source->Orientation[0] = 0.0f;
2350 Source->Orientation[1] = 0.0f;
2351 Source->Orientation[2] = 0.0f;
2352 Source->Velocity[0] = 0.0f;
2353 Source->Velocity[1] = 0.0f;
2354 Source->Velocity[2] = 0.0f;
2355 Source->RefDistance = 1.0f;
2356 Source->MaxDistance = FLT_MAX;
2357 Source->RollOffFactor = 1.0f;
2358 Source->Looping = AL_FALSE;
2359 Source->Gain = 1.0f;
2360 Source->MinGain = 0.0f;
2361 Source->MaxGain = 1.0f;
2362 Source->OuterGain = 0.0f;
2363 Source->OuterGainHF = 1.0f;
2365 Source->DryGainHFAuto = AL_TRUE;
2366 Source->WetGainAuto = AL_TRUE;
2367 Source->WetGainHFAuto = AL_TRUE;
2368 Source->AirAbsorptionFactor = 0.0f;
2369 Source->RoomRolloffFactor = 0.0f;
2370 Source->DopplerFactor = 1.0f;
2371 Source->DirectChannels = AL_FALSE;
2373 Source->DistanceModel = DefaultDistanceModel;
2375 Source->Resampler = DefaultResampler;
2377 Source->state = AL_INITIAL;
2378 Source->new_state = AL_NONE;
2379 Source->SourceType = AL_UNDETERMINED;
2380 Source->Offset = -1.0;
2382 Source->DirectGain = 1.0f;
2383 Source->DirectGainHF = 1.0f;
2384 for(i = 0;i < MAX_SENDS;i++)
2386 Source->Send[i].Gain = 1.0f;
2387 Source->Send[i].GainHF = 1.0f;
2390 Source->NeedsUpdate = AL_TRUE;
2392 Source->Hrtf.Moving = AL_FALSE;
2393 Source->Hrtf.Counter = 0;
2397 /* SetSourceState
2399 * Sets the source's new play state given its current state.
2401 ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
2403 if(state == AL_PLAYING)
2405 ALbufferlistitem *BufferList;
2406 ALsizei j, k;
2408 /* Check that there is a queue containing at least one valid, non zero
2409 * length Buffer. */
2410 BufferList = Source->queue;
2411 while(BufferList)
2413 if(BufferList->buffer != NULL && BufferList->buffer->SampleLen)
2414 break;
2415 BufferList = BufferList->next;
2418 if(Source->state != AL_PLAYING)
2420 for(j = 0;j < MaxChannels;j++)
2422 for(k = 0;k < SRC_HISTORY_LENGTH;k++)
2423 Source->Hrtf.History[j][k] = 0.0f;
2424 for(k = 0;k < HRIR_LENGTH;k++)
2426 Source->Hrtf.Values[j][k][0] = 0.0f;
2427 Source->Hrtf.Values[j][k][1] = 0.0f;
2432 if(Source->state != AL_PAUSED)
2434 Source->state = AL_PLAYING;
2435 Source->position = 0;
2436 Source->position_fraction = 0;
2437 Source->BuffersPlayed = 0;
2439 else
2440 Source->state = AL_PLAYING;
2442 // Check if an Offset has been set
2443 if(Source->Offset >= 0.0)
2444 ApplyOffset(Source);
2446 /* If there's nothing to play, or device is disconnected, go right to
2447 * stopped */
2448 if(!BufferList || !Context->Device->Connected)
2450 SetSourceState(Source, Context, AL_STOPPED);
2451 return;
2454 for(j = 0;j < Context->ActiveSourceCount;j++)
2456 if(Context->ActiveSources[j] == Source)
2457 break;
2459 if(j == Context->ActiveSourceCount)
2460 Context->ActiveSources[Context->ActiveSourceCount++] = Source;
2462 else if(state == AL_PAUSED)
2464 if(Source->state == AL_PLAYING)
2466 Source->state = AL_PAUSED;
2467 Source->Hrtf.Moving = AL_FALSE;
2468 Source->Hrtf.Counter = 0;
2471 else if(state == AL_STOPPED)
2473 if(Source->state != AL_INITIAL)
2475 Source->state = AL_STOPPED;
2476 Source->BuffersPlayed = Source->BuffersInQueue;
2477 Source->Hrtf.Moving = AL_FALSE;
2478 Source->Hrtf.Counter = 0;
2480 Source->Offset = -1.0;
2482 else if(state == AL_INITIAL)
2484 if(Source->state != AL_INITIAL)
2486 Source->state = AL_INITIAL;
2487 Source->position = 0;
2488 Source->position_fraction = 0;
2489 Source->BuffersPlayed = 0;
2490 Source->Hrtf.Moving = AL_FALSE;
2491 Source->Hrtf.Counter = 0;
2493 Source->Offset = -1.0;
2497 /* GetSourceOffset
2499 * Gets the current read offset for the given Source, in 32.32 fixed-point
2500 * samples. The offset is relative to the start of the queue (not the start of
2501 * the current buffer).
2503 static ALint64 GetSourceOffset(const ALsource *Source)
2505 const ALbufferlistitem *BufferList;
2506 ALuint64 readPos;
2507 ALuint i;
2509 if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
2510 return 0;
2512 /* NOTE: This is the offset into the *current* buffer, so add the length of
2513 * any played buffers */
2514 readPos = (ALuint64)Source->position << 32;
2515 readPos |= (ALuint64)Source->position_fraction << (32-FRACTIONBITS);
2516 BufferList = Source->queue;
2517 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2519 if(BufferList->buffer)
2520 readPos += (ALuint64)BufferList->buffer->SampleLen << 32;
2521 BufferList = BufferList->next;
2524 return (ALint64)minu64(readPos, MAKEU64(0x7fffffff,0xffffffff));
2527 /* GetSourceSecOffset
2529 * Gets the current read offset for the given Source, in seconds. The offset is
2530 * relative to the start of the queue (not the start of the current buffer).
2532 static ALdouble GetSourceSecOffset(const ALsource *Source)
2534 const ALbufferlistitem *BufferList;
2535 const ALbuffer *Buffer = NULL;
2536 ALuint64 readPos;
2537 ALuint i;
2539 BufferList = Source->queue;
2540 while(BufferList)
2542 if(BufferList->buffer)
2544 Buffer = BufferList->buffer;
2545 break;
2547 BufferList = BufferList->next;
2550 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2551 return 0.0;
2553 /* NOTE: This is the offset into the *current* buffer, so add the length of
2554 * any played buffers */
2555 readPos = (ALuint64)Source->position << FRACTIONBITS;
2556 readPos |= (ALuint64)Source->position_fraction;
2557 BufferList = Source->queue;
2558 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2560 if(BufferList->buffer)
2561 readPos += (ALuint64)BufferList->buffer->SampleLen << FRACTIONBITS;
2562 BufferList = BufferList->next;
2565 return (ALdouble)readPos / (ALdouble)FRACTIONONE / (ALdouble)Buffer->Frequency;
2568 /* GetSourceOffsets
2570 * Gets the current read and write offsets for the given Source, in the
2571 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2572 * the start of the queue (not the start of the current buffer).
2574 static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen)
2576 const ALbufferlistitem *BufferList;
2577 const ALbuffer *Buffer = NULL;
2578 ALuint readPos, writePos;
2579 ALuint totalBufferLen;
2580 ALuint i;
2582 // Find the first valid Buffer in the Queue
2583 BufferList = Source->queue;
2584 while(BufferList)
2586 if(BufferList->buffer)
2588 Buffer = BufferList->buffer;
2589 break;
2591 BufferList = BufferList->next;
2594 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2596 offset[0] = 0.0;
2597 offset[1] = 0.0;
2598 return;
2601 if(updateLen > 0.0 && updateLen < 0.015)
2602 updateLen = 0.015;
2604 /* NOTE: This is the offset into the *current* buffer, so add the length of
2605 * any played buffers */
2606 readPos = Source->position;
2607 totalBufferLen = 0;
2608 BufferList = Source->queue;
2609 for(i = 0;BufferList;i++)
2611 if(BufferList->buffer)
2613 if(i < Source->BuffersPlayed)
2614 readPos += BufferList->buffer->SampleLen;
2615 totalBufferLen += BufferList->buffer->SampleLen;
2617 BufferList = BufferList->next;
2619 if(Source->state == AL_PLAYING)
2620 writePos = readPos + (ALuint)(updateLen*Buffer->Frequency);
2621 else
2622 writePos = readPos;
2624 if(Source->Looping)
2626 readPos %= totalBufferLen;
2627 writePos %= totalBufferLen;
2629 else
2631 /* Wrap positions back to 0 */
2632 if(readPos >= totalBufferLen)
2633 readPos = 0;
2634 if(writePos >= totalBufferLen)
2635 writePos = 0;
2638 switch(name)
2640 case AL_SEC_OFFSET:
2641 offset[0] = (ALdouble)readPos / Buffer->Frequency;
2642 offset[1] = (ALdouble)writePos / Buffer->Frequency;
2643 break;
2645 case AL_SAMPLE_OFFSET:
2646 case AL_SAMPLE_RW_OFFSETS_SOFT:
2647 offset[0] = (ALdouble)readPos;
2648 offset[1] = (ALdouble)writePos;
2649 break;
2651 case AL_BYTE_OFFSET:
2652 case AL_BYTE_RW_OFFSETS_SOFT:
2653 if(Buffer->OriginalType == UserFmtIMA4)
2655 ALuint BlockSize = 36 * ChannelsFromFmt(Buffer->FmtChannels);
2656 ALuint FrameBlockSize = 65;
2658 /* Round down to nearest ADPCM block */
2659 offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
2660 if(Source->state != AL_PLAYING)
2661 offset[1] = offset[0];
2662 else
2664 /* Round up to nearest ADPCM block */
2665 offset[1] = (ALdouble)((writePos+FrameBlockSize-1) /
2666 FrameBlockSize * BlockSize);
2669 else
2671 ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2672 offset[0] = (ALdouble)(readPos * FrameSize);
2673 offset[1] = (ALdouble)(writePos * FrameSize);
2675 break;
2680 /* ApplyOffset
2682 * Apply the stored playback offset to the Source. This function will update
2683 * the number of buffers "played" given the stored offset.
2685 ALboolean ApplyOffset(ALsource *Source)
2687 const ALbufferlistitem *BufferList;
2688 const ALbuffer *Buffer;
2689 ALint bufferLen, totalBufferLen;
2690 ALint buffersPlayed;
2691 ALint offset;
2693 /* Get sample frame offset */
2694 offset = GetSampleOffset(Source);
2695 if(offset == -1)
2696 return AL_FALSE;
2698 buffersPlayed = 0;
2699 totalBufferLen = 0;
2701 BufferList = Source->queue;
2702 while(BufferList)
2704 Buffer = BufferList->buffer;
2705 bufferLen = Buffer ? Buffer->SampleLen : 0;
2707 if(bufferLen <= offset-totalBufferLen)
2709 /* Offset is past this buffer so increment to the next buffer */
2710 buffersPlayed++;
2712 else if(totalBufferLen <= offset)
2714 /* Offset is in this buffer */
2715 Source->BuffersPlayed = buffersPlayed;
2717 Source->position = offset - totalBufferLen;
2718 Source->position_fraction = 0;
2719 return AL_TRUE;
2722 totalBufferLen += bufferLen;
2724 BufferList = BufferList->next;
2727 /* Offset is out of range of the queue */
2728 return AL_FALSE;
2732 /* GetSampleOffset
2734 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2735 * Second offset supplied by the application). This takes into account the fact
2736 * that the buffer format may have been modifed since.
2738 static ALint GetSampleOffset(ALsource *Source)
2740 const ALbuffer *Buffer = NULL;
2741 const ALbufferlistitem *BufferList;
2742 ALint Offset = -1;
2744 /* Find the first valid Buffer in the Queue */
2745 BufferList = Source->queue;
2746 while(BufferList)
2748 if(BufferList->buffer)
2750 Buffer = BufferList->buffer;
2751 break;
2753 BufferList = BufferList->next;
2756 if(!Buffer)
2758 Source->Offset = -1.0;
2759 return -1;
2762 switch(Source->OffsetType)
2764 case AL_BYTE_OFFSET:
2765 /* Determine the ByteOffset (and ensure it is block aligned) */
2766 Offset = (ALint)Source->Offset;
2767 if(Buffer->OriginalType == UserFmtIMA4)
2769 Offset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels);
2770 Offset *= 65;
2772 else
2773 Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2774 break;
2776 case AL_SAMPLE_OFFSET:
2777 Offset = (ALint)Source->Offset;
2778 break;
2780 case AL_SEC_OFFSET:
2781 Offset = (ALint)(Source->Offset * Buffer->Frequency);
2782 break;
2784 Source->Offset = -1.0;
2786 return Offset;
2790 /* ReleaseALSources
2792 * Destroys all sources in the source map.
2794 ALvoid ReleaseALSources(ALCcontext *Context)
2796 ALsizei pos;
2797 ALuint j;
2798 for(pos = 0;pos < Context->SourceMap.size;pos++)
2800 ALsource *temp = Context->SourceMap.array[pos].value;
2801 Context->SourceMap.array[pos].value = NULL;
2803 while(temp->queue != NULL)
2805 ALbufferlistitem *BufferList = temp->queue;
2806 temp->queue = BufferList->next;
2808 if(BufferList->buffer != NULL)
2809 DecrementRef(&BufferList->buffer->ref);
2810 free(BufferList);
2813 for(j = 0;j < MAX_SENDS;++j)
2815 if(temp->Send[j].Slot)
2816 DecrementRef(&temp->Send[j].Slot->ref);
2817 temp->Send[j].Slot = NULL;
2820 FreeThunkEntry(temp->id);
2821 memset(temp, 0, sizeof(*temp));
2822 al_free(temp);