Use an enum to handle float source properties
[openal-soft.git] / OpenAL32 / alSource.c
blob698bbd6e03a8b1b40c631a301771468f644f8378
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 typedef enum SrcFloatProp {
57 sfvPitch = AL_PITCH,
58 sfvGain = AL_GAIN,
59 sfvMinGain = AL_MIN_GAIN,
60 sfvMaxGain = AL_MAX_GAIN,
61 sfvMaxDistance = AL_MAX_DISTANCE,
62 sfvRolloffFactor = AL_ROLLOFF_FACTOR,
63 sfvDopplerFactor = AL_DOPPLER_FACTOR,
64 sfvConeOuterGain = AL_CONE_OUTER_GAIN,
65 sfvSecOffset = AL_SEC_OFFSET,
66 sfvSampleOffset = AL_SAMPLE_OFFSET,
67 sfvByteOffset = AL_BYTE_OFFSET,
68 sfvConeInnerAngle = AL_CONE_INNER_ANGLE,
69 sfvConeOuterAngle = AL_CONE_OUTER_ANGLE,
70 sfvRefDistance = AL_REFERENCE_DISTANCE,
72 sfvPosition = AL_POSITION,
73 sfvVelocity = AL_VELOCITY,
74 sfvDirection = AL_DIRECTION,
76 sfvSourceRelative = AL_SOURCE_RELATIVE,
77 sfvLooping = AL_LOOPING,
78 sfvBuffer = AL_BUFFER,
79 sfvSourceState = AL_SOURCE_STATE,
80 sfvBuffersQueued = AL_BUFFERS_QUEUED,
81 sfvBuffersProcessed = AL_BUFFERS_PROCESSED,
82 sfvSourceType = AL_SOURCE_TYPE,
83 sfvDistanceModel = AL_DISTANCE_MODEL,
85 /* ALC_EXT_EFX */
86 sfvConeOuterGainHF = AL_CONE_OUTER_GAINHF,
87 sfvAirAbsorptionFactor = AL_AIR_ABSORPTION_FACTOR,
88 sfvRoomRolloffFactor = AL_ROOM_ROLLOFF_FACTOR,
89 sfvDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO,
90 sfvAuxSendFilterGainAuto = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,
91 sfvAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO,
93 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
94 sfvSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT,
95 sfvByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT,
97 /* AL_SOFT_source_latency */
98 sfvSecOffsetLatencySOFT = AL_SEC_OFFSET_LATENCY_SOFT,
100 /* AL_SOFT_direct_channels */
101 sfvDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT,
102 } SrcFloatProp;
104 static ALenum SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values);
105 static ALenum SetSourceiv(ALsource *Source, ALCcontext *Context, ALenum name, const ALint *values);
106 static ALenum SetSourcei64v(ALsource *Source, ALCcontext *Context, ALenum name, const ALint64SOFT *values);
108 static ALenum GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values);
109 static ALenum GetSourceiv(const ALsource *Source, ALCcontext *Context, ALenum name, ALint *values);
110 static ALenum GetSourcei64v(const ALsource *Source, ALCcontext *Context, ALenum name, ALint64 *values);
113 #define RETERR(x) do { \
114 alSetError(Context, (x)); \
115 return (x); \
116 } while(0)
118 #define CHECKVAL(x) do { \
119 if(!(x)) \
120 RETERR(AL_INVALID_VALUE); \
121 } while(0)
123 static ALenum SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values)
125 ALint ival;
127 switch(prop)
129 case AL_PITCH:
130 CHECKVAL(*values >= 0.0f);
132 Source->Pitch = *values;
133 Source->NeedsUpdate = AL_TRUE;
134 return AL_NO_ERROR;
136 case AL_CONE_INNER_ANGLE:
137 CHECKVAL(*values >= 0.0f && *values <= 360.0f);
139 Source->InnerAngle = *values;
140 Source->NeedsUpdate = AL_TRUE;
141 return AL_NO_ERROR;
143 case AL_CONE_OUTER_ANGLE:
144 CHECKVAL(*values >= 0.0f && *values <= 360.0f);
146 Source->OuterAngle = *values;
147 Source->NeedsUpdate = AL_TRUE;
148 return AL_NO_ERROR;
150 case AL_GAIN:
151 CHECKVAL(*values >= 0.0f);
153 Source->Gain = *values;
154 Source->NeedsUpdate = AL_TRUE;
155 return AL_NO_ERROR;
157 case AL_MAX_DISTANCE:
158 CHECKVAL(*values >= 0.0f);
160 Source->MaxDistance = *values;
161 Source->NeedsUpdate = AL_TRUE;
162 return AL_NO_ERROR;
164 case AL_ROLLOFF_FACTOR:
165 CHECKVAL(*values >= 0.0f);
167 Source->RollOffFactor = *values;
168 Source->NeedsUpdate = AL_TRUE;
169 return AL_NO_ERROR;
171 case AL_REFERENCE_DISTANCE:
172 CHECKVAL(*values >= 0.0f);
174 Source->RefDistance = *values;
175 Source->NeedsUpdate = AL_TRUE;
176 return AL_NO_ERROR;
178 case AL_MIN_GAIN:
179 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
181 Source->MinGain = *values;
182 Source->NeedsUpdate = AL_TRUE;
183 return AL_NO_ERROR;
185 case AL_MAX_GAIN:
186 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
188 Source->MaxGain = *values;
189 Source->NeedsUpdate = AL_TRUE;
190 return AL_NO_ERROR;
192 case AL_CONE_OUTER_GAIN:
193 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
195 Source->OuterGain = *values;
196 Source->NeedsUpdate = AL_TRUE;
197 return AL_NO_ERROR;
199 case AL_CONE_OUTER_GAINHF:
200 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
202 Source->OuterGainHF = *values;
203 Source->NeedsUpdate = AL_TRUE;
204 return AL_NO_ERROR;
206 case AL_AIR_ABSORPTION_FACTOR:
207 CHECKVAL(*values >= 0.0f && *values <= 10.0f);
209 Source->AirAbsorptionFactor = *values;
210 Source->NeedsUpdate = AL_TRUE;
211 return AL_NO_ERROR;
213 case AL_ROOM_ROLLOFF_FACTOR:
214 CHECKVAL(*values >= 0.0f && *values <= 10.0f);
216 Source->RoomRolloffFactor = *values;
217 Source->NeedsUpdate = AL_TRUE;
218 return AL_NO_ERROR;
220 case AL_DOPPLER_FACTOR:
221 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
223 Source->DopplerFactor = *values;
224 Source->NeedsUpdate = AL_TRUE;
225 return AL_NO_ERROR;
227 case AL_SEC_OFFSET:
228 case AL_SAMPLE_OFFSET:
229 case AL_BYTE_OFFSET:
230 CHECKVAL(*values >= 0.0f);
232 LockContext(Context);
233 Source->OffsetType = prop;
234 Source->Offset = *values;
236 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
237 !Context->DeferUpdates)
239 if(ApplyOffset(Source) == AL_FALSE)
241 UnlockContext(Context);
242 RETERR(AL_INVALID_VALUE);
245 UnlockContext(Context);
246 return AL_NO_ERROR;
249 case AL_SEC_OFFSET_LATENCY_SOFT:
250 /* Query only */
251 RETERR(AL_INVALID_OPERATION);
254 case AL_POSITION:
255 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
257 LockContext(Context);
258 Source->Position[0] = values[0];
259 Source->Position[1] = values[1];
260 Source->Position[2] = values[2];
261 UnlockContext(Context);
262 Source->NeedsUpdate = AL_TRUE;
263 return AL_NO_ERROR;
265 case AL_VELOCITY:
266 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
268 LockContext(Context);
269 Source->Velocity[0] = values[0];
270 Source->Velocity[1] = values[1];
271 Source->Velocity[2] = values[2];
272 UnlockContext(Context);
273 Source->NeedsUpdate = AL_TRUE;
274 return AL_NO_ERROR;
276 case AL_DIRECTION:
277 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
279 LockContext(Context);
280 Source->Orientation[0] = values[0];
281 Source->Orientation[1] = values[1];
282 Source->Orientation[2] = values[2];
283 UnlockContext(Context);
284 Source->NeedsUpdate = AL_TRUE;
285 return AL_NO_ERROR;
288 case sfvSampleRWOffsetsSOFT:
289 case sfvByteRWOffsetsSOFT:
290 RETERR(AL_INVALID_OPERATION);
293 case sfvSourceRelative:
294 case sfvLooping:
295 case sfvSourceState:
296 case sfvSourceType:
297 case sfvDistanceModel:
298 case sfvDirectFilterGainHFAuto:
299 case sfvAuxSendFilterGainAuto:
300 case sfvAuxSendFilterGainHFAuto:
301 case sfvDirectChannelsSOFT:
302 ival = (ALint)values[0];
303 return SetSourceiv(Source, Context, prop, &ival);
305 case sfvBuffer:
306 case sfvBuffersQueued:
307 case sfvBuffersProcessed:
308 ival = (ALint)((ALuint)values[0]);
309 return SetSourceiv(Source, Context, prop, &ival);
312 ERR("Unexpected property: 0x%04x\n", prop);
313 RETERR(AL_INVALID_ENUM);
316 static ALenum SetSourceiv(ALsource *Source, ALCcontext *Context, ALenum name, const ALint *values)
318 ALCdevice *device = Context->Device;
319 ALbuffer *buffer = NULL;
320 ALfilter *filter = NULL;
321 ALeffectslot *slot = NULL;
322 ALbufferlistitem *oldlist;
323 ALfloat fvals[3];
324 ALenum err;
326 switch(name)
328 case AL_SOURCE_RELATIVE:
329 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
331 Source->HeadRelative = (ALboolean)*values;
332 Source->NeedsUpdate = AL_TRUE;
333 break;
335 case AL_LOOPING:
336 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
338 Source->Looping = (ALboolean)*values;
339 break;
341 case AL_BUFFER:
342 CHECKVAL(*values == 0 || (buffer=LookupBuffer(device, *values)) != NULL);
344 LockContext(Context);
345 if(!(Source->state == AL_STOPPED || Source->state == AL_INITIAL))
347 UnlockContext(Context);
348 RETERR(AL_INVALID_OPERATION);
351 Source->BuffersInQueue = 0;
352 Source->BuffersPlayed = 0;
354 if(buffer != NULL)
356 ALbufferlistitem *BufferListItem;
358 /* Source is now Static */
359 Source->SourceType = AL_STATIC;
361 /* Add the selected buffer to a one-item queue */
362 BufferListItem = malloc(sizeof(ALbufferlistitem));
363 BufferListItem->buffer = buffer;
364 BufferListItem->next = NULL;
365 BufferListItem->prev = NULL;
366 IncrementRef(&buffer->ref);
368 oldlist = ExchangePtr((XchgPtr*)&Source->queue, BufferListItem);
369 Source->BuffersInQueue = 1;
371 ReadLock(&buffer->lock);
372 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
373 Source->SampleSize = BytesFromFmt(buffer->FmtType);
374 ReadUnlock(&buffer->lock);
375 if(buffer->FmtChannels == FmtMono)
376 Source->Update = CalcSourceParams;
377 else
378 Source->Update = CalcNonAttnSourceParams;
379 Source->NeedsUpdate = AL_TRUE;
381 else
383 /* Source is now Undetermined */
384 Source->SourceType = AL_UNDETERMINED;
385 oldlist = ExchangePtr((XchgPtr*)&Source->queue, NULL);
388 /* Delete all elements in the previous queue */
389 while(oldlist != NULL)
391 ALbufferlistitem *temp = oldlist;
392 oldlist = temp->next;
394 if(temp->buffer)
395 DecrementRef(&temp->buffer->ref);
396 free(temp);
398 UnlockContext(Context);
399 break;
401 case AL_SOURCE_STATE:
402 /* Query only */
403 RETERR(AL_INVALID_OPERATION);
405 case AL_SEC_OFFSET:
406 case AL_SAMPLE_OFFSET:
407 case AL_BYTE_OFFSET:
408 CHECKVAL(*values >= 0);
410 LockContext(Context);
411 Source->OffsetType = name;
412 Source->Offset = *values;
414 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
415 !Context->DeferUpdates)
417 if(ApplyOffset(Source) == AL_FALSE)
419 UnlockContext(Context);
420 RETERR(AL_INVALID_VALUE);
423 UnlockContext(Context);
424 break;
426 case AL_DIRECT_FILTER:
427 CHECKVAL(*values == 0 || (filter=LookupFilter(device, *values)) != NULL);
429 LockContext(Context);
430 if(!filter)
432 Source->DirectGain = 1.0f;
433 Source->DirectGainHF = 1.0f;
435 else
437 Source->DirectGain = filter->Gain;
438 Source->DirectGainHF = filter->GainHF;
440 UnlockContext(Context);
441 Source->NeedsUpdate = AL_TRUE;
442 break;
444 case AL_DIRECT_FILTER_GAINHF_AUTO:
445 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
447 Source->DryGainHFAuto = *values;
448 Source->NeedsUpdate = AL_TRUE;
449 break;
451 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
452 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
454 Source->WetGainAuto = *values;
455 Source->NeedsUpdate = AL_TRUE;
456 break;
458 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
459 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
461 Source->WetGainHFAuto = *values;
462 Source->NeedsUpdate = AL_TRUE;
463 break;
465 case AL_DIRECT_CHANNELS_SOFT:
466 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
468 Source->DirectChannels = *values;
469 Source->NeedsUpdate = AL_TRUE;
470 break;
472 case AL_DISTANCE_MODEL:
473 CHECKVAL(*values == AL_NONE ||
474 *values == AL_INVERSE_DISTANCE ||
475 *values == AL_INVERSE_DISTANCE_CLAMPED ||
476 *values == AL_LINEAR_DISTANCE ||
477 *values == AL_LINEAR_DISTANCE_CLAMPED ||
478 *values == AL_EXPONENT_DISTANCE ||
479 *values == AL_EXPONENT_DISTANCE_CLAMPED);
481 Source->DistanceModel = *values;
482 if(Context->SourceDistanceModel)
483 Source->NeedsUpdate = AL_TRUE;
484 break;
487 case AL_AUXILIARY_SEND_FILTER:
488 LockContext(Context);
489 if(!((ALuint)values[1] < device->NumAuxSends &&
490 (values[0] == 0 || (slot=LookupEffectSlot(Context, values[0])) != NULL) &&
491 (values[2] == 0 || (filter=LookupFilter(device, values[2])) != NULL)))
493 UnlockContext(Context);
494 RETERR(AL_INVALID_VALUE);
497 /* Add refcount on the new slot, and release the previous slot */
498 if(slot) IncrementRef(&slot->ref);
499 slot = ExchangePtr((XchgPtr*)&Source->Send[values[1]].Slot, slot);
500 if(slot) DecrementRef(&slot->ref);
502 if(!filter)
504 /* Disable filter */
505 Source->Send[values[1]].Gain = 1.0f;
506 Source->Send[values[1]].GainHF = 1.0f;
508 else
510 Source->Send[values[1]].Gain = filter->Gain;
511 Source->Send[values[1]].GainHF = filter->GainHF;
513 Source->NeedsUpdate = AL_TRUE;
514 UnlockContext(Context);
515 break;
518 case AL_MAX_DISTANCE:
519 case AL_ROLLOFF_FACTOR:
520 case AL_CONE_INNER_ANGLE:
521 case AL_CONE_OUTER_ANGLE:
522 case AL_REFERENCE_DISTANCE:
523 fvals[0] = (ALfloat)*values;
524 if((err=SetSourcefv(Source, Context, name, fvals)) != AL_NO_ERROR)
525 return err;
526 break;
528 case AL_POSITION:
529 case AL_VELOCITY:
530 case AL_DIRECTION:
531 fvals[0] = (ALfloat)values[0];
532 fvals[1] = (ALfloat)values[1];
533 fvals[2] = (ALfloat)values[2];
534 if((err=SetSourcefv(Source, Context, name, fvals)) != AL_NO_ERROR)
535 return err;
536 break;
538 default:
539 ERR("Unexpected param: 0x%04x\n", name);
540 RETERR(AL_INVALID_ENUM);
543 return AL_NO_ERROR;
546 static ALenum SetSourcei64v(ALsource *Source, ALCcontext *Context, ALenum name, const ALint64SOFT *values)
548 ALfloat fvals[3];
549 ALint ivals[3];
550 ALenum err;
552 switch(name)
554 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
555 /* Query only */
556 RETERR(AL_INVALID_OPERATION);
559 /* 1x int */
560 case AL_SOURCE_RELATIVE:
561 case AL_LOOPING:
562 case AL_SOURCE_STATE:
563 case AL_BYTE_OFFSET:
564 case AL_SAMPLE_OFFSET:
565 case AL_DIRECT_FILTER_GAINHF_AUTO:
566 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
567 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
568 case AL_DIRECT_CHANNELS_SOFT:
569 case AL_DISTANCE_MODEL:
570 CHECKVAL(*values <= INT_MAX && *values >= INT_MIN);
572 ivals[0] = (ALint)*values;
573 if((err=SetSourceiv(Source, Context, name, ivals)))
574 return err;
575 break;
577 /* 1x uint */
578 case AL_BUFFER:
579 case AL_DIRECT_FILTER:
580 CHECKVAL(*values <= UINT_MAX && *values >= 0);
582 ivals[0] = (ALuint)*values;
583 if((err=SetSourceiv(Source, Context, name, ivals)))
584 return err;
585 break;
587 /* 3x uint */
588 case AL_AUXILIARY_SEND_FILTER:
589 CHECKVAL(values[0] <= UINT_MAX && values[0] >= 0 &&
590 values[1] <= UINT_MAX && values[1] >= 0 &&
591 values[2] <= UINT_MAX && values[2] >= 0);
593 ivals[0] = (ALuint)values[0];
594 ivals[1] = (ALuint)values[1];
595 ivals[2] = (ALuint)values[2];
596 if((err=SetSourceiv(Source, Context, name, ivals)))
597 return err;
598 break;
600 /* 1x float */
601 case AL_MAX_DISTANCE:
602 case AL_ROLLOFF_FACTOR:
603 case AL_CONE_INNER_ANGLE:
604 case AL_CONE_OUTER_ANGLE:
605 case AL_REFERENCE_DISTANCE:
606 case AL_SEC_OFFSET:
607 fvals[0] = (ALfloat)*values;
608 if((err=SetSourcefv(Source, Context, name, fvals)) != AL_NO_ERROR)
609 return err;
610 break;
612 /* 3x float */
613 case AL_POSITION:
614 case AL_VELOCITY:
615 case AL_DIRECTION:
616 fvals[0] = (ALfloat)values[0];
617 fvals[1] = (ALfloat)values[1];
618 fvals[2] = (ALfloat)values[2];
619 if((err=SetSourcefv(Source, Context, name, fvals)) != AL_NO_ERROR)
620 return err;
621 break;
623 default:
624 ERR("Unexpected param: 0x%04x\n", name);
625 RETERR(AL_INVALID_ENUM);
628 return AL_NO_ERROR;
631 #undef CHECKVAL
634 static ALenum GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values)
636 ALdouble offsets[2];
637 ALdouble updateLen;
638 ALint ivals[3];
639 ALenum err;
641 switch(prop)
643 case AL_GAIN:
644 *values = Source->Gain;
645 return AL_NO_ERROR;
647 case AL_PITCH:
648 *values = Source->Pitch;
649 return AL_NO_ERROR;
651 case AL_MAX_DISTANCE:
652 *values = Source->MaxDistance;
653 return AL_NO_ERROR;
655 case AL_ROLLOFF_FACTOR:
656 *values = Source->RollOffFactor;
657 return AL_NO_ERROR;
659 case AL_REFERENCE_DISTANCE:
660 *values = Source->RefDistance;
661 return AL_NO_ERROR;
663 case AL_CONE_INNER_ANGLE:
664 *values = Source->InnerAngle;
665 return AL_NO_ERROR;
667 case AL_CONE_OUTER_ANGLE:
668 *values = Source->OuterAngle;
669 return AL_NO_ERROR;
671 case AL_MIN_GAIN:
672 *values = Source->MinGain;
673 return AL_NO_ERROR;
675 case AL_MAX_GAIN:
676 *values = Source->MaxGain;
677 return AL_NO_ERROR;
679 case AL_CONE_OUTER_GAIN:
680 *values = Source->OuterGain;
681 return AL_NO_ERROR;
683 case AL_SEC_OFFSET:
684 case AL_SAMPLE_OFFSET:
685 case AL_BYTE_OFFSET:
686 LockContext(Context);
687 updateLen = (ALdouble)Context->Device->UpdateSize /
688 Context->Device->Frequency;
689 GetSourceOffsets(Source, prop, offsets, updateLen);
690 UnlockContext(Context);
691 *values = offsets[0];
692 return AL_NO_ERROR;
694 case AL_CONE_OUTER_GAINHF:
695 *values = Source->OuterGainHF;
696 return AL_NO_ERROR;
698 case AL_AIR_ABSORPTION_FACTOR:
699 *values = Source->AirAbsorptionFactor;
700 return AL_NO_ERROR;
702 case AL_ROOM_ROLLOFF_FACTOR:
703 *values = Source->RoomRolloffFactor;
704 return AL_NO_ERROR;
706 case AL_DOPPLER_FACTOR:
707 *values = Source->DopplerFactor;
708 return AL_NO_ERROR;
710 case AL_SAMPLE_RW_OFFSETS_SOFT:
711 case AL_BYTE_RW_OFFSETS_SOFT:
712 LockContext(Context);
713 updateLen = (ALdouble)Context->Device->UpdateSize /
714 Context->Device->Frequency;
715 GetSourceOffsets(Source, prop, values, updateLen);
716 UnlockContext(Context);
717 return AL_NO_ERROR;
719 case AL_SEC_OFFSET_LATENCY_SOFT:
720 LockContext(Context);
721 values[0] = GetSourceSecOffset(Source);
722 values[1] = (ALdouble)ALCdevice_GetLatency(Context->Device) /
723 1000000000.0;
724 UnlockContext(Context);
725 return AL_NO_ERROR;
727 case AL_POSITION:
728 LockContext(Context);
729 values[0] = Source->Position[0];
730 values[1] = Source->Position[1];
731 values[2] = Source->Position[2];
732 UnlockContext(Context);
733 return AL_NO_ERROR;
735 case AL_VELOCITY:
736 LockContext(Context);
737 values[0] = Source->Velocity[0];
738 values[1] = Source->Velocity[1];
739 values[2] = Source->Velocity[2];
740 UnlockContext(Context);
741 return AL_NO_ERROR;
743 case AL_DIRECTION:
744 LockContext(Context);
745 values[0] = Source->Orientation[0];
746 values[1] = Source->Orientation[1];
747 values[2] = Source->Orientation[2];
748 UnlockContext(Context);
749 return AL_NO_ERROR;
751 case AL_SOURCE_RELATIVE:
752 case AL_LOOPING:
753 case AL_BUFFER:
754 case AL_SOURCE_STATE:
755 case AL_BUFFERS_QUEUED:
756 case AL_BUFFERS_PROCESSED:
757 case AL_SOURCE_TYPE:
758 case AL_DIRECT_FILTER_GAINHF_AUTO:
759 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
760 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
761 case AL_DIRECT_CHANNELS_SOFT:
762 case AL_DISTANCE_MODEL:
763 if((err=GetSourceiv(Source, Context, (int)prop, ivals)) == AL_NO_ERROR)
764 *values = (ALdouble)ivals[0];
765 return err;
768 ERR("Unexpected property: 0x%04x\n", prop);
769 RETERR(AL_INVALID_ENUM);
772 static ALenum GetSourceiv(const ALsource *Source, ALCcontext *Context, ALenum name, ALint *values)
774 ALbufferlistitem *BufferList;
775 ALdouble dvals[3];
776 ALenum err;
778 switch(name)
780 case AL_SOURCE_RELATIVE:
781 *values = Source->HeadRelative;
782 break;
784 case AL_LOOPING:
785 *values = Source->Looping;
786 break;
788 case AL_BUFFER:
789 LockContext(Context);
790 BufferList = Source->queue;
791 if(Source->SourceType != AL_STATIC)
793 ALuint i = Source->BuffersPlayed;
794 while(i > 0)
796 BufferList = BufferList->next;
797 i--;
800 *values = ((BufferList && BufferList->buffer) ?
801 BufferList->buffer->id : 0);
802 UnlockContext(Context);
803 break;
805 case AL_SOURCE_STATE:
806 *values = Source->state;
807 break;
809 case AL_BUFFERS_QUEUED:
810 *values = Source->BuffersInQueue;
811 break;
813 case AL_BUFFERS_PROCESSED:
814 LockContext(Context);
815 if(Source->Looping || Source->SourceType != AL_STREAMING)
817 /* Buffers on a looping source are in a perpetual state of
818 * PENDING, so don't report any as PROCESSED */
819 *values = 0;
821 else
822 *values = Source->BuffersPlayed;
823 UnlockContext(Context);
824 break;
826 case AL_SOURCE_TYPE:
827 *values = Source->SourceType;
828 break;
830 case AL_DIRECT_FILTER_GAINHF_AUTO:
831 *values = Source->DryGainHFAuto;
832 break;
834 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
835 *values = Source->WetGainAuto;
836 break;
838 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
839 *values = Source->WetGainHFAuto;
840 break;
842 case AL_DIRECT_CHANNELS_SOFT:
843 *values = Source->DirectChannels;
844 break;
846 case AL_DISTANCE_MODEL:
847 *values = Source->DistanceModel;
848 break;
850 case AL_MAX_DISTANCE:
851 case AL_ROLLOFF_FACTOR:
852 case AL_REFERENCE_DISTANCE:
853 case AL_CONE_INNER_ANGLE:
854 case AL_CONE_OUTER_ANGLE:
855 case AL_SEC_OFFSET:
856 case AL_SAMPLE_OFFSET:
857 case AL_BYTE_OFFSET:
858 case AL_DOPPLER_FACTOR:
859 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
860 return err;
861 *values = (ALint)dvals[0];
862 break;
864 case AL_SAMPLE_RW_OFFSETS_SOFT:
865 case AL_BYTE_RW_OFFSETS_SOFT:
866 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
867 return err;
868 values[0] = (ALint)dvals[0];
869 values[1] = (ALint)dvals[1];
870 break;
872 case AL_POSITION:
873 case AL_VELOCITY:
874 case AL_DIRECTION:
875 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
876 return err;
877 values[0] = (ALint)dvals[0];
878 values[1] = (ALint)dvals[1];
879 values[2] = (ALint)dvals[2];
880 break;
882 default:
883 ERR("Unexpected param: 0x%04x\n", name);
884 RETERR(AL_INVALID_ENUM);
887 return AL_NO_ERROR;
890 static ALenum GetSourcei64v(const ALsource *Source, ALCcontext *Context, ALenum name, ALint64 *values)
892 ALdouble dvals[3];
893 ALint ivals[3];
894 ALenum err;
896 switch(name)
898 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
899 LockContext(Context);
900 values[0] = GetSourceOffset(Source);
901 values[1] = ALCdevice_GetLatency(Context->Device);
902 UnlockContext(Context);
903 break;
905 case AL_MAX_DISTANCE:
906 case AL_ROLLOFF_FACTOR:
907 case AL_REFERENCE_DISTANCE:
908 case AL_CONE_INNER_ANGLE:
909 case AL_CONE_OUTER_ANGLE:
910 case AL_SEC_OFFSET:
911 case AL_SAMPLE_OFFSET:
912 case AL_BYTE_OFFSET:
913 case AL_DOPPLER_FACTOR:
914 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
915 return err;
916 *values = (ALint64)dvals[0];
917 break;
919 case AL_SAMPLE_RW_OFFSETS_SOFT:
920 case AL_BYTE_RW_OFFSETS_SOFT:
921 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
922 return err;
923 values[0] = (ALint64)dvals[0];
924 values[1] = (ALint64)dvals[1];
925 break;
927 case AL_POSITION:
928 case AL_VELOCITY:
929 case AL_DIRECTION:
930 if((err=GetSourcedv(Source, Context, name, dvals)) != AL_NO_ERROR)
931 return err;
932 values[0] = (ALint64)dvals[0];
933 values[1] = (ALint64)dvals[1];
934 values[2] = (ALint64)dvals[2];
935 break;
937 case AL_SOURCE_RELATIVE:
938 case AL_LOOPING:
939 case AL_BUFFER:
940 case AL_SOURCE_STATE:
941 case AL_BUFFERS_QUEUED:
942 case AL_BUFFERS_PROCESSED:
943 case AL_SOURCE_TYPE:
944 case AL_DIRECT_FILTER_GAINHF_AUTO:
945 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
946 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
947 case AL_DIRECT_CHANNELS_SOFT:
948 case AL_DISTANCE_MODEL:
949 if((err=GetSourceiv(Source, Context, name, ivals)) != AL_NO_ERROR)
950 return err;
951 *values = ivals[0];
952 break;
954 default:
955 ERR("Unexpected param: 0x%04x\n", name);
956 RETERR(AL_INVALID_ENUM);
959 return AL_NO_ERROR;
962 #undef RETERR
965 AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
967 ALCcontext *Context;
968 ALsizei cur = 0;
970 Context = GetContextRef();
971 if(!Context) return;
973 al_try
975 ALenum err;
977 CHECK_VALUE(Context, n >= 0);
978 for(cur = 0;cur < n;cur++)
980 ALsource *source = al_calloc(16, sizeof(ALsource));
981 if(!source)
982 al_throwerr(Context, AL_OUT_OF_MEMORY);
983 InitSourceParams(source);
985 err = NewThunkEntry(&source->id);
986 if(err == AL_NO_ERROR)
987 err = InsertUIntMapEntry(&Context->SourceMap, source->id, source);
988 if(err != AL_NO_ERROR)
990 FreeThunkEntry(source->id);
991 memset(source, 0, sizeof(ALsource));
992 al_free(source);
994 al_throwerr(Context, err);
997 sources[cur] = source->id;
1000 al_catchany()
1002 if(cur > 0)
1003 alDeleteSources(cur, sources);
1005 al_endtry;
1007 ALCcontext_DecRef(Context);
1011 AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
1013 ALCcontext *Context;
1015 Context = GetContextRef();
1016 if(!Context) return;
1018 al_try
1020 ALbufferlistitem *BufferList;
1021 ALsource *Source;
1022 ALsizei i, j;
1024 CHECK_VALUE(Context, n >= 0);
1026 /* Check that all Sources are valid */
1027 for(i = 0;i < n;i++)
1029 if(LookupSource(Context, sources[i]) == NULL)
1030 al_throwerr(Context, AL_INVALID_NAME);
1033 for(i = 0;i < n;i++)
1035 ALsource **srclist, **srclistend;
1037 if((Source=RemoveSource(Context, sources[i])) == NULL)
1038 continue;
1039 FreeThunkEntry(Source->id);
1041 LockContext(Context);
1042 srclist = Context->ActiveSources;
1043 srclistend = srclist + Context->ActiveSourceCount;
1044 while(srclist != srclistend)
1046 if(*srclist == Source)
1048 Context->ActiveSourceCount--;
1049 *srclist = *(--srclistend);
1050 break;
1052 srclist++;
1054 UnlockContext(Context);
1056 while(Source->queue != NULL)
1058 BufferList = Source->queue;
1059 Source->queue = BufferList->next;
1061 if(BufferList->buffer != NULL)
1062 DecrementRef(&BufferList->buffer->ref);
1063 free(BufferList);
1066 for(j = 0;j < MAX_SENDS;++j)
1068 if(Source->Send[j].Slot)
1069 DecrementRef(&Source->Send[j].Slot->ref);
1070 Source->Send[j].Slot = NULL;
1073 memset(Source, 0, sizeof(*Source));
1074 al_free(Source);
1077 al_endtry;
1079 ALCcontext_DecRef(Context);
1083 AL_API ALboolean AL_APIENTRY alIsSource(ALuint source)
1085 ALCcontext *Context;
1086 ALboolean result;
1088 Context = GetContextRef();
1089 if(!Context) return AL_FALSE;
1091 result = (LookupSource(Context, source) ? AL_TRUE : AL_FALSE);
1093 ALCcontext_DecRef(Context);
1095 return result;
1099 AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value)
1101 ALCcontext *Context;
1102 ALsource *Source;
1104 Context = GetContextRef();
1105 if(!Context) return;
1107 if((Source=LookupSource(Context, source)) == NULL)
1108 alSetError(Context, AL_INVALID_NAME);
1109 else switch(param)
1111 case AL_PITCH:
1112 case AL_CONE_INNER_ANGLE:
1113 case AL_CONE_OUTER_ANGLE:
1114 case AL_GAIN:
1115 case AL_MAX_DISTANCE:
1116 case AL_ROLLOFF_FACTOR:
1117 case AL_REFERENCE_DISTANCE:
1118 case AL_MIN_GAIN:
1119 case AL_MAX_GAIN:
1120 case AL_CONE_OUTER_GAIN:
1121 case AL_CONE_OUTER_GAINHF:
1122 case AL_AIR_ABSORPTION_FACTOR:
1123 case AL_ROOM_ROLLOFF_FACTOR:
1124 case AL_DOPPLER_FACTOR:
1125 case AL_SEC_OFFSET:
1126 case AL_SAMPLE_OFFSET:
1127 case AL_BYTE_OFFSET:
1128 SetSourcefv(Source, Context, param, &value);
1129 break;
1131 default:
1132 alSetError(Context, AL_INVALID_ENUM);
1135 ALCcontext_DecRef(Context);
1138 AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
1140 ALCcontext *Context;
1141 ALsource *Source;
1142 ALfloat fvals[3];
1144 Context = GetContextRef();
1145 if(!Context) return;
1147 if((Source=LookupSource(Context, source)) == NULL)
1148 alSetError(Context, AL_INVALID_NAME);
1149 else switch(param)
1151 case AL_POSITION:
1152 case AL_VELOCITY:
1153 case AL_DIRECTION:
1154 fvals[0] = value1;
1155 fvals[1] = value2;
1156 fvals[2] = value3;
1157 SetSourcefv(Source, Context, param, fvals);
1158 break;
1160 default:
1161 alSetError(Context, AL_INVALID_ENUM);
1164 ALCcontext_DecRef(Context);
1167 AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values)
1169 ALCcontext *Context;
1170 ALsource *Source;
1172 Context = GetContextRef();
1173 if(!Context) return;
1175 if((Source=LookupSource(Context, source)) == NULL)
1176 alSetError(Context, AL_INVALID_NAME);
1177 else if(!values)
1178 alSetError(Context, AL_INVALID_VALUE);
1179 else switch(param)
1181 case AL_PITCH:
1182 case AL_CONE_INNER_ANGLE:
1183 case AL_CONE_OUTER_ANGLE:
1184 case AL_GAIN:
1185 case AL_MAX_DISTANCE:
1186 case AL_ROLLOFF_FACTOR:
1187 case AL_REFERENCE_DISTANCE:
1188 case AL_MIN_GAIN:
1189 case AL_MAX_GAIN:
1190 case AL_CONE_OUTER_GAIN:
1191 case AL_CONE_OUTER_GAINHF:
1192 case AL_SEC_OFFSET:
1193 case AL_SAMPLE_OFFSET:
1194 case AL_BYTE_OFFSET:
1195 case AL_AIR_ABSORPTION_FACTOR:
1196 case AL_ROOM_ROLLOFF_FACTOR:
1198 case AL_POSITION:
1199 case AL_VELOCITY:
1200 case AL_DIRECTION:
1201 SetSourcefv(Source, Context, param, values);
1202 break;
1204 default:
1205 alSetError(Context, AL_INVALID_ENUM);
1208 ALCcontext_DecRef(Context);
1212 AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value)
1214 ALCcontext *Context;
1215 ALsource *Source;
1216 ALfloat fval;
1218 Context = GetContextRef();
1219 if(!Context) return;
1221 if((Source=LookupSource(Context, source)) == NULL)
1222 alSetError(Context, AL_INVALID_NAME);
1223 else switch(param)
1225 case AL_PITCH:
1226 case AL_CONE_INNER_ANGLE:
1227 case AL_CONE_OUTER_ANGLE:
1228 case AL_GAIN:
1229 case AL_MAX_DISTANCE:
1230 case AL_ROLLOFF_FACTOR:
1231 case AL_REFERENCE_DISTANCE:
1232 case AL_MIN_GAIN:
1233 case AL_MAX_GAIN:
1234 case AL_CONE_OUTER_GAIN:
1235 case AL_CONE_OUTER_GAINHF:
1236 case AL_AIR_ABSORPTION_FACTOR:
1237 case AL_ROOM_ROLLOFF_FACTOR:
1238 case AL_DOPPLER_FACTOR:
1239 case AL_SEC_OFFSET:
1240 case AL_SAMPLE_OFFSET:
1241 case AL_BYTE_OFFSET:
1242 fval = (ALfloat)value;
1243 SetSourcefv(Source, Context, param, &fval);
1244 break;
1246 default:
1247 alSetError(Context, AL_INVALID_ENUM);
1250 ALCcontext_DecRef(Context);
1253 AL_API ALvoid AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3)
1255 ALCcontext *Context;
1256 ALsource *Source;
1257 ALfloat fvals[3];
1259 Context = GetContextRef();
1260 if(!Context) return;
1262 if((Source=LookupSource(Context, source)) == NULL)
1263 alSetError(Context, AL_INVALID_NAME);
1264 else switch(param)
1266 case AL_POSITION:
1267 case AL_VELOCITY:
1268 case AL_DIRECTION:
1269 fvals[0] = (ALfloat)value1;
1270 fvals[1] = (ALfloat)value2;
1271 fvals[2] = (ALfloat)value3;
1272 SetSourcefv(Source, Context, param, fvals);
1273 break;
1275 default:
1276 alSetError(Context, AL_INVALID_ENUM);
1279 ALCcontext_DecRef(Context);
1282 AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values)
1284 ALCcontext *Context;
1285 ALsource *Source;
1286 ALfloat fvals[3];
1288 Context = GetContextRef();
1289 if(!Context) return;
1291 if((Source=LookupSource(Context, source)) == NULL)
1292 alSetError(Context, AL_INVALID_NAME);
1293 else if(!values)
1294 alSetError(Context, AL_INVALID_VALUE);
1295 else switch(param)
1297 case AL_PITCH:
1298 case AL_CONE_INNER_ANGLE:
1299 case AL_CONE_OUTER_ANGLE:
1300 case AL_GAIN:
1301 case AL_MAX_DISTANCE:
1302 case AL_ROLLOFF_FACTOR:
1303 case AL_REFERENCE_DISTANCE:
1304 case AL_MIN_GAIN:
1305 case AL_MAX_GAIN:
1306 case AL_CONE_OUTER_GAIN:
1307 case AL_CONE_OUTER_GAINHF:
1308 case AL_SEC_OFFSET:
1309 case AL_SAMPLE_OFFSET:
1310 case AL_BYTE_OFFSET:
1311 case AL_AIR_ABSORPTION_FACTOR:
1312 case AL_ROOM_ROLLOFF_FACTOR:
1313 fvals[0] = (ALfloat)values[0];
1314 SetSourcefv(Source, Context, param, fvals);
1315 break;
1317 case AL_SEC_OFFSET_LATENCY_SOFT:
1318 fvals[0] = (ALfloat)values[0];
1319 fvals[1] = (ALfloat)values[1];
1320 SetSourcefv(Source, Context, param, fvals);
1321 break;
1323 case AL_POSITION:
1324 case AL_VELOCITY:
1325 case AL_DIRECTION:
1326 fvals[0] = (ALfloat)values[0];
1327 fvals[1] = (ALfloat)values[1];
1328 fvals[2] = (ALfloat)values[2];
1329 SetSourcefv(Source, Context, param, fvals);
1330 break;
1332 default:
1333 alSetError(Context, AL_INVALID_ENUM);
1336 ALCcontext_DecRef(Context);
1340 AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value)
1342 ALCcontext *Context;
1343 ALsource *Source;
1345 Context = GetContextRef();
1346 if(!Context) return;
1348 if((Source=LookupSource(Context, source)) == NULL)
1349 alSetError(Context, AL_INVALID_NAME);
1350 else switch(param)
1352 case AL_MAX_DISTANCE:
1353 case AL_ROLLOFF_FACTOR:
1354 case AL_CONE_INNER_ANGLE:
1355 case AL_CONE_OUTER_ANGLE:
1356 case AL_REFERENCE_DISTANCE:
1357 case AL_SOURCE_RELATIVE:
1358 case AL_LOOPING:
1359 case AL_BUFFER:
1360 case AL_SOURCE_STATE:
1361 case AL_SEC_OFFSET:
1362 case AL_SAMPLE_OFFSET:
1363 case AL_BYTE_OFFSET:
1364 case AL_DIRECT_FILTER:
1365 case AL_DIRECT_FILTER_GAINHF_AUTO:
1366 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1367 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1368 case AL_DIRECT_CHANNELS_SOFT:
1369 case AL_DISTANCE_MODEL:
1370 SetSourceiv(Source, Context, param, &value);
1371 break;
1373 default:
1374 alSetError(Context, AL_INVALID_ENUM);
1377 ALCcontext_DecRef(Context);
1380 AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3)
1382 ALCcontext *Context;
1383 ALsource *Source;
1384 ALint ivals[3];
1386 Context = GetContextRef();
1387 if(!Context) return;
1389 if((Source=LookupSource(Context, source)) == NULL)
1390 alSetError(Context, AL_INVALID_NAME);
1391 else switch(param)
1393 case AL_POSITION:
1394 case AL_VELOCITY:
1395 case AL_DIRECTION:
1396 case AL_AUXILIARY_SEND_FILTER:
1397 ivals[0] = value1;
1398 ivals[1] = value2;
1399 ivals[2] = value3;
1400 SetSourceiv(Source, Context, param, ivals);
1401 break;
1403 default:
1404 alSetError(Context, AL_INVALID_ENUM);
1407 ALCcontext_DecRef(Context);
1410 AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values)
1412 ALCcontext *Context;
1413 ALsource *Source;
1415 Context = GetContextRef();
1416 if(!Context) return;
1418 if((Source=LookupSource(Context, source)) == NULL)
1419 alSetError(Context, AL_INVALID_NAME);
1420 else if(!values)
1421 alSetError(Context, AL_INVALID_VALUE);
1422 else switch(param)
1424 case AL_SOURCE_RELATIVE:
1425 case AL_CONE_INNER_ANGLE:
1426 case AL_CONE_OUTER_ANGLE:
1427 case AL_LOOPING:
1428 case AL_BUFFER:
1429 case AL_SOURCE_STATE:
1430 case AL_SEC_OFFSET:
1431 case AL_SAMPLE_OFFSET:
1432 case AL_BYTE_OFFSET:
1433 case AL_MAX_DISTANCE:
1434 case AL_ROLLOFF_FACTOR:
1435 case AL_REFERENCE_DISTANCE:
1436 case AL_DIRECT_FILTER:
1437 case AL_DIRECT_FILTER_GAINHF_AUTO:
1438 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1439 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1440 case AL_DISTANCE_MODEL:
1441 case AL_DIRECT_CHANNELS_SOFT:
1443 case AL_POSITION:
1444 case AL_VELOCITY:
1445 case AL_DIRECTION:
1446 case AL_AUXILIARY_SEND_FILTER:
1447 SetSourceiv(Source, Context, param, values);
1448 break;
1450 default:
1451 alSetError(Context, AL_INVALID_ENUM);
1454 ALCcontext_DecRef(Context);
1458 AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value)
1460 ALCcontext *Context;
1461 ALsource *Source;
1463 Context = GetContextRef();
1464 if(!Context) return;
1466 if((Source=LookupSource(Context, source)) == NULL)
1467 alSetError(Context, AL_INVALID_NAME);
1468 else switch(param)
1470 case AL_MAX_DISTANCE:
1471 case AL_ROLLOFF_FACTOR:
1472 case AL_CONE_INNER_ANGLE:
1473 case AL_CONE_OUTER_ANGLE:
1474 case AL_REFERENCE_DISTANCE:
1475 case AL_SOURCE_RELATIVE:
1476 case AL_LOOPING:
1477 case AL_SOURCE_STATE:
1478 case AL_SEC_OFFSET:
1479 case AL_SAMPLE_OFFSET:
1480 case AL_BYTE_OFFSET:
1481 case AL_DIRECT_FILTER_GAINHF_AUTO:
1482 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1483 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1484 case AL_DIRECT_CHANNELS_SOFT:
1485 case AL_DISTANCE_MODEL:
1486 case AL_BUFFER:
1487 case AL_DIRECT_FILTER:
1488 SetSourcei64v(Source, Context, param, &value);
1489 break;
1491 default:
1492 alSetError(Context, AL_INVALID_ENUM);
1495 ALCcontext_DecRef(Context);
1498 AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3)
1500 ALCcontext *Context;
1501 ALsource *Source;
1502 ALint64SOFT i64vals[3];
1504 Context = GetContextRef();
1505 if(!Context) return;
1507 if((Source=LookupSource(Context, source)) == NULL)
1508 alSetError(Context, AL_INVALID_NAME);
1509 else switch(param)
1511 case AL_POSITION:
1512 case AL_VELOCITY:
1513 case AL_DIRECTION:
1514 case AL_AUXILIARY_SEND_FILTER:
1515 i64vals[0] = value1;
1516 i64vals[1] = value2;
1517 i64vals[2] = value3;
1518 SetSourcei64v(Source, Context, param, i64vals);
1519 break;
1521 default:
1522 alSetError(Context, AL_INVALID_ENUM);
1525 ALCcontext_DecRef(Context);
1528 AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values)
1530 ALCcontext *Context;
1531 ALsource *Source;
1533 Context = GetContextRef();
1534 if(!Context) return;
1536 if((Source=LookupSource(Context, source)) == NULL)
1537 alSetError(Context, AL_INVALID_NAME);
1538 else if(!values)
1539 alSetError(Context, AL_INVALID_VALUE);
1540 else switch(param)
1542 case AL_SOURCE_RELATIVE:
1543 case AL_CONE_INNER_ANGLE:
1544 case AL_CONE_OUTER_ANGLE:
1545 case AL_LOOPING:
1546 case AL_SOURCE_STATE:
1547 case AL_SEC_OFFSET:
1548 case AL_SAMPLE_OFFSET:
1549 case AL_BYTE_OFFSET:
1550 case AL_MAX_DISTANCE:
1551 case AL_ROLLOFF_FACTOR:
1552 case AL_REFERENCE_DISTANCE:
1553 case AL_DIRECT_FILTER_GAINHF_AUTO:
1554 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1555 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1556 case AL_DISTANCE_MODEL:
1557 case AL_DIRECT_CHANNELS_SOFT:
1558 case AL_BUFFER:
1559 case AL_DIRECT_FILTER:
1561 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
1563 case AL_POSITION:
1564 case AL_VELOCITY:
1565 case AL_DIRECTION:
1566 case AL_AUXILIARY_SEND_FILTER:
1567 SetSourcei64v(Source, Context, param, values);
1568 break;
1570 default:
1571 alSetError(Context, AL_INVALID_ENUM);
1574 ALCcontext_DecRef(Context);
1578 AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value)
1580 ALCcontext *Context;
1581 ALsource *Source;
1582 ALdouble dval;
1584 Context = GetContextRef();
1585 if(!Context) return;
1587 if((Source=LookupSource(Context, source)) == NULL)
1588 alSetError(Context, AL_INVALID_NAME);
1589 else if(!value)
1590 alSetError(Context, AL_INVALID_VALUE);
1591 else switch(param)
1593 case AL_PITCH:
1594 case AL_GAIN:
1595 case AL_MIN_GAIN:
1596 case AL_MAX_GAIN:
1597 case AL_MAX_DISTANCE:
1598 case AL_ROLLOFF_FACTOR:
1599 case AL_CONE_OUTER_GAIN:
1600 case AL_CONE_OUTER_GAINHF:
1601 case AL_SEC_OFFSET:
1602 case AL_SAMPLE_OFFSET:
1603 case AL_BYTE_OFFSET:
1604 case AL_CONE_INNER_ANGLE:
1605 case AL_CONE_OUTER_ANGLE:
1606 case AL_REFERENCE_DISTANCE:
1607 case AL_AIR_ABSORPTION_FACTOR:
1608 case AL_ROOM_ROLLOFF_FACTOR:
1609 case AL_DOPPLER_FACTOR:
1610 if(GetSourcedv(Source, Context, param, &dval) == AL_NO_ERROR)
1611 *value = (ALfloat)dval;
1612 break;
1614 default:
1615 alSetError(Context, AL_INVALID_ENUM);
1618 ALCcontext_DecRef(Context);
1622 AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
1624 ALCcontext *Context;
1625 ALsource *Source;
1626 ALdouble dvals[3];
1628 Context = GetContextRef();
1629 if(!Context) return;
1631 if((Source=LookupSource(Context, source)) == NULL)
1632 alSetError(Context, AL_INVALID_NAME);
1633 else if(!(value1 && value2 && value3))
1634 alSetError(Context, AL_INVALID_VALUE);
1635 else switch(param)
1637 case AL_POSITION:
1638 case AL_VELOCITY:
1639 case AL_DIRECTION:
1640 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1642 *value1 = (ALfloat)dvals[0];
1643 *value2 = (ALfloat)dvals[1];
1644 *value3 = (ALfloat)dvals[2];
1646 break;
1648 default:
1649 alSetError(Context, AL_INVALID_ENUM);
1652 ALCcontext_DecRef(Context);
1656 AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values)
1658 ALCcontext *Context;
1659 ALsource *Source;
1660 ALdouble dvals[2];
1662 switch(param)
1664 case AL_PITCH:
1665 case AL_GAIN:
1666 case AL_MIN_GAIN:
1667 case AL_MAX_GAIN:
1668 case AL_MAX_DISTANCE:
1669 case AL_ROLLOFF_FACTOR:
1670 case AL_DOPPLER_FACTOR:
1671 case AL_CONE_OUTER_GAIN:
1672 case AL_SEC_OFFSET:
1673 case AL_SAMPLE_OFFSET:
1674 case AL_BYTE_OFFSET:
1675 case AL_CONE_INNER_ANGLE:
1676 case AL_CONE_OUTER_ANGLE:
1677 case AL_REFERENCE_DISTANCE:
1678 case AL_CONE_OUTER_GAINHF:
1679 case AL_AIR_ABSORPTION_FACTOR:
1680 case AL_ROOM_ROLLOFF_FACTOR:
1681 alGetSourcef(source, param, values);
1682 return;
1684 case AL_POSITION:
1685 case AL_VELOCITY:
1686 case AL_DIRECTION:
1687 alGetSource3f(source, param, values+0, values+1, values+2);
1688 return;
1691 Context = GetContextRef();
1692 if(!Context) return;
1694 if((Source=LookupSource(Context, source)) == NULL)
1695 alSetError(Context, AL_INVALID_NAME);
1696 else if(!values)
1697 alSetError(Context, AL_INVALID_VALUE);
1698 else switch(param)
1700 case AL_SAMPLE_RW_OFFSETS_SOFT:
1701 case AL_BYTE_RW_OFFSETS_SOFT:
1702 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1704 values[0] = (ALfloat)dvals[0];
1705 values[1] = (ALfloat)dvals[1];
1707 break;
1709 default:
1710 alSetError(Context, AL_INVALID_ENUM);
1713 ALCcontext_DecRef(Context);
1717 AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *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_PITCH:
1732 case AL_GAIN:
1733 case AL_MIN_GAIN:
1734 case AL_MAX_GAIN:
1735 case AL_MAX_DISTANCE:
1736 case AL_ROLLOFF_FACTOR:
1737 case AL_CONE_OUTER_GAIN:
1738 case AL_CONE_OUTER_GAINHF:
1739 case AL_SEC_OFFSET:
1740 case AL_SAMPLE_OFFSET:
1741 case AL_BYTE_OFFSET:
1742 case AL_CONE_INNER_ANGLE:
1743 case AL_CONE_OUTER_ANGLE:
1744 case AL_REFERENCE_DISTANCE:
1745 case AL_AIR_ABSORPTION_FACTOR:
1746 case AL_ROOM_ROLLOFF_FACTOR:
1747 case AL_DOPPLER_FACTOR:
1748 GetSourcedv(Source, Context, param, value);
1749 break;
1751 default:
1752 alSetError(Context, AL_INVALID_ENUM);
1755 ALCcontext_DecRef(Context);
1758 AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3)
1760 ALCcontext *Context;
1761 ALsource *Source;
1762 ALdouble dvals[3];
1764 Context = GetContextRef();
1765 if(!Context) return;
1767 if((Source=LookupSource(Context, source)) == NULL)
1768 alSetError(Context, AL_INVALID_NAME);
1769 else if(!(value1 && value2 && value3))
1770 alSetError(Context, AL_INVALID_VALUE);
1771 else switch(param)
1773 case AL_POSITION:
1774 case AL_VELOCITY:
1775 case AL_DIRECTION:
1776 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1778 *value1 = dvals[0];
1779 *value2 = dvals[1];
1780 *value3 = dvals[2];
1782 break;
1784 default:
1785 alSetError(Context, AL_INVALID_ENUM);
1788 ALCcontext_DecRef(Context);
1791 AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values)
1793 ALCcontext *Context;
1794 ALsource *Source;
1796 Context = GetContextRef();
1797 if(!Context) return;
1799 if((Source=LookupSource(Context, source)) == NULL)
1800 alSetError(Context, AL_INVALID_NAME);
1801 else if(!values)
1802 alSetError(Context, AL_INVALID_VALUE);
1803 else switch(param)
1805 case AL_PITCH:
1806 case AL_GAIN:
1807 case AL_MIN_GAIN:
1808 case AL_MAX_GAIN:
1809 case AL_MAX_DISTANCE:
1810 case AL_ROLLOFF_FACTOR:
1811 case AL_DOPPLER_FACTOR:
1812 case AL_CONE_OUTER_GAIN:
1813 case AL_SEC_OFFSET:
1814 case AL_SAMPLE_OFFSET:
1815 case AL_BYTE_OFFSET:
1816 case AL_CONE_INNER_ANGLE:
1817 case AL_CONE_OUTER_ANGLE:
1818 case AL_REFERENCE_DISTANCE:
1819 case AL_CONE_OUTER_GAINHF:
1820 case AL_AIR_ABSORPTION_FACTOR:
1821 case AL_ROOM_ROLLOFF_FACTOR:
1823 case AL_SAMPLE_RW_OFFSETS_SOFT:
1824 case AL_BYTE_RW_OFFSETS_SOFT:
1825 case AL_SEC_OFFSET_LATENCY_SOFT:
1827 case AL_POSITION:
1828 case AL_VELOCITY:
1829 case AL_DIRECTION:
1830 GetSourcedv(Source, Context, param, values);
1831 break;
1833 default:
1834 alSetError(Context, AL_INVALID_ENUM);
1837 ALCcontext_DecRef(Context);
1841 AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value)
1843 ALCcontext *Context;
1844 ALsource *Source;
1846 Context = GetContextRef();
1847 if(!Context) return;
1849 if((Source=LookupSource(Context, source)) == NULL)
1850 alSetError(Context, AL_INVALID_NAME);
1851 else if(!value)
1852 alSetError(Context, AL_INVALID_VALUE);
1853 else switch(param)
1855 case AL_MAX_DISTANCE:
1856 case AL_ROLLOFF_FACTOR:
1857 case AL_REFERENCE_DISTANCE:
1858 case AL_SOURCE_RELATIVE:
1859 case AL_CONE_INNER_ANGLE:
1860 case AL_CONE_OUTER_ANGLE:
1861 case AL_LOOPING:
1862 case AL_BUFFER:
1863 case AL_SOURCE_STATE:
1864 case AL_BUFFERS_QUEUED:
1865 case AL_BUFFERS_PROCESSED:
1866 case AL_SOURCE_TYPE:
1867 case AL_SEC_OFFSET:
1868 case AL_SAMPLE_OFFSET:
1869 case AL_BYTE_OFFSET:
1870 case AL_DIRECT_FILTER_GAINHF_AUTO:
1871 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1872 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1873 case AL_DOPPLER_FACTOR:
1874 case AL_DIRECT_CHANNELS_SOFT:
1875 case AL_DISTANCE_MODEL:
1876 GetSourceiv(Source, Context, param, value);
1877 break;
1879 default:
1880 alSetError(Context, AL_INVALID_ENUM);
1883 ALCcontext_DecRef(Context);
1887 AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3)
1889 ALCcontext *Context;
1890 ALsource *Source;
1891 ALint ivals[3];
1893 Context = GetContextRef();
1894 if(!Context) return;
1896 if((Source=LookupSource(Context, source)) == NULL)
1897 alSetError(Context, AL_INVALID_NAME);
1898 else if(!(value1 && value2 && value3))
1899 alSetError(Context, AL_INVALID_VALUE);
1900 else switch(param)
1902 case AL_POSITION:
1903 case AL_VELOCITY:
1904 case AL_DIRECTION:
1905 if(GetSourceiv(Source, Context, param, ivals) == AL_NO_ERROR)
1907 *value1 = ivals[0];
1908 *value2 = ivals[1];
1909 *value3 = ivals[2];
1911 break;
1913 default:
1914 alSetError(Context, AL_INVALID_ENUM);
1917 ALCcontext_DecRef(Context);
1921 AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values)
1923 ALCcontext *Context;
1924 ALsource *Source;
1926 Context = GetContextRef();
1927 if(!Context) return;
1929 if((Source=LookupSource(Context, source)) == NULL)
1930 alSetError(Context, AL_INVALID_NAME);
1931 else if(!values)
1932 alSetError(Context, AL_INVALID_VALUE);
1933 else switch(param)
1935 case AL_SOURCE_RELATIVE:
1936 case AL_CONE_INNER_ANGLE:
1937 case AL_CONE_OUTER_ANGLE:
1938 case AL_LOOPING:
1939 case AL_BUFFER:
1940 case AL_SOURCE_STATE:
1941 case AL_BUFFERS_QUEUED:
1942 case AL_BUFFERS_PROCESSED:
1943 case AL_SEC_OFFSET:
1944 case AL_SAMPLE_OFFSET:
1945 case AL_BYTE_OFFSET:
1946 case AL_MAX_DISTANCE:
1947 case AL_ROLLOFF_FACTOR:
1948 case AL_DOPPLER_FACTOR:
1949 case AL_REFERENCE_DISTANCE:
1950 case AL_SOURCE_TYPE:
1951 case AL_DIRECT_FILTER:
1952 case AL_DIRECT_FILTER_GAINHF_AUTO:
1953 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1954 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1955 case AL_DISTANCE_MODEL:
1956 case AL_DIRECT_CHANNELS_SOFT:
1958 case AL_SAMPLE_RW_OFFSETS_SOFT:
1959 case AL_BYTE_RW_OFFSETS_SOFT:
1961 case AL_POSITION:
1962 case AL_VELOCITY:
1963 case AL_DIRECTION:
1964 GetSourceiv(Source, Context, param, values);
1965 break;
1967 default:
1968 alSetError(Context, AL_INVALID_ENUM);
1971 ALCcontext_DecRef(Context);
1975 AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value)
1977 ALCcontext *Context;
1978 ALsource *Source;
1980 Context = GetContextRef();
1981 if(!Context) return;
1983 if((Source=LookupSource(Context, source)) == NULL)
1984 alSetError(Context, AL_INVALID_NAME);
1985 else if(!value)
1986 alSetError(Context, AL_INVALID_VALUE);
1987 else switch(param)
1989 case AL_MAX_DISTANCE:
1990 case AL_ROLLOFF_FACTOR:
1991 case AL_REFERENCE_DISTANCE:
1992 case AL_SOURCE_RELATIVE:
1993 case AL_CONE_INNER_ANGLE:
1994 case AL_CONE_OUTER_ANGLE:
1995 case AL_LOOPING:
1996 case AL_BUFFER:
1997 case AL_SOURCE_STATE:
1998 case AL_BUFFERS_QUEUED:
1999 case AL_BUFFERS_PROCESSED:
2000 case AL_SOURCE_TYPE:
2001 case AL_SEC_OFFSET:
2002 case AL_SAMPLE_OFFSET:
2003 case AL_BYTE_OFFSET:
2004 case AL_DIRECT_FILTER_GAINHF_AUTO:
2005 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
2006 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
2007 case AL_DOPPLER_FACTOR:
2008 case AL_DIRECT_CHANNELS_SOFT:
2009 case AL_DISTANCE_MODEL:
2010 GetSourcei64v(Source, Context, param, value);
2011 break;
2013 default:
2014 alSetError(Context, AL_INVALID_ENUM);
2017 ALCcontext_DecRef(Context);
2020 AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3)
2022 ALCcontext *Context;
2023 ALsource *Source;
2024 ALint64 i64vals[3];
2026 Context = GetContextRef();
2027 if(!Context) return;
2029 if((Source=LookupSource(Context, source)) == NULL)
2030 alSetError(Context, AL_INVALID_NAME);
2031 else if(!(value1 && value2 && value3))
2032 alSetError(Context, AL_INVALID_VALUE);
2033 else switch(param)
2035 case AL_POSITION:
2036 case AL_VELOCITY:
2037 case AL_DIRECTION:
2038 if(GetSourcei64v(Source, Context, param, i64vals) == AL_NO_ERROR)
2040 *value1 = i64vals[0];
2041 *value2 = i64vals[1];
2042 *value3 = i64vals[2];
2044 break;
2046 default:
2047 alSetError(Context, AL_INVALID_ENUM);
2050 ALCcontext_DecRef(Context);
2053 AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values)
2055 ALCcontext *Context;
2056 ALsource *Source;
2058 Context = GetContextRef();
2059 if(!Context) return;
2061 if((Source=LookupSource(Context, source)) == NULL)
2062 alSetError(Context, AL_INVALID_NAME);
2063 else if(!values)
2064 alSetError(Context, AL_INVALID_VALUE);
2065 else switch(param)
2067 case AL_MAX_DISTANCE:
2068 case AL_ROLLOFF_FACTOR:
2069 case AL_REFERENCE_DISTANCE:
2070 case AL_SOURCE_RELATIVE:
2071 case AL_CONE_INNER_ANGLE:
2072 case AL_CONE_OUTER_ANGLE:
2073 case AL_LOOPING:
2074 case AL_BUFFER:
2075 case AL_SOURCE_STATE:
2076 case AL_BUFFERS_QUEUED:
2077 case AL_BUFFERS_PROCESSED:
2078 case AL_SOURCE_TYPE:
2079 case AL_SEC_OFFSET:
2080 case AL_SAMPLE_OFFSET:
2081 case AL_BYTE_OFFSET:
2082 case AL_DIRECT_FILTER_GAINHF_AUTO:
2083 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
2084 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
2085 case AL_DOPPLER_FACTOR:
2086 case AL_DIRECT_CHANNELS_SOFT:
2087 case AL_DISTANCE_MODEL:
2089 case AL_SAMPLE_RW_OFFSETS_SOFT:
2090 case AL_BYTE_RW_OFFSETS_SOFT:
2091 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
2093 case AL_POSITION:
2094 case AL_VELOCITY:
2095 case AL_DIRECTION:
2096 GetSourcei64v(Source, Context, param, values);
2097 break;
2099 default:
2100 alSetError(Context, AL_INVALID_ENUM);
2103 ALCcontext_DecRef(Context);
2107 AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint source)
2109 alSourcePlayv(1, &source);
2111 AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
2113 ALCcontext *Context;
2114 ALsource *Source;
2115 ALsizei i;
2117 Context = GetContextRef();
2118 if(!Context) return;
2120 al_try
2122 CHECK_VALUE(Context, n >= 0);
2123 for(i = 0;i < n;i++)
2125 if(!LookupSource(Context, sources[i]))
2126 al_throwerr(Context, AL_INVALID_NAME);
2129 LockContext(Context);
2130 while(Context->MaxActiveSources-Context->ActiveSourceCount < n)
2132 void *temp = NULL;
2133 ALsizei newcount;
2135 newcount = Context->MaxActiveSources << 1;
2136 if(newcount > 0)
2137 temp = realloc(Context->ActiveSources,
2138 sizeof(*Context->ActiveSources) * newcount);
2139 if(!temp)
2141 UnlockContext(Context);
2142 al_throwerr(Context, AL_OUT_OF_MEMORY);
2145 Context->ActiveSources = temp;
2146 Context->MaxActiveSources = newcount;
2149 for(i = 0;i < n;i++)
2151 Source = LookupSource(Context, sources[i]);
2152 if(Context->DeferUpdates) Source->new_state = AL_PLAYING;
2153 else SetSourceState(Source, Context, AL_PLAYING);
2155 UnlockContext(Context);
2157 al_endtry;
2159 ALCcontext_DecRef(Context);
2162 AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source)
2164 alSourcePausev(1, &source);
2166 AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
2168 ALCcontext *Context;
2169 ALsource *Source;
2170 ALsizei i;
2172 Context = GetContextRef();
2173 if(!Context) return;
2175 al_try
2177 CHECK_VALUE(Context, n >= 0);
2178 for(i = 0;i < n;i++)
2180 if(!LookupSource(Context, sources[i]))
2181 al_throwerr(Context, AL_INVALID_NAME);
2184 LockContext(Context);
2185 for(i = 0;i < n;i++)
2187 Source = LookupSource(Context, sources[i]);
2188 if(Context->DeferUpdates) Source->new_state = AL_PAUSED;
2189 else SetSourceState(Source, Context, AL_PAUSED);
2191 UnlockContext(Context);
2193 al_endtry;
2195 ALCcontext_DecRef(Context);
2198 AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source)
2200 alSourceStopv(1, &source);
2202 AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
2204 ALCcontext *Context;
2205 ALsource *Source;
2206 ALsizei i;
2208 Context = GetContextRef();
2209 if(!Context) return;
2211 al_try
2213 CHECK_VALUE(Context, n >= 0);
2214 for(i = 0;i < n;i++)
2216 if(!LookupSource(Context, sources[i]))
2217 al_throwerr(Context, AL_INVALID_NAME);
2220 LockContext(Context);
2221 for(i = 0;i < n;i++)
2223 Source = LookupSource(Context, sources[i]);
2224 Source->new_state = AL_NONE;
2225 SetSourceState(Source, Context, AL_STOPPED);
2227 UnlockContext(Context);
2229 al_endtry;
2231 ALCcontext_DecRef(Context);
2234 AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source)
2236 alSourceRewindv(1, &source);
2238 AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
2240 ALCcontext *Context;
2241 ALsource *Source;
2242 ALsizei i;
2244 Context = GetContextRef();
2245 if(!Context) return;
2247 al_try
2249 CHECK_VALUE(Context, n >= 0);
2250 for(i = 0;i < n;i++)
2252 if(!LookupSource(Context, sources[i]))
2253 al_throwerr(Context, AL_INVALID_NAME);
2256 LockContext(Context);
2257 for(i = 0;i < n;i++)
2259 Source = LookupSource(Context, sources[i]);
2260 Source->new_state = AL_NONE;
2261 SetSourceState(Source, Context, AL_INITIAL);
2263 UnlockContext(Context);
2265 al_endtry;
2267 ALCcontext_DecRef(Context);
2271 AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers)
2273 ALCcontext *Context;
2274 ALsource *Source;
2275 ALsizei i;
2276 ALbufferlistitem *BufferListStart = NULL;
2277 ALbufferlistitem *BufferList;
2278 ALbuffer *BufferFmt;
2280 if(nb == 0)
2281 return;
2283 Context = GetContextRef();
2284 if(!Context) return;
2286 al_try
2288 ALCdevice *device = Context->Device;
2290 CHECK_VALUE(Context, nb >= 0);
2292 if((Source=LookupSource(Context, source)) == NULL)
2293 al_throwerr(Context, AL_INVALID_NAME);
2295 LockContext(Context);
2296 if(Source->SourceType == AL_STATIC)
2298 UnlockContext(Context);
2299 /* Can't queue on a Static Source */
2300 al_throwerr(Context, AL_INVALID_OPERATION);
2303 BufferFmt = NULL;
2305 /* Check for a valid Buffer, for its frequency and format */
2306 BufferList = Source->queue;
2307 while(BufferList)
2309 if(BufferList->buffer)
2311 BufferFmt = BufferList->buffer;
2312 break;
2314 BufferList = BufferList->next;
2317 for(i = 0;i < nb;i++)
2319 ALbuffer *buffer = NULL;
2320 if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
2322 UnlockContext(Context);
2323 al_throwerr(Context, AL_INVALID_NAME);
2326 if(!BufferListStart)
2328 BufferListStart = malloc(sizeof(ALbufferlistitem));
2329 BufferListStart->buffer = buffer;
2330 BufferListStart->next = NULL;
2331 BufferListStart->prev = NULL;
2332 BufferList = BufferListStart;
2334 else
2336 BufferList->next = malloc(sizeof(ALbufferlistitem));
2337 BufferList->next->buffer = buffer;
2338 BufferList->next->next = NULL;
2339 BufferList->next->prev = BufferList;
2340 BufferList = BufferList->next;
2342 if(!buffer) continue;
2343 IncrementRef(&buffer->ref);
2345 ReadLock(&buffer->lock);
2346 if(BufferFmt == NULL)
2348 BufferFmt = buffer;
2350 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
2351 Source->SampleSize = BytesFromFmt(buffer->FmtType);
2352 if(buffer->FmtChannels == FmtMono)
2353 Source->Update = CalcSourceParams;
2354 else
2355 Source->Update = CalcNonAttnSourceParams;
2357 Source->NeedsUpdate = AL_TRUE;
2359 else if(BufferFmt->Frequency != buffer->Frequency ||
2360 BufferFmt->OriginalChannels != buffer->OriginalChannels ||
2361 BufferFmt->OriginalType != buffer->OriginalType)
2363 ReadUnlock(&buffer->lock);
2364 UnlockContext(Context);
2365 al_throwerr(Context, AL_INVALID_OPERATION);
2367 ReadUnlock(&buffer->lock);
2370 /* Source is now streaming */
2371 Source->SourceType = AL_STREAMING;
2373 if(Source->queue == NULL)
2374 Source->queue = BufferListStart;
2375 else
2377 /* Append to the end of the queue */
2378 BufferList = Source->queue;
2379 while(BufferList->next != NULL)
2380 BufferList = BufferList->next;
2382 BufferListStart->prev = BufferList;
2383 BufferList->next = BufferListStart;
2386 Source->BuffersInQueue += nb;
2388 UnlockContext(Context);
2390 al_catchany()
2392 while(BufferListStart)
2394 BufferList = BufferListStart;
2395 BufferListStart = BufferList->next;
2397 if(BufferList->buffer)
2398 DecrementRef(&BufferList->buffer->ref);
2399 free(BufferList);
2402 al_endtry;
2404 ALCcontext_DecRef(Context);
2407 AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers)
2409 ALCcontext *Context;
2410 ALsource *Source;
2411 ALsizei i;
2412 ALbufferlistitem *BufferList;
2414 if(nb == 0)
2415 return;
2417 Context = GetContextRef();
2418 if(!Context) return;
2420 al_try
2422 CHECK_VALUE(Context, nb >= 0);
2424 if((Source=LookupSource(Context, source)) == NULL)
2425 al_throwerr(Context, AL_INVALID_NAME);
2427 LockContext(Context);
2428 if(Source->Looping || Source->SourceType != AL_STREAMING ||
2429 (ALuint)nb > Source->BuffersPlayed)
2431 UnlockContext(Context);
2432 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2433 al_throwerr(Context, AL_INVALID_VALUE);
2436 for(i = 0;i < nb;i++)
2438 BufferList = Source->queue;
2439 Source->queue = BufferList->next;
2440 Source->BuffersInQueue--;
2441 Source->BuffersPlayed--;
2443 if(BufferList->buffer)
2445 buffers[i] = BufferList->buffer->id;
2446 DecrementRef(&BufferList->buffer->ref);
2448 else
2449 buffers[i] = 0;
2451 free(BufferList);
2453 if(Source->queue)
2454 Source->queue->prev = NULL;
2455 UnlockContext(Context);
2457 al_endtry;
2459 ALCcontext_DecRef(Context);
2463 static ALvoid InitSourceParams(ALsource *Source)
2465 ALuint i;
2467 Source->InnerAngle = 360.0f;
2468 Source->OuterAngle = 360.0f;
2469 Source->Pitch = 1.0f;
2470 Source->Position[0] = 0.0f;
2471 Source->Position[1] = 0.0f;
2472 Source->Position[2] = 0.0f;
2473 Source->Orientation[0] = 0.0f;
2474 Source->Orientation[1] = 0.0f;
2475 Source->Orientation[2] = 0.0f;
2476 Source->Velocity[0] = 0.0f;
2477 Source->Velocity[1] = 0.0f;
2478 Source->Velocity[2] = 0.0f;
2479 Source->RefDistance = 1.0f;
2480 Source->MaxDistance = FLT_MAX;
2481 Source->RollOffFactor = 1.0f;
2482 Source->Looping = AL_FALSE;
2483 Source->Gain = 1.0f;
2484 Source->MinGain = 0.0f;
2485 Source->MaxGain = 1.0f;
2486 Source->OuterGain = 0.0f;
2487 Source->OuterGainHF = 1.0f;
2489 Source->DryGainHFAuto = AL_TRUE;
2490 Source->WetGainAuto = AL_TRUE;
2491 Source->WetGainHFAuto = AL_TRUE;
2492 Source->AirAbsorptionFactor = 0.0f;
2493 Source->RoomRolloffFactor = 0.0f;
2494 Source->DopplerFactor = 1.0f;
2495 Source->DirectChannels = AL_FALSE;
2497 Source->DistanceModel = DefaultDistanceModel;
2499 Source->Resampler = DefaultResampler;
2501 Source->state = AL_INITIAL;
2502 Source->new_state = AL_NONE;
2503 Source->SourceType = AL_UNDETERMINED;
2504 Source->Offset = -1.0;
2506 Source->DirectGain = 1.0f;
2507 Source->DirectGainHF = 1.0f;
2508 for(i = 0;i < MAX_SENDS;i++)
2510 Source->Send[i].Gain = 1.0f;
2511 Source->Send[i].GainHF = 1.0f;
2514 Source->NeedsUpdate = AL_TRUE;
2516 Source->Hrtf.Moving = AL_FALSE;
2517 Source->Hrtf.Counter = 0;
2521 /* SetSourceState
2523 * Sets the source's new play state given its current state.
2525 ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
2527 if(state == AL_PLAYING)
2529 ALbufferlistitem *BufferList;
2530 ALsizei j, k;
2532 /* Check that there is a queue containing at least one valid, non zero
2533 * length Buffer. */
2534 BufferList = Source->queue;
2535 while(BufferList)
2537 if(BufferList->buffer != NULL && BufferList->buffer->SampleLen)
2538 break;
2539 BufferList = BufferList->next;
2542 if(Source->state != AL_PLAYING)
2544 for(j = 0;j < MaxChannels;j++)
2546 for(k = 0;k < SRC_HISTORY_LENGTH;k++)
2547 Source->Hrtf.History[j][k] = 0.0f;
2548 for(k = 0;k < HRIR_LENGTH;k++)
2550 Source->Hrtf.Values[j][k][0] = 0.0f;
2551 Source->Hrtf.Values[j][k][1] = 0.0f;
2556 if(Source->state != AL_PAUSED)
2558 Source->state = AL_PLAYING;
2559 Source->position = 0;
2560 Source->position_fraction = 0;
2561 Source->BuffersPlayed = 0;
2563 else
2564 Source->state = AL_PLAYING;
2566 // Check if an Offset has been set
2567 if(Source->Offset >= 0.0)
2568 ApplyOffset(Source);
2570 /* If there's nothing to play, or device is disconnected, go right to
2571 * stopped */
2572 if(!BufferList || !Context->Device->Connected)
2574 SetSourceState(Source, Context, AL_STOPPED);
2575 return;
2578 for(j = 0;j < Context->ActiveSourceCount;j++)
2580 if(Context->ActiveSources[j] == Source)
2581 break;
2583 if(j == Context->ActiveSourceCount)
2584 Context->ActiveSources[Context->ActiveSourceCount++] = Source;
2586 else if(state == AL_PAUSED)
2588 if(Source->state == AL_PLAYING)
2590 Source->state = AL_PAUSED;
2591 Source->Hrtf.Moving = AL_FALSE;
2592 Source->Hrtf.Counter = 0;
2595 else if(state == AL_STOPPED)
2597 if(Source->state != AL_INITIAL)
2599 Source->state = AL_STOPPED;
2600 Source->BuffersPlayed = Source->BuffersInQueue;
2601 Source->Hrtf.Moving = AL_FALSE;
2602 Source->Hrtf.Counter = 0;
2604 Source->Offset = -1.0;
2606 else if(state == AL_INITIAL)
2608 if(Source->state != AL_INITIAL)
2610 Source->state = AL_INITIAL;
2611 Source->position = 0;
2612 Source->position_fraction = 0;
2613 Source->BuffersPlayed = 0;
2614 Source->Hrtf.Moving = AL_FALSE;
2615 Source->Hrtf.Counter = 0;
2617 Source->Offset = -1.0;
2621 /* GetSourceOffset
2623 * Gets the current read offset for the given Source, in 32.32 fixed-point
2624 * samples. The offset is relative to the start of the queue (not the start of
2625 * the current buffer).
2627 static ALint64 GetSourceOffset(const ALsource *Source)
2629 const ALbufferlistitem *BufferList;
2630 ALuint64 readPos;
2631 ALuint i;
2633 if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
2634 return 0;
2636 /* NOTE: This is the offset into the *current* buffer, so add the length of
2637 * any played buffers */
2638 readPos = (ALuint64)Source->position << 32;
2639 readPos |= (ALuint64)Source->position_fraction << (32-FRACTIONBITS);
2640 BufferList = Source->queue;
2641 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2643 if(BufferList->buffer)
2644 readPos += (ALuint64)BufferList->buffer->SampleLen << 32;
2645 BufferList = BufferList->next;
2648 return (ALint64)minu64(readPos, MAKEU64(0x7fffffff,0xffffffff));
2651 /* GetSourceSecOffset
2653 * Gets the current read offset for the given Source, in seconds. The offset is
2654 * relative to the start of the queue (not the start of the current buffer).
2656 static ALdouble GetSourceSecOffset(const ALsource *Source)
2658 const ALbufferlistitem *BufferList;
2659 const ALbuffer *Buffer = NULL;
2660 ALuint64 readPos;
2661 ALuint i;
2663 BufferList = Source->queue;
2664 while(BufferList)
2666 if(BufferList->buffer)
2668 Buffer = BufferList->buffer;
2669 break;
2671 BufferList = BufferList->next;
2674 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2675 return 0.0;
2677 /* NOTE: This is the offset into the *current* buffer, so add the length of
2678 * any played buffers */
2679 readPos = (ALuint64)Source->position << FRACTIONBITS;
2680 readPos |= (ALuint64)Source->position_fraction;
2681 BufferList = Source->queue;
2682 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2684 if(BufferList->buffer)
2685 readPos += (ALuint64)BufferList->buffer->SampleLen << FRACTIONBITS;
2686 BufferList = BufferList->next;
2689 return (ALdouble)readPos / (ALdouble)FRACTIONONE / (ALdouble)Buffer->Frequency;
2692 /* GetSourceOffsets
2694 * Gets the current read and write offsets for the given Source, in the
2695 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2696 * the start of the queue (not the start of the current buffer).
2698 static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen)
2700 const ALbufferlistitem *BufferList;
2701 const ALbuffer *Buffer = NULL;
2702 ALuint readPos, writePos;
2703 ALuint totalBufferLen;
2704 ALuint i;
2706 // Find the first valid Buffer in the Queue
2707 BufferList = Source->queue;
2708 while(BufferList)
2710 if(BufferList->buffer)
2712 Buffer = BufferList->buffer;
2713 break;
2715 BufferList = BufferList->next;
2718 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2720 offset[0] = 0.0;
2721 offset[1] = 0.0;
2722 return;
2725 if(updateLen > 0.0 && updateLen < 0.015)
2726 updateLen = 0.015;
2728 /* NOTE: This is the offset into the *current* buffer, so add the length of
2729 * any played buffers */
2730 readPos = Source->position;
2731 totalBufferLen = 0;
2732 BufferList = Source->queue;
2733 for(i = 0;BufferList;i++)
2735 if(BufferList->buffer)
2737 if(i < Source->BuffersPlayed)
2738 readPos += BufferList->buffer->SampleLen;
2739 totalBufferLen += BufferList->buffer->SampleLen;
2741 BufferList = BufferList->next;
2743 if(Source->state == AL_PLAYING)
2744 writePos = readPos + (ALuint)(updateLen*Buffer->Frequency);
2745 else
2746 writePos = readPos;
2748 if(Source->Looping)
2750 readPos %= totalBufferLen;
2751 writePos %= totalBufferLen;
2753 else
2755 /* Wrap positions back to 0 */
2756 if(readPos >= totalBufferLen)
2757 readPos = 0;
2758 if(writePos >= totalBufferLen)
2759 writePos = 0;
2762 switch(name)
2764 case AL_SEC_OFFSET:
2765 offset[0] = (ALdouble)readPos / Buffer->Frequency;
2766 offset[1] = (ALdouble)writePos / Buffer->Frequency;
2767 break;
2769 case AL_SAMPLE_OFFSET:
2770 case AL_SAMPLE_RW_OFFSETS_SOFT:
2771 offset[0] = (ALdouble)readPos;
2772 offset[1] = (ALdouble)writePos;
2773 break;
2775 case AL_BYTE_OFFSET:
2776 case AL_BYTE_RW_OFFSETS_SOFT:
2777 if(Buffer->OriginalType == UserFmtIMA4)
2779 ALuint BlockSize = 36 * ChannelsFromFmt(Buffer->FmtChannels);
2780 ALuint FrameBlockSize = 65;
2782 /* Round down to nearest ADPCM block */
2783 offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
2784 if(Source->state != AL_PLAYING)
2785 offset[1] = offset[0];
2786 else
2788 /* Round up to nearest ADPCM block */
2789 offset[1] = (ALdouble)((writePos+FrameBlockSize-1) /
2790 FrameBlockSize * BlockSize);
2793 else
2795 ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2796 offset[0] = (ALdouble)(readPos * FrameSize);
2797 offset[1] = (ALdouble)(writePos * FrameSize);
2799 break;
2804 /* ApplyOffset
2806 * Apply the stored playback offset to the Source. This function will update
2807 * the number of buffers "played" given the stored offset.
2809 ALboolean ApplyOffset(ALsource *Source)
2811 const ALbufferlistitem *BufferList;
2812 const ALbuffer *Buffer;
2813 ALint bufferLen, totalBufferLen;
2814 ALint buffersPlayed;
2815 ALint offset;
2817 /* Get sample frame offset */
2818 offset = GetSampleOffset(Source);
2819 if(offset == -1)
2820 return AL_FALSE;
2822 buffersPlayed = 0;
2823 totalBufferLen = 0;
2825 BufferList = Source->queue;
2826 while(BufferList)
2828 Buffer = BufferList->buffer;
2829 bufferLen = Buffer ? Buffer->SampleLen : 0;
2831 if(bufferLen <= offset-totalBufferLen)
2833 /* Offset is past this buffer so increment to the next buffer */
2834 buffersPlayed++;
2836 else if(totalBufferLen <= offset)
2838 /* Offset is in this buffer */
2839 Source->BuffersPlayed = buffersPlayed;
2841 Source->position = offset - totalBufferLen;
2842 Source->position_fraction = 0;
2843 return AL_TRUE;
2846 totalBufferLen += bufferLen;
2848 BufferList = BufferList->next;
2851 /* Offset is out of range of the queue */
2852 return AL_FALSE;
2856 /* GetSampleOffset
2858 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2859 * Second offset supplied by the application). This takes into account the fact
2860 * that the buffer format may have been modifed since.
2862 static ALint GetSampleOffset(ALsource *Source)
2864 const ALbuffer *Buffer = NULL;
2865 const ALbufferlistitem *BufferList;
2866 ALint Offset = -1;
2868 /* Find the first valid Buffer in the Queue */
2869 BufferList = Source->queue;
2870 while(BufferList)
2872 if(BufferList->buffer)
2874 Buffer = BufferList->buffer;
2875 break;
2877 BufferList = BufferList->next;
2880 if(!Buffer)
2882 Source->Offset = -1.0;
2883 return -1;
2886 switch(Source->OffsetType)
2888 case AL_BYTE_OFFSET:
2889 /* Determine the ByteOffset (and ensure it is block aligned) */
2890 Offset = (ALint)Source->Offset;
2891 if(Buffer->OriginalType == UserFmtIMA4)
2893 Offset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels);
2894 Offset *= 65;
2896 else
2897 Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2898 break;
2900 case AL_SAMPLE_OFFSET:
2901 Offset = (ALint)Source->Offset;
2902 break;
2904 case AL_SEC_OFFSET:
2905 Offset = (ALint)(Source->Offset * Buffer->Frequency);
2906 break;
2908 Source->Offset = -1.0;
2910 return Offset;
2914 /* ReleaseALSources
2916 * Destroys all sources in the source map.
2918 ALvoid ReleaseALSources(ALCcontext *Context)
2920 ALsizei pos;
2921 ALuint j;
2922 for(pos = 0;pos < Context->SourceMap.size;pos++)
2924 ALsource *temp = Context->SourceMap.array[pos].value;
2925 Context->SourceMap.array[pos].value = NULL;
2927 while(temp->queue != NULL)
2929 ALbufferlistitem *BufferList = temp->queue;
2930 temp->queue = BufferList->next;
2932 if(BufferList->buffer != NULL)
2933 DecrementRef(&BufferList->buffer->ref);
2934 free(BufferList);
2937 for(j = 0;j < MAX_SENDS;++j)
2939 if(temp->Send[j].Slot)
2940 DecrementRef(&temp->Send[j].Slot->ref);
2941 temp->Send[j].Slot = NULL;
2944 FreeThunkEntry(temp->id);
2945 memset(temp, 0, sizeof(*temp));
2946 al_free(temp);