Use an enum to handle int source properties
[openal-soft.git] / OpenAL32 / alSource.c
blobe57ad392ba5b5a01ecc2cf5c2783d66569d0d7ed
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 typedef enum SrcIntProp {
105 sivMaxDistance = AL_MAX_DISTANCE,
106 sivRolloffFactor = AL_ROLLOFF_FACTOR,
107 sivRefDistance = AL_REFERENCE_DISTANCE,
108 sivSourceRelative = AL_SOURCE_RELATIVE,
109 sivConeInnerAngle = AL_CONE_INNER_ANGLE,
110 sivConeOuterAngle = AL_CONE_OUTER_ANGLE,
111 sivLooping = AL_LOOPING,
112 sivBuffer = AL_BUFFER,
113 sivSourceState = AL_SOURCE_STATE,
114 sivBuffersQueued = AL_BUFFERS_QUEUED,
115 sivBuffersProcessed = AL_BUFFERS_PROCESSED,
116 sivSourceType = AL_SOURCE_TYPE,
117 sivSecOffset = AL_SEC_OFFSET,
118 sivSampleOffset = AL_SAMPLE_OFFSET,
119 sivByteOffset = AL_BYTE_OFFSET,
120 sivDopplerFactor = AL_DOPPLER_FACTOR,
121 sivPosition = AL_POSITION,
122 sivVelocity = AL_VELOCITY,
123 sivDirection = AL_DIRECTION,
125 /* ALC_EXT_EFX */
126 sivDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO,
127 sivAuxSendFilterGainAutio = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,
128 sivAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO,
129 sivDirectFilter = AL_DIRECT_FILTER,
130 sivAuxSendFilter = AL_AUXILIARY_SEND_FILTER,
132 /* AL_SOFT_direct_channels */
133 sivDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT,
135 /* AL_EXT_source_distance_model */
136 sivDistanceModel = AL_DISTANCE_MODEL,
138 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
139 sivSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT,
140 sivByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT,
142 /* AL_SOFT_source_latency */
143 sivSampleOffsetLatencySOFT = AL_SAMPLE_OFFSET_LATENCY_SOFT,
144 } SrcIntProp;
146 static ALenum SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values);
147 static ALenum SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint *values);
148 static ALenum SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values);
150 static ALenum GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values);
151 static ALenum GetSourceiv(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values);
152 static ALenum GetSourcei64v(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values);
155 #define RETERR(x) do { \
156 alSetError(Context, (x)); \
157 return (x); \
158 } while(0)
160 #define CHECKVAL(x) do { \
161 if(!(x)) \
162 RETERR(AL_INVALID_VALUE); \
163 } while(0)
165 static ALenum SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values)
167 ALint ival;
169 switch(prop)
171 case AL_PITCH:
172 CHECKVAL(*values >= 0.0f);
174 Source->Pitch = *values;
175 Source->NeedsUpdate = AL_TRUE;
176 return AL_NO_ERROR;
178 case AL_CONE_INNER_ANGLE:
179 CHECKVAL(*values >= 0.0f && *values <= 360.0f);
181 Source->InnerAngle = *values;
182 Source->NeedsUpdate = AL_TRUE;
183 return AL_NO_ERROR;
185 case AL_CONE_OUTER_ANGLE:
186 CHECKVAL(*values >= 0.0f && *values <= 360.0f);
188 Source->OuterAngle = *values;
189 Source->NeedsUpdate = AL_TRUE;
190 return AL_NO_ERROR;
192 case AL_GAIN:
193 CHECKVAL(*values >= 0.0f);
195 Source->Gain = *values;
196 Source->NeedsUpdate = AL_TRUE;
197 return AL_NO_ERROR;
199 case AL_MAX_DISTANCE:
200 CHECKVAL(*values >= 0.0f);
202 Source->MaxDistance = *values;
203 Source->NeedsUpdate = AL_TRUE;
204 return AL_NO_ERROR;
206 case AL_ROLLOFF_FACTOR:
207 CHECKVAL(*values >= 0.0f);
209 Source->RollOffFactor = *values;
210 Source->NeedsUpdate = AL_TRUE;
211 return AL_NO_ERROR;
213 case AL_REFERENCE_DISTANCE:
214 CHECKVAL(*values >= 0.0f);
216 Source->RefDistance = *values;
217 Source->NeedsUpdate = AL_TRUE;
218 return AL_NO_ERROR;
220 case AL_MIN_GAIN:
221 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
223 Source->MinGain = *values;
224 Source->NeedsUpdate = AL_TRUE;
225 return AL_NO_ERROR;
227 case AL_MAX_GAIN:
228 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
230 Source->MaxGain = *values;
231 Source->NeedsUpdate = AL_TRUE;
232 return AL_NO_ERROR;
234 case AL_CONE_OUTER_GAIN:
235 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
237 Source->OuterGain = *values;
238 Source->NeedsUpdate = AL_TRUE;
239 return AL_NO_ERROR;
241 case AL_CONE_OUTER_GAINHF:
242 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
244 Source->OuterGainHF = *values;
245 Source->NeedsUpdate = AL_TRUE;
246 return AL_NO_ERROR;
248 case AL_AIR_ABSORPTION_FACTOR:
249 CHECKVAL(*values >= 0.0f && *values <= 10.0f);
251 Source->AirAbsorptionFactor = *values;
252 Source->NeedsUpdate = AL_TRUE;
253 return AL_NO_ERROR;
255 case AL_ROOM_ROLLOFF_FACTOR:
256 CHECKVAL(*values >= 0.0f && *values <= 10.0f);
258 Source->RoomRolloffFactor = *values;
259 Source->NeedsUpdate = AL_TRUE;
260 return AL_NO_ERROR;
262 case AL_DOPPLER_FACTOR:
263 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
265 Source->DopplerFactor = *values;
266 Source->NeedsUpdate = AL_TRUE;
267 return AL_NO_ERROR;
269 case AL_SEC_OFFSET:
270 case AL_SAMPLE_OFFSET:
271 case AL_BYTE_OFFSET:
272 CHECKVAL(*values >= 0.0f);
274 LockContext(Context);
275 Source->OffsetType = prop;
276 Source->Offset = *values;
278 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
279 !Context->DeferUpdates)
281 if(ApplyOffset(Source) == AL_FALSE)
283 UnlockContext(Context);
284 RETERR(AL_INVALID_VALUE);
287 UnlockContext(Context);
288 return AL_NO_ERROR;
291 case AL_SEC_OFFSET_LATENCY_SOFT:
292 /* Query only */
293 RETERR(AL_INVALID_OPERATION);
296 case AL_POSITION:
297 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
299 LockContext(Context);
300 Source->Position[0] = values[0];
301 Source->Position[1] = values[1];
302 Source->Position[2] = values[2];
303 UnlockContext(Context);
304 Source->NeedsUpdate = AL_TRUE;
305 return AL_NO_ERROR;
307 case AL_VELOCITY:
308 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
310 LockContext(Context);
311 Source->Velocity[0] = values[0];
312 Source->Velocity[1] = values[1];
313 Source->Velocity[2] = values[2];
314 UnlockContext(Context);
315 Source->NeedsUpdate = AL_TRUE;
316 return AL_NO_ERROR;
318 case AL_DIRECTION:
319 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
321 LockContext(Context);
322 Source->Orientation[0] = values[0];
323 Source->Orientation[1] = values[1];
324 Source->Orientation[2] = values[2];
325 UnlockContext(Context);
326 Source->NeedsUpdate = AL_TRUE;
327 return AL_NO_ERROR;
330 case sfvSampleRWOffsetsSOFT:
331 case sfvByteRWOffsetsSOFT:
332 RETERR(AL_INVALID_OPERATION);
335 case sfvSourceRelative:
336 case sfvLooping:
337 case sfvSourceState:
338 case sfvSourceType:
339 case sfvDistanceModel:
340 case sfvDirectFilterGainHFAuto:
341 case sfvAuxSendFilterGainAuto:
342 case sfvAuxSendFilterGainHFAuto:
343 case sfvDirectChannelsSOFT:
344 ival = (ALint)values[0];
345 return SetSourceiv(Source, Context, prop, &ival);
347 case sfvBuffer:
348 case sfvBuffersQueued:
349 case sfvBuffersProcessed:
350 ival = (ALint)((ALuint)values[0]);
351 return SetSourceiv(Source, Context, prop, &ival);
354 ERR("Unexpected property: 0x%04x\n", prop);
355 RETERR(AL_INVALID_ENUM);
358 static ALenum SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint *values)
360 ALCdevice *device = Context->Device;
361 ALbuffer *buffer = NULL;
362 ALfilter *filter = NULL;
363 ALeffectslot *slot = NULL;
364 ALbufferlistitem *oldlist;
365 ALfloat fvals[3];
367 switch(prop)
369 case AL_SOURCE_RELATIVE:
370 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
372 Source->HeadRelative = (ALboolean)*values;
373 Source->NeedsUpdate = AL_TRUE;
374 return AL_NO_ERROR;
376 case AL_LOOPING:
377 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
379 Source->Looping = (ALboolean)*values;
380 return AL_NO_ERROR;
382 case AL_BUFFER:
383 CHECKVAL(*values == 0 || (buffer=LookupBuffer(device, *values)) != NULL);
385 LockContext(Context);
386 if(!(Source->state == AL_STOPPED || Source->state == AL_INITIAL))
388 UnlockContext(Context);
389 RETERR(AL_INVALID_OPERATION);
392 Source->BuffersInQueue = 0;
393 Source->BuffersPlayed = 0;
395 if(buffer != NULL)
397 ALbufferlistitem *BufferListItem;
399 /* Source is now Static */
400 Source->SourceType = AL_STATIC;
402 /* Add the selected buffer to a one-item queue */
403 BufferListItem = malloc(sizeof(ALbufferlistitem));
404 BufferListItem->buffer = buffer;
405 BufferListItem->next = NULL;
406 BufferListItem->prev = NULL;
407 IncrementRef(&buffer->ref);
409 oldlist = ExchangePtr((XchgPtr*)&Source->queue, BufferListItem);
410 Source->BuffersInQueue = 1;
412 ReadLock(&buffer->lock);
413 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
414 Source->SampleSize = BytesFromFmt(buffer->FmtType);
415 ReadUnlock(&buffer->lock);
416 if(buffer->FmtChannels == FmtMono)
417 Source->Update = CalcSourceParams;
418 else
419 Source->Update = CalcNonAttnSourceParams;
420 Source->NeedsUpdate = AL_TRUE;
422 else
424 /* Source is now Undetermined */
425 Source->SourceType = AL_UNDETERMINED;
426 oldlist = ExchangePtr((XchgPtr*)&Source->queue, NULL);
429 /* Delete all elements in the previous queue */
430 while(oldlist != NULL)
432 ALbufferlistitem *temp = oldlist;
433 oldlist = temp->next;
435 if(temp->buffer)
436 DecrementRef(&temp->buffer->ref);
437 free(temp);
439 UnlockContext(Context);
440 return AL_NO_ERROR;
442 case sivSourceState:
443 case sivSourceType:
444 case sivBuffersQueued:
445 case sivBuffersProcessed:
446 /* Query only */
447 RETERR(AL_INVALID_OPERATION);
449 case AL_SEC_OFFSET:
450 case AL_SAMPLE_OFFSET:
451 case AL_BYTE_OFFSET:
452 CHECKVAL(*values >= 0);
454 LockContext(Context);
455 Source->OffsetType = prop;
456 Source->Offset = *values;
458 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
459 !Context->DeferUpdates)
461 if(ApplyOffset(Source) == AL_FALSE)
463 UnlockContext(Context);
464 RETERR(AL_INVALID_VALUE);
467 UnlockContext(Context);
468 return AL_NO_ERROR;
471 case sivSampleRWOffsetsSOFT:
472 case sivByteRWOffsetsSOFT:
473 case sivSampleOffsetLatencySOFT:
474 /* Query only */
475 RETERR(AL_INVALID_OPERATION);
478 case AL_DIRECT_FILTER:
479 CHECKVAL(*values == 0 || (filter=LookupFilter(device, *values)) != NULL);
481 LockContext(Context);
482 if(!filter)
484 Source->DirectGain = 1.0f;
485 Source->DirectGainHF = 1.0f;
487 else
489 Source->DirectGain = filter->Gain;
490 Source->DirectGainHF = filter->GainHF;
492 UnlockContext(Context);
493 Source->NeedsUpdate = AL_TRUE;
494 return AL_NO_ERROR;
496 case AL_DIRECT_FILTER_GAINHF_AUTO:
497 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
499 Source->DryGainHFAuto = *values;
500 Source->NeedsUpdate = AL_TRUE;
501 return AL_NO_ERROR;
503 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
504 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
506 Source->WetGainAuto = *values;
507 Source->NeedsUpdate = AL_TRUE;
508 return AL_NO_ERROR;
510 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
511 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
513 Source->WetGainHFAuto = *values;
514 Source->NeedsUpdate = AL_TRUE;
515 return AL_NO_ERROR;
517 case AL_DIRECT_CHANNELS_SOFT:
518 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
520 Source->DirectChannels = *values;
521 Source->NeedsUpdate = AL_TRUE;
522 return AL_NO_ERROR;
524 case AL_DISTANCE_MODEL:
525 CHECKVAL(*values == AL_NONE ||
526 *values == AL_INVERSE_DISTANCE ||
527 *values == AL_INVERSE_DISTANCE_CLAMPED ||
528 *values == AL_LINEAR_DISTANCE ||
529 *values == AL_LINEAR_DISTANCE_CLAMPED ||
530 *values == AL_EXPONENT_DISTANCE ||
531 *values == AL_EXPONENT_DISTANCE_CLAMPED);
533 Source->DistanceModel = *values;
534 if(Context->SourceDistanceModel)
535 Source->NeedsUpdate = AL_TRUE;
536 return AL_NO_ERROR;
539 case AL_AUXILIARY_SEND_FILTER:
540 LockContext(Context);
541 if(!((ALuint)values[1] < device->NumAuxSends &&
542 (values[0] == 0 || (slot=LookupEffectSlot(Context, values[0])) != NULL) &&
543 (values[2] == 0 || (filter=LookupFilter(device, values[2])) != NULL)))
545 UnlockContext(Context);
546 RETERR(AL_INVALID_VALUE);
549 /* Add refcount on the new slot, and release the previous slot */
550 if(slot) IncrementRef(&slot->ref);
551 slot = ExchangePtr((XchgPtr*)&Source->Send[values[1]].Slot, slot);
552 if(slot) DecrementRef(&slot->ref);
554 if(!filter)
556 /* Disable filter */
557 Source->Send[values[1]].Gain = 1.0f;
558 Source->Send[values[1]].GainHF = 1.0f;
560 else
562 Source->Send[values[1]].Gain = filter->Gain;
563 Source->Send[values[1]].GainHF = filter->GainHF;
565 Source->NeedsUpdate = AL_TRUE;
566 UnlockContext(Context);
567 return AL_NO_ERROR;
570 case AL_MAX_DISTANCE:
571 case AL_ROLLOFF_FACTOR:
572 case AL_CONE_INNER_ANGLE:
573 case AL_CONE_OUTER_ANGLE:
574 case AL_REFERENCE_DISTANCE:
575 case sivDopplerFactor:
576 fvals[0] = (ALfloat)*values;
577 return SetSourcefv(Source, Context, (int)prop, fvals);
579 case AL_POSITION:
580 case AL_VELOCITY:
581 case AL_DIRECTION:
582 fvals[0] = (ALfloat)values[0];
583 fvals[1] = (ALfloat)values[1];
584 fvals[2] = (ALfloat)values[2];
585 return SetSourcefv(Source, Context, (int)prop, fvals);
588 ERR("Unexpected property: 0x%04x\n", prop);
589 RETERR(AL_INVALID_ENUM);
592 static ALenum SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values)
594 ALfloat fvals[3];
595 ALint ivals[3];
597 switch(prop)
599 case sivSampleRWOffsetsSOFT:
600 case sivByteRWOffsetsSOFT:
601 case sivSampleOffsetLatencySOFT:
602 /* Query only */
603 RETERR(AL_INVALID_OPERATION);
606 /* 1x int */
607 case AL_SOURCE_RELATIVE:
608 case AL_LOOPING:
609 case AL_SOURCE_STATE:
610 case AL_BYTE_OFFSET:
611 case AL_SAMPLE_OFFSET:
612 case sivSourceType:
613 case sivBuffersQueued:
614 case sivBuffersProcessed:
615 case AL_DIRECT_FILTER_GAINHF_AUTO:
616 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
617 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
618 case AL_DIRECT_CHANNELS_SOFT:
619 case AL_DISTANCE_MODEL:
620 CHECKVAL(*values <= INT_MAX && *values >= INT_MIN);
622 ivals[0] = (ALint)*values;
623 return SetSourceiv(Source, Context, (int)prop, ivals);
625 /* 1x uint */
626 case AL_BUFFER:
627 case AL_DIRECT_FILTER:
628 CHECKVAL(*values <= UINT_MAX && *values >= 0);
630 ivals[0] = (ALuint)*values;
631 return SetSourceiv(Source, Context, (int)prop, ivals);
633 /* 3x uint */
634 case AL_AUXILIARY_SEND_FILTER:
635 CHECKVAL(values[0] <= UINT_MAX && values[0] >= 0 &&
636 values[1] <= UINT_MAX && values[1] >= 0 &&
637 values[2] <= UINT_MAX && values[2] >= 0);
639 ivals[0] = (ALuint)values[0];
640 ivals[1] = (ALuint)values[1];
641 ivals[2] = (ALuint)values[2];
642 return SetSourceiv(Source, Context, (int)prop, ivals);
644 /* 1x float */
645 case AL_MAX_DISTANCE:
646 case AL_ROLLOFF_FACTOR:
647 case AL_CONE_INNER_ANGLE:
648 case AL_CONE_OUTER_ANGLE:
649 case AL_REFERENCE_DISTANCE:
650 case AL_SEC_OFFSET:
651 case sivDopplerFactor:
652 fvals[0] = (ALfloat)*values;
653 return SetSourcefv(Source, Context, (int)prop, fvals);
655 /* 3x float */
656 case AL_POSITION:
657 case AL_VELOCITY:
658 case AL_DIRECTION:
659 fvals[0] = (ALfloat)values[0];
660 fvals[1] = (ALfloat)values[1];
661 fvals[2] = (ALfloat)values[2];
662 return SetSourcefv(Source, Context, (int)prop, fvals);
665 ERR("Unexpected property: 0x%04x\n", prop);
666 RETERR(AL_INVALID_ENUM);
669 #undef CHECKVAL
672 static ALenum GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values)
674 ALdouble offsets[2];
675 ALdouble updateLen;
676 ALint ivals[3];
677 ALenum err;
679 switch(prop)
681 case AL_GAIN:
682 *values = Source->Gain;
683 return AL_NO_ERROR;
685 case AL_PITCH:
686 *values = Source->Pitch;
687 return AL_NO_ERROR;
689 case AL_MAX_DISTANCE:
690 *values = Source->MaxDistance;
691 return AL_NO_ERROR;
693 case AL_ROLLOFF_FACTOR:
694 *values = Source->RollOffFactor;
695 return AL_NO_ERROR;
697 case AL_REFERENCE_DISTANCE:
698 *values = Source->RefDistance;
699 return AL_NO_ERROR;
701 case AL_CONE_INNER_ANGLE:
702 *values = Source->InnerAngle;
703 return AL_NO_ERROR;
705 case AL_CONE_OUTER_ANGLE:
706 *values = Source->OuterAngle;
707 return AL_NO_ERROR;
709 case AL_MIN_GAIN:
710 *values = Source->MinGain;
711 return AL_NO_ERROR;
713 case AL_MAX_GAIN:
714 *values = Source->MaxGain;
715 return AL_NO_ERROR;
717 case AL_CONE_OUTER_GAIN:
718 *values = Source->OuterGain;
719 return AL_NO_ERROR;
721 case AL_SEC_OFFSET:
722 case AL_SAMPLE_OFFSET:
723 case AL_BYTE_OFFSET:
724 LockContext(Context);
725 updateLen = (ALdouble)Context->Device->UpdateSize /
726 Context->Device->Frequency;
727 GetSourceOffsets(Source, prop, offsets, updateLen);
728 UnlockContext(Context);
729 *values = offsets[0];
730 return AL_NO_ERROR;
732 case AL_CONE_OUTER_GAINHF:
733 *values = Source->OuterGainHF;
734 return AL_NO_ERROR;
736 case AL_AIR_ABSORPTION_FACTOR:
737 *values = Source->AirAbsorptionFactor;
738 return AL_NO_ERROR;
740 case AL_ROOM_ROLLOFF_FACTOR:
741 *values = Source->RoomRolloffFactor;
742 return AL_NO_ERROR;
744 case AL_DOPPLER_FACTOR:
745 *values = Source->DopplerFactor;
746 return AL_NO_ERROR;
748 case AL_SAMPLE_RW_OFFSETS_SOFT:
749 case AL_BYTE_RW_OFFSETS_SOFT:
750 LockContext(Context);
751 updateLen = (ALdouble)Context->Device->UpdateSize /
752 Context->Device->Frequency;
753 GetSourceOffsets(Source, prop, values, updateLen);
754 UnlockContext(Context);
755 return AL_NO_ERROR;
757 case AL_SEC_OFFSET_LATENCY_SOFT:
758 LockContext(Context);
759 values[0] = GetSourceSecOffset(Source);
760 values[1] = (ALdouble)ALCdevice_GetLatency(Context->Device) /
761 1000000000.0;
762 UnlockContext(Context);
763 return AL_NO_ERROR;
765 case AL_POSITION:
766 LockContext(Context);
767 values[0] = Source->Position[0];
768 values[1] = Source->Position[1];
769 values[2] = Source->Position[2];
770 UnlockContext(Context);
771 return AL_NO_ERROR;
773 case AL_VELOCITY:
774 LockContext(Context);
775 values[0] = Source->Velocity[0];
776 values[1] = Source->Velocity[1];
777 values[2] = Source->Velocity[2];
778 UnlockContext(Context);
779 return AL_NO_ERROR;
781 case AL_DIRECTION:
782 LockContext(Context);
783 values[0] = Source->Orientation[0];
784 values[1] = Source->Orientation[1];
785 values[2] = Source->Orientation[2];
786 UnlockContext(Context);
787 return AL_NO_ERROR;
789 case AL_SOURCE_RELATIVE:
790 case AL_LOOPING:
791 case AL_BUFFER:
792 case AL_SOURCE_STATE:
793 case AL_BUFFERS_QUEUED:
794 case AL_BUFFERS_PROCESSED:
795 case AL_SOURCE_TYPE:
796 case AL_DIRECT_FILTER_GAINHF_AUTO:
797 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
798 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
799 case AL_DIRECT_CHANNELS_SOFT:
800 case AL_DISTANCE_MODEL:
801 if((err=GetSourceiv(Source, Context, (int)prop, ivals)) == AL_NO_ERROR)
802 *values = (ALdouble)ivals[0];
803 return err;
806 ERR("Unexpected property: 0x%04x\n", prop);
807 RETERR(AL_INVALID_ENUM);
810 static ALenum GetSourceiv(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values)
812 ALbufferlistitem *BufferList;
813 ALdouble dvals[3];
814 ALenum err;
816 switch(prop)
818 case AL_SOURCE_RELATIVE:
819 *values = Source->HeadRelative;
820 return AL_NO_ERROR;
822 case AL_LOOPING:
823 *values = Source->Looping;
824 return AL_NO_ERROR;
826 case AL_BUFFER:
827 LockContext(Context);
828 BufferList = Source->queue;
829 if(Source->SourceType != AL_STATIC)
831 ALuint i = Source->BuffersPlayed;
832 while(i > 0)
834 BufferList = BufferList->next;
835 i--;
838 *values = ((BufferList && BufferList->buffer) ?
839 BufferList->buffer->id : 0);
840 UnlockContext(Context);
841 return AL_NO_ERROR;
843 case AL_SOURCE_STATE:
844 *values = Source->state;
845 return AL_NO_ERROR;
847 case AL_BUFFERS_QUEUED:
848 *values = Source->BuffersInQueue;
849 return AL_NO_ERROR;
851 case AL_BUFFERS_PROCESSED:
852 LockContext(Context);
853 if(Source->Looping || Source->SourceType != AL_STREAMING)
855 /* Buffers on a looping source are in a perpetual state of
856 * PENDING, so don't report any as PROCESSED */
857 *values = 0;
859 else
860 *values = Source->BuffersPlayed;
861 UnlockContext(Context);
862 return AL_NO_ERROR;
864 case AL_SOURCE_TYPE:
865 *values = Source->SourceType;
866 return AL_NO_ERROR;
868 case AL_DIRECT_FILTER_GAINHF_AUTO:
869 *values = Source->DryGainHFAuto;
870 return AL_NO_ERROR;
872 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
873 *values = Source->WetGainAuto;
874 return AL_NO_ERROR;
876 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
877 *values = Source->WetGainHFAuto;
878 return AL_NO_ERROR;
880 case AL_DIRECT_CHANNELS_SOFT:
881 *values = Source->DirectChannels;
882 return AL_NO_ERROR;
884 case AL_DISTANCE_MODEL:
885 *values = Source->DistanceModel;
886 return AL_NO_ERROR;
888 case AL_MAX_DISTANCE:
889 case AL_ROLLOFF_FACTOR:
890 case AL_REFERENCE_DISTANCE:
891 case AL_CONE_INNER_ANGLE:
892 case AL_CONE_OUTER_ANGLE:
893 case AL_SEC_OFFSET:
894 case AL_SAMPLE_OFFSET:
895 case AL_BYTE_OFFSET:
896 case AL_DOPPLER_FACTOR:
897 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
898 *values = (ALint)dvals[0];
899 return err;
901 case AL_SAMPLE_RW_OFFSETS_SOFT:
902 case AL_BYTE_RW_OFFSETS_SOFT:
903 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
905 values[0] = (ALint)dvals[0];
906 values[1] = (ALint)dvals[1];
908 return err;
910 case AL_POSITION:
911 case AL_VELOCITY:
912 case AL_DIRECTION:
913 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
915 values[0] = (ALint)dvals[0];
916 values[1] = (ALint)dvals[1];
917 values[2] = (ALint)dvals[2];
919 return err;
921 case sivSampleOffsetLatencySOFT:
922 /* i64 only */
923 break;
925 case sivDirectFilter:
926 case sivAuxSendFilter:
927 /* ??? */
928 break;
931 ERR("Unexpected property: 0x%04x\n", prop);
932 RETERR(AL_INVALID_ENUM);
935 static ALenum GetSourcei64v(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values)
937 ALdouble dvals[3];
938 ALint ivals[3];
939 ALenum err;
941 switch(prop)
943 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
944 LockContext(Context);
945 values[0] = GetSourceOffset(Source);
946 values[1] = ALCdevice_GetLatency(Context->Device);
947 UnlockContext(Context);
948 return AL_NO_ERROR;
950 case AL_MAX_DISTANCE:
951 case AL_ROLLOFF_FACTOR:
952 case AL_REFERENCE_DISTANCE:
953 case AL_CONE_INNER_ANGLE:
954 case AL_CONE_OUTER_ANGLE:
955 case AL_SEC_OFFSET:
956 case AL_SAMPLE_OFFSET:
957 case AL_BYTE_OFFSET:
958 case AL_DOPPLER_FACTOR:
959 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
960 *values = (ALint64)dvals[0];
961 return err;
963 case AL_SAMPLE_RW_OFFSETS_SOFT:
964 case AL_BYTE_RW_OFFSETS_SOFT:
965 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
967 values[0] = (ALint64)dvals[0];
968 values[1] = (ALint64)dvals[1];
970 return err;
972 case AL_POSITION:
973 case AL_VELOCITY:
974 case AL_DIRECTION:
975 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
977 values[0] = (ALint64)dvals[0];
978 values[1] = (ALint64)dvals[1];
979 values[2] = (ALint64)dvals[2];
981 return err;
983 case AL_SOURCE_RELATIVE:
984 case AL_LOOPING:
985 case AL_BUFFER:
986 case AL_SOURCE_STATE:
987 case AL_BUFFERS_QUEUED:
988 case AL_BUFFERS_PROCESSED:
989 case AL_SOURCE_TYPE:
990 case AL_DIRECT_FILTER_GAINHF_AUTO:
991 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
992 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
993 case AL_DIRECT_CHANNELS_SOFT:
994 case AL_DISTANCE_MODEL:
995 if((err=GetSourceiv(Source, Context, (int)prop, ivals)) == AL_NO_ERROR)
996 *values = ivals[0];
997 return err;
999 /* ??? */
1000 case sivDirectFilter:
1001 case sivAuxSendFilter:
1002 break;
1005 ERR("Unexpected property: 0x%04x\n", prop);
1006 RETERR(AL_INVALID_ENUM);
1009 #undef RETERR
1012 AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
1014 ALCcontext *Context;
1015 ALsizei cur = 0;
1017 Context = GetContextRef();
1018 if(!Context) return;
1020 al_try
1022 ALenum err;
1024 CHECK_VALUE(Context, n >= 0);
1025 for(cur = 0;cur < n;cur++)
1027 ALsource *source = al_calloc(16, sizeof(ALsource));
1028 if(!source)
1029 al_throwerr(Context, AL_OUT_OF_MEMORY);
1030 InitSourceParams(source);
1032 err = NewThunkEntry(&source->id);
1033 if(err == AL_NO_ERROR)
1034 err = InsertUIntMapEntry(&Context->SourceMap, source->id, source);
1035 if(err != AL_NO_ERROR)
1037 FreeThunkEntry(source->id);
1038 memset(source, 0, sizeof(ALsource));
1039 al_free(source);
1041 al_throwerr(Context, err);
1044 sources[cur] = source->id;
1047 al_catchany()
1049 if(cur > 0)
1050 alDeleteSources(cur, sources);
1052 al_endtry;
1054 ALCcontext_DecRef(Context);
1058 AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
1060 ALCcontext *Context;
1062 Context = GetContextRef();
1063 if(!Context) return;
1065 al_try
1067 ALbufferlistitem *BufferList;
1068 ALsource *Source;
1069 ALsizei i, j;
1071 CHECK_VALUE(Context, n >= 0);
1073 /* Check that all Sources are valid */
1074 for(i = 0;i < n;i++)
1076 if(LookupSource(Context, sources[i]) == NULL)
1077 al_throwerr(Context, AL_INVALID_NAME);
1080 for(i = 0;i < n;i++)
1082 ALsource **srclist, **srclistend;
1084 if((Source=RemoveSource(Context, sources[i])) == NULL)
1085 continue;
1086 FreeThunkEntry(Source->id);
1088 LockContext(Context);
1089 srclist = Context->ActiveSources;
1090 srclistend = srclist + Context->ActiveSourceCount;
1091 while(srclist != srclistend)
1093 if(*srclist == Source)
1095 Context->ActiveSourceCount--;
1096 *srclist = *(--srclistend);
1097 break;
1099 srclist++;
1101 UnlockContext(Context);
1103 while(Source->queue != NULL)
1105 BufferList = Source->queue;
1106 Source->queue = BufferList->next;
1108 if(BufferList->buffer != NULL)
1109 DecrementRef(&BufferList->buffer->ref);
1110 free(BufferList);
1113 for(j = 0;j < MAX_SENDS;++j)
1115 if(Source->Send[j].Slot)
1116 DecrementRef(&Source->Send[j].Slot->ref);
1117 Source->Send[j].Slot = NULL;
1120 memset(Source, 0, sizeof(*Source));
1121 al_free(Source);
1124 al_endtry;
1126 ALCcontext_DecRef(Context);
1130 AL_API ALboolean AL_APIENTRY alIsSource(ALuint source)
1132 ALCcontext *Context;
1133 ALboolean result;
1135 Context = GetContextRef();
1136 if(!Context) return AL_FALSE;
1138 result = (LookupSource(Context, source) ? AL_TRUE : AL_FALSE);
1140 ALCcontext_DecRef(Context);
1142 return result;
1146 AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value)
1148 ALCcontext *Context;
1149 ALsource *Source;
1151 Context = GetContextRef();
1152 if(!Context) return;
1154 if((Source=LookupSource(Context, source)) == NULL)
1155 alSetError(Context, AL_INVALID_NAME);
1156 else switch(param)
1158 case AL_PITCH:
1159 case AL_CONE_INNER_ANGLE:
1160 case AL_CONE_OUTER_ANGLE:
1161 case AL_GAIN:
1162 case AL_MAX_DISTANCE:
1163 case AL_ROLLOFF_FACTOR:
1164 case AL_REFERENCE_DISTANCE:
1165 case AL_MIN_GAIN:
1166 case AL_MAX_GAIN:
1167 case AL_CONE_OUTER_GAIN:
1168 case AL_CONE_OUTER_GAINHF:
1169 case AL_AIR_ABSORPTION_FACTOR:
1170 case AL_ROOM_ROLLOFF_FACTOR:
1171 case AL_DOPPLER_FACTOR:
1172 case AL_SEC_OFFSET:
1173 case AL_SAMPLE_OFFSET:
1174 case AL_BYTE_OFFSET:
1175 SetSourcefv(Source, Context, param, &value);
1176 break;
1178 default:
1179 alSetError(Context, AL_INVALID_ENUM);
1182 ALCcontext_DecRef(Context);
1185 AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
1187 ALCcontext *Context;
1188 ALsource *Source;
1189 ALfloat fvals[3];
1191 Context = GetContextRef();
1192 if(!Context) return;
1194 if((Source=LookupSource(Context, source)) == NULL)
1195 alSetError(Context, AL_INVALID_NAME);
1196 else switch(param)
1198 case AL_POSITION:
1199 case AL_VELOCITY:
1200 case AL_DIRECTION:
1201 fvals[0] = value1;
1202 fvals[1] = value2;
1203 fvals[2] = value3;
1204 SetSourcefv(Source, Context, param, fvals);
1205 break;
1207 default:
1208 alSetError(Context, AL_INVALID_ENUM);
1211 ALCcontext_DecRef(Context);
1214 AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values)
1216 ALCcontext *Context;
1217 ALsource *Source;
1219 Context = GetContextRef();
1220 if(!Context) return;
1222 if((Source=LookupSource(Context, source)) == NULL)
1223 alSetError(Context, AL_INVALID_NAME);
1224 else if(!values)
1225 alSetError(Context, AL_INVALID_VALUE);
1226 else switch(param)
1228 case AL_PITCH:
1229 case AL_CONE_INNER_ANGLE:
1230 case AL_CONE_OUTER_ANGLE:
1231 case AL_GAIN:
1232 case AL_MAX_DISTANCE:
1233 case AL_ROLLOFF_FACTOR:
1234 case AL_REFERENCE_DISTANCE:
1235 case AL_MIN_GAIN:
1236 case AL_MAX_GAIN:
1237 case AL_CONE_OUTER_GAIN:
1238 case AL_CONE_OUTER_GAINHF:
1239 case AL_SEC_OFFSET:
1240 case AL_SAMPLE_OFFSET:
1241 case AL_BYTE_OFFSET:
1242 case AL_AIR_ABSORPTION_FACTOR:
1243 case AL_ROOM_ROLLOFF_FACTOR:
1245 case AL_POSITION:
1246 case AL_VELOCITY:
1247 case AL_DIRECTION:
1248 SetSourcefv(Source, Context, param, values);
1249 break;
1251 default:
1252 alSetError(Context, AL_INVALID_ENUM);
1255 ALCcontext_DecRef(Context);
1259 AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value)
1261 ALCcontext *Context;
1262 ALsource *Source;
1263 ALfloat fval;
1265 Context = GetContextRef();
1266 if(!Context) return;
1268 if((Source=LookupSource(Context, source)) == NULL)
1269 alSetError(Context, AL_INVALID_NAME);
1270 else switch(param)
1272 case AL_PITCH:
1273 case AL_CONE_INNER_ANGLE:
1274 case AL_CONE_OUTER_ANGLE:
1275 case AL_GAIN:
1276 case AL_MAX_DISTANCE:
1277 case AL_ROLLOFF_FACTOR:
1278 case AL_REFERENCE_DISTANCE:
1279 case AL_MIN_GAIN:
1280 case AL_MAX_GAIN:
1281 case AL_CONE_OUTER_GAIN:
1282 case AL_CONE_OUTER_GAINHF:
1283 case AL_AIR_ABSORPTION_FACTOR:
1284 case AL_ROOM_ROLLOFF_FACTOR:
1285 case AL_DOPPLER_FACTOR:
1286 case AL_SEC_OFFSET:
1287 case AL_SAMPLE_OFFSET:
1288 case AL_BYTE_OFFSET:
1289 fval = (ALfloat)value;
1290 SetSourcefv(Source, Context, param, &fval);
1291 break;
1293 default:
1294 alSetError(Context, AL_INVALID_ENUM);
1297 ALCcontext_DecRef(Context);
1300 AL_API ALvoid AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3)
1302 ALCcontext *Context;
1303 ALsource *Source;
1304 ALfloat fvals[3];
1306 Context = GetContextRef();
1307 if(!Context) return;
1309 if((Source=LookupSource(Context, source)) == NULL)
1310 alSetError(Context, AL_INVALID_NAME);
1311 else switch(param)
1313 case AL_POSITION:
1314 case AL_VELOCITY:
1315 case AL_DIRECTION:
1316 fvals[0] = (ALfloat)value1;
1317 fvals[1] = (ALfloat)value2;
1318 fvals[2] = (ALfloat)value3;
1319 SetSourcefv(Source, Context, param, fvals);
1320 break;
1322 default:
1323 alSetError(Context, AL_INVALID_ENUM);
1326 ALCcontext_DecRef(Context);
1329 AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values)
1331 ALCcontext *Context;
1332 ALsource *Source;
1333 ALfloat fvals[3];
1335 Context = GetContextRef();
1336 if(!Context) return;
1338 if((Source=LookupSource(Context, source)) == NULL)
1339 alSetError(Context, AL_INVALID_NAME);
1340 else if(!values)
1341 alSetError(Context, AL_INVALID_VALUE);
1342 else switch(param)
1344 case AL_PITCH:
1345 case AL_CONE_INNER_ANGLE:
1346 case AL_CONE_OUTER_ANGLE:
1347 case AL_GAIN:
1348 case AL_MAX_DISTANCE:
1349 case AL_ROLLOFF_FACTOR:
1350 case AL_REFERENCE_DISTANCE:
1351 case AL_MIN_GAIN:
1352 case AL_MAX_GAIN:
1353 case AL_CONE_OUTER_GAIN:
1354 case AL_CONE_OUTER_GAINHF:
1355 case AL_SEC_OFFSET:
1356 case AL_SAMPLE_OFFSET:
1357 case AL_BYTE_OFFSET:
1358 case AL_AIR_ABSORPTION_FACTOR:
1359 case AL_ROOM_ROLLOFF_FACTOR:
1360 fvals[0] = (ALfloat)values[0];
1361 SetSourcefv(Source, Context, param, fvals);
1362 break;
1364 case AL_SEC_OFFSET_LATENCY_SOFT:
1365 fvals[0] = (ALfloat)values[0];
1366 fvals[1] = (ALfloat)values[1];
1367 SetSourcefv(Source, Context, param, fvals);
1368 break;
1370 case AL_POSITION:
1371 case AL_VELOCITY:
1372 case AL_DIRECTION:
1373 fvals[0] = (ALfloat)values[0];
1374 fvals[1] = (ALfloat)values[1];
1375 fvals[2] = (ALfloat)values[2];
1376 SetSourcefv(Source, Context, param, fvals);
1377 break;
1379 default:
1380 alSetError(Context, AL_INVALID_ENUM);
1383 ALCcontext_DecRef(Context);
1387 AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value)
1389 ALCcontext *Context;
1390 ALsource *Source;
1392 Context = GetContextRef();
1393 if(!Context) return;
1395 if((Source=LookupSource(Context, source)) == NULL)
1396 alSetError(Context, AL_INVALID_NAME);
1397 else switch(param)
1399 case AL_MAX_DISTANCE:
1400 case AL_ROLLOFF_FACTOR:
1401 case AL_CONE_INNER_ANGLE:
1402 case AL_CONE_OUTER_ANGLE:
1403 case AL_REFERENCE_DISTANCE:
1404 case AL_SOURCE_RELATIVE:
1405 case AL_LOOPING:
1406 case AL_BUFFER:
1407 case AL_SOURCE_STATE:
1408 case AL_SEC_OFFSET:
1409 case AL_SAMPLE_OFFSET:
1410 case AL_BYTE_OFFSET:
1411 case AL_DIRECT_FILTER:
1412 case AL_DIRECT_FILTER_GAINHF_AUTO:
1413 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1414 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1415 case AL_DIRECT_CHANNELS_SOFT:
1416 case AL_DISTANCE_MODEL:
1417 SetSourceiv(Source, Context, param, &value);
1418 break;
1420 default:
1421 alSetError(Context, AL_INVALID_ENUM);
1424 ALCcontext_DecRef(Context);
1427 AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3)
1429 ALCcontext *Context;
1430 ALsource *Source;
1431 ALint ivals[3];
1433 Context = GetContextRef();
1434 if(!Context) return;
1436 if((Source=LookupSource(Context, source)) == NULL)
1437 alSetError(Context, AL_INVALID_NAME);
1438 else switch(param)
1440 case AL_POSITION:
1441 case AL_VELOCITY:
1442 case AL_DIRECTION:
1443 case AL_AUXILIARY_SEND_FILTER:
1444 ivals[0] = value1;
1445 ivals[1] = value2;
1446 ivals[2] = value3;
1447 SetSourceiv(Source, Context, param, ivals);
1448 break;
1450 default:
1451 alSetError(Context, AL_INVALID_ENUM);
1454 ALCcontext_DecRef(Context);
1457 AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values)
1459 ALCcontext *Context;
1460 ALsource *Source;
1462 Context = GetContextRef();
1463 if(!Context) return;
1465 if((Source=LookupSource(Context, source)) == NULL)
1466 alSetError(Context, AL_INVALID_NAME);
1467 else if(!values)
1468 alSetError(Context, AL_INVALID_VALUE);
1469 else switch(param)
1471 case AL_SOURCE_RELATIVE:
1472 case AL_CONE_INNER_ANGLE:
1473 case AL_CONE_OUTER_ANGLE:
1474 case AL_LOOPING:
1475 case AL_BUFFER:
1476 case AL_SOURCE_STATE:
1477 case AL_SEC_OFFSET:
1478 case AL_SAMPLE_OFFSET:
1479 case AL_BYTE_OFFSET:
1480 case AL_MAX_DISTANCE:
1481 case AL_ROLLOFF_FACTOR:
1482 case AL_REFERENCE_DISTANCE:
1483 case AL_DIRECT_FILTER:
1484 case AL_DIRECT_FILTER_GAINHF_AUTO:
1485 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1486 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1487 case AL_DISTANCE_MODEL:
1488 case AL_DIRECT_CHANNELS_SOFT:
1490 case AL_POSITION:
1491 case AL_VELOCITY:
1492 case AL_DIRECTION:
1493 case AL_AUXILIARY_SEND_FILTER:
1494 SetSourceiv(Source, Context, param, values);
1495 break;
1497 default:
1498 alSetError(Context, AL_INVALID_ENUM);
1501 ALCcontext_DecRef(Context);
1505 AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value)
1507 ALCcontext *Context;
1508 ALsource *Source;
1510 Context = GetContextRef();
1511 if(!Context) return;
1513 if((Source=LookupSource(Context, source)) == NULL)
1514 alSetError(Context, AL_INVALID_NAME);
1515 else switch(param)
1517 case AL_MAX_DISTANCE:
1518 case AL_ROLLOFF_FACTOR:
1519 case AL_CONE_INNER_ANGLE:
1520 case AL_CONE_OUTER_ANGLE:
1521 case AL_REFERENCE_DISTANCE:
1522 case AL_SOURCE_RELATIVE:
1523 case AL_LOOPING:
1524 case AL_SOURCE_STATE:
1525 case AL_SEC_OFFSET:
1526 case AL_SAMPLE_OFFSET:
1527 case AL_BYTE_OFFSET:
1528 case AL_DIRECT_FILTER_GAINHF_AUTO:
1529 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1530 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1531 case AL_DIRECT_CHANNELS_SOFT:
1532 case AL_DISTANCE_MODEL:
1533 case AL_BUFFER:
1534 case AL_DIRECT_FILTER:
1535 SetSourcei64v(Source, Context, param, &value);
1536 break;
1538 default:
1539 alSetError(Context, AL_INVALID_ENUM);
1542 ALCcontext_DecRef(Context);
1545 AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3)
1547 ALCcontext *Context;
1548 ALsource *Source;
1549 ALint64SOFT i64vals[3];
1551 Context = GetContextRef();
1552 if(!Context) return;
1554 if((Source=LookupSource(Context, source)) == NULL)
1555 alSetError(Context, AL_INVALID_NAME);
1556 else switch(param)
1558 case AL_POSITION:
1559 case AL_VELOCITY:
1560 case AL_DIRECTION:
1561 case AL_AUXILIARY_SEND_FILTER:
1562 i64vals[0] = value1;
1563 i64vals[1] = value2;
1564 i64vals[2] = value3;
1565 SetSourcei64v(Source, Context, param, i64vals);
1566 break;
1568 default:
1569 alSetError(Context, AL_INVALID_ENUM);
1572 ALCcontext_DecRef(Context);
1575 AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values)
1577 ALCcontext *Context;
1578 ALsource *Source;
1580 Context = GetContextRef();
1581 if(!Context) return;
1583 if((Source=LookupSource(Context, source)) == NULL)
1584 alSetError(Context, AL_INVALID_NAME);
1585 else if(!values)
1586 alSetError(Context, AL_INVALID_VALUE);
1587 else switch(param)
1589 case AL_SOURCE_RELATIVE:
1590 case AL_CONE_INNER_ANGLE:
1591 case AL_CONE_OUTER_ANGLE:
1592 case AL_LOOPING:
1593 case AL_SOURCE_STATE:
1594 case AL_SEC_OFFSET:
1595 case AL_SAMPLE_OFFSET:
1596 case AL_BYTE_OFFSET:
1597 case AL_MAX_DISTANCE:
1598 case AL_ROLLOFF_FACTOR:
1599 case AL_REFERENCE_DISTANCE:
1600 case AL_DIRECT_FILTER_GAINHF_AUTO:
1601 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1602 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1603 case AL_DISTANCE_MODEL:
1604 case AL_DIRECT_CHANNELS_SOFT:
1605 case AL_BUFFER:
1606 case AL_DIRECT_FILTER:
1608 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
1610 case AL_POSITION:
1611 case AL_VELOCITY:
1612 case AL_DIRECTION:
1613 case AL_AUXILIARY_SEND_FILTER:
1614 SetSourcei64v(Source, Context, param, values);
1615 break;
1617 default:
1618 alSetError(Context, AL_INVALID_ENUM);
1621 ALCcontext_DecRef(Context);
1625 AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value)
1627 ALCcontext *Context;
1628 ALsource *Source;
1629 ALdouble dval;
1631 Context = GetContextRef();
1632 if(!Context) return;
1634 if((Source=LookupSource(Context, source)) == NULL)
1635 alSetError(Context, AL_INVALID_NAME);
1636 else if(!value)
1637 alSetError(Context, AL_INVALID_VALUE);
1638 else switch(param)
1640 case AL_PITCH:
1641 case AL_GAIN:
1642 case AL_MIN_GAIN:
1643 case AL_MAX_GAIN:
1644 case AL_MAX_DISTANCE:
1645 case AL_ROLLOFF_FACTOR:
1646 case AL_CONE_OUTER_GAIN:
1647 case AL_CONE_OUTER_GAINHF:
1648 case AL_SEC_OFFSET:
1649 case AL_SAMPLE_OFFSET:
1650 case AL_BYTE_OFFSET:
1651 case AL_CONE_INNER_ANGLE:
1652 case AL_CONE_OUTER_ANGLE:
1653 case AL_REFERENCE_DISTANCE:
1654 case AL_AIR_ABSORPTION_FACTOR:
1655 case AL_ROOM_ROLLOFF_FACTOR:
1656 case AL_DOPPLER_FACTOR:
1657 if(GetSourcedv(Source, Context, param, &dval) == AL_NO_ERROR)
1658 *value = (ALfloat)dval;
1659 break;
1661 default:
1662 alSetError(Context, AL_INVALID_ENUM);
1665 ALCcontext_DecRef(Context);
1669 AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
1671 ALCcontext *Context;
1672 ALsource *Source;
1673 ALdouble dvals[3];
1675 Context = GetContextRef();
1676 if(!Context) return;
1678 if((Source=LookupSource(Context, source)) == NULL)
1679 alSetError(Context, AL_INVALID_NAME);
1680 else if(!(value1 && value2 && value3))
1681 alSetError(Context, AL_INVALID_VALUE);
1682 else switch(param)
1684 case AL_POSITION:
1685 case AL_VELOCITY:
1686 case AL_DIRECTION:
1687 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1689 *value1 = (ALfloat)dvals[0];
1690 *value2 = (ALfloat)dvals[1];
1691 *value3 = (ALfloat)dvals[2];
1693 break;
1695 default:
1696 alSetError(Context, AL_INVALID_ENUM);
1699 ALCcontext_DecRef(Context);
1703 AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values)
1705 ALCcontext *Context;
1706 ALsource *Source;
1707 ALdouble dvals[2];
1709 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:
1728 alGetSourcef(source, param, values);
1729 return;
1731 case AL_POSITION:
1732 case AL_VELOCITY:
1733 case AL_DIRECTION:
1734 alGetSource3f(source, param, values+0, values+1, values+2);
1735 return;
1738 Context = GetContextRef();
1739 if(!Context) return;
1741 if((Source=LookupSource(Context, source)) == NULL)
1742 alSetError(Context, AL_INVALID_NAME);
1743 else if(!values)
1744 alSetError(Context, AL_INVALID_VALUE);
1745 else switch(param)
1747 case AL_SAMPLE_RW_OFFSETS_SOFT:
1748 case AL_BYTE_RW_OFFSETS_SOFT:
1749 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1751 values[0] = (ALfloat)dvals[0];
1752 values[1] = (ALfloat)dvals[1];
1754 break;
1756 default:
1757 alSetError(Context, AL_INVALID_ENUM);
1760 ALCcontext_DecRef(Context);
1764 AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value)
1766 ALCcontext *Context;
1767 ALsource *Source;
1769 Context = GetContextRef();
1770 if(!Context) return;
1772 if((Source=LookupSource(Context, source)) == NULL)
1773 alSetError(Context, AL_INVALID_NAME);
1774 else if(!value)
1775 alSetError(Context, AL_INVALID_VALUE);
1776 else switch(param)
1778 case AL_PITCH:
1779 case AL_GAIN:
1780 case AL_MIN_GAIN:
1781 case AL_MAX_GAIN:
1782 case AL_MAX_DISTANCE:
1783 case AL_ROLLOFF_FACTOR:
1784 case AL_CONE_OUTER_GAIN:
1785 case AL_CONE_OUTER_GAINHF:
1786 case AL_SEC_OFFSET:
1787 case AL_SAMPLE_OFFSET:
1788 case AL_BYTE_OFFSET:
1789 case AL_CONE_INNER_ANGLE:
1790 case AL_CONE_OUTER_ANGLE:
1791 case AL_REFERENCE_DISTANCE:
1792 case AL_AIR_ABSORPTION_FACTOR:
1793 case AL_ROOM_ROLLOFF_FACTOR:
1794 case AL_DOPPLER_FACTOR:
1795 GetSourcedv(Source, Context, param, value);
1796 break;
1798 default:
1799 alSetError(Context, AL_INVALID_ENUM);
1802 ALCcontext_DecRef(Context);
1805 AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3)
1807 ALCcontext *Context;
1808 ALsource *Source;
1809 ALdouble dvals[3];
1811 Context = GetContextRef();
1812 if(!Context) return;
1814 if((Source=LookupSource(Context, source)) == NULL)
1815 alSetError(Context, AL_INVALID_NAME);
1816 else if(!(value1 && value2 && value3))
1817 alSetError(Context, AL_INVALID_VALUE);
1818 else switch(param)
1820 case AL_POSITION:
1821 case AL_VELOCITY:
1822 case AL_DIRECTION:
1823 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1825 *value1 = dvals[0];
1826 *value2 = dvals[1];
1827 *value3 = dvals[2];
1829 break;
1831 default:
1832 alSetError(Context, AL_INVALID_ENUM);
1835 ALCcontext_DecRef(Context);
1838 AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values)
1840 ALCcontext *Context;
1841 ALsource *Source;
1843 Context = GetContextRef();
1844 if(!Context) return;
1846 if((Source=LookupSource(Context, source)) == NULL)
1847 alSetError(Context, AL_INVALID_NAME);
1848 else if(!values)
1849 alSetError(Context, AL_INVALID_VALUE);
1850 else switch(param)
1852 case AL_PITCH:
1853 case AL_GAIN:
1854 case AL_MIN_GAIN:
1855 case AL_MAX_GAIN:
1856 case AL_MAX_DISTANCE:
1857 case AL_ROLLOFF_FACTOR:
1858 case AL_DOPPLER_FACTOR:
1859 case AL_CONE_OUTER_GAIN:
1860 case AL_SEC_OFFSET:
1861 case AL_SAMPLE_OFFSET:
1862 case AL_BYTE_OFFSET:
1863 case AL_CONE_INNER_ANGLE:
1864 case AL_CONE_OUTER_ANGLE:
1865 case AL_REFERENCE_DISTANCE:
1866 case AL_CONE_OUTER_GAINHF:
1867 case AL_AIR_ABSORPTION_FACTOR:
1868 case AL_ROOM_ROLLOFF_FACTOR:
1870 case AL_SAMPLE_RW_OFFSETS_SOFT:
1871 case AL_BYTE_RW_OFFSETS_SOFT:
1872 case AL_SEC_OFFSET_LATENCY_SOFT:
1874 case AL_POSITION:
1875 case AL_VELOCITY:
1876 case AL_DIRECTION:
1877 GetSourcedv(Source, Context, param, values);
1878 break;
1880 default:
1881 alSetError(Context, AL_INVALID_ENUM);
1884 ALCcontext_DecRef(Context);
1888 AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value)
1890 ALCcontext *Context;
1891 ALsource *Source;
1893 Context = GetContextRef();
1894 if(!Context) return;
1896 if((Source=LookupSource(Context, source)) == NULL)
1897 alSetError(Context, AL_INVALID_NAME);
1898 else if(!value)
1899 alSetError(Context, AL_INVALID_VALUE);
1900 else switch(param)
1902 case AL_MAX_DISTANCE:
1903 case AL_ROLLOFF_FACTOR:
1904 case AL_REFERENCE_DISTANCE:
1905 case AL_SOURCE_RELATIVE:
1906 case AL_CONE_INNER_ANGLE:
1907 case AL_CONE_OUTER_ANGLE:
1908 case AL_LOOPING:
1909 case AL_BUFFER:
1910 case AL_SOURCE_STATE:
1911 case AL_BUFFERS_QUEUED:
1912 case AL_BUFFERS_PROCESSED:
1913 case AL_SOURCE_TYPE:
1914 case AL_SEC_OFFSET:
1915 case AL_SAMPLE_OFFSET:
1916 case AL_BYTE_OFFSET:
1917 case AL_DIRECT_FILTER_GAINHF_AUTO:
1918 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1919 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1920 case AL_DOPPLER_FACTOR:
1921 case AL_DIRECT_CHANNELS_SOFT:
1922 case AL_DISTANCE_MODEL:
1923 GetSourceiv(Source, Context, param, value);
1924 break;
1926 default:
1927 alSetError(Context, AL_INVALID_ENUM);
1930 ALCcontext_DecRef(Context);
1934 AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3)
1936 ALCcontext *Context;
1937 ALsource *Source;
1938 ALint ivals[3];
1940 Context = GetContextRef();
1941 if(!Context) return;
1943 if((Source=LookupSource(Context, source)) == NULL)
1944 alSetError(Context, AL_INVALID_NAME);
1945 else if(!(value1 && value2 && value3))
1946 alSetError(Context, AL_INVALID_VALUE);
1947 else switch(param)
1949 case AL_POSITION:
1950 case AL_VELOCITY:
1951 case AL_DIRECTION:
1952 if(GetSourceiv(Source, Context, param, ivals) == AL_NO_ERROR)
1954 *value1 = ivals[0];
1955 *value2 = ivals[1];
1956 *value3 = ivals[2];
1958 break;
1960 default:
1961 alSetError(Context, AL_INVALID_ENUM);
1964 ALCcontext_DecRef(Context);
1968 AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values)
1970 ALCcontext *Context;
1971 ALsource *Source;
1973 Context = GetContextRef();
1974 if(!Context) return;
1976 if((Source=LookupSource(Context, source)) == NULL)
1977 alSetError(Context, AL_INVALID_NAME);
1978 else if(!values)
1979 alSetError(Context, AL_INVALID_VALUE);
1980 else switch(param)
1982 case AL_SOURCE_RELATIVE:
1983 case AL_CONE_INNER_ANGLE:
1984 case AL_CONE_OUTER_ANGLE:
1985 case AL_LOOPING:
1986 case AL_BUFFER:
1987 case AL_SOURCE_STATE:
1988 case AL_BUFFERS_QUEUED:
1989 case AL_BUFFERS_PROCESSED:
1990 case AL_SEC_OFFSET:
1991 case AL_SAMPLE_OFFSET:
1992 case AL_BYTE_OFFSET:
1993 case AL_MAX_DISTANCE:
1994 case AL_ROLLOFF_FACTOR:
1995 case AL_DOPPLER_FACTOR:
1996 case AL_REFERENCE_DISTANCE:
1997 case AL_SOURCE_TYPE:
1998 case AL_DIRECT_FILTER:
1999 case AL_DIRECT_FILTER_GAINHF_AUTO:
2000 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
2001 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
2002 case AL_DISTANCE_MODEL:
2003 case AL_DIRECT_CHANNELS_SOFT:
2005 case AL_SAMPLE_RW_OFFSETS_SOFT:
2006 case AL_BYTE_RW_OFFSETS_SOFT:
2008 case AL_POSITION:
2009 case AL_VELOCITY:
2010 case AL_DIRECTION:
2011 GetSourceiv(Source, Context, param, values);
2012 break;
2014 default:
2015 alSetError(Context, AL_INVALID_ENUM);
2018 ALCcontext_DecRef(Context);
2022 AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value)
2024 ALCcontext *Context;
2025 ALsource *Source;
2027 Context = GetContextRef();
2028 if(!Context) return;
2030 if((Source=LookupSource(Context, source)) == NULL)
2031 alSetError(Context, AL_INVALID_NAME);
2032 else if(!value)
2033 alSetError(Context, AL_INVALID_VALUE);
2034 else switch(param)
2036 case AL_MAX_DISTANCE:
2037 case AL_ROLLOFF_FACTOR:
2038 case AL_REFERENCE_DISTANCE:
2039 case AL_SOURCE_RELATIVE:
2040 case AL_CONE_INNER_ANGLE:
2041 case AL_CONE_OUTER_ANGLE:
2042 case AL_LOOPING:
2043 case AL_BUFFER:
2044 case AL_SOURCE_STATE:
2045 case AL_BUFFERS_QUEUED:
2046 case AL_BUFFERS_PROCESSED:
2047 case AL_SOURCE_TYPE:
2048 case AL_SEC_OFFSET:
2049 case AL_SAMPLE_OFFSET:
2050 case AL_BYTE_OFFSET:
2051 case AL_DIRECT_FILTER_GAINHF_AUTO:
2052 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
2053 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
2054 case AL_DOPPLER_FACTOR:
2055 case AL_DIRECT_CHANNELS_SOFT:
2056 case AL_DISTANCE_MODEL:
2057 GetSourcei64v(Source, Context, param, value);
2058 break;
2060 default:
2061 alSetError(Context, AL_INVALID_ENUM);
2064 ALCcontext_DecRef(Context);
2067 AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3)
2069 ALCcontext *Context;
2070 ALsource *Source;
2071 ALint64 i64vals[3];
2073 Context = GetContextRef();
2074 if(!Context) return;
2076 if((Source=LookupSource(Context, source)) == NULL)
2077 alSetError(Context, AL_INVALID_NAME);
2078 else if(!(value1 && value2 && value3))
2079 alSetError(Context, AL_INVALID_VALUE);
2080 else switch(param)
2082 case AL_POSITION:
2083 case AL_VELOCITY:
2084 case AL_DIRECTION:
2085 if(GetSourcei64v(Source, Context, param, i64vals) == AL_NO_ERROR)
2087 *value1 = i64vals[0];
2088 *value2 = i64vals[1];
2089 *value3 = i64vals[2];
2091 break;
2093 default:
2094 alSetError(Context, AL_INVALID_ENUM);
2097 ALCcontext_DecRef(Context);
2100 AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values)
2102 ALCcontext *Context;
2103 ALsource *Source;
2105 Context = GetContextRef();
2106 if(!Context) return;
2108 if((Source=LookupSource(Context, source)) == NULL)
2109 alSetError(Context, AL_INVALID_NAME);
2110 else if(!values)
2111 alSetError(Context, AL_INVALID_VALUE);
2112 else switch(param)
2114 case AL_MAX_DISTANCE:
2115 case AL_ROLLOFF_FACTOR:
2116 case AL_REFERENCE_DISTANCE:
2117 case AL_SOURCE_RELATIVE:
2118 case AL_CONE_INNER_ANGLE:
2119 case AL_CONE_OUTER_ANGLE:
2120 case AL_LOOPING:
2121 case AL_BUFFER:
2122 case AL_SOURCE_STATE:
2123 case AL_BUFFERS_QUEUED:
2124 case AL_BUFFERS_PROCESSED:
2125 case AL_SOURCE_TYPE:
2126 case AL_SEC_OFFSET:
2127 case AL_SAMPLE_OFFSET:
2128 case AL_BYTE_OFFSET:
2129 case AL_DIRECT_FILTER_GAINHF_AUTO:
2130 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
2131 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
2132 case AL_DOPPLER_FACTOR:
2133 case AL_DIRECT_CHANNELS_SOFT:
2134 case AL_DISTANCE_MODEL:
2136 case AL_SAMPLE_RW_OFFSETS_SOFT:
2137 case AL_BYTE_RW_OFFSETS_SOFT:
2138 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
2140 case AL_POSITION:
2141 case AL_VELOCITY:
2142 case AL_DIRECTION:
2143 GetSourcei64v(Source, Context, param, values);
2144 break;
2146 default:
2147 alSetError(Context, AL_INVALID_ENUM);
2150 ALCcontext_DecRef(Context);
2154 AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint source)
2156 alSourcePlayv(1, &source);
2158 AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
2160 ALCcontext *Context;
2161 ALsource *Source;
2162 ALsizei i;
2164 Context = GetContextRef();
2165 if(!Context) return;
2167 al_try
2169 CHECK_VALUE(Context, n >= 0);
2170 for(i = 0;i < n;i++)
2172 if(!LookupSource(Context, sources[i]))
2173 al_throwerr(Context, AL_INVALID_NAME);
2176 LockContext(Context);
2177 while(Context->MaxActiveSources-Context->ActiveSourceCount < n)
2179 void *temp = NULL;
2180 ALsizei newcount;
2182 newcount = Context->MaxActiveSources << 1;
2183 if(newcount > 0)
2184 temp = realloc(Context->ActiveSources,
2185 sizeof(*Context->ActiveSources) * newcount);
2186 if(!temp)
2188 UnlockContext(Context);
2189 al_throwerr(Context, AL_OUT_OF_MEMORY);
2192 Context->ActiveSources = temp;
2193 Context->MaxActiveSources = newcount;
2196 for(i = 0;i < n;i++)
2198 Source = LookupSource(Context, sources[i]);
2199 if(Context->DeferUpdates) Source->new_state = AL_PLAYING;
2200 else SetSourceState(Source, Context, AL_PLAYING);
2202 UnlockContext(Context);
2204 al_endtry;
2206 ALCcontext_DecRef(Context);
2209 AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source)
2211 alSourcePausev(1, &source);
2213 AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
2215 ALCcontext *Context;
2216 ALsource *Source;
2217 ALsizei i;
2219 Context = GetContextRef();
2220 if(!Context) return;
2222 al_try
2224 CHECK_VALUE(Context, n >= 0);
2225 for(i = 0;i < n;i++)
2227 if(!LookupSource(Context, sources[i]))
2228 al_throwerr(Context, AL_INVALID_NAME);
2231 LockContext(Context);
2232 for(i = 0;i < n;i++)
2234 Source = LookupSource(Context, sources[i]);
2235 if(Context->DeferUpdates) Source->new_state = AL_PAUSED;
2236 else SetSourceState(Source, Context, AL_PAUSED);
2238 UnlockContext(Context);
2240 al_endtry;
2242 ALCcontext_DecRef(Context);
2245 AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source)
2247 alSourceStopv(1, &source);
2249 AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
2251 ALCcontext *Context;
2252 ALsource *Source;
2253 ALsizei i;
2255 Context = GetContextRef();
2256 if(!Context) return;
2258 al_try
2260 CHECK_VALUE(Context, n >= 0);
2261 for(i = 0;i < n;i++)
2263 if(!LookupSource(Context, sources[i]))
2264 al_throwerr(Context, AL_INVALID_NAME);
2267 LockContext(Context);
2268 for(i = 0;i < n;i++)
2270 Source = LookupSource(Context, sources[i]);
2271 Source->new_state = AL_NONE;
2272 SetSourceState(Source, Context, AL_STOPPED);
2274 UnlockContext(Context);
2276 al_endtry;
2278 ALCcontext_DecRef(Context);
2281 AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source)
2283 alSourceRewindv(1, &source);
2285 AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
2287 ALCcontext *Context;
2288 ALsource *Source;
2289 ALsizei i;
2291 Context = GetContextRef();
2292 if(!Context) return;
2294 al_try
2296 CHECK_VALUE(Context, n >= 0);
2297 for(i = 0;i < n;i++)
2299 if(!LookupSource(Context, sources[i]))
2300 al_throwerr(Context, AL_INVALID_NAME);
2303 LockContext(Context);
2304 for(i = 0;i < n;i++)
2306 Source = LookupSource(Context, sources[i]);
2307 Source->new_state = AL_NONE;
2308 SetSourceState(Source, Context, AL_INITIAL);
2310 UnlockContext(Context);
2312 al_endtry;
2314 ALCcontext_DecRef(Context);
2318 AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers)
2320 ALCcontext *Context;
2321 ALsource *Source;
2322 ALsizei i;
2323 ALbufferlistitem *BufferListStart = NULL;
2324 ALbufferlistitem *BufferList;
2325 ALbuffer *BufferFmt;
2327 if(nb == 0)
2328 return;
2330 Context = GetContextRef();
2331 if(!Context) return;
2333 al_try
2335 ALCdevice *device = Context->Device;
2337 CHECK_VALUE(Context, nb >= 0);
2339 if((Source=LookupSource(Context, source)) == NULL)
2340 al_throwerr(Context, AL_INVALID_NAME);
2342 LockContext(Context);
2343 if(Source->SourceType == AL_STATIC)
2345 UnlockContext(Context);
2346 /* Can't queue on a Static Source */
2347 al_throwerr(Context, AL_INVALID_OPERATION);
2350 BufferFmt = NULL;
2352 /* Check for a valid Buffer, for its frequency and format */
2353 BufferList = Source->queue;
2354 while(BufferList)
2356 if(BufferList->buffer)
2358 BufferFmt = BufferList->buffer;
2359 break;
2361 BufferList = BufferList->next;
2364 for(i = 0;i < nb;i++)
2366 ALbuffer *buffer = NULL;
2367 if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
2369 UnlockContext(Context);
2370 al_throwerr(Context, AL_INVALID_NAME);
2373 if(!BufferListStart)
2375 BufferListStart = malloc(sizeof(ALbufferlistitem));
2376 BufferListStart->buffer = buffer;
2377 BufferListStart->next = NULL;
2378 BufferListStart->prev = NULL;
2379 BufferList = BufferListStart;
2381 else
2383 BufferList->next = malloc(sizeof(ALbufferlistitem));
2384 BufferList->next->buffer = buffer;
2385 BufferList->next->next = NULL;
2386 BufferList->next->prev = BufferList;
2387 BufferList = BufferList->next;
2389 if(!buffer) continue;
2390 IncrementRef(&buffer->ref);
2392 ReadLock(&buffer->lock);
2393 if(BufferFmt == NULL)
2395 BufferFmt = buffer;
2397 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
2398 Source->SampleSize = BytesFromFmt(buffer->FmtType);
2399 if(buffer->FmtChannels == FmtMono)
2400 Source->Update = CalcSourceParams;
2401 else
2402 Source->Update = CalcNonAttnSourceParams;
2404 Source->NeedsUpdate = AL_TRUE;
2406 else if(BufferFmt->Frequency != buffer->Frequency ||
2407 BufferFmt->OriginalChannels != buffer->OriginalChannels ||
2408 BufferFmt->OriginalType != buffer->OriginalType)
2410 ReadUnlock(&buffer->lock);
2411 UnlockContext(Context);
2412 al_throwerr(Context, AL_INVALID_OPERATION);
2414 ReadUnlock(&buffer->lock);
2417 /* Source is now streaming */
2418 Source->SourceType = AL_STREAMING;
2420 if(Source->queue == NULL)
2421 Source->queue = BufferListStart;
2422 else
2424 /* Append to the end of the queue */
2425 BufferList = Source->queue;
2426 while(BufferList->next != NULL)
2427 BufferList = BufferList->next;
2429 BufferListStart->prev = BufferList;
2430 BufferList->next = BufferListStart;
2433 Source->BuffersInQueue += nb;
2435 UnlockContext(Context);
2437 al_catchany()
2439 while(BufferListStart)
2441 BufferList = BufferListStart;
2442 BufferListStart = BufferList->next;
2444 if(BufferList->buffer)
2445 DecrementRef(&BufferList->buffer->ref);
2446 free(BufferList);
2449 al_endtry;
2451 ALCcontext_DecRef(Context);
2454 AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers)
2456 ALCcontext *Context;
2457 ALsource *Source;
2458 ALsizei i;
2459 ALbufferlistitem *BufferList;
2461 if(nb == 0)
2462 return;
2464 Context = GetContextRef();
2465 if(!Context) return;
2467 al_try
2469 CHECK_VALUE(Context, nb >= 0);
2471 if((Source=LookupSource(Context, source)) == NULL)
2472 al_throwerr(Context, AL_INVALID_NAME);
2474 LockContext(Context);
2475 if(Source->Looping || Source->SourceType != AL_STREAMING ||
2476 (ALuint)nb > Source->BuffersPlayed)
2478 UnlockContext(Context);
2479 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2480 al_throwerr(Context, AL_INVALID_VALUE);
2483 for(i = 0;i < nb;i++)
2485 BufferList = Source->queue;
2486 Source->queue = BufferList->next;
2487 Source->BuffersInQueue--;
2488 Source->BuffersPlayed--;
2490 if(BufferList->buffer)
2492 buffers[i] = BufferList->buffer->id;
2493 DecrementRef(&BufferList->buffer->ref);
2495 else
2496 buffers[i] = 0;
2498 free(BufferList);
2500 if(Source->queue)
2501 Source->queue->prev = NULL;
2502 UnlockContext(Context);
2504 al_endtry;
2506 ALCcontext_DecRef(Context);
2510 static ALvoid InitSourceParams(ALsource *Source)
2512 ALuint i;
2514 Source->InnerAngle = 360.0f;
2515 Source->OuterAngle = 360.0f;
2516 Source->Pitch = 1.0f;
2517 Source->Position[0] = 0.0f;
2518 Source->Position[1] = 0.0f;
2519 Source->Position[2] = 0.0f;
2520 Source->Orientation[0] = 0.0f;
2521 Source->Orientation[1] = 0.0f;
2522 Source->Orientation[2] = 0.0f;
2523 Source->Velocity[0] = 0.0f;
2524 Source->Velocity[1] = 0.0f;
2525 Source->Velocity[2] = 0.0f;
2526 Source->RefDistance = 1.0f;
2527 Source->MaxDistance = FLT_MAX;
2528 Source->RollOffFactor = 1.0f;
2529 Source->Looping = AL_FALSE;
2530 Source->Gain = 1.0f;
2531 Source->MinGain = 0.0f;
2532 Source->MaxGain = 1.0f;
2533 Source->OuterGain = 0.0f;
2534 Source->OuterGainHF = 1.0f;
2536 Source->DryGainHFAuto = AL_TRUE;
2537 Source->WetGainAuto = AL_TRUE;
2538 Source->WetGainHFAuto = AL_TRUE;
2539 Source->AirAbsorptionFactor = 0.0f;
2540 Source->RoomRolloffFactor = 0.0f;
2541 Source->DopplerFactor = 1.0f;
2542 Source->DirectChannels = AL_FALSE;
2544 Source->DistanceModel = DefaultDistanceModel;
2546 Source->Resampler = DefaultResampler;
2548 Source->state = AL_INITIAL;
2549 Source->new_state = AL_NONE;
2550 Source->SourceType = AL_UNDETERMINED;
2551 Source->Offset = -1.0;
2553 Source->DirectGain = 1.0f;
2554 Source->DirectGainHF = 1.0f;
2555 for(i = 0;i < MAX_SENDS;i++)
2557 Source->Send[i].Gain = 1.0f;
2558 Source->Send[i].GainHF = 1.0f;
2561 Source->NeedsUpdate = AL_TRUE;
2563 Source->Hrtf.Moving = AL_FALSE;
2564 Source->Hrtf.Counter = 0;
2568 /* SetSourceState
2570 * Sets the source's new play state given its current state.
2572 ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
2574 if(state == AL_PLAYING)
2576 ALbufferlistitem *BufferList;
2577 ALsizei j, k;
2579 /* Check that there is a queue containing at least one valid, non zero
2580 * length Buffer. */
2581 BufferList = Source->queue;
2582 while(BufferList)
2584 if(BufferList->buffer != NULL && BufferList->buffer->SampleLen)
2585 break;
2586 BufferList = BufferList->next;
2589 if(Source->state != AL_PLAYING)
2591 for(j = 0;j < MaxChannels;j++)
2593 for(k = 0;k < SRC_HISTORY_LENGTH;k++)
2594 Source->Hrtf.History[j][k] = 0.0f;
2595 for(k = 0;k < HRIR_LENGTH;k++)
2597 Source->Hrtf.Values[j][k][0] = 0.0f;
2598 Source->Hrtf.Values[j][k][1] = 0.0f;
2603 if(Source->state != AL_PAUSED)
2605 Source->state = AL_PLAYING;
2606 Source->position = 0;
2607 Source->position_fraction = 0;
2608 Source->BuffersPlayed = 0;
2610 else
2611 Source->state = AL_PLAYING;
2613 // Check if an Offset has been set
2614 if(Source->Offset >= 0.0)
2615 ApplyOffset(Source);
2617 /* If there's nothing to play, or device is disconnected, go right to
2618 * stopped */
2619 if(!BufferList || !Context->Device->Connected)
2621 SetSourceState(Source, Context, AL_STOPPED);
2622 return;
2625 for(j = 0;j < Context->ActiveSourceCount;j++)
2627 if(Context->ActiveSources[j] == Source)
2628 break;
2630 if(j == Context->ActiveSourceCount)
2631 Context->ActiveSources[Context->ActiveSourceCount++] = Source;
2633 else if(state == AL_PAUSED)
2635 if(Source->state == AL_PLAYING)
2637 Source->state = AL_PAUSED;
2638 Source->Hrtf.Moving = AL_FALSE;
2639 Source->Hrtf.Counter = 0;
2642 else if(state == AL_STOPPED)
2644 if(Source->state != AL_INITIAL)
2646 Source->state = AL_STOPPED;
2647 Source->BuffersPlayed = Source->BuffersInQueue;
2648 Source->Hrtf.Moving = AL_FALSE;
2649 Source->Hrtf.Counter = 0;
2651 Source->Offset = -1.0;
2653 else if(state == AL_INITIAL)
2655 if(Source->state != AL_INITIAL)
2657 Source->state = AL_INITIAL;
2658 Source->position = 0;
2659 Source->position_fraction = 0;
2660 Source->BuffersPlayed = 0;
2661 Source->Hrtf.Moving = AL_FALSE;
2662 Source->Hrtf.Counter = 0;
2664 Source->Offset = -1.0;
2668 /* GetSourceOffset
2670 * Gets the current read offset for the given Source, in 32.32 fixed-point
2671 * samples. The offset is relative to the start of the queue (not the start of
2672 * the current buffer).
2674 static ALint64 GetSourceOffset(const ALsource *Source)
2676 const ALbufferlistitem *BufferList;
2677 ALuint64 readPos;
2678 ALuint i;
2680 if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
2681 return 0;
2683 /* NOTE: This is the offset into the *current* buffer, so add the length of
2684 * any played buffers */
2685 readPos = (ALuint64)Source->position << 32;
2686 readPos |= (ALuint64)Source->position_fraction << (32-FRACTIONBITS);
2687 BufferList = Source->queue;
2688 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2690 if(BufferList->buffer)
2691 readPos += (ALuint64)BufferList->buffer->SampleLen << 32;
2692 BufferList = BufferList->next;
2695 return (ALint64)minu64(readPos, MAKEU64(0x7fffffff,0xffffffff));
2698 /* GetSourceSecOffset
2700 * Gets the current read offset for the given Source, in seconds. The offset is
2701 * relative to the start of the queue (not the start of the current buffer).
2703 static ALdouble GetSourceSecOffset(const ALsource *Source)
2705 const ALbufferlistitem *BufferList;
2706 const ALbuffer *Buffer = NULL;
2707 ALuint64 readPos;
2708 ALuint i;
2710 BufferList = Source->queue;
2711 while(BufferList)
2713 if(BufferList->buffer)
2715 Buffer = BufferList->buffer;
2716 break;
2718 BufferList = BufferList->next;
2721 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2722 return 0.0;
2724 /* NOTE: This is the offset into the *current* buffer, so add the length of
2725 * any played buffers */
2726 readPos = (ALuint64)Source->position << FRACTIONBITS;
2727 readPos |= (ALuint64)Source->position_fraction;
2728 BufferList = Source->queue;
2729 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2731 if(BufferList->buffer)
2732 readPos += (ALuint64)BufferList->buffer->SampleLen << FRACTIONBITS;
2733 BufferList = BufferList->next;
2736 return (ALdouble)readPos / (ALdouble)FRACTIONONE / (ALdouble)Buffer->Frequency;
2739 /* GetSourceOffsets
2741 * Gets the current read and write offsets for the given Source, in the
2742 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2743 * the start of the queue (not the start of the current buffer).
2745 static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen)
2747 const ALbufferlistitem *BufferList;
2748 const ALbuffer *Buffer = NULL;
2749 ALuint readPos, writePos;
2750 ALuint totalBufferLen;
2751 ALuint i;
2753 // Find the first valid Buffer in the Queue
2754 BufferList = Source->queue;
2755 while(BufferList)
2757 if(BufferList->buffer)
2759 Buffer = BufferList->buffer;
2760 break;
2762 BufferList = BufferList->next;
2765 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2767 offset[0] = 0.0;
2768 offset[1] = 0.0;
2769 return;
2772 if(updateLen > 0.0 && updateLen < 0.015)
2773 updateLen = 0.015;
2775 /* NOTE: This is the offset into the *current* buffer, so add the length of
2776 * any played buffers */
2777 readPos = Source->position;
2778 totalBufferLen = 0;
2779 BufferList = Source->queue;
2780 for(i = 0;BufferList;i++)
2782 if(BufferList->buffer)
2784 if(i < Source->BuffersPlayed)
2785 readPos += BufferList->buffer->SampleLen;
2786 totalBufferLen += BufferList->buffer->SampleLen;
2788 BufferList = BufferList->next;
2790 if(Source->state == AL_PLAYING)
2791 writePos = readPos + (ALuint)(updateLen*Buffer->Frequency);
2792 else
2793 writePos = readPos;
2795 if(Source->Looping)
2797 readPos %= totalBufferLen;
2798 writePos %= totalBufferLen;
2800 else
2802 /* Wrap positions back to 0 */
2803 if(readPos >= totalBufferLen)
2804 readPos = 0;
2805 if(writePos >= totalBufferLen)
2806 writePos = 0;
2809 switch(name)
2811 case AL_SEC_OFFSET:
2812 offset[0] = (ALdouble)readPos / Buffer->Frequency;
2813 offset[1] = (ALdouble)writePos / Buffer->Frequency;
2814 break;
2816 case AL_SAMPLE_OFFSET:
2817 case AL_SAMPLE_RW_OFFSETS_SOFT:
2818 offset[0] = (ALdouble)readPos;
2819 offset[1] = (ALdouble)writePos;
2820 break;
2822 case AL_BYTE_OFFSET:
2823 case AL_BYTE_RW_OFFSETS_SOFT:
2824 if(Buffer->OriginalType == UserFmtIMA4)
2826 ALuint BlockSize = 36 * ChannelsFromFmt(Buffer->FmtChannels);
2827 ALuint FrameBlockSize = 65;
2829 /* Round down to nearest ADPCM block */
2830 offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
2831 if(Source->state != AL_PLAYING)
2832 offset[1] = offset[0];
2833 else
2835 /* Round up to nearest ADPCM block */
2836 offset[1] = (ALdouble)((writePos+FrameBlockSize-1) /
2837 FrameBlockSize * BlockSize);
2840 else
2842 ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2843 offset[0] = (ALdouble)(readPos * FrameSize);
2844 offset[1] = (ALdouble)(writePos * FrameSize);
2846 break;
2851 /* ApplyOffset
2853 * Apply the stored playback offset to the Source. This function will update
2854 * the number of buffers "played" given the stored offset.
2856 ALboolean ApplyOffset(ALsource *Source)
2858 const ALbufferlistitem *BufferList;
2859 const ALbuffer *Buffer;
2860 ALint bufferLen, totalBufferLen;
2861 ALint buffersPlayed;
2862 ALint offset;
2864 /* Get sample frame offset */
2865 offset = GetSampleOffset(Source);
2866 if(offset == -1)
2867 return AL_FALSE;
2869 buffersPlayed = 0;
2870 totalBufferLen = 0;
2872 BufferList = Source->queue;
2873 while(BufferList)
2875 Buffer = BufferList->buffer;
2876 bufferLen = Buffer ? Buffer->SampleLen : 0;
2878 if(bufferLen <= offset-totalBufferLen)
2880 /* Offset is past this buffer so increment to the next buffer */
2881 buffersPlayed++;
2883 else if(totalBufferLen <= offset)
2885 /* Offset is in this buffer */
2886 Source->BuffersPlayed = buffersPlayed;
2888 Source->position = offset - totalBufferLen;
2889 Source->position_fraction = 0;
2890 return AL_TRUE;
2893 totalBufferLen += bufferLen;
2895 BufferList = BufferList->next;
2898 /* Offset is out of range of the queue */
2899 return AL_FALSE;
2903 /* GetSampleOffset
2905 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2906 * Second offset supplied by the application). This takes into account the fact
2907 * that the buffer format may have been modifed since.
2909 static ALint GetSampleOffset(ALsource *Source)
2911 const ALbuffer *Buffer = NULL;
2912 const ALbufferlistitem *BufferList;
2913 ALint Offset = -1;
2915 /* Find the first valid Buffer in the Queue */
2916 BufferList = Source->queue;
2917 while(BufferList)
2919 if(BufferList->buffer)
2921 Buffer = BufferList->buffer;
2922 break;
2924 BufferList = BufferList->next;
2927 if(!Buffer)
2929 Source->Offset = -1.0;
2930 return -1;
2933 switch(Source->OffsetType)
2935 case AL_BYTE_OFFSET:
2936 /* Determine the ByteOffset (and ensure it is block aligned) */
2937 Offset = (ALint)Source->Offset;
2938 if(Buffer->OriginalType == UserFmtIMA4)
2940 Offset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels);
2941 Offset *= 65;
2943 else
2944 Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2945 break;
2947 case AL_SAMPLE_OFFSET:
2948 Offset = (ALint)Source->Offset;
2949 break;
2951 case AL_SEC_OFFSET:
2952 Offset = (ALint)(Source->Offset * Buffer->Frequency);
2953 break;
2955 Source->Offset = -1.0;
2957 return Offset;
2961 /* ReleaseALSources
2963 * Destroys all sources in the source map.
2965 ALvoid ReleaseALSources(ALCcontext *Context)
2967 ALsizei pos;
2968 ALuint j;
2969 for(pos = 0;pos < Context->SourceMap.size;pos++)
2971 ALsource *temp = Context->SourceMap.array[pos].value;
2972 Context->SourceMap.array[pos].value = NULL;
2974 while(temp->queue != NULL)
2976 ALbufferlistitem *BufferList = temp->queue;
2977 temp->queue = BufferList->next;
2979 if(BufferList->buffer != NULL)
2980 DecrementRef(&BufferList->buffer->ref);
2981 free(BufferList);
2984 for(j = 0;j < MAX_SENDS;++j)
2986 if(temp->Send[j].Slot)
2987 DecrementRef(&temp->Send[j].Slot->ref);
2988 temp->Send[j].Slot = NULL;
2991 FreeThunkEntry(temp->id);
2992 memset(temp, 0, sizeof(*temp));
2993 al_free(temp);