Add a comment to note the extension for sfvDistanceModel
[openal-soft.git] / OpenAL32 / alSource.c
blob61d0c52e0dda8cb8d385f3147230f2430494b338
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,
84 /* ALC_EXT_EFX */
85 sfvConeOuterGainHF = AL_CONE_OUTER_GAINHF,
86 sfvAirAbsorptionFactor = AL_AIR_ABSORPTION_FACTOR,
87 sfvRoomRolloffFactor = AL_ROOM_ROLLOFF_FACTOR,
88 sfvDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO,
89 sfvAuxSendFilterGainAuto = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,
90 sfvAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO,
92 /* AL_SOFT_direct_channels */
93 sfvDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT,
95 /* AL_EXT_source_distance_model */
96 sfvDistanceModel = AL_DISTANCE_MODEL,
98 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
99 sfvSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT,
100 sfvByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT,
102 /* AL_SOFT_source_latency */
103 sfvSecOffsetLatencySOFT = AL_SEC_OFFSET_LATENCY_SOFT,
104 } SrcFloatProp;
106 typedef enum SrcIntProp {
107 sivMaxDistance = AL_MAX_DISTANCE,
108 sivRolloffFactor = AL_ROLLOFF_FACTOR,
109 sivRefDistance = AL_REFERENCE_DISTANCE,
110 sivSourceRelative = AL_SOURCE_RELATIVE,
111 sivConeInnerAngle = AL_CONE_INNER_ANGLE,
112 sivConeOuterAngle = AL_CONE_OUTER_ANGLE,
113 sivLooping = AL_LOOPING,
114 sivBuffer = AL_BUFFER,
115 sivSourceState = AL_SOURCE_STATE,
116 sivBuffersQueued = AL_BUFFERS_QUEUED,
117 sivBuffersProcessed = AL_BUFFERS_PROCESSED,
118 sivSourceType = AL_SOURCE_TYPE,
119 sivSecOffset = AL_SEC_OFFSET,
120 sivSampleOffset = AL_SAMPLE_OFFSET,
121 sivByteOffset = AL_BYTE_OFFSET,
122 sivDopplerFactor = AL_DOPPLER_FACTOR,
123 sivPosition = AL_POSITION,
124 sivVelocity = AL_VELOCITY,
125 sivDirection = AL_DIRECTION,
127 /* ALC_EXT_EFX */
128 sivDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO,
129 sivAuxSendFilterGainAutio = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,
130 sivAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO,
131 sivDirectFilter = AL_DIRECT_FILTER,
132 sivAuxSendFilter = AL_AUXILIARY_SEND_FILTER,
134 /* AL_SOFT_direct_channels */
135 sivDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT,
137 /* AL_EXT_source_distance_model */
138 sivDistanceModel = AL_DISTANCE_MODEL,
140 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
141 sivSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT,
142 sivByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT,
144 /* AL_SOFT_source_latency */
145 sivSampleOffsetLatencySOFT = AL_SAMPLE_OFFSET_LATENCY_SOFT,
146 } SrcIntProp;
148 static ALenum SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values);
149 static ALenum SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint *values);
150 static ALenum SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values);
152 static ALenum GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values);
153 static ALenum GetSourceiv(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values);
154 static ALenum GetSourcei64v(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values);
157 #define RETERR(x) do { \
158 alSetError(Context, (x)); \
159 return (x); \
160 } while(0)
162 #define CHECKVAL(x) do { \
163 if(!(x)) \
164 RETERR(AL_INVALID_VALUE); \
165 } while(0)
167 static ALenum SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values)
169 ALint ival;
171 switch(prop)
173 case AL_PITCH:
174 CHECKVAL(*values >= 0.0f);
176 Source->Pitch = *values;
177 Source->NeedsUpdate = AL_TRUE;
178 return AL_NO_ERROR;
180 case AL_CONE_INNER_ANGLE:
181 CHECKVAL(*values >= 0.0f && *values <= 360.0f);
183 Source->InnerAngle = *values;
184 Source->NeedsUpdate = AL_TRUE;
185 return AL_NO_ERROR;
187 case AL_CONE_OUTER_ANGLE:
188 CHECKVAL(*values >= 0.0f && *values <= 360.0f);
190 Source->OuterAngle = *values;
191 Source->NeedsUpdate = AL_TRUE;
192 return AL_NO_ERROR;
194 case AL_GAIN:
195 CHECKVAL(*values >= 0.0f);
197 Source->Gain = *values;
198 Source->NeedsUpdate = AL_TRUE;
199 return AL_NO_ERROR;
201 case AL_MAX_DISTANCE:
202 CHECKVAL(*values >= 0.0f);
204 Source->MaxDistance = *values;
205 Source->NeedsUpdate = AL_TRUE;
206 return AL_NO_ERROR;
208 case AL_ROLLOFF_FACTOR:
209 CHECKVAL(*values >= 0.0f);
211 Source->RollOffFactor = *values;
212 Source->NeedsUpdate = AL_TRUE;
213 return AL_NO_ERROR;
215 case AL_REFERENCE_DISTANCE:
216 CHECKVAL(*values >= 0.0f);
218 Source->RefDistance = *values;
219 Source->NeedsUpdate = AL_TRUE;
220 return AL_NO_ERROR;
222 case AL_MIN_GAIN:
223 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
225 Source->MinGain = *values;
226 Source->NeedsUpdate = AL_TRUE;
227 return AL_NO_ERROR;
229 case AL_MAX_GAIN:
230 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
232 Source->MaxGain = *values;
233 Source->NeedsUpdate = AL_TRUE;
234 return AL_NO_ERROR;
236 case AL_CONE_OUTER_GAIN:
237 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
239 Source->OuterGain = *values;
240 Source->NeedsUpdate = AL_TRUE;
241 return AL_NO_ERROR;
243 case AL_CONE_OUTER_GAINHF:
244 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
246 Source->OuterGainHF = *values;
247 Source->NeedsUpdate = AL_TRUE;
248 return AL_NO_ERROR;
250 case AL_AIR_ABSORPTION_FACTOR:
251 CHECKVAL(*values >= 0.0f && *values <= 10.0f);
253 Source->AirAbsorptionFactor = *values;
254 Source->NeedsUpdate = AL_TRUE;
255 return AL_NO_ERROR;
257 case AL_ROOM_ROLLOFF_FACTOR:
258 CHECKVAL(*values >= 0.0f && *values <= 10.0f);
260 Source->RoomRolloffFactor = *values;
261 Source->NeedsUpdate = AL_TRUE;
262 return AL_NO_ERROR;
264 case AL_DOPPLER_FACTOR:
265 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
267 Source->DopplerFactor = *values;
268 Source->NeedsUpdate = AL_TRUE;
269 return AL_NO_ERROR;
271 case AL_SEC_OFFSET:
272 case AL_SAMPLE_OFFSET:
273 case AL_BYTE_OFFSET:
274 CHECKVAL(*values >= 0.0f);
276 LockContext(Context);
277 Source->OffsetType = prop;
278 Source->Offset = *values;
280 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
281 !Context->DeferUpdates)
283 if(ApplyOffset(Source) == AL_FALSE)
285 UnlockContext(Context);
286 RETERR(AL_INVALID_VALUE);
289 UnlockContext(Context);
290 return AL_NO_ERROR;
293 case AL_SEC_OFFSET_LATENCY_SOFT:
294 /* Query only */
295 RETERR(AL_INVALID_OPERATION);
298 case AL_POSITION:
299 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
301 LockContext(Context);
302 Source->Position[0] = values[0];
303 Source->Position[1] = values[1];
304 Source->Position[2] = values[2];
305 UnlockContext(Context);
306 Source->NeedsUpdate = AL_TRUE;
307 return AL_NO_ERROR;
309 case AL_VELOCITY:
310 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
312 LockContext(Context);
313 Source->Velocity[0] = values[0];
314 Source->Velocity[1] = values[1];
315 Source->Velocity[2] = values[2];
316 UnlockContext(Context);
317 Source->NeedsUpdate = AL_TRUE;
318 return AL_NO_ERROR;
320 case AL_DIRECTION:
321 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
323 LockContext(Context);
324 Source->Orientation[0] = values[0];
325 Source->Orientation[1] = values[1];
326 Source->Orientation[2] = values[2];
327 UnlockContext(Context);
328 Source->NeedsUpdate = AL_TRUE;
329 return AL_NO_ERROR;
332 case sfvSampleRWOffsetsSOFT:
333 case sfvByteRWOffsetsSOFT:
334 RETERR(AL_INVALID_OPERATION);
337 case sfvSourceRelative:
338 case sfvLooping:
339 case sfvSourceState:
340 case sfvSourceType:
341 case sfvDistanceModel:
342 case sfvDirectFilterGainHFAuto:
343 case sfvAuxSendFilterGainAuto:
344 case sfvAuxSendFilterGainHFAuto:
345 case sfvDirectChannelsSOFT:
346 ival = (ALint)values[0];
347 return SetSourceiv(Source, Context, prop, &ival);
349 case sfvBuffer:
350 case sfvBuffersQueued:
351 case sfvBuffersProcessed:
352 ival = (ALint)((ALuint)values[0]);
353 return SetSourceiv(Source, Context, prop, &ival);
356 ERR("Unexpected property: 0x%04x\n", prop);
357 RETERR(AL_INVALID_ENUM);
360 static ALenum SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint *values)
362 ALCdevice *device = Context->Device;
363 ALbuffer *buffer = NULL;
364 ALfilter *filter = NULL;
365 ALeffectslot *slot = NULL;
366 ALbufferlistitem *oldlist;
367 ALfloat fvals[3];
369 switch(prop)
371 case AL_SOURCE_RELATIVE:
372 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
374 Source->HeadRelative = (ALboolean)*values;
375 Source->NeedsUpdate = AL_TRUE;
376 return AL_NO_ERROR;
378 case AL_LOOPING:
379 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
381 Source->Looping = (ALboolean)*values;
382 return AL_NO_ERROR;
384 case AL_BUFFER:
385 CHECKVAL(*values == 0 || (buffer=LookupBuffer(device, *values)) != NULL);
387 LockContext(Context);
388 if(!(Source->state == AL_STOPPED || Source->state == AL_INITIAL))
390 UnlockContext(Context);
391 RETERR(AL_INVALID_OPERATION);
394 Source->BuffersInQueue = 0;
395 Source->BuffersPlayed = 0;
397 if(buffer != NULL)
399 ALbufferlistitem *BufferListItem;
401 /* Source is now Static */
402 Source->SourceType = AL_STATIC;
404 /* Add the selected buffer to a one-item queue */
405 BufferListItem = malloc(sizeof(ALbufferlistitem));
406 BufferListItem->buffer = buffer;
407 BufferListItem->next = NULL;
408 BufferListItem->prev = NULL;
409 IncrementRef(&buffer->ref);
411 oldlist = ExchangePtr((XchgPtr*)&Source->queue, BufferListItem);
412 Source->BuffersInQueue = 1;
414 ReadLock(&buffer->lock);
415 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
416 Source->SampleSize = BytesFromFmt(buffer->FmtType);
417 ReadUnlock(&buffer->lock);
418 if(buffer->FmtChannels == FmtMono)
419 Source->Update = CalcSourceParams;
420 else
421 Source->Update = CalcNonAttnSourceParams;
422 Source->NeedsUpdate = AL_TRUE;
424 else
426 /* Source is now Undetermined */
427 Source->SourceType = AL_UNDETERMINED;
428 oldlist = ExchangePtr((XchgPtr*)&Source->queue, NULL);
431 /* Delete all elements in the previous queue */
432 while(oldlist != NULL)
434 ALbufferlistitem *temp = oldlist;
435 oldlist = temp->next;
437 if(temp->buffer)
438 DecrementRef(&temp->buffer->ref);
439 free(temp);
441 UnlockContext(Context);
442 return AL_NO_ERROR;
444 case sivSourceState:
445 case sivSourceType:
446 case sivBuffersQueued:
447 case sivBuffersProcessed:
448 /* Query only */
449 RETERR(AL_INVALID_OPERATION);
451 case AL_SEC_OFFSET:
452 case AL_SAMPLE_OFFSET:
453 case AL_BYTE_OFFSET:
454 CHECKVAL(*values >= 0);
456 LockContext(Context);
457 Source->OffsetType = prop;
458 Source->Offset = *values;
460 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
461 !Context->DeferUpdates)
463 if(ApplyOffset(Source) == AL_FALSE)
465 UnlockContext(Context);
466 RETERR(AL_INVALID_VALUE);
469 UnlockContext(Context);
470 return AL_NO_ERROR;
473 case sivSampleRWOffsetsSOFT:
474 case sivByteRWOffsetsSOFT:
475 case sivSampleOffsetLatencySOFT:
476 /* Query only */
477 RETERR(AL_INVALID_OPERATION);
480 case AL_DIRECT_FILTER:
481 CHECKVAL(*values == 0 || (filter=LookupFilter(device, *values)) != NULL);
483 LockContext(Context);
484 if(!filter)
486 Source->DirectGain = 1.0f;
487 Source->DirectGainHF = 1.0f;
489 else
491 Source->DirectGain = filter->Gain;
492 Source->DirectGainHF = filter->GainHF;
494 UnlockContext(Context);
495 Source->NeedsUpdate = AL_TRUE;
496 return AL_NO_ERROR;
498 case AL_DIRECT_FILTER_GAINHF_AUTO:
499 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
501 Source->DryGainHFAuto = *values;
502 Source->NeedsUpdate = AL_TRUE;
503 return AL_NO_ERROR;
505 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
506 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
508 Source->WetGainAuto = *values;
509 Source->NeedsUpdate = AL_TRUE;
510 return AL_NO_ERROR;
512 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
513 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
515 Source->WetGainHFAuto = *values;
516 Source->NeedsUpdate = AL_TRUE;
517 return AL_NO_ERROR;
519 case AL_DIRECT_CHANNELS_SOFT:
520 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
522 Source->DirectChannels = *values;
523 Source->NeedsUpdate = AL_TRUE;
524 return AL_NO_ERROR;
526 case AL_DISTANCE_MODEL:
527 CHECKVAL(*values == AL_NONE ||
528 *values == AL_INVERSE_DISTANCE ||
529 *values == AL_INVERSE_DISTANCE_CLAMPED ||
530 *values == AL_LINEAR_DISTANCE ||
531 *values == AL_LINEAR_DISTANCE_CLAMPED ||
532 *values == AL_EXPONENT_DISTANCE ||
533 *values == AL_EXPONENT_DISTANCE_CLAMPED);
535 Source->DistanceModel = *values;
536 if(Context->SourceDistanceModel)
537 Source->NeedsUpdate = AL_TRUE;
538 return AL_NO_ERROR;
541 case AL_AUXILIARY_SEND_FILTER:
542 LockContext(Context);
543 if(!((ALuint)values[1] < device->NumAuxSends &&
544 (values[0] == 0 || (slot=LookupEffectSlot(Context, values[0])) != NULL) &&
545 (values[2] == 0 || (filter=LookupFilter(device, values[2])) != NULL)))
547 UnlockContext(Context);
548 RETERR(AL_INVALID_VALUE);
551 /* Add refcount on the new slot, and release the previous slot */
552 if(slot) IncrementRef(&slot->ref);
553 slot = ExchangePtr((XchgPtr*)&Source->Send[values[1]].Slot, slot);
554 if(slot) DecrementRef(&slot->ref);
556 if(!filter)
558 /* Disable filter */
559 Source->Send[values[1]].Gain = 1.0f;
560 Source->Send[values[1]].GainHF = 1.0f;
562 else
564 Source->Send[values[1]].Gain = filter->Gain;
565 Source->Send[values[1]].GainHF = filter->GainHF;
567 Source->NeedsUpdate = AL_TRUE;
568 UnlockContext(Context);
569 return AL_NO_ERROR;
572 case AL_MAX_DISTANCE:
573 case AL_ROLLOFF_FACTOR:
574 case AL_CONE_INNER_ANGLE:
575 case AL_CONE_OUTER_ANGLE:
576 case AL_REFERENCE_DISTANCE:
577 case sivDopplerFactor:
578 fvals[0] = (ALfloat)*values;
579 return SetSourcefv(Source, Context, (int)prop, fvals);
581 case AL_POSITION:
582 case AL_VELOCITY:
583 case AL_DIRECTION:
584 fvals[0] = (ALfloat)values[0];
585 fvals[1] = (ALfloat)values[1];
586 fvals[2] = (ALfloat)values[2];
587 return SetSourcefv(Source, Context, (int)prop, fvals);
590 ERR("Unexpected property: 0x%04x\n", prop);
591 RETERR(AL_INVALID_ENUM);
594 static ALenum SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values)
596 ALfloat fvals[3];
597 ALint ivals[3];
599 switch(prop)
601 case sivSampleRWOffsetsSOFT:
602 case sivByteRWOffsetsSOFT:
603 case sivSampleOffsetLatencySOFT:
604 /* Query only */
605 RETERR(AL_INVALID_OPERATION);
608 /* 1x int */
609 case AL_SOURCE_RELATIVE:
610 case AL_LOOPING:
611 case AL_SOURCE_STATE:
612 case AL_BYTE_OFFSET:
613 case AL_SAMPLE_OFFSET:
614 case sivSourceType:
615 case sivBuffersQueued:
616 case sivBuffersProcessed:
617 case AL_DIRECT_FILTER_GAINHF_AUTO:
618 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
619 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
620 case AL_DIRECT_CHANNELS_SOFT:
621 case AL_DISTANCE_MODEL:
622 CHECKVAL(*values <= INT_MAX && *values >= INT_MIN);
624 ivals[0] = (ALint)*values;
625 return SetSourceiv(Source, Context, (int)prop, ivals);
627 /* 1x uint */
628 case AL_BUFFER:
629 case AL_DIRECT_FILTER:
630 CHECKVAL(*values <= UINT_MAX && *values >= 0);
632 ivals[0] = (ALuint)*values;
633 return SetSourceiv(Source, Context, (int)prop, ivals);
635 /* 3x uint */
636 case AL_AUXILIARY_SEND_FILTER:
637 CHECKVAL(values[0] <= UINT_MAX && values[0] >= 0 &&
638 values[1] <= UINT_MAX && values[1] >= 0 &&
639 values[2] <= UINT_MAX && values[2] >= 0);
641 ivals[0] = (ALuint)values[0];
642 ivals[1] = (ALuint)values[1];
643 ivals[2] = (ALuint)values[2];
644 return SetSourceiv(Source, Context, (int)prop, ivals);
646 /* 1x float */
647 case AL_MAX_DISTANCE:
648 case AL_ROLLOFF_FACTOR:
649 case AL_CONE_INNER_ANGLE:
650 case AL_CONE_OUTER_ANGLE:
651 case AL_REFERENCE_DISTANCE:
652 case AL_SEC_OFFSET:
653 case sivDopplerFactor:
654 fvals[0] = (ALfloat)*values;
655 return SetSourcefv(Source, Context, (int)prop, fvals);
657 /* 3x float */
658 case AL_POSITION:
659 case AL_VELOCITY:
660 case AL_DIRECTION:
661 fvals[0] = (ALfloat)values[0];
662 fvals[1] = (ALfloat)values[1];
663 fvals[2] = (ALfloat)values[2];
664 return SetSourcefv(Source, Context, (int)prop, fvals);
667 ERR("Unexpected property: 0x%04x\n", prop);
668 RETERR(AL_INVALID_ENUM);
671 #undef CHECKVAL
674 static ALenum GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values)
676 ALdouble offsets[2];
677 ALdouble updateLen;
678 ALint ivals[3];
679 ALenum err;
681 switch(prop)
683 case AL_GAIN:
684 *values = Source->Gain;
685 return AL_NO_ERROR;
687 case AL_PITCH:
688 *values = Source->Pitch;
689 return AL_NO_ERROR;
691 case AL_MAX_DISTANCE:
692 *values = Source->MaxDistance;
693 return AL_NO_ERROR;
695 case AL_ROLLOFF_FACTOR:
696 *values = Source->RollOffFactor;
697 return AL_NO_ERROR;
699 case AL_REFERENCE_DISTANCE:
700 *values = Source->RefDistance;
701 return AL_NO_ERROR;
703 case AL_CONE_INNER_ANGLE:
704 *values = Source->InnerAngle;
705 return AL_NO_ERROR;
707 case AL_CONE_OUTER_ANGLE:
708 *values = Source->OuterAngle;
709 return AL_NO_ERROR;
711 case AL_MIN_GAIN:
712 *values = Source->MinGain;
713 return AL_NO_ERROR;
715 case AL_MAX_GAIN:
716 *values = Source->MaxGain;
717 return AL_NO_ERROR;
719 case AL_CONE_OUTER_GAIN:
720 *values = Source->OuterGain;
721 return AL_NO_ERROR;
723 case AL_SEC_OFFSET:
724 case AL_SAMPLE_OFFSET:
725 case AL_BYTE_OFFSET:
726 LockContext(Context);
727 updateLen = (ALdouble)Context->Device->UpdateSize /
728 Context->Device->Frequency;
729 GetSourceOffsets(Source, prop, offsets, updateLen);
730 UnlockContext(Context);
731 *values = offsets[0];
732 return AL_NO_ERROR;
734 case AL_CONE_OUTER_GAINHF:
735 *values = Source->OuterGainHF;
736 return AL_NO_ERROR;
738 case AL_AIR_ABSORPTION_FACTOR:
739 *values = Source->AirAbsorptionFactor;
740 return AL_NO_ERROR;
742 case AL_ROOM_ROLLOFF_FACTOR:
743 *values = Source->RoomRolloffFactor;
744 return AL_NO_ERROR;
746 case AL_DOPPLER_FACTOR:
747 *values = Source->DopplerFactor;
748 return AL_NO_ERROR;
750 case AL_SAMPLE_RW_OFFSETS_SOFT:
751 case AL_BYTE_RW_OFFSETS_SOFT:
752 LockContext(Context);
753 updateLen = (ALdouble)Context->Device->UpdateSize /
754 Context->Device->Frequency;
755 GetSourceOffsets(Source, prop, values, updateLen);
756 UnlockContext(Context);
757 return AL_NO_ERROR;
759 case AL_SEC_OFFSET_LATENCY_SOFT:
760 LockContext(Context);
761 values[0] = GetSourceSecOffset(Source);
762 values[1] = (ALdouble)ALCdevice_GetLatency(Context->Device) /
763 1000000000.0;
764 UnlockContext(Context);
765 return AL_NO_ERROR;
767 case AL_POSITION:
768 LockContext(Context);
769 values[0] = Source->Position[0];
770 values[1] = Source->Position[1];
771 values[2] = Source->Position[2];
772 UnlockContext(Context);
773 return AL_NO_ERROR;
775 case AL_VELOCITY:
776 LockContext(Context);
777 values[0] = Source->Velocity[0];
778 values[1] = Source->Velocity[1];
779 values[2] = Source->Velocity[2];
780 UnlockContext(Context);
781 return AL_NO_ERROR;
783 case AL_DIRECTION:
784 LockContext(Context);
785 values[0] = Source->Orientation[0];
786 values[1] = Source->Orientation[1];
787 values[2] = Source->Orientation[2];
788 UnlockContext(Context);
789 return AL_NO_ERROR;
791 case AL_SOURCE_RELATIVE:
792 case AL_LOOPING:
793 case AL_BUFFER:
794 case AL_SOURCE_STATE:
795 case AL_BUFFERS_QUEUED:
796 case AL_BUFFERS_PROCESSED:
797 case AL_SOURCE_TYPE:
798 case AL_DIRECT_FILTER_GAINHF_AUTO:
799 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
800 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
801 case AL_DIRECT_CHANNELS_SOFT:
802 case AL_DISTANCE_MODEL:
803 if((err=GetSourceiv(Source, Context, (int)prop, ivals)) == AL_NO_ERROR)
804 *values = (ALdouble)ivals[0];
805 return err;
808 ERR("Unexpected property: 0x%04x\n", prop);
809 RETERR(AL_INVALID_ENUM);
812 static ALenum GetSourceiv(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values)
814 ALbufferlistitem *BufferList;
815 ALdouble dvals[3];
816 ALenum err;
818 switch(prop)
820 case AL_SOURCE_RELATIVE:
821 *values = Source->HeadRelative;
822 return AL_NO_ERROR;
824 case AL_LOOPING:
825 *values = Source->Looping;
826 return AL_NO_ERROR;
828 case AL_BUFFER:
829 LockContext(Context);
830 BufferList = Source->queue;
831 if(Source->SourceType != AL_STATIC)
833 ALuint i = Source->BuffersPlayed;
834 while(i > 0)
836 BufferList = BufferList->next;
837 i--;
840 *values = ((BufferList && BufferList->buffer) ?
841 BufferList->buffer->id : 0);
842 UnlockContext(Context);
843 return AL_NO_ERROR;
845 case AL_SOURCE_STATE:
846 *values = Source->state;
847 return AL_NO_ERROR;
849 case AL_BUFFERS_QUEUED:
850 *values = Source->BuffersInQueue;
851 return AL_NO_ERROR;
853 case AL_BUFFERS_PROCESSED:
854 LockContext(Context);
855 if(Source->Looping || Source->SourceType != AL_STREAMING)
857 /* Buffers on a looping source are in a perpetual state of
858 * PENDING, so don't report any as PROCESSED */
859 *values = 0;
861 else
862 *values = Source->BuffersPlayed;
863 UnlockContext(Context);
864 return AL_NO_ERROR;
866 case AL_SOURCE_TYPE:
867 *values = Source->SourceType;
868 return AL_NO_ERROR;
870 case AL_DIRECT_FILTER_GAINHF_AUTO:
871 *values = Source->DryGainHFAuto;
872 return AL_NO_ERROR;
874 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
875 *values = Source->WetGainAuto;
876 return AL_NO_ERROR;
878 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
879 *values = Source->WetGainHFAuto;
880 return AL_NO_ERROR;
882 case AL_DIRECT_CHANNELS_SOFT:
883 *values = Source->DirectChannels;
884 return AL_NO_ERROR;
886 case AL_DISTANCE_MODEL:
887 *values = Source->DistanceModel;
888 return AL_NO_ERROR;
890 case AL_MAX_DISTANCE:
891 case AL_ROLLOFF_FACTOR:
892 case AL_REFERENCE_DISTANCE:
893 case AL_CONE_INNER_ANGLE:
894 case AL_CONE_OUTER_ANGLE:
895 case AL_SEC_OFFSET:
896 case AL_SAMPLE_OFFSET:
897 case AL_BYTE_OFFSET:
898 case AL_DOPPLER_FACTOR:
899 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
900 *values = (ALint)dvals[0];
901 return err;
903 case AL_SAMPLE_RW_OFFSETS_SOFT:
904 case AL_BYTE_RW_OFFSETS_SOFT:
905 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
907 values[0] = (ALint)dvals[0];
908 values[1] = (ALint)dvals[1];
910 return err;
912 case AL_POSITION:
913 case AL_VELOCITY:
914 case AL_DIRECTION:
915 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
917 values[0] = (ALint)dvals[0];
918 values[1] = (ALint)dvals[1];
919 values[2] = (ALint)dvals[2];
921 return err;
923 case sivSampleOffsetLatencySOFT:
924 /* i64 only */
925 break;
927 case sivDirectFilter:
928 case sivAuxSendFilter:
929 /* ??? */
930 break;
933 ERR("Unexpected property: 0x%04x\n", prop);
934 RETERR(AL_INVALID_ENUM);
937 static ALenum GetSourcei64v(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values)
939 ALdouble dvals[3];
940 ALint ivals[3];
941 ALenum err;
943 switch(prop)
945 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
946 LockContext(Context);
947 values[0] = GetSourceOffset(Source);
948 values[1] = ALCdevice_GetLatency(Context->Device);
949 UnlockContext(Context);
950 return AL_NO_ERROR;
952 case AL_MAX_DISTANCE:
953 case AL_ROLLOFF_FACTOR:
954 case AL_REFERENCE_DISTANCE:
955 case AL_CONE_INNER_ANGLE:
956 case AL_CONE_OUTER_ANGLE:
957 case AL_SEC_OFFSET:
958 case AL_SAMPLE_OFFSET:
959 case AL_BYTE_OFFSET:
960 case AL_DOPPLER_FACTOR:
961 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
962 *values = (ALint64)dvals[0];
963 return err;
965 case AL_SAMPLE_RW_OFFSETS_SOFT:
966 case AL_BYTE_RW_OFFSETS_SOFT:
967 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
969 values[0] = (ALint64)dvals[0];
970 values[1] = (ALint64)dvals[1];
972 return err;
974 case AL_POSITION:
975 case AL_VELOCITY:
976 case AL_DIRECTION:
977 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
979 values[0] = (ALint64)dvals[0];
980 values[1] = (ALint64)dvals[1];
981 values[2] = (ALint64)dvals[2];
983 return err;
985 case AL_SOURCE_RELATIVE:
986 case AL_LOOPING:
987 case AL_BUFFER:
988 case AL_SOURCE_STATE:
989 case AL_BUFFERS_QUEUED:
990 case AL_BUFFERS_PROCESSED:
991 case AL_SOURCE_TYPE:
992 case AL_DIRECT_FILTER_GAINHF_AUTO:
993 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
994 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
995 case AL_DIRECT_CHANNELS_SOFT:
996 case AL_DISTANCE_MODEL:
997 if((err=GetSourceiv(Source, Context, (int)prop, ivals)) == AL_NO_ERROR)
998 *values = ivals[0];
999 return err;
1001 /* ??? */
1002 case sivDirectFilter:
1003 case sivAuxSendFilter:
1004 break;
1007 ERR("Unexpected property: 0x%04x\n", prop);
1008 RETERR(AL_INVALID_ENUM);
1011 #undef RETERR
1014 AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
1016 ALCcontext *Context;
1017 ALsizei cur = 0;
1019 Context = GetContextRef();
1020 if(!Context) return;
1022 al_try
1024 ALenum err;
1026 CHECK_VALUE(Context, n >= 0);
1027 for(cur = 0;cur < n;cur++)
1029 ALsource *source = al_calloc(16, sizeof(ALsource));
1030 if(!source)
1031 al_throwerr(Context, AL_OUT_OF_MEMORY);
1032 InitSourceParams(source);
1034 err = NewThunkEntry(&source->id);
1035 if(err == AL_NO_ERROR)
1036 err = InsertUIntMapEntry(&Context->SourceMap, source->id, source);
1037 if(err != AL_NO_ERROR)
1039 FreeThunkEntry(source->id);
1040 memset(source, 0, sizeof(ALsource));
1041 al_free(source);
1043 al_throwerr(Context, err);
1046 sources[cur] = source->id;
1049 al_catchany()
1051 if(cur > 0)
1052 alDeleteSources(cur, sources);
1054 al_endtry;
1056 ALCcontext_DecRef(Context);
1060 AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
1062 ALCcontext *Context;
1064 Context = GetContextRef();
1065 if(!Context) return;
1067 al_try
1069 ALbufferlistitem *BufferList;
1070 ALsource *Source;
1071 ALsizei i, j;
1073 CHECK_VALUE(Context, n >= 0);
1075 /* Check that all Sources are valid */
1076 for(i = 0;i < n;i++)
1078 if(LookupSource(Context, sources[i]) == NULL)
1079 al_throwerr(Context, AL_INVALID_NAME);
1082 for(i = 0;i < n;i++)
1084 ALsource **srclist, **srclistend;
1086 if((Source=RemoveSource(Context, sources[i])) == NULL)
1087 continue;
1088 FreeThunkEntry(Source->id);
1090 LockContext(Context);
1091 srclist = Context->ActiveSources;
1092 srclistend = srclist + Context->ActiveSourceCount;
1093 while(srclist != srclistend)
1095 if(*srclist == Source)
1097 Context->ActiveSourceCount--;
1098 *srclist = *(--srclistend);
1099 break;
1101 srclist++;
1103 UnlockContext(Context);
1105 while(Source->queue != NULL)
1107 BufferList = Source->queue;
1108 Source->queue = BufferList->next;
1110 if(BufferList->buffer != NULL)
1111 DecrementRef(&BufferList->buffer->ref);
1112 free(BufferList);
1115 for(j = 0;j < MAX_SENDS;++j)
1117 if(Source->Send[j].Slot)
1118 DecrementRef(&Source->Send[j].Slot->ref);
1119 Source->Send[j].Slot = NULL;
1122 memset(Source, 0, sizeof(*Source));
1123 al_free(Source);
1126 al_endtry;
1128 ALCcontext_DecRef(Context);
1132 AL_API ALboolean AL_APIENTRY alIsSource(ALuint source)
1134 ALCcontext *Context;
1135 ALboolean result;
1137 Context = GetContextRef();
1138 if(!Context) return AL_FALSE;
1140 result = (LookupSource(Context, source) ? AL_TRUE : AL_FALSE);
1142 ALCcontext_DecRef(Context);
1144 return result;
1148 AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value)
1150 ALCcontext *Context;
1151 ALsource *Source;
1153 Context = GetContextRef();
1154 if(!Context) return;
1156 if((Source=LookupSource(Context, source)) == NULL)
1157 alSetError(Context, AL_INVALID_NAME);
1158 else switch(param)
1160 case AL_PITCH:
1161 case AL_CONE_INNER_ANGLE:
1162 case AL_CONE_OUTER_ANGLE:
1163 case AL_GAIN:
1164 case AL_MAX_DISTANCE:
1165 case AL_ROLLOFF_FACTOR:
1166 case AL_REFERENCE_DISTANCE:
1167 case AL_MIN_GAIN:
1168 case AL_MAX_GAIN:
1169 case AL_CONE_OUTER_GAIN:
1170 case AL_CONE_OUTER_GAINHF:
1171 case AL_AIR_ABSORPTION_FACTOR:
1172 case AL_ROOM_ROLLOFF_FACTOR:
1173 case AL_DOPPLER_FACTOR:
1174 case AL_SEC_OFFSET:
1175 case AL_SAMPLE_OFFSET:
1176 case AL_BYTE_OFFSET:
1177 SetSourcefv(Source, Context, param, &value);
1178 break;
1180 default:
1181 alSetError(Context, AL_INVALID_ENUM);
1184 ALCcontext_DecRef(Context);
1187 AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
1189 ALCcontext *Context;
1190 ALsource *Source;
1191 ALfloat fvals[3];
1193 Context = GetContextRef();
1194 if(!Context) return;
1196 if((Source=LookupSource(Context, source)) == NULL)
1197 alSetError(Context, AL_INVALID_NAME);
1198 else switch(param)
1200 case AL_POSITION:
1201 case AL_VELOCITY:
1202 case AL_DIRECTION:
1203 fvals[0] = value1;
1204 fvals[1] = value2;
1205 fvals[2] = value3;
1206 SetSourcefv(Source, Context, param, fvals);
1207 break;
1209 default:
1210 alSetError(Context, AL_INVALID_ENUM);
1213 ALCcontext_DecRef(Context);
1216 AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values)
1218 ALCcontext *Context;
1219 ALsource *Source;
1221 Context = GetContextRef();
1222 if(!Context) return;
1224 if((Source=LookupSource(Context, source)) == NULL)
1225 alSetError(Context, AL_INVALID_NAME);
1226 else if(!values)
1227 alSetError(Context, AL_INVALID_VALUE);
1228 else switch(param)
1230 case AL_PITCH:
1231 case AL_CONE_INNER_ANGLE:
1232 case AL_CONE_OUTER_ANGLE:
1233 case AL_GAIN:
1234 case AL_MAX_DISTANCE:
1235 case AL_ROLLOFF_FACTOR:
1236 case AL_REFERENCE_DISTANCE:
1237 case AL_MIN_GAIN:
1238 case AL_MAX_GAIN:
1239 case AL_CONE_OUTER_GAIN:
1240 case AL_CONE_OUTER_GAINHF:
1241 case AL_SEC_OFFSET:
1242 case AL_SAMPLE_OFFSET:
1243 case AL_BYTE_OFFSET:
1244 case AL_AIR_ABSORPTION_FACTOR:
1245 case AL_ROOM_ROLLOFF_FACTOR:
1247 case AL_POSITION:
1248 case AL_VELOCITY:
1249 case AL_DIRECTION:
1250 SetSourcefv(Source, Context, param, values);
1251 break;
1253 default:
1254 alSetError(Context, AL_INVALID_ENUM);
1257 ALCcontext_DecRef(Context);
1261 AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value)
1263 ALCcontext *Context;
1264 ALsource *Source;
1265 ALfloat fval;
1267 Context = GetContextRef();
1268 if(!Context) return;
1270 if((Source=LookupSource(Context, source)) == NULL)
1271 alSetError(Context, AL_INVALID_NAME);
1272 else switch(param)
1274 case AL_PITCH:
1275 case AL_CONE_INNER_ANGLE:
1276 case AL_CONE_OUTER_ANGLE:
1277 case AL_GAIN:
1278 case AL_MAX_DISTANCE:
1279 case AL_ROLLOFF_FACTOR:
1280 case AL_REFERENCE_DISTANCE:
1281 case AL_MIN_GAIN:
1282 case AL_MAX_GAIN:
1283 case AL_CONE_OUTER_GAIN:
1284 case AL_CONE_OUTER_GAINHF:
1285 case AL_AIR_ABSORPTION_FACTOR:
1286 case AL_ROOM_ROLLOFF_FACTOR:
1287 case AL_DOPPLER_FACTOR:
1288 case AL_SEC_OFFSET:
1289 case AL_SAMPLE_OFFSET:
1290 case AL_BYTE_OFFSET:
1291 fval = (ALfloat)value;
1292 SetSourcefv(Source, Context, param, &fval);
1293 break;
1295 default:
1296 alSetError(Context, AL_INVALID_ENUM);
1299 ALCcontext_DecRef(Context);
1302 AL_API ALvoid AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3)
1304 ALCcontext *Context;
1305 ALsource *Source;
1306 ALfloat fvals[3];
1308 Context = GetContextRef();
1309 if(!Context) return;
1311 if((Source=LookupSource(Context, source)) == NULL)
1312 alSetError(Context, AL_INVALID_NAME);
1313 else switch(param)
1315 case AL_POSITION:
1316 case AL_VELOCITY:
1317 case AL_DIRECTION:
1318 fvals[0] = (ALfloat)value1;
1319 fvals[1] = (ALfloat)value2;
1320 fvals[2] = (ALfloat)value3;
1321 SetSourcefv(Source, Context, param, fvals);
1322 break;
1324 default:
1325 alSetError(Context, AL_INVALID_ENUM);
1328 ALCcontext_DecRef(Context);
1331 AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values)
1333 ALCcontext *Context;
1334 ALsource *Source;
1335 ALfloat fvals[3];
1337 Context = GetContextRef();
1338 if(!Context) return;
1340 if((Source=LookupSource(Context, source)) == NULL)
1341 alSetError(Context, AL_INVALID_NAME);
1342 else if(!values)
1343 alSetError(Context, AL_INVALID_VALUE);
1344 else switch(param)
1346 case AL_PITCH:
1347 case AL_CONE_INNER_ANGLE:
1348 case AL_CONE_OUTER_ANGLE:
1349 case AL_GAIN:
1350 case AL_MAX_DISTANCE:
1351 case AL_ROLLOFF_FACTOR:
1352 case AL_REFERENCE_DISTANCE:
1353 case AL_MIN_GAIN:
1354 case AL_MAX_GAIN:
1355 case AL_CONE_OUTER_GAIN:
1356 case AL_CONE_OUTER_GAINHF:
1357 case AL_SEC_OFFSET:
1358 case AL_SAMPLE_OFFSET:
1359 case AL_BYTE_OFFSET:
1360 case AL_AIR_ABSORPTION_FACTOR:
1361 case AL_ROOM_ROLLOFF_FACTOR:
1362 fvals[0] = (ALfloat)values[0];
1363 SetSourcefv(Source, Context, param, fvals);
1364 break;
1366 case AL_SEC_OFFSET_LATENCY_SOFT:
1367 fvals[0] = (ALfloat)values[0];
1368 fvals[1] = (ALfloat)values[1];
1369 SetSourcefv(Source, Context, param, fvals);
1370 break;
1372 case AL_POSITION:
1373 case AL_VELOCITY:
1374 case AL_DIRECTION:
1375 fvals[0] = (ALfloat)values[0];
1376 fvals[1] = (ALfloat)values[1];
1377 fvals[2] = (ALfloat)values[2];
1378 SetSourcefv(Source, Context, param, fvals);
1379 break;
1381 default:
1382 alSetError(Context, AL_INVALID_ENUM);
1385 ALCcontext_DecRef(Context);
1389 AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value)
1391 ALCcontext *Context;
1392 ALsource *Source;
1394 Context = GetContextRef();
1395 if(!Context) return;
1397 if((Source=LookupSource(Context, source)) == NULL)
1398 alSetError(Context, AL_INVALID_NAME);
1399 else switch(param)
1401 case AL_MAX_DISTANCE:
1402 case AL_ROLLOFF_FACTOR:
1403 case AL_CONE_INNER_ANGLE:
1404 case AL_CONE_OUTER_ANGLE:
1405 case AL_REFERENCE_DISTANCE:
1406 case AL_SOURCE_RELATIVE:
1407 case AL_LOOPING:
1408 case AL_BUFFER:
1409 case AL_SOURCE_STATE:
1410 case AL_SEC_OFFSET:
1411 case AL_SAMPLE_OFFSET:
1412 case AL_BYTE_OFFSET:
1413 case AL_DIRECT_FILTER:
1414 case AL_DIRECT_FILTER_GAINHF_AUTO:
1415 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1416 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1417 case AL_DIRECT_CHANNELS_SOFT:
1418 case AL_DISTANCE_MODEL:
1419 SetSourceiv(Source, Context, param, &value);
1420 break;
1422 default:
1423 alSetError(Context, AL_INVALID_ENUM);
1426 ALCcontext_DecRef(Context);
1429 AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3)
1431 ALCcontext *Context;
1432 ALsource *Source;
1433 ALint ivals[3];
1435 Context = GetContextRef();
1436 if(!Context) return;
1438 if((Source=LookupSource(Context, source)) == NULL)
1439 alSetError(Context, AL_INVALID_NAME);
1440 else switch(param)
1442 case AL_POSITION:
1443 case AL_VELOCITY:
1444 case AL_DIRECTION:
1445 case AL_AUXILIARY_SEND_FILTER:
1446 ivals[0] = value1;
1447 ivals[1] = value2;
1448 ivals[2] = value3;
1449 SetSourceiv(Source, Context, param, ivals);
1450 break;
1452 default:
1453 alSetError(Context, AL_INVALID_ENUM);
1456 ALCcontext_DecRef(Context);
1459 AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values)
1461 ALCcontext *Context;
1462 ALsource *Source;
1464 Context = GetContextRef();
1465 if(!Context) return;
1467 if((Source=LookupSource(Context, source)) == NULL)
1468 alSetError(Context, AL_INVALID_NAME);
1469 else if(!values)
1470 alSetError(Context, AL_INVALID_VALUE);
1471 else switch(param)
1473 case AL_SOURCE_RELATIVE:
1474 case AL_CONE_INNER_ANGLE:
1475 case AL_CONE_OUTER_ANGLE:
1476 case AL_LOOPING:
1477 case AL_BUFFER:
1478 case AL_SOURCE_STATE:
1479 case AL_SEC_OFFSET:
1480 case AL_SAMPLE_OFFSET:
1481 case AL_BYTE_OFFSET:
1482 case AL_MAX_DISTANCE:
1483 case AL_ROLLOFF_FACTOR:
1484 case AL_REFERENCE_DISTANCE:
1485 case AL_DIRECT_FILTER:
1486 case AL_DIRECT_FILTER_GAINHF_AUTO:
1487 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1488 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1489 case AL_DISTANCE_MODEL:
1490 case AL_DIRECT_CHANNELS_SOFT:
1492 case AL_POSITION:
1493 case AL_VELOCITY:
1494 case AL_DIRECTION:
1495 case AL_AUXILIARY_SEND_FILTER:
1496 SetSourceiv(Source, Context, param, values);
1497 break;
1499 default:
1500 alSetError(Context, AL_INVALID_ENUM);
1503 ALCcontext_DecRef(Context);
1507 AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value)
1509 ALCcontext *Context;
1510 ALsource *Source;
1512 Context = GetContextRef();
1513 if(!Context) return;
1515 if((Source=LookupSource(Context, source)) == NULL)
1516 alSetError(Context, AL_INVALID_NAME);
1517 else switch(param)
1519 case AL_MAX_DISTANCE:
1520 case AL_ROLLOFF_FACTOR:
1521 case AL_CONE_INNER_ANGLE:
1522 case AL_CONE_OUTER_ANGLE:
1523 case AL_REFERENCE_DISTANCE:
1524 case AL_SOURCE_RELATIVE:
1525 case AL_LOOPING:
1526 case AL_SOURCE_STATE:
1527 case AL_SEC_OFFSET:
1528 case AL_SAMPLE_OFFSET:
1529 case AL_BYTE_OFFSET:
1530 case AL_DIRECT_FILTER_GAINHF_AUTO:
1531 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1532 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1533 case AL_DIRECT_CHANNELS_SOFT:
1534 case AL_DISTANCE_MODEL:
1535 case AL_BUFFER:
1536 case AL_DIRECT_FILTER:
1537 SetSourcei64v(Source, Context, param, &value);
1538 break;
1540 default:
1541 alSetError(Context, AL_INVALID_ENUM);
1544 ALCcontext_DecRef(Context);
1547 AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3)
1549 ALCcontext *Context;
1550 ALsource *Source;
1551 ALint64SOFT i64vals[3];
1553 Context = GetContextRef();
1554 if(!Context) return;
1556 if((Source=LookupSource(Context, source)) == NULL)
1557 alSetError(Context, AL_INVALID_NAME);
1558 else switch(param)
1560 case AL_POSITION:
1561 case AL_VELOCITY:
1562 case AL_DIRECTION:
1563 case AL_AUXILIARY_SEND_FILTER:
1564 i64vals[0] = value1;
1565 i64vals[1] = value2;
1566 i64vals[2] = value3;
1567 SetSourcei64v(Source, Context, param, i64vals);
1568 break;
1570 default:
1571 alSetError(Context, AL_INVALID_ENUM);
1574 ALCcontext_DecRef(Context);
1577 AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values)
1579 ALCcontext *Context;
1580 ALsource *Source;
1582 Context = GetContextRef();
1583 if(!Context) return;
1585 if((Source=LookupSource(Context, source)) == NULL)
1586 alSetError(Context, AL_INVALID_NAME);
1587 else if(!values)
1588 alSetError(Context, AL_INVALID_VALUE);
1589 else switch(param)
1591 case AL_SOURCE_RELATIVE:
1592 case AL_CONE_INNER_ANGLE:
1593 case AL_CONE_OUTER_ANGLE:
1594 case AL_LOOPING:
1595 case AL_SOURCE_STATE:
1596 case AL_SEC_OFFSET:
1597 case AL_SAMPLE_OFFSET:
1598 case AL_BYTE_OFFSET:
1599 case AL_MAX_DISTANCE:
1600 case AL_ROLLOFF_FACTOR:
1601 case AL_REFERENCE_DISTANCE:
1602 case AL_DIRECT_FILTER_GAINHF_AUTO:
1603 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1604 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1605 case AL_DISTANCE_MODEL:
1606 case AL_DIRECT_CHANNELS_SOFT:
1607 case AL_BUFFER:
1608 case AL_DIRECT_FILTER:
1610 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
1612 case AL_POSITION:
1613 case AL_VELOCITY:
1614 case AL_DIRECTION:
1615 case AL_AUXILIARY_SEND_FILTER:
1616 SetSourcei64v(Source, Context, param, values);
1617 break;
1619 default:
1620 alSetError(Context, AL_INVALID_ENUM);
1623 ALCcontext_DecRef(Context);
1627 AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value)
1629 ALCcontext *Context;
1630 ALsource *Source;
1631 ALdouble dval;
1633 Context = GetContextRef();
1634 if(!Context) return;
1636 if((Source=LookupSource(Context, source)) == NULL)
1637 alSetError(Context, AL_INVALID_NAME);
1638 else if(!value)
1639 alSetError(Context, AL_INVALID_VALUE);
1640 else switch(param)
1642 case AL_PITCH:
1643 case AL_GAIN:
1644 case AL_MIN_GAIN:
1645 case AL_MAX_GAIN:
1646 case AL_MAX_DISTANCE:
1647 case AL_ROLLOFF_FACTOR:
1648 case AL_CONE_OUTER_GAIN:
1649 case AL_CONE_OUTER_GAINHF:
1650 case AL_SEC_OFFSET:
1651 case AL_SAMPLE_OFFSET:
1652 case AL_BYTE_OFFSET:
1653 case AL_CONE_INNER_ANGLE:
1654 case AL_CONE_OUTER_ANGLE:
1655 case AL_REFERENCE_DISTANCE:
1656 case AL_AIR_ABSORPTION_FACTOR:
1657 case AL_ROOM_ROLLOFF_FACTOR:
1658 case AL_DOPPLER_FACTOR:
1659 if(GetSourcedv(Source, Context, param, &dval) == AL_NO_ERROR)
1660 *value = (ALfloat)dval;
1661 break;
1663 default:
1664 alSetError(Context, AL_INVALID_ENUM);
1667 ALCcontext_DecRef(Context);
1671 AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
1673 ALCcontext *Context;
1674 ALsource *Source;
1675 ALdouble dvals[3];
1677 Context = GetContextRef();
1678 if(!Context) return;
1680 if((Source=LookupSource(Context, source)) == NULL)
1681 alSetError(Context, AL_INVALID_NAME);
1682 else if(!(value1 && value2 && value3))
1683 alSetError(Context, AL_INVALID_VALUE);
1684 else switch(param)
1686 case AL_POSITION:
1687 case AL_VELOCITY:
1688 case AL_DIRECTION:
1689 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1691 *value1 = (ALfloat)dvals[0];
1692 *value2 = (ALfloat)dvals[1];
1693 *value3 = (ALfloat)dvals[2];
1695 break;
1697 default:
1698 alSetError(Context, AL_INVALID_ENUM);
1701 ALCcontext_DecRef(Context);
1705 AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values)
1707 ALCcontext *Context;
1708 ALsource *Source;
1709 ALdouble dvals[2];
1711 switch(param)
1713 case AL_PITCH:
1714 case AL_GAIN:
1715 case AL_MIN_GAIN:
1716 case AL_MAX_GAIN:
1717 case AL_MAX_DISTANCE:
1718 case AL_ROLLOFF_FACTOR:
1719 case AL_DOPPLER_FACTOR:
1720 case AL_CONE_OUTER_GAIN:
1721 case AL_SEC_OFFSET:
1722 case AL_SAMPLE_OFFSET:
1723 case AL_BYTE_OFFSET:
1724 case AL_CONE_INNER_ANGLE:
1725 case AL_CONE_OUTER_ANGLE:
1726 case AL_REFERENCE_DISTANCE:
1727 case AL_CONE_OUTER_GAINHF:
1728 case AL_AIR_ABSORPTION_FACTOR:
1729 case AL_ROOM_ROLLOFF_FACTOR:
1730 alGetSourcef(source, param, values);
1731 return;
1733 case AL_POSITION:
1734 case AL_VELOCITY:
1735 case AL_DIRECTION:
1736 alGetSource3f(source, param, values+0, values+1, values+2);
1737 return;
1740 Context = GetContextRef();
1741 if(!Context) return;
1743 if((Source=LookupSource(Context, source)) == NULL)
1744 alSetError(Context, AL_INVALID_NAME);
1745 else if(!values)
1746 alSetError(Context, AL_INVALID_VALUE);
1747 else switch(param)
1749 case AL_SAMPLE_RW_OFFSETS_SOFT:
1750 case AL_BYTE_RW_OFFSETS_SOFT:
1751 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1753 values[0] = (ALfloat)dvals[0];
1754 values[1] = (ALfloat)dvals[1];
1756 break;
1758 default:
1759 alSetError(Context, AL_INVALID_ENUM);
1762 ALCcontext_DecRef(Context);
1766 AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value)
1768 ALCcontext *Context;
1769 ALsource *Source;
1771 Context = GetContextRef();
1772 if(!Context) return;
1774 if((Source=LookupSource(Context, source)) == NULL)
1775 alSetError(Context, AL_INVALID_NAME);
1776 else if(!value)
1777 alSetError(Context, AL_INVALID_VALUE);
1778 else switch(param)
1780 case AL_PITCH:
1781 case AL_GAIN:
1782 case AL_MIN_GAIN:
1783 case AL_MAX_GAIN:
1784 case AL_MAX_DISTANCE:
1785 case AL_ROLLOFF_FACTOR:
1786 case AL_CONE_OUTER_GAIN:
1787 case AL_CONE_OUTER_GAINHF:
1788 case AL_SEC_OFFSET:
1789 case AL_SAMPLE_OFFSET:
1790 case AL_BYTE_OFFSET:
1791 case AL_CONE_INNER_ANGLE:
1792 case AL_CONE_OUTER_ANGLE:
1793 case AL_REFERENCE_DISTANCE:
1794 case AL_AIR_ABSORPTION_FACTOR:
1795 case AL_ROOM_ROLLOFF_FACTOR:
1796 case AL_DOPPLER_FACTOR:
1797 GetSourcedv(Source, Context, param, value);
1798 break;
1800 default:
1801 alSetError(Context, AL_INVALID_ENUM);
1804 ALCcontext_DecRef(Context);
1807 AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3)
1809 ALCcontext *Context;
1810 ALsource *Source;
1811 ALdouble dvals[3];
1813 Context = GetContextRef();
1814 if(!Context) return;
1816 if((Source=LookupSource(Context, source)) == NULL)
1817 alSetError(Context, AL_INVALID_NAME);
1818 else if(!(value1 && value2 && value3))
1819 alSetError(Context, AL_INVALID_VALUE);
1820 else switch(param)
1822 case AL_POSITION:
1823 case AL_VELOCITY:
1824 case AL_DIRECTION:
1825 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1827 *value1 = dvals[0];
1828 *value2 = dvals[1];
1829 *value3 = dvals[2];
1831 break;
1833 default:
1834 alSetError(Context, AL_INVALID_ENUM);
1837 ALCcontext_DecRef(Context);
1840 AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values)
1842 ALCcontext *Context;
1843 ALsource *Source;
1845 Context = GetContextRef();
1846 if(!Context) return;
1848 if((Source=LookupSource(Context, source)) == NULL)
1849 alSetError(Context, AL_INVALID_NAME);
1850 else if(!values)
1851 alSetError(Context, AL_INVALID_VALUE);
1852 else switch(param)
1854 case AL_PITCH:
1855 case AL_GAIN:
1856 case AL_MIN_GAIN:
1857 case AL_MAX_GAIN:
1858 case AL_MAX_DISTANCE:
1859 case AL_ROLLOFF_FACTOR:
1860 case AL_DOPPLER_FACTOR:
1861 case AL_CONE_OUTER_GAIN:
1862 case AL_SEC_OFFSET:
1863 case AL_SAMPLE_OFFSET:
1864 case AL_BYTE_OFFSET:
1865 case AL_CONE_INNER_ANGLE:
1866 case AL_CONE_OUTER_ANGLE:
1867 case AL_REFERENCE_DISTANCE:
1868 case AL_CONE_OUTER_GAINHF:
1869 case AL_AIR_ABSORPTION_FACTOR:
1870 case AL_ROOM_ROLLOFF_FACTOR:
1872 case AL_SAMPLE_RW_OFFSETS_SOFT:
1873 case AL_BYTE_RW_OFFSETS_SOFT:
1874 case AL_SEC_OFFSET_LATENCY_SOFT:
1876 case AL_POSITION:
1877 case AL_VELOCITY:
1878 case AL_DIRECTION:
1879 GetSourcedv(Source, Context, param, values);
1880 break;
1882 default:
1883 alSetError(Context, AL_INVALID_ENUM);
1886 ALCcontext_DecRef(Context);
1890 AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value)
1892 ALCcontext *Context;
1893 ALsource *Source;
1895 Context = GetContextRef();
1896 if(!Context) return;
1898 if((Source=LookupSource(Context, source)) == NULL)
1899 alSetError(Context, AL_INVALID_NAME);
1900 else if(!value)
1901 alSetError(Context, AL_INVALID_VALUE);
1902 else switch(param)
1904 case AL_MAX_DISTANCE:
1905 case AL_ROLLOFF_FACTOR:
1906 case AL_REFERENCE_DISTANCE:
1907 case AL_SOURCE_RELATIVE:
1908 case AL_CONE_INNER_ANGLE:
1909 case AL_CONE_OUTER_ANGLE:
1910 case AL_LOOPING:
1911 case AL_BUFFER:
1912 case AL_SOURCE_STATE:
1913 case AL_BUFFERS_QUEUED:
1914 case AL_BUFFERS_PROCESSED:
1915 case AL_SOURCE_TYPE:
1916 case AL_SEC_OFFSET:
1917 case AL_SAMPLE_OFFSET:
1918 case AL_BYTE_OFFSET:
1919 case AL_DIRECT_FILTER_GAINHF_AUTO:
1920 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1921 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1922 case AL_DOPPLER_FACTOR:
1923 case AL_DIRECT_CHANNELS_SOFT:
1924 case AL_DISTANCE_MODEL:
1925 GetSourceiv(Source, Context, param, value);
1926 break;
1928 default:
1929 alSetError(Context, AL_INVALID_ENUM);
1932 ALCcontext_DecRef(Context);
1936 AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3)
1938 ALCcontext *Context;
1939 ALsource *Source;
1940 ALint ivals[3];
1942 Context = GetContextRef();
1943 if(!Context) return;
1945 if((Source=LookupSource(Context, source)) == NULL)
1946 alSetError(Context, AL_INVALID_NAME);
1947 else if(!(value1 && value2 && value3))
1948 alSetError(Context, AL_INVALID_VALUE);
1949 else switch(param)
1951 case AL_POSITION:
1952 case AL_VELOCITY:
1953 case AL_DIRECTION:
1954 if(GetSourceiv(Source, Context, param, ivals) == AL_NO_ERROR)
1956 *value1 = ivals[0];
1957 *value2 = ivals[1];
1958 *value3 = ivals[2];
1960 break;
1962 default:
1963 alSetError(Context, AL_INVALID_ENUM);
1966 ALCcontext_DecRef(Context);
1970 AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values)
1972 ALCcontext *Context;
1973 ALsource *Source;
1975 Context = GetContextRef();
1976 if(!Context) return;
1978 if((Source=LookupSource(Context, source)) == NULL)
1979 alSetError(Context, AL_INVALID_NAME);
1980 else if(!values)
1981 alSetError(Context, AL_INVALID_VALUE);
1982 else switch(param)
1984 case AL_SOURCE_RELATIVE:
1985 case AL_CONE_INNER_ANGLE:
1986 case AL_CONE_OUTER_ANGLE:
1987 case AL_LOOPING:
1988 case AL_BUFFER:
1989 case AL_SOURCE_STATE:
1990 case AL_BUFFERS_QUEUED:
1991 case AL_BUFFERS_PROCESSED:
1992 case AL_SEC_OFFSET:
1993 case AL_SAMPLE_OFFSET:
1994 case AL_BYTE_OFFSET:
1995 case AL_MAX_DISTANCE:
1996 case AL_ROLLOFF_FACTOR:
1997 case AL_DOPPLER_FACTOR:
1998 case AL_REFERENCE_DISTANCE:
1999 case AL_SOURCE_TYPE:
2000 case AL_DIRECT_FILTER:
2001 case AL_DIRECT_FILTER_GAINHF_AUTO:
2002 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
2003 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
2004 case AL_DISTANCE_MODEL:
2005 case AL_DIRECT_CHANNELS_SOFT:
2007 case AL_SAMPLE_RW_OFFSETS_SOFT:
2008 case AL_BYTE_RW_OFFSETS_SOFT:
2010 case AL_POSITION:
2011 case AL_VELOCITY:
2012 case AL_DIRECTION:
2013 GetSourceiv(Source, Context, param, values);
2014 break;
2016 default:
2017 alSetError(Context, AL_INVALID_ENUM);
2020 ALCcontext_DecRef(Context);
2024 AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value)
2026 ALCcontext *Context;
2027 ALsource *Source;
2029 Context = GetContextRef();
2030 if(!Context) return;
2032 if((Source=LookupSource(Context, source)) == NULL)
2033 alSetError(Context, AL_INVALID_NAME);
2034 else if(!value)
2035 alSetError(Context, AL_INVALID_VALUE);
2036 else switch(param)
2038 case AL_MAX_DISTANCE:
2039 case AL_ROLLOFF_FACTOR:
2040 case AL_REFERENCE_DISTANCE:
2041 case AL_SOURCE_RELATIVE:
2042 case AL_CONE_INNER_ANGLE:
2043 case AL_CONE_OUTER_ANGLE:
2044 case AL_LOOPING:
2045 case AL_BUFFER:
2046 case AL_SOURCE_STATE:
2047 case AL_BUFFERS_QUEUED:
2048 case AL_BUFFERS_PROCESSED:
2049 case AL_SOURCE_TYPE:
2050 case AL_SEC_OFFSET:
2051 case AL_SAMPLE_OFFSET:
2052 case AL_BYTE_OFFSET:
2053 case AL_DIRECT_FILTER_GAINHF_AUTO:
2054 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
2055 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
2056 case AL_DOPPLER_FACTOR:
2057 case AL_DIRECT_CHANNELS_SOFT:
2058 case AL_DISTANCE_MODEL:
2059 GetSourcei64v(Source, Context, param, value);
2060 break;
2062 default:
2063 alSetError(Context, AL_INVALID_ENUM);
2066 ALCcontext_DecRef(Context);
2069 AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3)
2071 ALCcontext *Context;
2072 ALsource *Source;
2073 ALint64 i64vals[3];
2075 Context = GetContextRef();
2076 if(!Context) return;
2078 if((Source=LookupSource(Context, source)) == NULL)
2079 alSetError(Context, AL_INVALID_NAME);
2080 else if(!(value1 && value2 && value3))
2081 alSetError(Context, AL_INVALID_VALUE);
2082 else switch(param)
2084 case AL_POSITION:
2085 case AL_VELOCITY:
2086 case AL_DIRECTION:
2087 if(GetSourcei64v(Source, Context, param, i64vals) == AL_NO_ERROR)
2089 *value1 = i64vals[0];
2090 *value2 = i64vals[1];
2091 *value3 = i64vals[2];
2093 break;
2095 default:
2096 alSetError(Context, AL_INVALID_ENUM);
2099 ALCcontext_DecRef(Context);
2102 AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values)
2104 ALCcontext *Context;
2105 ALsource *Source;
2107 Context = GetContextRef();
2108 if(!Context) return;
2110 if((Source=LookupSource(Context, source)) == NULL)
2111 alSetError(Context, AL_INVALID_NAME);
2112 else if(!values)
2113 alSetError(Context, AL_INVALID_VALUE);
2114 else switch(param)
2116 case AL_MAX_DISTANCE:
2117 case AL_ROLLOFF_FACTOR:
2118 case AL_REFERENCE_DISTANCE:
2119 case AL_SOURCE_RELATIVE:
2120 case AL_CONE_INNER_ANGLE:
2121 case AL_CONE_OUTER_ANGLE:
2122 case AL_LOOPING:
2123 case AL_BUFFER:
2124 case AL_SOURCE_STATE:
2125 case AL_BUFFERS_QUEUED:
2126 case AL_BUFFERS_PROCESSED:
2127 case AL_SOURCE_TYPE:
2128 case AL_SEC_OFFSET:
2129 case AL_SAMPLE_OFFSET:
2130 case AL_BYTE_OFFSET:
2131 case AL_DIRECT_FILTER_GAINHF_AUTO:
2132 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
2133 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
2134 case AL_DOPPLER_FACTOR:
2135 case AL_DIRECT_CHANNELS_SOFT:
2136 case AL_DISTANCE_MODEL:
2138 case AL_SAMPLE_RW_OFFSETS_SOFT:
2139 case AL_BYTE_RW_OFFSETS_SOFT:
2140 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
2142 case AL_POSITION:
2143 case AL_VELOCITY:
2144 case AL_DIRECTION:
2145 GetSourcei64v(Source, Context, param, values);
2146 break;
2148 default:
2149 alSetError(Context, AL_INVALID_ENUM);
2152 ALCcontext_DecRef(Context);
2156 AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint source)
2158 alSourcePlayv(1, &source);
2160 AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
2162 ALCcontext *Context;
2163 ALsource *Source;
2164 ALsizei i;
2166 Context = GetContextRef();
2167 if(!Context) return;
2169 al_try
2171 CHECK_VALUE(Context, n >= 0);
2172 for(i = 0;i < n;i++)
2174 if(!LookupSource(Context, sources[i]))
2175 al_throwerr(Context, AL_INVALID_NAME);
2178 LockContext(Context);
2179 while(Context->MaxActiveSources-Context->ActiveSourceCount < n)
2181 void *temp = NULL;
2182 ALsizei newcount;
2184 newcount = Context->MaxActiveSources << 1;
2185 if(newcount > 0)
2186 temp = realloc(Context->ActiveSources,
2187 sizeof(*Context->ActiveSources) * newcount);
2188 if(!temp)
2190 UnlockContext(Context);
2191 al_throwerr(Context, AL_OUT_OF_MEMORY);
2194 Context->ActiveSources = temp;
2195 Context->MaxActiveSources = newcount;
2198 for(i = 0;i < n;i++)
2200 Source = LookupSource(Context, sources[i]);
2201 if(Context->DeferUpdates) Source->new_state = AL_PLAYING;
2202 else SetSourceState(Source, Context, AL_PLAYING);
2204 UnlockContext(Context);
2206 al_endtry;
2208 ALCcontext_DecRef(Context);
2211 AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source)
2213 alSourcePausev(1, &source);
2215 AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
2217 ALCcontext *Context;
2218 ALsource *Source;
2219 ALsizei i;
2221 Context = GetContextRef();
2222 if(!Context) return;
2224 al_try
2226 CHECK_VALUE(Context, n >= 0);
2227 for(i = 0;i < n;i++)
2229 if(!LookupSource(Context, sources[i]))
2230 al_throwerr(Context, AL_INVALID_NAME);
2233 LockContext(Context);
2234 for(i = 0;i < n;i++)
2236 Source = LookupSource(Context, sources[i]);
2237 if(Context->DeferUpdates) Source->new_state = AL_PAUSED;
2238 else SetSourceState(Source, Context, AL_PAUSED);
2240 UnlockContext(Context);
2242 al_endtry;
2244 ALCcontext_DecRef(Context);
2247 AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source)
2249 alSourceStopv(1, &source);
2251 AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
2253 ALCcontext *Context;
2254 ALsource *Source;
2255 ALsizei i;
2257 Context = GetContextRef();
2258 if(!Context) return;
2260 al_try
2262 CHECK_VALUE(Context, n >= 0);
2263 for(i = 0;i < n;i++)
2265 if(!LookupSource(Context, sources[i]))
2266 al_throwerr(Context, AL_INVALID_NAME);
2269 LockContext(Context);
2270 for(i = 0;i < n;i++)
2272 Source = LookupSource(Context, sources[i]);
2273 Source->new_state = AL_NONE;
2274 SetSourceState(Source, Context, AL_STOPPED);
2276 UnlockContext(Context);
2278 al_endtry;
2280 ALCcontext_DecRef(Context);
2283 AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source)
2285 alSourceRewindv(1, &source);
2287 AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
2289 ALCcontext *Context;
2290 ALsource *Source;
2291 ALsizei i;
2293 Context = GetContextRef();
2294 if(!Context) return;
2296 al_try
2298 CHECK_VALUE(Context, n >= 0);
2299 for(i = 0;i < n;i++)
2301 if(!LookupSource(Context, sources[i]))
2302 al_throwerr(Context, AL_INVALID_NAME);
2305 LockContext(Context);
2306 for(i = 0;i < n;i++)
2308 Source = LookupSource(Context, sources[i]);
2309 Source->new_state = AL_NONE;
2310 SetSourceState(Source, Context, AL_INITIAL);
2312 UnlockContext(Context);
2314 al_endtry;
2316 ALCcontext_DecRef(Context);
2320 AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers)
2322 ALCcontext *Context;
2323 ALsource *Source;
2324 ALsizei i;
2325 ALbufferlistitem *BufferListStart = NULL;
2326 ALbufferlistitem *BufferList;
2327 ALbuffer *BufferFmt;
2329 if(nb == 0)
2330 return;
2332 Context = GetContextRef();
2333 if(!Context) return;
2335 al_try
2337 ALCdevice *device = Context->Device;
2339 CHECK_VALUE(Context, nb >= 0);
2341 if((Source=LookupSource(Context, source)) == NULL)
2342 al_throwerr(Context, AL_INVALID_NAME);
2344 LockContext(Context);
2345 if(Source->SourceType == AL_STATIC)
2347 UnlockContext(Context);
2348 /* Can't queue on a Static Source */
2349 al_throwerr(Context, AL_INVALID_OPERATION);
2352 BufferFmt = NULL;
2354 /* Check for a valid Buffer, for its frequency and format */
2355 BufferList = Source->queue;
2356 while(BufferList)
2358 if(BufferList->buffer)
2360 BufferFmt = BufferList->buffer;
2361 break;
2363 BufferList = BufferList->next;
2366 for(i = 0;i < nb;i++)
2368 ALbuffer *buffer = NULL;
2369 if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
2371 UnlockContext(Context);
2372 al_throwerr(Context, AL_INVALID_NAME);
2375 if(!BufferListStart)
2377 BufferListStart = malloc(sizeof(ALbufferlistitem));
2378 BufferListStart->buffer = buffer;
2379 BufferListStart->next = NULL;
2380 BufferListStart->prev = NULL;
2381 BufferList = BufferListStart;
2383 else
2385 BufferList->next = malloc(sizeof(ALbufferlistitem));
2386 BufferList->next->buffer = buffer;
2387 BufferList->next->next = NULL;
2388 BufferList->next->prev = BufferList;
2389 BufferList = BufferList->next;
2391 if(!buffer) continue;
2392 IncrementRef(&buffer->ref);
2394 ReadLock(&buffer->lock);
2395 if(BufferFmt == NULL)
2397 BufferFmt = buffer;
2399 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
2400 Source->SampleSize = BytesFromFmt(buffer->FmtType);
2401 if(buffer->FmtChannels == FmtMono)
2402 Source->Update = CalcSourceParams;
2403 else
2404 Source->Update = CalcNonAttnSourceParams;
2406 Source->NeedsUpdate = AL_TRUE;
2408 else if(BufferFmt->Frequency != buffer->Frequency ||
2409 BufferFmt->OriginalChannels != buffer->OriginalChannels ||
2410 BufferFmt->OriginalType != buffer->OriginalType)
2412 ReadUnlock(&buffer->lock);
2413 UnlockContext(Context);
2414 al_throwerr(Context, AL_INVALID_OPERATION);
2416 ReadUnlock(&buffer->lock);
2419 /* Source is now streaming */
2420 Source->SourceType = AL_STREAMING;
2422 if(Source->queue == NULL)
2423 Source->queue = BufferListStart;
2424 else
2426 /* Append to the end of the queue */
2427 BufferList = Source->queue;
2428 while(BufferList->next != NULL)
2429 BufferList = BufferList->next;
2431 BufferListStart->prev = BufferList;
2432 BufferList->next = BufferListStart;
2435 Source->BuffersInQueue += nb;
2437 UnlockContext(Context);
2439 al_catchany()
2441 while(BufferListStart)
2443 BufferList = BufferListStart;
2444 BufferListStart = BufferList->next;
2446 if(BufferList->buffer)
2447 DecrementRef(&BufferList->buffer->ref);
2448 free(BufferList);
2451 al_endtry;
2453 ALCcontext_DecRef(Context);
2456 AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers)
2458 ALCcontext *Context;
2459 ALsource *Source;
2460 ALsizei i;
2461 ALbufferlistitem *BufferList;
2463 if(nb == 0)
2464 return;
2466 Context = GetContextRef();
2467 if(!Context) return;
2469 al_try
2471 CHECK_VALUE(Context, nb >= 0);
2473 if((Source=LookupSource(Context, source)) == NULL)
2474 al_throwerr(Context, AL_INVALID_NAME);
2476 LockContext(Context);
2477 if(Source->Looping || Source->SourceType != AL_STREAMING ||
2478 (ALuint)nb > Source->BuffersPlayed)
2480 UnlockContext(Context);
2481 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2482 al_throwerr(Context, AL_INVALID_VALUE);
2485 for(i = 0;i < nb;i++)
2487 BufferList = Source->queue;
2488 Source->queue = BufferList->next;
2489 Source->BuffersInQueue--;
2490 Source->BuffersPlayed--;
2492 if(BufferList->buffer)
2494 buffers[i] = BufferList->buffer->id;
2495 DecrementRef(&BufferList->buffer->ref);
2497 else
2498 buffers[i] = 0;
2500 free(BufferList);
2502 if(Source->queue)
2503 Source->queue->prev = NULL;
2504 UnlockContext(Context);
2506 al_endtry;
2508 ALCcontext_DecRef(Context);
2512 static ALvoid InitSourceParams(ALsource *Source)
2514 ALuint i;
2516 Source->InnerAngle = 360.0f;
2517 Source->OuterAngle = 360.0f;
2518 Source->Pitch = 1.0f;
2519 Source->Position[0] = 0.0f;
2520 Source->Position[1] = 0.0f;
2521 Source->Position[2] = 0.0f;
2522 Source->Orientation[0] = 0.0f;
2523 Source->Orientation[1] = 0.0f;
2524 Source->Orientation[2] = 0.0f;
2525 Source->Velocity[0] = 0.0f;
2526 Source->Velocity[1] = 0.0f;
2527 Source->Velocity[2] = 0.0f;
2528 Source->RefDistance = 1.0f;
2529 Source->MaxDistance = FLT_MAX;
2530 Source->RollOffFactor = 1.0f;
2531 Source->Looping = AL_FALSE;
2532 Source->Gain = 1.0f;
2533 Source->MinGain = 0.0f;
2534 Source->MaxGain = 1.0f;
2535 Source->OuterGain = 0.0f;
2536 Source->OuterGainHF = 1.0f;
2538 Source->DryGainHFAuto = AL_TRUE;
2539 Source->WetGainAuto = AL_TRUE;
2540 Source->WetGainHFAuto = AL_TRUE;
2541 Source->AirAbsorptionFactor = 0.0f;
2542 Source->RoomRolloffFactor = 0.0f;
2543 Source->DopplerFactor = 1.0f;
2544 Source->DirectChannels = AL_FALSE;
2546 Source->DistanceModel = DefaultDistanceModel;
2548 Source->Resampler = DefaultResampler;
2550 Source->state = AL_INITIAL;
2551 Source->new_state = AL_NONE;
2552 Source->SourceType = AL_UNDETERMINED;
2553 Source->Offset = -1.0;
2555 Source->DirectGain = 1.0f;
2556 Source->DirectGainHF = 1.0f;
2557 for(i = 0;i < MAX_SENDS;i++)
2559 Source->Send[i].Gain = 1.0f;
2560 Source->Send[i].GainHF = 1.0f;
2563 Source->NeedsUpdate = AL_TRUE;
2565 Source->Hrtf.Moving = AL_FALSE;
2566 Source->Hrtf.Counter = 0;
2570 /* SetSourceState
2572 * Sets the source's new play state given its current state.
2574 ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
2576 if(state == AL_PLAYING)
2578 ALbufferlistitem *BufferList;
2579 ALsizei j, k;
2581 /* Check that there is a queue containing at least one valid, non zero
2582 * length Buffer. */
2583 BufferList = Source->queue;
2584 while(BufferList)
2586 if(BufferList->buffer != NULL && BufferList->buffer->SampleLen)
2587 break;
2588 BufferList = BufferList->next;
2591 if(Source->state != AL_PLAYING)
2593 for(j = 0;j < MaxChannels;j++)
2595 for(k = 0;k < SRC_HISTORY_LENGTH;k++)
2596 Source->Hrtf.History[j][k] = 0.0f;
2597 for(k = 0;k < HRIR_LENGTH;k++)
2599 Source->Hrtf.Values[j][k][0] = 0.0f;
2600 Source->Hrtf.Values[j][k][1] = 0.0f;
2605 if(Source->state != AL_PAUSED)
2607 Source->state = AL_PLAYING;
2608 Source->position = 0;
2609 Source->position_fraction = 0;
2610 Source->BuffersPlayed = 0;
2612 else
2613 Source->state = AL_PLAYING;
2615 // Check if an Offset has been set
2616 if(Source->Offset >= 0.0)
2617 ApplyOffset(Source);
2619 /* If there's nothing to play, or device is disconnected, go right to
2620 * stopped */
2621 if(!BufferList || !Context->Device->Connected)
2623 SetSourceState(Source, Context, AL_STOPPED);
2624 return;
2627 for(j = 0;j < Context->ActiveSourceCount;j++)
2629 if(Context->ActiveSources[j] == Source)
2630 break;
2632 if(j == Context->ActiveSourceCount)
2633 Context->ActiveSources[Context->ActiveSourceCount++] = Source;
2635 else if(state == AL_PAUSED)
2637 if(Source->state == AL_PLAYING)
2639 Source->state = AL_PAUSED;
2640 Source->Hrtf.Moving = AL_FALSE;
2641 Source->Hrtf.Counter = 0;
2644 else if(state == AL_STOPPED)
2646 if(Source->state != AL_INITIAL)
2648 Source->state = AL_STOPPED;
2649 Source->BuffersPlayed = Source->BuffersInQueue;
2650 Source->Hrtf.Moving = AL_FALSE;
2651 Source->Hrtf.Counter = 0;
2653 Source->Offset = -1.0;
2655 else if(state == AL_INITIAL)
2657 if(Source->state != AL_INITIAL)
2659 Source->state = AL_INITIAL;
2660 Source->position = 0;
2661 Source->position_fraction = 0;
2662 Source->BuffersPlayed = 0;
2663 Source->Hrtf.Moving = AL_FALSE;
2664 Source->Hrtf.Counter = 0;
2666 Source->Offset = -1.0;
2670 /* GetSourceOffset
2672 * Gets the current read offset for the given Source, in 32.32 fixed-point
2673 * samples. The offset is relative to the start of the queue (not the start of
2674 * the current buffer).
2676 static ALint64 GetSourceOffset(const ALsource *Source)
2678 const ALbufferlistitem *BufferList;
2679 ALuint64 readPos;
2680 ALuint i;
2682 if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
2683 return 0;
2685 /* NOTE: This is the offset into the *current* buffer, so add the length of
2686 * any played buffers */
2687 readPos = (ALuint64)Source->position << 32;
2688 readPos |= (ALuint64)Source->position_fraction << (32-FRACTIONBITS);
2689 BufferList = Source->queue;
2690 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2692 if(BufferList->buffer)
2693 readPos += (ALuint64)BufferList->buffer->SampleLen << 32;
2694 BufferList = BufferList->next;
2697 return (ALint64)minu64(readPos, MAKEU64(0x7fffffff,0xffffffff));
2700 /* GetSourceSecOffset
2702 * Gets the current read offset for the given Source, in seconds. The offset is
2703 * relative to the start of the queue (not the start of the current buffer).
2705 static ALdouble GetSourceSecOffset(const ALsource *Source)
2707 const ALbufferlistitem *BufferList;
2708 const ALbuffer *Buffer = NULL;
2709 ALuint64 readPos;
2710 ALuint i;
2712 BufferList = Source->queue;
2713 while(BufferList)
2715 if(BufferList->buffer)
2717 Buffer = BufferList->buffer;
2718 break;
2720 BufferList = BufferList->next;
2723 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2724 return 0.0;
2726 /* NOTE: This is the offset into the *current* buffer, so add the length of
2727 * any played buffers */
2728 readPos = (ALuint64)Source->position << FRACTIONBITS;
2729 readPos |= (ALuint64)Source->position_fraction;
2730 BufferList = Source->queue;
2731 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2733 if(BufferList->buffer)
2734 readPos += (ALuint64)BufferList->buffer->SampleLen << FRACTIONBITS;
2735 BufferList = BufferList->next;
2738 return (ALdouble)readPos / (ALdouble)FRACTIONONE / (ALdouble)Buffer->Frequency;
2741 /* GetSourceOffsets
2743 * Gets the current read and write offsets for the given Source, in the
2744 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2745 * the start of the queue (not the start of the current buffer).
2747 static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen)
2749 const ALbufferlistitem *BufferList;
2750 const ALbuffer *Buffer = NULL;
2751 ALuint readPos, writePos;
2752 ALuint totalBufferLen;
2753 ALuint i;
2755 // Find the first valid Buffer in the Queue
2756 BufferList = Source->queue;
2757 while(BufferList)
2759 if(BufferList->buffer)
2761 Buffer = BufferList->buffer;
2762 break;
2764 BufferList = BufferList->next;
2767 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2769 offset[0] = 0.0;
2770 offset[1] = 0.0;
2771 return;
2774 if(updateLen > 0.0 && updateLen < 0.015)
2775 updateLen = 0.015;
2777 /* NOTE: This is the offset into the *current* buffer, so add the length of
2778 * any played buffers */
2779 readPos = Source->position;
2780 totalBufferLen = 0;
2781 BufferList = Source->queue;
2782 for(i = 0;BufferList;i++)
2784 if(BufferList->buffer)
2786 if(i < Source->BuffersPlayed)
2787 readPos += BufferList->buffer->SampleLen;
2788 totalBufferLen += BufferList->buffer->SampleLen;
2790 BufferList = BufferList->next;
2792 if(Source->state == AL_PLAYING)
2793 writePos = readPos + (ALuint)(updateLen*Buffer->Frequency);
2794 else
2795 writePos = readPos;
2797 if(Source->Looping)
2799 readPos %= totalBufferLen;
2800 writePos %= totalBufferLen;
2802 else
2804 /* Wrap positions back to 0 */
2805 if(readPos >= totalBufferLen)
2806 readPos = 0;
2807 if(writePos >= totalBufferLen)
2808 writePos = 0;
2811 switch(name)
2813 case AL_SEC_OFFSET:
2814 offset[0] = (ALdouble)readPos / Buffer->Frequency;
2815 offset[1] = (ALdouble)writePos / Buffer->Frequency;
2816 break;
2818 case AL_SAMPLE_OFFSET:
2819 case AL_SAMPLE_RW_OFFSETS_SOFT:
2820 offset[0] = (ALdouble)readPos;
2821 offset[1] = (ALdouble)writePos;
2822 break;
2824 case AL_BYTE_OFFSET:
2825 case AL_BYTE_RW_OFFSETS_SOFT:
2826 if(Buffer->OriginalType == UserFmtIMA4)
2828 ALuint BlockSize = 36 * ChannelsFromFmt(Buffer->FmtChannels);
2829 ALuint FrameBlockSize = 65;
2831 /* Round down to nearest ADPCM block */
2832 offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
2833 if(Source->state != AL_PLAYING)
2834 offset[1] = offset[0];
2835 else
2837 /* Round up to nearest ADPCM block */
2838 offset[1] = (ALdouble)((writePos+FrameBlockSize-1) /
2839 FrameBlockSize * BlockSize);
2842 else
2844 ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2845 offset[0] = (ALdouble)(readPos * FrameSize);
2846 offset[1] = (ALdouble)(writePos * FrameSize);
2848 break;
2853 /* ApplyOffset
2855 * Apply the stored playback offset to the Source. This function will update
2856 * the number of buffers "played" given the stored offset.
2858 ALboolean ApplyOffset(ALsource *Source)
2860 const ALbufferlistitem *BufferList;
2861 const ALbuffer *Buffer;
2862 ALint bufferLen, totalBufferLen;
2863 ALint buffersPlayed;
2864 ALint offset;
2866 /* Get sample frame offset */
2867 offset = GetSampleOffset(Source);
2868 if(offset == -1)
2869 return AL_FALSE;
2871 buffersPlayed = 0;
2872 totalBufferLen = 0;
2874 BufferList = Source->queue;
2875 while(BufferList)
2877 Buffer = BufferList->buffer;
2878 bufferLen = Buffer ? Buffer->SampleLen : 0;
2880 if(bufferLen <= offset-totalBufferLen)
2882 /* Offset is past this buffer so increment to the next buffer */
2883 buffersPlayed++;
2885 else if(totalBufferLen <= offset)
2887 /* Offset is in this buffer */
2888 Source->BuffersPlayed = buffersPlayed;
2890 Source->position = offset - totalBufferLen;
2891 Source->position_fraction = 0;
2892 return AL_TRUE;
2895 totalBufferLen += bufferLen;
2897 BufferList = BufferList->next;
2900 /* Offset is out of range of the queue */
2901 return AL_FALSE;
2905 /* GetSampleOffset
2907 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2908 * Second offset supplied by the application). This takes into account the fact
2909 * that the buffer format may have been modifed since.
2911 static ALint GetSampleOffset(ALsource *Source)
2913 const ALbuffer *Buffer = NULL;
2914 const ALbufferlistitem *BufferList;
2915 ALint Offset = -1;
2917 /* Find the first valid Buffer in the Queue */
2918 BufferList = Source->queue;
2919 while(BufferList)
2921 if(BufferList->buffer)
2923 Buffer = BufferList->buffer;
2924 break;
2926 BufferList = BufferList->next;
2929 if(!Buffer)
2931 Source->Offset = -1.0;
2932 return -1;
2935 switch(Source->OffsetType)
2937 case AL_BYTE_OFFSET:
2938 /* Determine the ByteOffset (and ensure it is block aligned) */
2939 Offset = (ALint)Source->Offset;
2940 if(Buffer->OriginalType == UserFmtIMA4)
2942 Offset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels);
2943 Offset *= 65;
2945 else
2946 Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2947 break;
2949 case AL_SAMPLE_OFFSET:
2950 Offset = (ALint)Source->Offset;
2951 break;
2953 case AL_SEC_OFFSET:
2954 Offset = (ALint)(Source->Offset * Buffer->Frequency);
2955 break;
2957 Source->Offset = -1.0;
2959 return Offset;
2963 /* ReleaseALSources
2965 * Destroys all sources in the source map.
2967 ALvoid ReleaseALSources(ALCcontext *Context)
2969 ALsizei pos;
2970 ALuint j;
2971 for(pos = 0;pos < Context->SourceMap.size;pos++)
2973 ALsource *temp = Context->SourceMap.array[pos].value;
2974 Context->SourceMap.array[pos].value = NULL;
2976 while(temp->queue != NULL)
2978 ALbufferlistitem *BufferList = temp->queue;
2979 temp->queue = BufferList->next;
2981 if(BufferList->buffer != NULL)
2982 DecrementRef(&BufferList->buffer->ref);
2983 free(BufferList);
2986 for(j = 0;j < MAX_SENDS;++j)
2988 if(temp->Send[j].Slot)
2989 DecrementRef(&temp->Send[j].Slot->ref);
2990 temp->Send[j].Slot = NULL;
2993 FreeThunkEntry(temp->id);
2994 memset(temp, 0, sizeof(*temp));
2995 al_free(temp);