Add retrieval of missing source properties
[openal-soft.git] / OpenAL32 / alSource.c
blob2e8a952bcda27735e132fb26d9a9aa5856f9ca75
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);
58 static ALenum SetSourcei64v(ALsource *Source, ALCcontext *Context, ALenum name, const ALint64SOFT *values);
60 static ALenum GetSourcedv(const ALsource *Source, ALCcontext *Context, ALenum name, ALdouble *values);
61 static ALenum GetSourceiv(const ALsource *Source, ALCcontext *Context, ALenum name, ALint *values);
62 static ALenum GetSourcei64v(const ALsource *Source, ALCcontext *Context, ALenum name, ALint64 *values);
65 #define RETERR(x) do { \
66 alSetError(Context, (x)); \
67 return (x); \
68 } while(0)
70 #define CHECKVAL(x) do { \
71 if(!(x)) \
72 RETERR(AL_INVALID_VALUE); \
73 } while(0)
75 static ALenum SetSourcefv(ALsource *Source, ALCcontext *Context, ALenum name, const ALfloat *values)
77 switch(name)
79 case AL_PITCH:
80 CHECKVAL(*values >= 0.0f);
82 Source->Pitch = *values;
83 Source->NeedsUpdate = AL_TRUE;
84 break;
86 case AL_CONE_INNER_ANGLE:
87 CHECKVAL(*values >= 0.0f && *values <= 360.0f);
89 Source->InnerAngle = *values;
90 Source->NeedsUpdate = AL_TRUE;
91 break;
93 case AL_CONE_OUTER_ANGLE:
94 CHECKVAL(*values >= 0.0f && *values <= 360.0f);
96 Source->OuterAngle = *values;
97 Source->NeedsUpdate = AL_TRUE;
98 break;
100 case AL_GAIN:
101 CHECKVAL(*values >= 0.0f);
103 Source->Gain = *values;
104 Source->NeedsUpdate = AL_TRUE;
105 break;
107 case AL_MAX_DISTANCE:
108 CHECKVAL(*values >= 0.0f);
110 Source->MaxDistance = *values;
111 Source->NeedsUpdate = AL_TRUE;
112 break;
114 case AL_ROLLOFF_FACTOR:
115 CHECKVAL(*values >= 0.0f);
117 Source->RollOffFactor = *values;
118 Source->NeedsUpdate = AL_TRUE;
119 break;
121 case AL_REFERENCE_DISTANCE:
122 CHECKVAL(*values >= 0.0f);
124 Source->RefDistance = *values;
125 Source->NeedsUpdate = AL_TRUE;
126 break;
128 case AL_MIN_GAIN:
129 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
131 Source->MinGain = *values;
132 Source->NeedsUpdate = AL_TRUE;
133 break;
135 case AL_MAX_GAIN:
136 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
138 Source->MaxGain = *values;
139 Source->NeedsUpdate = AL_TRUE;
140 break;
142 case AL_CONE_OUTER_GAIN:
143 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
145 Source->OuterGain = *values;
146 Source->NeedsUpdate = AL_TRUE;
147 break;
149 case AL_CONE_OUTER_GAINHF:
150 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
152 Source->OuterGainHF = *values;
153 Source->NeedsUpdate = AL_TRUE;
154 break;
156 case AL_AIR_ABSORPTION_FACTOR:
157 CHECKVAL(*values >= 0.0f && *values <= 10.0f);
159 Source->AirAbsorptionFactor = *values;
160 Source->NeedsUpdate = AL_TRUE;
161 break;
163 case AL_ROOM_ROLLOFF_FACTOR:
164 CHECKVAL(*values >= 0.0f && *values <= 10.0f);
166 Source->RoomRolloffFactor = *values;
167 Source->NeedsUpdate = AL_TRUE;
168 break;
170 case AL_DOPPLER_FACTOR:
171 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
173 Source->DopplerFactor = *values;
174 Source->NeedsUpdate = AL_TRUE;
175 break;
177 case AL_SEC_OFFSET:
178 case AL_SAMPLE_OFFSET:
179 case AL_BYTE_OFFSET:
180 CHECKVAL(*values >= 0.0f);
182 LockContext(Context);
183 Source->OffsetType = name;
184 Source->Offset = *values;
186 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
187 !Context->DeferUpdates)
189 if(ApplyOffset(Source) == AL_FALSE)
191 UnlockContext(Context);
192 RETERR(AL_INVALID_VALUE);
195 UnlockContext(Context);
196 break;
199 case AL_POSITION:
200 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
202 LockContext(Context);
203 Source->Position[0] = values[0];
204 Source->Position[1] = values[1];
205 Source->Position[2] = values[2];
206 UnlockContext(Context);
207 Source->NeedsUpdate = AL_TRUE;
208 break;
210 case AL_VELOCITY:
211 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
213 LockContext(Context);
214 Source->Velocity[0] = values[0];
215 Source->Velocity[1] = values[1];
216 Source->Velocity[2] = values[2];
217 UnlockContext(Context);
218 Source->NeedsUpdate = AL_TRUE;
219 break;
221 case AL_DIRECTION:
222 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
224 LockContext(Context);
225 Source->Orientation[0] = values[0];
226 Source->Orientation[1] = values[1];
227 Source->Orientation[2] = values[2];
228 UnlockContext(Context);
229 Source->NeedsUpdate = AL_TRUE;
230 break;
233 default:
234 RETERR(AL_INVALID_ENUM);
237 return AL_NO_ERROR;
240 static ALenum SetSourceiv(ALsource *Source, ALCcontext *Context, ALenum name, const ALint *values)
242 ALCdevice *device = Context->Device;
243 ALbuffer *buffer = NULL;
244 ALfilter *filter = NULL;
245 ALeffectslot *slot = NULL;
246 ALbufferlistitem *oldlist;
247 ALfloat fvals[3];
248 ALenum err;
250 switch(name)
252 case AL_SOURCE_RELATIVE:
253 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
255 Source->HeadRelative = (ALboolean)*values;
256 Source->NeedsUpdate = AL_TRUE;
257 break;
259 case AL_LOOPING:
260 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
262 Source->Looping = (ALboolean)*values;
263 break;
265 case AL_BUFFER:
266 CHECKVAL(*values == 0 || (buffer=LookupBuffer(device, *values)) != NULL);
268 LockContext(Context);
269 if(!(Source->state == AL_STOPPED || Source->state == AL_INITIAL))
271 UnlockContext(Context);
272 RETERR(AL_INVALID_OPERATION);
275 Source->BuffersInQueue = 0;
276 Source->BuffersPlayed = 0;
278 if(buffer != NULL)
280 ALbufferlistitem *BufferListItem;
282 /* Source is now Static */
283 Source->SourceType = AL_STATIC;
285 /* Add the selected buffer to a one-item queue */
286 BufferListItem = malloc(sizeof(ALbufferlistitem));
287 BufferListItem->buffer = buffer;
288 BufferListItem->next = NULL;
289 BufferListItem->prev = NULL;
290 IncrementRef(&buffer->ref);
292 oldlist = ExchangePtr((XchgPtr*)&Source->queue, BufferListItem);
293 Source->BuffersInQueue = 1;
295 ReadLock(&buffer->lock);
296 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
297 Source->SampleSize = BytesFromFmt(buffer->FmtType);
298 ReadUnlock(&buffer->lock);
299 if(buffer->FmtChannels == FmtMono)
300 Source->Update = CalcSourceParams;
301 else
302 Source->Update = CalcNonAttnSourceParams;
303 Source->NeedsUpdate = AL_TRUE;
305 else
307 /* Source is now Undetermined */
308 Source->SourceType = AL_UNDETERMINED;
309 oldlist = ExchangePtr((XchgPtr*)&Source->queue, NULL);
312 /* Delete all elements in the previous queue */
313 while(oldlist != NULL)
315 ALbufferlistitem *temp = oldlist;
316 oldlist = temp->next;
318 if(temp->buffer)
319 DecrementRef(&temp->buffer->ref);
320 free(temp);
322 UnlockContext(Context);
323 break;
325 case AL_SOURCE_STATE:
326 /* Query only */
327 RETERR(AL_INVALID_OPERATION);
329 case AL_SEC_OFFSET:
330 case AL_SAMPLE_OFFSET:
331 case AL_BYTE_OFFSET:
332 CHECKVAL(*values >= 0);
334 LockContext(Context);
335 Source->OffsetType = name;
336 Source->Offset = *values;
338 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
339 !Context->DeferUpdates)
341 if(ApplyOffset(Source) == AL_FALSE)
343 UnlockContext(Context);
344 RETERR(AL_INVALID_VALUE);
347 UnlockContext(Context);
348 break;
350 case AL_DIRECT_FILTER:
351 CHECKVAL(*values == 0 || (filter=LookupFilter(device, *values)) != NULL);
353 LockContext(Context);
354 if(!filter)
356 Source->DirectGain = 1.0f;
357 Source->DirectGainHF = 1.0f;
359 else
361 Source->DirectGain = filter->Gain;
362 Source->DirectGainHF = filter->GainHF;
364 UnlockContext(Context);
365 Source->NeedsUpdate = AL_TRUE;
366 break;
368 case AL_DIRECT_FILTER_GAINHF_AUTO:
369 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
371 Source->DryGainHFAuto = *values;
372 Source->NeedsUpdate = AL_TRUE;
373 break;
375 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
376 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
378 Source->WetGainAuto = *values;
379 Source->NeedsUpdate = AL_TRUE;
380 break;
382 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
383 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
385 Source->WetGainHFAuto = *values;
386 Source->NeedsUpdate = AL_TRUE;
387 break;
389 case AL_DIRECT_CHANNELS_SOFT:
390 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
392 Source->DirectChannels = *values;
393 Source->NeedsUpdate = AL_TRUE;
394 break;
396 case AL_DISTANCE_MODEL:
397 CHECKVAL(*values == AL_NONE ||
398 *values == AL_INVERSE_DISTANCE ||
399 *values == AL_INVERSE_DISTANCE_CLAMPED ||
400 *values == AL_LINEAR_DISTANCE ||
401 *values == AL_LINEAR_DISTANCE_CLAMPED ||
402 *values == AL_EXPONENT_DISTANCE ||
403 *values == AL_EXPONENT_DISTANCE_CLAMPED);
405 Source->DistanceModel = *values;
406 if(Context->SourceDistanceModel)
407 Source->NeedsUpdate = AL_TRUE;
408 break;
411 case AL_AUXILIARY_SEND_FILTER:
412 LockContext(Context);
413 if(!((ALuint)values[1] < device->NumAuxSends &&
414 (values[0] == 0 || (slot=LookupEffectSlot(Context, values[0])) != NULL) &&
415 (values[2] == 0 || (filter=LookupFilter(device, values[2])) != NULL)))
417 UnlockContext(Context);
418 RETERR(AL_INVALID_VALUE);
421 /* Add refcount on the new slot, and release the previous slot */
422 if(slot) IncrementRef(&slot->ref);
423 slot = ExchangePtr((XchgPtr*)&Source->Send[values[1]].Slot, slot);
424 if(slot) DecrementRef(&slot->ref);
426 if(!filter)
428 /* Disable filter */
429 Source->Send[values[1]].Gain = 1.0f;
430 Source->Send[values[1]].GainHF = 1.0f;
432 else
434 Source->Send[values[1]].Gain = filter->Gain;
435 Source->Send[values[1]].GainHF = filter->GainHF;
437 Source->NeedsUpdate = AL_TRUE;
438 UnlockContext(Context);
439 break;
442 case AL_MAX_DISTANCE:
443 case AL_ROLLOFF_FACTOR:
444 case AL_CONE_INNER_ANGLE:
445 case AL_CONE_OUTER_ANGLE:
446 case AL_REFERENCE_DISTANCE:
447 fvals[0] = (ALfloat)*values;
448 if((err=SetSourcefv(Source, Context, name, fvals)) != AL_NO_ERROR)
449 return err;
450 break;
452 case AL_POSITION:
453 case AL_VELOCITY:
454 case AL_DIRECTION:
455 fvals[0] = (ALfloat)values[0];
456 fvals[1] = (ALfloat)values[1];
457 fvals[2] = (ALfloat)values[2];
458 if((err=SetSourcefv(Source, Context, name, fvals)) != AL_NO_ERROR)
459 return err;
460 break;
462 default:
463 RETERR(AL_INVALID_ENUM);
466 return AL_NO_ERROR;
469 static ALenum SetSourcei64v(ALsource *Source, ALCcontext *Context, ALenum name, const ALint64SOFT *values)
471 ALfloat fvals[3];
472 ALint ivals[3];
473 ALenum err;
475 switch(name)
477 /* 1x int */
478 case AL_SOURCE_RELATIVE:
479 case AL_LOOPING:
480 case AL_SOURCE_STATE:
481 case AL_BYTE_OFFSET:
482 case AL_SAMPLE_OFFSET:
483 case AL_DIRECT_FILTER_GAINHF_AUTO:
484 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
485 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
486 case AL_DIRECT_CHANNELS_SOFT:
487 case AL_DISTANCE_MODEL:
488 CHECKVAL(*values <= INT_MAX && *values >= INT_MIN);
490 ivals[0] = *values;
491 if((err=SetSourceiv(Source, Context, name, ivals)))
492 return err;
493 break;
495 /* 1x uint */
496 case AL_BUFFER:
497 case AL_DIRECT_FILTER:
498 CHECKVAL(*values <= UINT_MAX && *values >= 0);
500 ivals[0] = (ALuint)*values;
501 if((err=SetSourceiv(Source, Context, name, ivals)))
502 return err;
503 break;
505 /* 3x uint */
506 case AL_AUXILIARY_SEND_FILTER:
507 CHECKVAL(values[0] <= UINT_MAX && values[0] >= 0 &&
508 values[1] <= UINT_MAX && values[1] >= 0 &&
509 values[2] <= UINT_MAX && values[2] >= 0);
511 ivals[0] = (ALuint)values[0];
512 ivals[1] = (ALuint)values[1];
513 ivals[2] = (ALuint)values[2];
514 if((err=SetSourceiv(Source, Context, name, ivals)))
515 return err;
516 break;
518 /* 1x float */
519 case AL_MAX_DISTANCE:
520 case AL_ROLLOFF_FACTOR:
521 case AL_CONE_INNER_ANGLE:
522 case AL_CONE_OUTER_ANGLE:
523 case AL_REFERENCE_DISTANCE:
524 case AL_SEC_OFFSET:
525 fvals[0] = (ALfloat)*values;
526 if((err=SetSourcefv(Source, Context, name, fvals)) != AL_NO_ERROR)
527 return err;
528 break;
530 /* 3x float */
531 case AL_POSITION:
532 case AL_VELOCITY:
533 case AL_DIRECTION:
534 fvals[0] = (ALfloat)values[0];
535 fvals[1] = (ALfloat)values[1];
536 fvals[2] = (ALfloat)values[2];
537 if((err=SetSourcefv(Source, Context, name, fvals)) != AL_NO_ERROR)
538 return err;
539 break;
541 default:
542 RETERR(AL_INVALID_ENUM);
545 return AL_NO_ERROR;
548 #undef CHECKVAL
551 static ALenum GetSourcedv(const ALsource *Source, ALCcontext *Context, ALenum name, ALdouble *values)
553 ALdouble offsets[2];
554 ALdouble updateLen;
555 ALint ivals[3];
556 ALenum err;
558 switch(name)
560 case AL_PITCH:
561 *values = Source->Pitch;
562 break;
564 case AL_MAX_DISTANCE:
565 *values = Source->MaxDistance;
566 break;
568 case AL_ROLLOFF_FACTOR:
569 *values = Source->RollOffFactor;
570 break;
572 case AL_REFERENCE_DISTANCE:
573 *values = Source->RefDistance;
574 break;
576 case AL_CONE_INNER_ANGLE:
577 *values = Source->InnerAngle;
578 break;
580 case AL_CONE_OUTER_ANGLE:
581 *values = Source->OuterAngle;
582 break;
584 case AL_MIN_GAIN:
585 *values = Source->MinGain;
586 break;
588 case AL_MAX_GAIN:
589 *values = Source->MaxGain;
590 break;
592 case AL_CONE_OUTER_GAIN:
593 *values = Source->OuterGain;
594 break;
596 case AL_SEC_OFFSET:
597 case AL_SAMPLE_OFFSET:
598 case AL_BYTE_OFFSET:
599 LockContext(Context);
600 updateLen = (ALdouble)Context->Device->UpdateSize /
601 Context->Device->Frequency;
602 GetSourceOffsets(Source, name, offsets, updateLen);
603 UnlockContext(Context);
604 *values = offsets[0];
605 break;
607 case AL_CONE_OUTER_GAINHF:
608 *values = Source->OuterGainHF;
609 break;
611 case AL_AIR_ABSORPTION_FACTOR:
612 *values = Source->AirAbsorptionFactor;
613 break;
615 case AL_ROOM_ROLLOFF_FACTOR:
616 *values = Source->RoomRolloffFactor;
617 break;
619 case AL_DOPPLER_FACTOR:
620 *values = Source->DopplerFactor;
621 break;
623 case AL_SAMPLE_RW_OFFSETS_SOFT:
624 case AL_BYTE_RW_OFFSETS_SOFT:
625 LockContext(Context);
626 updateLen = (ALdouble)Context->Device->UpdateSize /
627 Context->Device->Frequency;
628 GetSourceOffsets(Source, name, values, updateLen);
629 UnlockContext(Context);
630 break;
632 case AL_SEC_OFFSET_LATENCY_SOFT:
633 LockContext(Context);
634 values[0] = GetSourceSecOffset(Source);
635 values[1] = (ALdouble)ALCdevice_GetLatency(Context->Device) /
636 1000000000.0;
637 UnlockContext(Context);
638 break;
640 case AL_POSITION:
641 LockContext(Context);
642 values[0] = Source->Position[0];
643 values[1] = Source->Position[1];
644 values[2] = Source->Position[2];
645 UnlockContext(Context);
646 break;
648 case AL_VELOCITY:
649 LockContext(Context);
650 values[0] = Source->Velocity[0];
651 values[1] = Source->Velocity[1];
652 values[2] = Source->Velocity[2];
653 UnlockContext(Context);
654 break;
656 case AL_DIRECTION:
657 LockContext(Context);
658 values[0] = Source->Orientation[0];
659 values[1] = Source->Orientation[1];
660 values[2] = Source->Orientation[2];
661 UnlockContext(Context);
662 break;
664 case AL_SOURCE_RELATIVE:
665 case AL_LOOPING:
666 case AL_BUFFER:
667 case AL_SOURCE_STATE:
668 case AL_BUFFERS_QUEUED:
669 case AL_BUFFERS_PROCESSED:
670 case AL_SOURCE_TYPE:
671 case AL_DIRECT_FILTER_GAINHF_AUTO:
672 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
673 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
674 case AL_DIRECT_CHANNELS_SOFT:
675 case AL_DISTANCE_MODEL:
676 if((err=GetSourceiv(Source, Context, name, ivals)) != AL_NO_ERROR)
677 return err;
678 *values = (ALdouble)ivals[0];
679 break;
681 default:
682 RETERR(AL_INVALID_ENUM);
685 return AL_NO_ERROR;
688 static ALenum GetSourceiv(const ALsource *Source, ALCcontext *Context, ALenum name, ALint *values)
690 ALbufferlistitem *BufferList;
691 ALdouble dvals[3];
692 ALenum err;
694 switch(name)
696 case AL_SOURCE_RELATIVE:
697 *values = Source->HeadRelative;
698 break;
700 case AL_LOOPING:
701 *values = Source->Looping;
702 break;
704 case AL_BUFFER:
705 LockContext(Context);
706 BufferList = Source->queue;
707 if(Source->SourceType != AL_STATIC)
709 ALuint i = Source->BuffersPlayed;
710 while(i > 0)
712 BufferList = BufferList->next;
713 i--;
716 *values = ((BufferList && BufferList->buffer) ?
717 BufferList->buffer->id : 0);
718 UnlockContext(Context);
719 break;
721 case AL_SOURCE_STATE:
722 *values = Source->state;
723 break;
725 case AL_BUFFERS_QUEUED:
726 *values = Source->BuffersInQueue;
727 break;
729 case AL_BUFFERS_PROCESSED:
730 LockContext(Context);
731 if(Source->Looping || Source->SourceType != AL_STREAMING)
733 /* Buffers on a looping source are in a perpetual state of
734 * PENDING, so don't report any as PROCESSED */
735 *values = 0;
737 else
738 *values = Source->BuffersPlayed;
739 UnlockContext(Context);
740 break;
742 case AL_SOURCE_TYPE:
743 *values = Source->SourceType;
744 break;
746 case AL_DIRECT_FILTER_GAINHF_AUTO:
747 *values = Source->DryGainHFAuto;
748 break;
750 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
751 *values = Source->WetGainAuto;
752 break;
754 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
755 *values = Source->WetGainHFAuto;
756 break;
758 case AL_DIRECT_CHANNELS_SOFT:
759 *values = Source->DirectChannels;
760 break;
762 case AL_DISTANCE_MODEL:
763 *values = Source->DistanceModel;
764 break;
766 case AL_MAX_DISTANCE:
767 case AL_ROLLOFF_FACTOR:
768 case AL_REFERENCE_DISTANCE:
769 case AL_CONE_INNER_ANGLE:
770 case AL_CONE_OUTER_ANGLE:
771 case AL_SEC_OFFSET:
772 case AL_SAMPLE_OFFSET:
773 case AL_BYTE_OFFSET:
774 case AL_DOPPLER_FACTOR:
775 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
776 return err;
777 *values = (ALint)dvals[0];
778 break;
780 case AL_SAMPLE_RW_OFFSETS_SOFT:
781 case AL_BYTE_RW_OFFSETS_SOFT:
782 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
783 return err;
784 values[0] = (ALint)dvals[0];
785 values[1] = (ALint)dvals[0];
786 break;
788 case AL_POSITION:
789 case AL_VELOCITY:
790 case AL_DIRECTION:
791 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
792 return err;
793 values[0] = (ALint)dvals[0];
794 values[1] = (ALint)dvals[1];
795 values[2] = (ALint)dvals[2];
796 break;
798 default:
799 RETERR(AL_INVALID_ENUM);
802 return AL_NO_ERROR;
805 static ALenum GetSourcei64v(const ALsource *Source, ALCcontext *Context, ALenum name, ALint64 *values)
807 ALdouble dvals[3];
808 ALint ivals[3];
809 ALenum err;
811 switch(name)
813 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
814 LockContext(Context);
815 values[0] = GetSourceOffset(Source);
816 values[1] = ALCdevice_GetLatency(Context->Device);
817 UnlockContext(Context);
818 break;
820 case AL_MAX_DISTANCE:
821 case AL_ROLLOFF_FACTOR:
822 case AL_REFERENCE_DISTANCE:
823 case AL_CONE_INNER_ANGLE:
824 case AL_CONE_OUTER_ANGLE:
825 case AL_SEC_OFFSET:
826 case AL_SAMPLE_OFFSET:
827 case AL_BYTE_OFFSET:
828 case AL_DOPPLER_FACTOR:
829 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
830 return err;
831 *values = (ALint64)dvals[0];
832 break;
834 case AL_SAMPLE_RW_OFFSETS_SOFT:
835 case AL_BYTE_RW_OFFSETS_SOFT:
836 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
837 return err;
838 values[0] = (ALint64)dvals[0];
839 values[1] = (ALint64)dvals[0];
840 break;
842 case AL_POSITION:
843 case AL_VELOCITY:
844 case AL_DIRECTION:
845 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
846 return err;
847 values[0] = (ALint64)dvals[0];
848 values[1] = (ALint64)dvals[1];
849 values[2] = (ALint64)dvals[2];
850 break;
852 case AL_SOURCE_RELATIVE:
853 case AL_LOOPING:
854 case AL_BUFFER:
855 case AL_SOURCE_STATE:
856 case AL_BUFFERS_QUEUED:
857 case AL_BUFFERS_PROCESSED:
858 case AL_SOURCE_TYPE:
859 case AL_DIRECT_FILTER_GAINHF_AUTO:
860 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
861 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
862 case AL_DIRECT_CHANNELS_SOFT:
863 case AL_DISTANCE_MODEL:
864 if((err=GetSourceiv(Source, Context, name, ivals)) != AL_NO_ERROR)
865 return err;
866 *values = ivals[0];
867 break;
869 default:
870 RETERR(AL_INVALID_ENUM);
873 return AL_NO_ERROR;
876 #undef RETERR
879 AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
881 ALCcontext *Context;
882 ALsizei cur = 0;
884 Context = GetContextRef();
885 if(!Context) return;
887 al_try
889 ALenum err;
891 CHECK_VALUE(Context, n >= 0);
892 for(cur = 0;cur < n;cur++)
894 ALsource *source = al_calloc(16, sizeof(ALsource));
895 if(!source)
896 al_throwerr(Context, AL_OUT_OF_MEMORY);
897 InitSourceParams(source);
899 err = NewThunkEntry(&source->id);
900 if(err == AL_NO_ERROR)
901 err = InsertUIntMapEntry(&Context->SourceMap, source->id, source);
902 if(err != AL_NO_ERROR)
904 FreeThunkEntry(source->id);
905 memset(source, 0, sizeof(ALsource));
906 al_free(source);
908 al_throwerr(Context, err);
911 sources[cur] = source->id;
914 al_catchany()
916 if(cur > 0)
917 alDeleteSources(cur, sources);
919 al_endtry;
921 ALCcontext_DecRef(Context);
925 AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
927 ALCcontext *Context;
929 Context = GetContextRef();
930 if(!Context) return;
932 al_try
934 ALbufferlistitem *BufferList;
935 ALsource *Source;
936 ALsizei i, j;
938 CHECK_VALUE(Context, n >= 0);
940 /* Check that all Sources are valid */
941 for(i = 0;i < n;i++)
943 if(LookupSource(Context, sources[i]) == NULL)
944 al_throwerr(Context, AL_INVALID_NAME);
947 for(i = 0;i < n;i++)
949 ALsource **srclist, **srclistend;
951 if((Source=RemoveSource(Context, sources[i])) == NULL)
952 continue;
953 FreeThunkEntry(Source->id);
955 LockContext(Context);
956 srclist = Context->ActiveSources;
957 srclistend = srclist + Context->ActiveSourceCount;
958 while(srclist != srclistend)
960 if(*srclist == Source)
962 Context->ActiveSourceCount--;
963 *srclist = *(--srclistend);
964 break;
966 srclist++;
968 UnlockContext(Context);
970 while(Source->queue != NULL)
972 BufferList = Source->queue;
973 Source->queue = BufferList->next;
975 if(BufferList->buffer != NULL)
976 DecrementRef(&BufferList->buffer->ref);
977 free(BufferList);
980 for(j = 0;j < MAX_SENDS;++j)
982 if(Source->Send[j].Slot)
983 DecrementRef(&Source->Send[j].Slot->ref);
984 Source->Send[j].Slot = NULL;
987 memset(Source, 0, sizeof(*Source));
988 al_free(Source);
991 al_endtry;
993 ALCcontext_DecRef(Context);
997 AL_API ALboolean AL_APIENTRY alIsSource(ALuint source)
999 ALCcontext *Context;
1000 ALboolean result;
1002 Context = GetContextRef();
1003 if(!Context) return AL_FALSE;
1005 result = (LookupSource(Context, source) ? AL_TRUE : AL_FALSE);
1007 ALCcontext_DecRef(Context);
1009 return result;
1013 AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value)
1015 ALCcontext *Context;
1016 ALsource *Source;
1018 Context = GetContextRef();
1019 if(!Context) return;
1021 if((Source=LookupSource(Context, source)) == NULL)
1022 alSetError(Context, AL_INVALID_NAME);
1023 else switch(param)
1025 case AL_PITCH:
1026 case AL_CONE_INNER_ANGLE:
1027 case AL_CONE_OUTER_ANGLE:
1028 case AL_GAIN:
1029 case AL_MAX_DISTANCE:
1030 case AL_ROLLOFF_FACTOR:
1031 case AL_REFERENCE_DISTANCE:
1032 case AL_MIN_GAIN:
1033 case AL_MAX_GAIN:
1034 case AL_CONE_OUTER_GAIN:
1035 case AL_CONE_OUTER_GAINHF:
1036 case AL_AIR_ABSORPTION_FACTOR:
1037 case AL_ROOM_ROLLOFF_FACTOR:
1038 case AL_DOPPLER_FACTOR:
1039 case AL_SEC_OFFSET:
1040 case AL_SAMPLE_OFFSET:
1041 case AL_BYTE_OFFSET:
1042 SetSourcefv(Source, Context, param, &value);
1043 break;
1045 default:
1046 alSetError(Context, AL_INVALID_ENUM);
1049 ALCcontext_DecRef(Context);
1052 AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
1054 ALCcontext *Context;
1055 ALsource *Source;
1056 ALfloat fvals[3];
1058 Context = GetContextRef();
1059 if(!Context) return;
1061 if((Source=LookupSource(Context, source)) == NULL)
1062 alSetError(Context, AL_INVALID_NAME);
1063 else switch(param)
1065 case AL_POSITION:
1066 case AL_VELOCITY:
1067 case AL_DIRECTION:
1068 fvals[0] = value1;
1069 fvals[1] = value2;
1070 fvals[2] = value3;
1071 SetSourcefv(Source, Context, param, fvals);
1072 break;
1074 default:
1075 alSetError(Context, AL_INVALID_ENUM);
1078 ALCcontext_DecRef(Context);
1081 AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values)
1083 ALCcontext *Context;
1084 ALsource *Source;
1086 Context = GetContextRef();
1087 if(!Context) return;
1089 if((Source=LookupSource(Context, source)) == NULL)
1090 alSetError(Context, AL_INVALID_NAME);
1091 else if(!values)
1092 alSetError(Context, AL_INVALID_VALUE);
1093 else switch(param)
1095 case AL_PITCH:
1096 case AL_CONE_INNER_ANGLE:
1097 case AL_CONE_OUTER_ANGLE:
1098 case AL_GAIN:
1099 case AL_MAX_DISTANCE:
1100 case AL_ROLLOFF_FACTOR:
1101 case AL_REFERENCE_DISTANCE:
1102 case AL_MIN_GAIN:
1103 case AL_MAX_GAIN:
1104 case AL_CONE_OUTER_GAIN:
1105 case AL_CONE_OUTER_GAINHF:
1106 case AL_SEC_OFFSET:
1107 case AL_SAMPLE_OFFSET:
1108 case AL_BYTE_OFFSET:
1109 case AL_AIR_ABSORPTION_FACTOR:
1110 case AL_ROOM_ROLLOFF_FACTOR:
1112 case AL_POSITION:
1113 case AL_VELOCITY:
1114 case AL_DIRECTION:
1115 SetSourcefv(Source, Context, param, values);
1116 break;
1118 default:
1119 alSetError(Context, AL_INVALID_ENUM);
1122 ALCcontext_DecRef(Context);
1126 AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value)
1128 ALCcontext *Context;
1129 ALsource *Source;
1130 ALfloat fval;
1132 Context = GetContextRef();
1133 if(!Context) return;
1135 if((Source=LookupSource(Context, source)) == NULL)
1136 alSetError(Context, AL_INVALID_NAME);
1137 else switch(param)
1139 case AL_PITCH:
1140 case AL_CONE_INNER_ANGLE:
1141 case AL_CONE_OUTER_ANGLE:
1142 case AL_GAIN:
1143 case AL_MAX_DISTANCE:
1144 case AL_ROLLOFF_FACTOR:
1145 case AL_REFERENCE_DISTANCE:
1146 case AL_MIN_GAIN:
1147 case AL_MAX_GAIN:
1148 case AL_CONE_OUTER_GAIN:
1149 case AL_CONE_OUTER_GAINHF:
1150 case AL_AIR_ABSORPTION_FACTOR:
1151 case AL_ROOM_ROLLOFF_FACTOR:
1152 case AL_DOPPLER_FACTOR:
1153 case AL_SEC_OFFSET:
1154 case AL_SAMPLE_OFFSET:
1155 case AL_BYTE_OFFSET:
1156 fval = value;
1157 SetSourcefv(Source, Context, param, &fval);
1158 break;
1160 default:
1161 alSetError(Context, AL_INVALID_ENUM);
1164 ALCcontext_DecRef(Context);
1167 AL_API ALvoid AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3)
1169 ALCcontext *Context;
1170 ALsource *Source;
1171 ALfloat fvals[3];
1173 Context = GetContextRef();
1174 if(!Context) return;
1176 if((Source=LookupSource(Context, source)) == NULL)
1177 alSetError(Context, AL_INVALID_NAME);
1178 else switch(param)
1180 case AL_POSITION:
1181 case AL_VELOCITY:
1182 case AL_DIRECTION:
1183 fvals[0] = value1;
1184 fvals[1] = value2;
1185 fvals[2] = value3;
1186 SetSourcefv(Source, Context, param, fvals);
1187 break;
1189 default:
1190 alSetError(Context, AL_INVALID_ENUM);
1193 ALCcontext_DecRef(Context);
1196 AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values)
1198 ALCcontext *Context;
1199 ALsource *Source;
1200 ALfloat fvals[3];
1202 Context = GetContextRef();
1203 if(!Context) return;
1205 if((Source=LookupSource(Context, source)) == NULL)
1206 alSetError(Context, AL_INVALID_NAME);
1207 else if(!values)
1208 alSetError(Context, AL_INVALID_VALUE);
1209 else switch(param)
1211 case AL_PITCH:
1212 case AL_CONE_INNER_ANGLE:
1213 case AL_CONE_OUTER_ANGLE:
1214 case AL_GAIN:
1215 case AL_MAX_DISTANCE:
1216 case AL_ROLLOFF_FACTOR:
1217 case AL_REFERENCE_DISTANCE:
1218 case AL_MIN_GAIN:
1219 case AL_MAX_GAIN:
1220 case AL_CONE_OUTER_GAIN:
1221 case AL_CONE_OUTER_GAINHF:
1222 case AL_SEC_OFFSET:
1223 case AL_SAMPLE_OFFSET:
1224 case AL_BYTE_OFFSET:
1225 case AL_AIR_ABSORPTION_FACTOR:
1226 case AL_ROOM_ROLLOFF_FACTOR:
1227 fvals[0] = values[0];
1228 SetSourcefv(Source, Context, param, fvals);
1229 break;
1231 case AL_POSITION:
1232 case AL_VELOCITY:
1233 case AL_DIRECTION:
1234 fvals[0] = values[0];
1235 fvals[1] = values[1];
1236 fvals[2] = values[2];
1237 SetSourcefv(Source, Context, param, fvals);
1238 break;
1240 default:
1241 alSetError(Context, AL_INVALID_ENUM);
1244 ALCcontext_DecRef(Context);
1248 AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value)
1250 ALCcontext *Context;
1251 ALsource *Source;
1253 Context = GetContextRef();
1254 if(!Context) return;
1256 if((Source=LookupSource(Context, source)) == NULL)
1257 alSetError(Context, AL_INVALID_NAME);
1258 else switch(param)
1260 case AL_MAX_DISTANCE:
1261 case AL_ROLLOFF_FACTOR:
1262 case AL_CONE_INNER_ANGLE:
1263 case AL_CONE_OUTER_ANGLE:
1264 case AL_REFERENCE_DISTANCE:
1265 case AL_SOURCE_RELATIVE:
1266 case AL_LOOPING:
1267 case AL_BUFFER:
1268 case AL_SOURCE_STATE:
1269 case AL_SEC_OFFSET:
1270 case AL_SAMPLE_OFFSET:
1271 case AL_BYTE_OFFSET:
1272 case AL_DIRECT_FILTER:
1273 case AL_DIRECT_FILTER_GAINHF_AUTO:
1274 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1275 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1276 case AL_DIRECT_CHANNELS_SOFT:
1277 case AL_DISTANCE_MODEL:
1278 SetSourceiv(Source, Context, param, &value);
1279 break;
1281 default:
1282 alSetError(Context, AL_INVALID_ENUM);
1285 ALCcontext_DecRef(Context);
1288 AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3)
1290 ALCcontext *Context;
1291 ALsource *Source;
1292 ALint ivals[3];
1294 Context = GetContextRef();
1295 if(!Context) return;
1297 if((Source=LookupSource(Context, source)) == NULL)
1298 alSetError(Context, AL_INVALID_NAME);
1299 else switch(param)
1301 case AL_POSITION:
1302 case AL_VELOCITY:
1303 case AL_DIRECTION:
1304 case AL_AUXILIARY_SEND_FILTER:
1305 ivals[0] = value1;
1306 ivals[1] = value2;
1307 ivals[2] = value3;
1308 SetSourceiv(Source, Context, param, ivals);
1309 break;
1311 default:
1312 alSetError(Context, AL_INVALID_ENUM);
1315 ALCcontext_DecRef(Context);
1318 AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values)
1320 ALCcontext *Context;
1321 ALsource *Source;
1323 Context = GetContextRef();
1324 if(!Context) return;
1326 if((Source=LookupSource(Context, source)) == NULL)
1327 alSetError(Context, AL_INVALID_NAME);
1328 else if(!values)
1329 alSetError(Context, AL_INVALID_VALUE);
1330 else switch(param)
1332 case AL_SOURCE_RELATIVE:
1333 case AL_CONE_INNER_ANGLE:
1334 case AL_CONE_OUTER_ANGLE:
1335 case AL_LOOPING:
1336 case AL_BUFFER:
1337 case AL_SOURCE_STATE:
1338 case AL_SEC_OFFSET:
1339 case AL_SAMPLE_OFFSET:
1340 case AL_BYTE_OFFSET:
1341 case AL_MAX_DISTANCE:
1342 case AL_ROLLOFF_FACTOR:
1343 case AL_REFERENCE_DISTANCE:
1344 case AL_DIRECT_FILTER:
1345 case AL_DIRECT_FILTER_GAINHF_AUTO:
1346 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1347 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1348 case AL_DISTANCE_MODEL:
1349 case AL_DIRECT_CHANNELS_SOFT:
1351 case AL_POSITION:
1352 case AL_VELOCITY:
1353 case AL_DIRECTION:
1354 case AL_AUXILIARY_SEND_FILTER:
1355 SetSourceiv(Source, Context, param, values);
1356 break;
1358 default:
1359 alSetError(Context, AL_INVALID_ENUM);
1362 ALCcontext_DecRef(Context);
1366 AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value)
1368 ALCcontext *Context;
1369 ALsource *Source;
1371 Context = GetContextRef();
1372 if(!Context) return;
1374 if((Source=LookupSource(Context, source)) == NULL)
1375 alSetError(Context, AL_INVALID_NAME);
1376 else switch(param)
1378 case AL_MAX_DISTANCE:
1379 case AL_ROLLOFF_FACTOR:
1380 case AL_CONE_INNER_ANGLE:
1381 case AL_CONE_OUTER_ANGLE:
1382 case AL_REFERENCE_DISTANCE:
1383 case AL_SOURCE_RELATIVE:
1384 case AL_LOOPING:
1385 case AL_SOURCE_STATE:
1386 case AL_SEC_OFFSET:
1387 case AL_SAMPLE_OFFSET:
1388 case AL_BYTE_OFFSET:
1389 case AL_DIRECT_FILTER_GAINHF_AUTO:
1390 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1391 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1392 case AL_DIRECT_CHANNELS_SOFT:
1393 case AL_DISTANCE_MODEL:
1394 case AL_BUFFER:
1395 case AL_DIRECT_FILTER:
1396 SetSourcei64v(Source, Context, param, &value);
1397 break;
1399 default:
1400 alSetError(Context, AL_INVALID_ENUM);
1403 ALCcontext_DecRef(Context);
1406 AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3)
1408 ALCcontext *Context;
1409 ALsource *Source;
1410 ALint64SOFT i64vals[3];
1412 Context = GetContextRef();
1413 if(!Context) return;
1415 if((Source=LookupSource(Context, source)) == NULL)
1416 alSetError(Context, AL_INVALID_NAME);
1417 else switch(param)
1419 case AL_POSITION:
1420 case AL_VELOCITY:
1421 case AL_DIRECTION:
1422 case AL_AUXILIARY_SEND_FILTER:
1423 i64vals[0] = value1;
1424 i64vals[1] = value2;
1425 i64vals[2] = value3;
1426 SetSourcei64v(Source, Context, param, i64vals);
1427 break;
1429 default:
1430 alSetError(Context, AL_INVALID_ENUM);
1433 ALCcontext_DecRef(Context);
1436 AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values)
1438 ALCcontext *Context;
1439 ALsource *Source;
1441 Context = GetContextRef();
1442 if(!Context) return;
1444 if((Source=LookupSource(Context, source)) == NULL)
1445 alSetError(Context, AL_INVALID_NAME);
1446 else if(!values)
1447 alSetError(Context, AL_INVALID_VALUE);
1448 else switch(param)
1450 case AL_SOURCE_RELATIVE:
1451 case AL_CONE_INNER_ANGLE:
1452 case AL_CONE_OUTER_ANGLE:
1453 case AL_LOOPING:
1454 case AL_SOURCE_STATE:
1455 case AL_SEC_OFFSET:
1456 case AL_SAMPLE_OFFSET:
1457 case AL_BYTE_OFFSET:
1458 case AL_MAX_DISTANCE:
1459 case AL_ROLLOFF_FACTOR:
1460 case AL_REFERENCE_DISTANCE:
1461 case AL_DIRECT_FILTER_GAINHF_AUTO:
1462 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1463 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1464 case AL_DISTANCE_MODEL:
1465 case AL_DIRECT_CHANNELS_SOFT:
1466 case AL_BUFFER:
1467 case AL_DIRECT_FILTER:
1469 case AL_POSITION:
1470 case AL_VELOCITY:
1471 case AL_DIRECTION:
1472 case AL_AUXILIARY_SEND_FILTER:
1473 SetSourcei64v(Source, Context, param, values);
1474 break;
1476 default:
1477 alSetError(Context, AL_INVALID_ENUM);
1480 ALCcontext_DecRef(Context);
1484 AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value)
1486 ALCcontext *Context;
1487 ALsource *Source;
1488 ALdouble dval;
1490 Context = GetContextRef();
1491 if(!Context) return;
1493 if((Source=LookupSource(Context, source)) == NULL)
1494 alSetError(Context, AL_INVALID_NAME);
1495 else if(!value)
1496 alSetError(Context, AL_INVALID_VALUE);
1497 else switch(param)
1499 case AL_PITCH:
1500 case AL_GAIN:
1501 case AL_MIN_GAIN:
1502 case AL_MAX_GAIN:
1503 case AL_MAX_DISTANCE:
1504 case AL_ROLLOFF_FACTOR:
1505 case AL_CONE_OUTER_GAIN:
1506 case AL_CONE_OUTER_GAINHF:
1507 case AL_SEC_OFFSET:
1508 case AL_SAMPLE_OFFSET:
1509 case AL_BYTE_OFFSET:
1510 case AL_CONE_INNER_ANGLE:
1511 case AL_CONE_OUTER_ANGLE:
1512 case AL_REFERENCE_DISTANCE:
1513 case AL_AIR_ABSORPTION_FACTOR:
1514 case AL_ROOM_ROLLOFF_FACTOR:
1515 case AL_DOPPLER_FACTOR:
1516 if(GetSourcedv(Source, Context, param, &dval) == AL_NO_ERROR)
1517 *value = (ALfloat)dval;
1518 break;
1520 default:
1521 alSetError(Context, AL_INVALID_ENUM);
1524 ALCcontext_DecRef(Context);
1528 AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
1530 ALCcontext *Context;
1531 ALsource *Source;
1532 ALdouble dvals[3];
1534 Context = GetContextRef();
1535 if(!Context) return;
1537 if((Source=LookupSource(Context, source)) == NULL)
1538 alSetError(Context, AL_INVALID_NAME);
1539 else if(!(value1 && value2 && value3))
1540 alSetError(Context, AL_INVALID_VALUE);
1541 else switch(param)
1543 case AL_POSITION:
1544 case AL_VELOCITY:
1545 case AL_DIRECTION:
1546 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1548 *value1 = (ALfloat)dvals[0];
1549 *value2 = (ALfloat)dvals[1];
1550 *value3 = (ALfloat)dvals[2];
1552 break;
1554 default:
1555 alSetError(Context, AL_INVALID_ENUM);
1558 ALCcontext_DecRef(Context);
1562 AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values)
1564 ALCcontext *Context;
1565 ALsource *Source;
1566 ALdouble dvals[2];
1568 switch(param)
1570 case AL_PITCH:
1571 case AL_GAIN:
1572 case AL_MIN_GAIN:
1573 case AL_MAX_GAIN:
1574 case AL_MAX_DISTANCE:
1575 case AL_ROLLOFF_FACTOR:
1576 case AL_DOPPLER_FACTOR:
1577 case AL_CONE_OUTER_GAIN:
1578 case AL_SEC_OFFSET:
1579 case AL_SAMPLE_OFFSET:
1580 case AL_BYTE_OFFSET:
1581 case AL_CONE_INNER_ANGLE:
1582 case AL_CONE_OUTER_ANGLE:
1583 case AL_REFERENCE_DISTANCE:
1584 case AL_CONE_OUTER_GAINHF:
1585 case AL_AIR_ABSORPTION_FACTOR:
1586 case AL_ROOM_ROLLOFF_FACTOR:
1587 alGetSourcef(source, param, values);
1588 return;
1590 case AL_POSITION:
1591 case AL_VELOCITY:
1592 case AL_DIRECTION:
1593 alGetSource3f(source, param, values+0, values+1, values+2);
1594 return;
1597 Context = GetContextRef();
1598 if(!Context) return;
1600 if((Source=LookupSource(Context, source)) == NULL)
1601 alSetError(Context, AL_INVALID_NAME);
1602 else if(!values)
1603 alSetError(Context, AL_INVALID_VALUE);
1604 else switch(param)
1606 case AL_SAMPLE_RW_OFFSETS_SOFT:
1607 case AL_BYTE_RW_OFFSETS_SOFT:
1608 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1610 values[0] = (ALfloat)dvals[0];
1611 values[1] = (ALfloat)dvals[1];
1613 break;
1615 default:
1616 alSetError(Context, AL_INVALID_ENUM);
1619 ALCcontext_DecRef(Context);
1623 AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value)
1625 ALCcontext *Context;
1626 ALsource *Source;
1628 Context = GetContextRef();
1629 if(!Context) return;
1631 if((Source=LookupSource(Context, source)) == NULL)
1632 alSetError(Context, AL_INVALID_NAME);
1633 else if(!value)
1634 alSetError(Context, AL_INVALID_VALUE);
1635 else switch(param)
1637 case AL_PITCH:
1638 case AL_GAIN:
1639 case AL_MIN_GAIN:
1640 case AL_MAX_GAIN:
1641 case AL_MAX_DISTANCE:
1642 case AL_ROLLOFF_FACTOR:
1643 case AL_CONE_OUTER_GAIN:
1644 case AL_CONE_OUTER_GAINHF:
1645 case AL_SEC_OFFSET:
1646 case AL_SAMPLE_OFFSET:
1647 case AL_BYTE_OFFSET:
1648 case AL_CONE_INNER_ANGLE:
1649 case AL_CONE_OUTER_ANGLE:
1650 case AL_REFERENCE_DISTANCE:
1651 case AL_AIR_ABSORPTION_FACTOR:
1652 case AL_ROOM_ROLLOFF_FACTOR:
1653 case AL_DOPPLER_FACTOR:
1654 GetSourcedv(Source, Context, param, value);
1655 break;
1657 default:
1658 alSetError(Context, AL_INVALID_ENUM);
1661 ALCcontext_DecRef(Context);
1664 AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3)
1666 ALCcontext *Context;
1667 ALsource *Source;
1668 ALdouble dvals[3];
1670 Context = GetContextRef();
1671 if(!Context) return;
1673 if((Source=LookupSource(Context, source)) == NULL)
1674 alSetError(Context, AL_INVALID_NAME);
1675 else if(!(value1 && value2 && value3))
1676 alSetError(Context, AL_INVALID_VALUE);
1677 else switch(param)
1679 case AL_POSITION:
1680 case AL_VELOCITY:
1681 case AL_DIRECTION:
1682 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1684 *value1 = dvals[0];
1685 *value2 = dvals[1];
1686 *value3 = dvals[2];
1688 break;
1690 default:
1691 alSetError(Context, AL_INVALID_ENUM);
1694 ALCcontext_DecRef(Context);
1697 AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values)
1699 ALCcontext *Context;
1700 ALsource *Source;
1702 Context = GetContextRef();
1703 if(!Context) return;
1705 if((Source=LookupSource(Context, source)) == NULL)
1706 alSetError(Context, AL_INVALID_NAME);
1707 else if(!values)
1708 alSetError(Context, AL_INVALID_VALUE);
1709 else switch(param)
1711 case AL_PITCH:
1712 case AL_GAIN:
1713 case AL_MIN_GAIN:
1714 case AL_MAX_GAIN:
1715 case AL_MAX_DISTANCE:
1716 case AL_ROLLOFF_FACTOR:
1717 case AL_DOPPLER_FACTOR:
1718 case AL_CONE_OUTER_GAIN:
1719 case AL_SEC_OFFSET:
1720 case AL_SAMPLE_OFFSET:
1721 case AL_BYTE_OFFSET:
1722 case AL_CONE_INNER_ANGLE:
1723 case AL_CONE_OUTER_ANGLE:
1724 case AL_REFERENCE_DISTANCE:
1725 case AL_CONE_OUTER_GAINHF:
1726 case AL_AIR_ABSORPTION_FACTOR:
1727 case AL_ROOM_ROLLOFF_FACTOR:
1729 case AL_SAMPLE_RW_OFFSETS_SOFT:
1730 case AL_BYTE_RW_OFFSETS_SOFT:
1731 case AL_SEC_OFFSET_LATENCY_SOFT:
1733 case AL_POSITION:
1734 case AL_VELOCITY:
1735 case AL_DIRECTION:
1736 GetSourcedv(Source, Context, param, values);
1737 break;
1739 default:
1740 alSetError(Context, AL_INVALID_ENUM);
1743 ALCcontext_DecRef(Context);
1747 AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value)
1749 ALCcontext *Context;
1750 ALsource *Source;
1752 Context = GetContextRef();
1753 if(!Context) return;
1755 if((Source=LookupSource(Context, source)) == NULL)
1756 alSetError(Context, AL_INVALID_NAME);
1757 else if(!value)
1758 alSetError(Context, AL_INVALID_VALUE);
1759 else switch(param)
1761 case AL_MAX_DISTANCE:
1762 case AL_ROLLOFF_FACTOR:
1763 case AL_REFERENCE_DISTANCE:
1764 case AL_SOURCE_RELATIVE:
1765 case AL_CONE_INNER_ANGLE:
1766 case AL_CONE_OUTER_ANGLE:
1767 case AL_LOOPING:
1768 case AL_BUFFER:
1769 case AL_SOURCE_STATE:
1770 case AL_BUFFERS_QUEUED:
1771 case AL_BUFFERS_PROCESSED:
1772 case AL_SOURCE_TYPE:
1773 case AL_SEC_OFFSET:
1774 case AL_SAMPLE_OFFSET:
1775 case AL_BYTE_OFFSET:
1776 case AL_DIRECT_FILTER_GAINHF_AUTO:
1777 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1778 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1779 case AL_DOPPLER_FACTOR:
1780 case AL_DIRECT_CHANNELS_SOFT:
1781 case AL_DISTANCE_MODEL:
1782 GetSourceiv(Source, Context, param, value);
1783 break;
1785 default:
1786 alSetError(Context, AL_INVALID_ENUM);
1789 ALCcontext_DecRef(Context);
1793 AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3)
1795 ALCcontext *Context;
1796 ALsource *Source;
1797 ALint ivals[3];
1799 Context = GetContextRef();
1800 if(!Context) return;
1802 if((Source=LookupSource(Context, source)) == NULL)
1803 alSetError(Context, AL_INVALID_NAME);
1804 else if(!(value1 && value2 && value3))
1805 alSetError(Context, AL_INVALID_VALUE);
1806 else switch(param)
1808 case AL_POSITION:
1809 case AL_VELOCITY:
1810 case AL_DIRECTION:
1811 if(GetSourceiv(Source, Context, param, ivals) == AL_NO_ERROR)
1813 *value1 = ivals[0];
1814 *value2 = ivals[1];
1815 *value3 = ivals[2];
1817 break;
1819 default:
1820 alSetError(Context, AL_INVALID_ENUM);
1823 ALCcontext_DecRef(Context);
1827 AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values)
1829 ALCcontext *Context;
1830 ALsource *Source;
1832 Context = GetContextRef();
1833 if(!Context) return;
1835 if((Source=LookupSource(Context, source)) == NULL)
1836 alSetError(Context, AL_INVALID_NAME);
1837 else if(!values)
1838 alSetError(Context, AL_INVALID_VALUE);
1839 else switch(param)
1841 case AL_SOURCE_RELATIVE:
1842 case AL_CONE_INNER_ANGLE:
1843 case AL_CONE_OUTER_ANGLE:
1844 case AL_LOOPING:
1845 case AL_BUFFER:
1846 case AL_SOURCE_STATE:
1847 case AL_BUFFERS_QUEUED:
1848 case AL_BUFFERS_PROCESSED:
1849 case AL_SEC_OFFSET:
1850 case AL_SAMPLE_OFFSET:
1851 case AL_BYTE_OFFSET:
1852 case AL_MAX_DISTANCE:
1853 case AL_ROLLOFF_FACTOR:
1854 case AL_DOPPLER_FACTOR:
1855 case AL_REFERENCE_DISTANCE:
1856 case AL_SOURCE_TYPE:
1857 case AL_DIRECT_FILTER:
1858 case AL_DIRECT_FILTER_GAINHF_AUTO:
1859 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1860 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1861 case AL_DISTANCE_MODEL:
1862 case AL_DIRECT_CHANNELS_SOFT:
1864 case AL_SAMPLE_RW_OFFSETS_SOFT:
1865 case AL_BYTE_RW_OFFSETS_SOFT:
1867 case AL_POSITION:
1868 case AL_VELOCITY:
1869 case AL_DIRECTION:
1870 GetSourceiv(Source, Context, param, values);
1871 break;
1873 default:
1874 alSetError(Context, AL_INVALID_ENUM);
1877 ALCcontext_DecRef(Context);
1881 AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value)
1883 ALCcontext *Context;
1884 ALsource *Source;
1886 Context = GetContextRef();
1887 if(!Context) return;
1889 if((Source=LookupSource(Context, source)) == NULL)
1890 alSetError(Context, AL_INVALID_NAME);
1891 else if(!value)
1892 alSetError(Context, AL_INVALID_VALUE);
1893 else switch(param)
1895 case AL_MAX_DISTANCE:
1896 case AL_ROLLOFF_FACTOR:
1897 case AL_REFERENCE_DISTANCE:
1898 case AL_SOURCE_RELATIVE:
1899 case AL_CONE_INNER_ANGLE:
1900 case AL_CONE_OUTER_ANGLE:
1901 case AL_LOOPING:
1902 case AL_BUFFER:
1903 case AL_SOURCE_STATE:
1904 case AL_BUFFERS_QUEUED:
1905 case AL_BUFFERS_PROCESSED:
1906 case AL_SOURCE_TYPE:
1907 case AL_SEC_OFFSET:
1908 case AL_SAMPLE_OFFSET:
1909 case AL_BYTE_OFFSET:
1910 case AL_DIRECT_FILTER_GAINHF_AUTO:
1911 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1912 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1913 case AL_DOPPLER_FACTOR:
1914 case AL_DIRECT_CHANNELS_SOFT:
1915 case AL_DISTANCE_MODEL:
1916 GetSourcei64v(Source, Context, param, value);
1917 break;
1919 default:
1920 alSetError(Context, AL_INVALID_ENUM);
1923 ALCcontext_DecRef(Context);
1926 AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3)
1928 ALCcontext *Context;
1929 ALsource *Source;
1930 ALint64 i64vals[3];
1932 Context = GetContextRef();
1933 if(!Context) return;
1935 if((Source=LookupSource(Context, source)) == NULL)
1936 alSetError(Context, AL_INVALID_NAME);
1937 else if(!(value1 && value2 && value3))
1938 alSetError(Context, AL_INVALID_VALUE);
1939 else switch(param)
1941 case AL_POSITION:
1942 case AL_VELOCITY:
1943 case AL_DIRECTION:
1944 if(GetSourcei64v(Source, Context, param, i64vals) == AL_NO_ERROR)
1946 *value1 = i64vals[0];
1947 *value2 = i64vals[1];
1948 *value3 = i64vals[2];
1950 break;
1952 default:
1953 alSetError(Context, AL_INVALID_ENUM);
1956 ALCcontext_DecRef(Context);
1959 AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values)
1961 ALCcontext *Context;
1962 ALsource *Source;
1964 Context = GetContextRef();
1965 if(!Context) return;
1967 if((Source=LookupSource(Context, source)) == NULL)
1968 alSetError(Context, AL_INVALID_NAME);
1969 else if(!values)
1970 alSetError(Context, AL_INVALID_VALUE);
1971 else switch(param)
1973 case AL_MAX_DISTANCE:
1974 case AL_ROLLOFF_FACTOR:
1975 case AL_REFERENCE_DISTANCE:
1976 case AL_SOURCE_RELATIVE:
1977 case AL_CONE_INNER_ANGLE:
1978 case AL_CONE_OUTER_ANGLE:
1979 case AL_LOOPING:
1980 case AL_BUFFER:
1981 case AL_SOURCE_STATE:
1982 case AL_BUFFERS_QUEUED:
1983 case AL_BUFFERS_PROCESSED:
1984 case AL_SOURCE_TYPE:
1985 case AL_SEC_OFFSET:
1986 case AL_SAMPLE_OFFSET:
1987 case AL_BYTE_OFFSET:
1988 case AL_DIRECT_FILTER_GAINHF_AUTO:
1989 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1990 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1991 case AL_DOPPLER_FACTOR:
1992 case AL_DIRECT_CHANNELS_SOFT:
1993 case AL_DISTANCE_MODEL:
1995 case AL_SAMPLE_RW_OFFSETS_SOFT:
1996 case AL_BYTE_RW_OFFSETS_SOFT:
1997 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
1999 case AL_POSITION:
2000 case AL_VELOCITY:
2001 case AL_DIRECTION:
2002 GetSourcei64v(Source, Context, param, values);
2003 break;
2005 default:
2006 alSetError(Context, AL_INVALID_ENUM);
2009 ALCcontext_DecRef(Context);
2013 AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint source)
2015 alSourcePlayv(1, &source);
2017 AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
2019 ALCcontext *Context;
2020 ALsource *Source;
2021 ALsizei i;
2023 Context = GetContextRef();
2024 if(!Context) return;
2026 al_try
2028 CHECK_VALUE(Context, n >= 0);
2029 for(i = 0;i < n;i++)
2031 if(!LookupSource(Context, sources[i]))
2032 al_throwerr(Context, AL_INVALID_NAME);
2035 LockContext(Context);
2036 while(Context->MaxActiveSources-Context->ActiveSourceCount < n)
2038 void *temp = NULL;
2039 ALsizei newcount;
2041 newcount = Context->MaxActiveSources << 1;
2042 if(newcount > 0)
2043 temp = realloc(Context->ActiveSources,
2044 sizeof(*Context->ActiveSources) * newcount);
2045 if(!temp)
2047 UnlockContext(Context);
2048 al_throwerr(Context, AL_OUT_OF_MEMORY);
2051 Context->ActiveSources = temp;
2052 Context->MaxActiveSources = newcount;
2055 for(i = 0;i < n;i++)
2057 Source = LookupSource(Context, sources[i]);
2058 if(Context->DeferUpdates) Source->new_state = AL_PLAYING;
2059 else SetSourceState(Source, Context, AL_PLAYING);
2061 UnlockContext(Context);
2063 al_endtry;
2065 ALCcontext_DecRef(Context);
2068 AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source)
2070 alSourcePausev(1, &source);
2072 AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
2074 ALCcontext *Context;
2075 ALsource *Source;
2076 ALsizei i;
2078 Context = GetContextRef();
2079 if(!Context) return;
2081 al_try
2083 CHECK_VALUE(Context, n >= 0);
2084 for(i = 0;i < n;i++)
2086 if(!LookupSource(Context, sources[i]))
2087 al_throwerr(Context, AL_INVALID_NAME);
2090 LockContext(Context);
2091 for(i = 0;i < n;i++)
2093 Source = LookupSource(Context, sources[i]);
2094 if(Context->DeferUpdates) Source->new_state = AL_PAUSED;
2095 else SetSourceState(Source, Context, AL_PAUSED);
2097 UnlockContext(Context);
2099 al_endtry;
2101 ALCcontext_DecRef(Context);
2104 AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source)
2106 alSourceStopv(1, &source);
2108 AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
2110 ALCcontext *Context;
2111 ALsource *Source;
2112 ALsizei i;
2114 Context = GetContextRef();
2115 if(!Context) return;
2117 al_try
2119 CHECK_VALUE(Context, n >= 0);
2120 for(i = 0;i < n;i++)
2122 if(!LookupSource(Context, sources[i]))
2123 al_throwerr(Context, AL_INVALID_NAME);
2126 LockContext(Context);
2127 for(i = 0;i < n;i++)
2129 Source = LookupSource(Context, sources[i]);
2130 Source->new_state = AL_NONE;
2131 SetSourceState(Source, Context, AL_STOPPED);
2133 UnlockContext(Context);
2135 al_endtry;
2137 ALCcontext_DecRef(Context);
2140 AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source)
2142 alSourceRewindv(1, &source);
2144 AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
2146 ALCcontext *Context;
2147 ALsource *Source;
2148 ALsizei i;
2150 Context = GetContextRef();
2151 if(!Context) return;
2153 al_try
2155 CHECK_VALUE(Context, n >= 0);
2156 for(i = 0;i < n;i++)
2158 if(!LookupSource(Context, sources[i]))
2159 al_throwerr(Context, AL_INVALID_NAME);
2162 LockContext(Context);
2163 for(i = 0;i < n;i++)
2165 Source = LookupSource(Context, sources[i]);
2166 Source->new_state = AL_NONE;
2167 SetSourceState(Source, Context, AL_INITIAL);
2169 UnlockContext(Context);
2171 al_endtry;
2173 ALCcontext_DecRef(Context);
2177 AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers)
2179 ALCcontext *Context;
2180 ALsource *Source;
2181 ALsizei i;
2182 ALbufferlistitem *BufferListStart = NULL;
2183 ALbufferlistitem *BufferList;
2184 ALbuffer *BufferFmt;
2186 if(nb == 0)
2187 return;
2189 Context = GetContextRef();
2190 if(!Context) return;
2192 al_try
2194 ALCdevice *device = Context->Device;
2196 CHECK_VALUE(Context, nb >= 0);
2198 if((Source=LookupSource(Context, source)) == NULL)
2199 al_throwerr(Context, AL_INVALID_NAME);
2201 LockContext(Context);
2202 if(Source->SourceType == AL_STATIC)
2204 UnlockContext(Context);
2205 /* Can't queue on a Static Source */
2206 al_throwerr(Context, AL_INVALID_OPERATION);
2209 BufferFmt = NULL;
2211 /* Check for a valid Buffer, for its frequency and format */
2212 BufferList = Source->queue;
2213 while(BufferList)
2215 if(BufferList->buffer)
2217 BufferFmt = BufferList->buffer;
2218 break;
2220 BufferList = BufferList->next;
2223 for(i = 0;i < nb;i++)
2225 ALbuffer *buffer = NULL;
2226 if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
2228 UnlockContext(Context);
2229 al_throwerr(Context, AL_INVALID_NAME);
2232 if(!BufferListStart)
2234 BufferListStart = malloc(sizeof(ALbufferlistitem));
2235 BufferListStart->buffer = buffer;
2236 BufferListStart->next = NULL;
2237 BufferListStart->prev = NULL;
2238 BufferList = BufferListStart;
2240 else
2242 BufferList->next = malloc(sizeof(ALbufferlistitem));
2243 BufferList->next->buffer = buffer;
2244 BufferList->next->next = NULL;
2245 BufferList->next->prev = BufferList;
2246 BufferList = BufferList->next;
2248 if(!buffer) continue;
2249 IncrementRef(&buffer->ref);
2251 ReadLock(&buffer->lock);
2252 if(BufferFmt == NULL)
2254 BufferFmt = buffer;
2256 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
2257 Source->SampleSize = BytesFromFmt(buffer->FmtType);
2258 if(buffer->FmtChannels == FmtMono)
2259 Source->Update = CalcSourceParams;
2260 else
2261 Source->Update = CalcNonAttnSourceParams;
2263 Source->NeedsUpdate = AL_TRUE;
2265 else if(BufferFmt->Frequency != buffer->Frequency ||
2266 BufferFmt->OriginalChannels != buffer->OriginalChannels ||
2267 BufferFmt->OriginalType != buffer->OriginalType)
2269 ReadUnlock(&buffer->lock);
2270 UnlockContext(Context);
2271 al_throwerr(Context, AL_INVALID_OPERATION);
2273 ReadUnlock(&buffer->lock);
2276 /* Source is now streaming */
2277 Source->SourceType = AL_STREAMING;
2279 if(Source->queue == NULL)
2280 Source->queue = BufferListStart;
2281 else
2283 /* Append to the end of the queue */
2284 BufferList = Source->queue;
2285 while(BufferList->next != NULL)
2286 BufferList = BufferList->next;
2288 BufferListStart->prev = BufferList;
2289 BufferList->next = BufferListStart;
2292 Source->BuffersInQueue += nb;
2294 UnlockContext(Context);
2296 al_catchany()
2298 while(BufferListStart)
2300 BufferList = BufferListStart;
2301 BufferListStart = BufferList->next;
2303 if(BufferList->buffer)
2304 DecrementRef(&BufferList->buffer->ref);
2305 free(BufferList);
2308 al_endtry;
2310 ALCcontext_DecRef(Context);
2313 AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers)
2315 ALCcontext *Context;
2316 ALsource *Source;
2317 ALsizei i;
2318 ALbufferlistitem *BufferList;
2320 if(nb == 0)
2321 return;
2323 Context = GetContextRef();
2324 if(!Context) return;
2326 al_try
2328 CHECK_VALUE(Context, nb >= 0);
2330 if((Source=LookupSource(Context, source)) == NULL)
2331 al_throwerr(Context, AL_INVALID_NAME);
2333 LockContext(Context);
2334 if(Source->Looping || Source->SourceType != AL_STREAMING ||
2335 (ALuint)nb > Source->BuffersPlayed)
2337 UnlockContext(Context);
2338 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2339 al_throwerr(Context, AL_INVALID_VALUE);
2342 for(i = 0;i < nb;i++)
2344 BufferList = Source->queue;
2345 Source->queue = BufferList->next;
2346 Source->BuffersInQueue--;
2347 Source->BuffersPlayed--;
2349 if(BufferList->buffer)
2351 buffers[i] = BufferList->buffer->id;
2352 DecrementRef(&BufferList->buffer->ref);
2354 else
2355 buffers[i] = 0;
2357 free(BufferList);
2359 if(Source->queue)
2360 Source->queue->prev = NULL;
2361 UnlockContext(Context);
2363 al_endtry;
2365 ALCcontext_DecRef(Context);
2369 static ALvoid InitSourceParams(ALsource *Source)
2371 ALuint i;
2373 Source->InnerAngle = 360.0f;
2374 Source->OuterAngle = 360.0f;
2375 Source->Pitch = 1.0f;
2376 Source->Position[0] = 0.0f;
2377 Source->Position[1] = 0.0f;
2378 Source->Position[2] = 0.0f;
2379 Source->Orientation[0] = 0.0f;
2380 Source->Orientation[1] = 0.0f;
2381 Source->Orientation[2] = 0.0f;
2382 Source->Velocity[0] = 0.0f;
2383 Source->Velocity[1] = 0.0f;
2384 Source->Velocity[2] = 0.0f;
2385 Source->RefDistance = 1.0f;
2386 Source->MaxDistance = FLT_MAX;
2387 Source->RollOffFactor = 1.0f;
2388 Source->Looping = AL_FALSE;
2389 Source->Gain = 1.0f;
2390 Source->MinGain = 0.0f;
2391 Source->MaxGain = 1.0f;
2392 Source->OuterGain = 0.0f;
2393 Source->OuterGainHF = 1.0f;
2395 Source->DryGainHFAuto = AL_TRUE;
2396 Source->WetGainAuto = AL_TRUE;
2397 Source->WetGainHFAuto = AL_TRUE;
2398 Source->AirAbsorptionFactor = 0.0f;
2399 Source->RoomRolloffFactor = 0.0f;
2400 Source->DopplerFactor = 1.0f;
2401 Source->DirectChannels = AL_FALSE;
2403 Source->DistanceModel = DefaultDistanceModel;
2405 Source->Resampler = DefaultResampler;
2407 Source->state = AL_INITIAL;
2408 Source->new_state = AL_NONE;
2409 Source->SourceType = AL_UNDETERMINED;
2410 Source->Offset = -1.0;
2412 Source->DirectGain = 1.0f;
2413 Source->DirectGainHF = 1.0f;
2414 for(i = 0;i < MAX_SENDS;i++)
2416 Source->Send[i].Gain = 1.0f;
2417 Source->Send[i].GainHF = 1.0f;
2420 Source->NeedsUpdate = AL_TRUE;
2422 Source->Hrtf.Moving = AL_FALSE;
2423 Source->Hrtf.Counter = 0;
2427 /* SetSourceState
2429 * Sets the source's new play state given its current state.
2431 ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
2433 if(state == AL_PLAYING)
2435 ALbufferlistitem *BufferList;
2436 ALsizei j, k;
2438 /* Check that there is a queue containing at least one valid, non zero
2439 * length Buffer. */
2440 BufferList = Source->queue;
2441 while(BufferList)
2443 if(BufferList->buffer != NULL && BufferList->buffer->SampleLen)
2444 break;
2445 BufferList = BufferList->next;
2448 if(Source->state != AL_PLAYING)
2450 for(j = 0;j < MaxChannels;j++)
2452 for(k = 0;k < SRC_HISTORY_LENGTH;k++)
2453 Source->Hrtf.History[j][k] = 0.0f;
2454 for(k = 0;k < HRIR_LENGTH;k++)
2456 Source->Hrtf.Values[j][k][0] = 0.0f;
2457 Source->Hrtf.Values[j][k][1] = 0.0f;
2462 if(Source->state != AL_PAUSED)
2464 Source->state = AL_PLAYING;
2465 Source->position = 0;
2466 Source->position_fraction = 0;
2467 Source->BuffersPlayed = 0;
2469 else
2470 Source->state = AL_PLAYING;
2472 // Check if an Offset has been set
2473 if(Source->Offset >= 0.0)
2474 ApplyOffset(Source);
2476 /* If there's nothing to play, or device is disconnected, go right to
2477 * stopped */
2478 if(!BufferList || !Context->Device->Connected)
2480 SetSourceState(Source, Context, AL_STOPPED);
2481 return;
2484 for(j = 0;j < Context->ActiveSourceCount;j++)
2486 if(Context->ActiveSources[j] == Source)
2487 break;
2489 if(j == Context->ActiveSourceCount)
2490 Context->ActiveSources[Context->ActiveSourceCount++] = Source;
2492 else if(state == AL_PAUSED)
2494 if(Source->state == AL_PLAYING)
2496 Source->state = AL_PAUSED;
2497 Source->Hrtf.Moving = AL_FALSE;
2498 Source->Hrtf.Counter = 0;
2501 else if(state == AL_STOPPED)
2503 if(Source->state != AL_INITIAL)
2505 Source->state = AL_STOPPED;
2506 Source->BuffersPlayed = Source->BuffersInQueue;
2507 Source->Hrtf.Moving = AL_FALSE;
2508 Source->Hrtf.Counter = 0;
2510 Source->Offset = -1.0;
2512 else if(state == AL_INITIAL)
2514 if(Source->state != AL_INITIAL)
2516 Source->state = AL_INITIAL;
2517 Source->position = 0;
2518 Source->position_fraction = 0;
2519 Source->BuffersPlayed = 0;
2520 Source->Hrtf.Moving = AL_FALSE;
2521 Source->Hrtf.Counter = 0;
2523 Source->Offset = -1.0;
2527 /* GetSourceOffset
2529 * Gets the current read offset for the given Source, in 32.32 fixed-point
2530 * samples. The offset is relative to the start of the queue (not the start of
2531 * the current buffer).
2533 static ALint64 GetSourceOffset(const ALsource *Source)
2535 const ALbufferlistitem *BufferList;
2536 ALuint64 readPos;
2537 ALuint i;
2539 if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
2540 return 0;
2542 /* NOTE: This is the offset into the *current* buffer, so add the length of
2543 * any played buffers */
2544 readPos = (ALuint64)Source->position << 32;
2545 readPos |= (ALuint64)Source->position_fraction << (32-FRACTIONBITS);
2546 BufferList = Source->queue;
2547 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2549 if(BufferList->buffer)
2550 readPos += (ALuint64)BufferList->buffer->SampleLen << 32;
2551 BufferList = BufferList->next;
2554 return (ALint64)minu64(readPos, MAKEU64(0x7fffffff,0xffffffff));
2557 /* GetSourceSecOffset
2559 * Gets the current read offset for the given Source, in seconds. The offset is
2560 * relative to the start of the queue (not the start of the current buffer).
2562 static ALdouble GetSourceSecOffset(const ALsource *Source)
2564 const ALbufferlistitem *BufferList;
2565 const ALbuffer *Buffer = NULL;
2566 ALuint64 readPos;
2567 ALuint i;
2569 BufferList = Source->queue;
2570 while(BufferList)
2572 if(BufferList->buffer)
2574 Buffer = BufferList->buffer;
2575 break;
2577 BufferList = BufferList->next;
2580 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2581 return 0.0;
2583 /* NOTE: This is the offset into the *current* buffer, so add the length of
2584 * any played buffers */
2585 readPos = (ALuint64)Source->position << FRACTIONBITS;
2586 readPos |= (ALuint64)Source->position_fraction;
2587 BufferList = Source->queue;
2588 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2590 if(BufferList->buffer)
2591 readPos += (ALuint64)BufferList->buffer->SampleLen << FRACTIONBITS;
2592 BufferList = BufferList->next;
2595 return (ALdouble)readPos / (ALdouble)FRACTIONONE / (ALdouble)Buffer->Frequency;
2598 /* GetSourceOffsets
2600 * Gets the current read and write offsets for the given Source, in the
2601 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2602 * the start of the queue (not the start of the current buffer).
2604 static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen)
2606 const ALbufferlistitem *BufferList;
2607 const ALbuffer *Buffer = NULL;
2608 ALuint readPos, writePos;
2609 ALuint totalBufferLen;
2610 ALuint i;
2612 // Find the first valid Buffer in the Queue
2613 BufferList = Source->queue;
2614 while(BufferList)
2616 if(BufferList->buffer)
2618 Buffer = BufferList->buffer;
2619 break;
2621 BufferList = BufferList->next;
2624 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2626 offset[0] = 0.0;
2627 offset[1] = 0.0;
2628 return;
2631 if(updateLen > 0.0 && updateLen < 0.015)
2632 updateLen = 0.015;
2634 /* NOTE: This is the offset into the *current* buffer, so add the length of
2635 * any played buffers */
2636 readPos = Source->position;
2637 totalBufferLen = 0;
2638 BufferList = Source->queue;
2639 for(i = 0;BufferList;i++)
2641 if(BufferList->buffer)
2643 if(i < Source->BuffersPlayed)
2644 readPos += BufferList->buffer->SampleLen;
2645 totalBufferLen += BufferList->buffer->SampleLen;
2647 BufferList = BufferList->next;
2649 if(Source->state == AL_PLAYING)
2650 writePos = readPos + (ALuint)(updateLen*Buffer->Frequency);
2651 else
2652 writePos = readPos;
2654 if(Source->Looping)
2656 readPos %= totalBufferLen;
2657 writePos %= totalBufferLen;
2659 else
2661 /* Wrap positions back to 0 */
2662 if(readPos >= totalBufferLen)
2663 readPos = 0;
2664 if(writePos >= totalBufferLen)
2665 writePos = 0;
2668 switch(name)
2670 case AL_SEC_OFFSET:
2671 offset[0] = (ALdouble)readPos / Buffer->Frequency;
2672 offset[1] = (ALdouble)writePos / Buffer->Frequency;
2673 break;
2675 case AL_SAMPLE_OFFSET:
2676 case AL_SAMPLE_RW_OFFSETS_SOFT:
2677 offset[0] = (ALdouble)readPos;
2678 offset[1] = (ALdouble)writePos;
2679 break;
2681 case AL_BYTE_OFFSET:
2682 case AL_BYTE_RW_OFFSETS_SOFT:
2683 if(Buffer->OriginalType == UserFmtIMA4)
2685 ALuint BlockSize = 36 * ChannelsFromFmt(Buffer->FmtChannels);
2686 ALuint FrameBlockSize = 65;
2688 /* Round down to nearest ADPCM block */
2689 offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
2690 if(Source->state != AL_PLAYING)
2691 offset[1] = offset[0];
2692 else
2694 /* Round up to nearest ADPCM block */
2695 offset[1] = (ALdouble)((writePos+FrameBlockSize-1) /
2696 FrameBlockSize * BlockSize);
2699 else
2701 ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2702 offset[0] = (ALdouble)(readPos * FrameSize);
2703 offset[1] = (ALdouble)(writePos * FrameSize);
2705 break;
2710 /* ApplyOffset
2712 * Apply the stored playback offset to the Source. This function will update
2713 * the number of buffers "played" given the stored offset.
2715 ALboolean ApplyOffset(ALsource *Source)
2717 const ALbufferlistitem *BufferList;
2718 const ALbuffer *Buffer;
2719 ALint bufferLen, totalBufferLen;
2720 ALint buffersPlayed;
2721 ALint offset;
2723 /* Get sample frame offset */
2724 offset = GetSampleOffset(Source);
2725 if(offset == -1)
2726 return AL_FALSE;
2728 buffersPlayed = 0;
2729 totalBufferLen = 0;
2731 BufferList = Source->queue;
2732 while(BufferList)
2734 Buffer = BufferList->buffer;
2735 bufferLen = Buffer ? Buffer->SampleLen : 0;
2737 if(bufferLen <= offset-totalBufferLen)
2739 /* Offset is past this buffer so increment to the next buffer */
2740 buffersPlayed++;
2742 else if(totalBufferLen <= offset)
2744 /* Offset is in this buffer */
2745 Source->BuffersPlayed = buffersPlayed;
2747 Source->position = offset - totalBufferLen;
2748 Source->position_fraction = 0;
2749 return AL_TRUE;
2752 totalBufferLen += bufferLen;
2754 BufferList = BufferList->next;
2757 /* Offset is out of range of the queue */
2758 return AL_FALSE;
2762 /* GetSampleOffset
2764 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2765 * Second offset supplied by the application). This takes into account the fact
2766 * that the buffer format may have been modifed since.
2768 static ALint GetSampleOffset(ALsource *Source)
2770 const ALbuffer *Buffer = NULL;
2771 const ALbufferlistitem *BufferList;
2772 ALint Offset = -1;
2774 /* Find the first valid Buffer in the Queue */
2775 BufferList = Source->queue;
2776 while(BufferList)
2778 if(BufferList->buffer)
2780 Buffer = BufferList->buffer;
2781 break;
2783 BufferList = BufferList->next;
2786 if(!Buffer)
2788 Source->Offset = -1.0;
2789 return -1;
2792 switch(Source->OffsetType)
2794 case AL_BYTE_OFFSET:
2795 /* Determine the ByteOffset (and ensure it is block aligned) */
2796 Offset = (ALint)Source->Offset;
2797 if(Buffer->OriginalType == UserFmtIMA4)
2799 Offset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels);
2800 Offset *= 65;
2802 else
2803 Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2804 break;
2806 case AL_SAMPLE_OFFSET:
2807 Offset = (ALint)Source->Offset;
2808 break;
2810 case AL_SEC_OFFSET:
2811 Offset = (ALint)(Source->Offset * Buffer->Frequency);
2812 break;
2814 Source->Offset = -1.0;
2816 return Offset;
2820 /* ReleaseALSources
2822 * Destroys all sources in the source map.
2824 ALvoid ReleaseALSources(ALCcontext *Context)
2826 ALsizei pos;
2827 ALuint j;
2828 for(pos = 0;pos < Context->SourceMap.size;pos++)
2830 ALsource *temp = Context->SourceMap.array[pos].value;
2831 Context->SourceMap.array[pos].value = NULL;
2833 while(temp->queue != NULL)
2835 ALbufferlistitem *BufferList = temp->queue;
2836 temp->queue = BufferList->next;
2838 if(BufferList->buffer != NULL)
2839 DecrementRef(&BufferList->buffer->ref);
2840 free(BufferList);
2843 for(j = 0;j < MAX_SENDS;++j)
2845 if(temp->Send[j].Slot)
2846 DecrementRef(&temp->Send[j].Slot->ref);
2847 temp->Send[j].Slot = NULL;
2850 FreeThunkEntry(temp->id);
2851 memset(temp, 0, sizeof(*temp));
2852 al_free(temp);