2a3953020152ae44378bb1463938d716e225777a
[openal-soft.git] / OpenAL32 / alSource.c
blob2a3953020152ae44378bb1463938d716e225777a
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 sfPitch = AL_PITCH,
58 sfGain = AL_GAIN,
59 sfMinGain = AL_MIN_GAIN,
60 sfMaxGain = AL_MAX_GAIN,
61 sfMaxDistance = AL_MAX_DISTANCE,
62 sfRolloffFactor = AL_ROLLOFF_FACTOR,
63 sfDopplerFactor = AL_DOPPLER_FACTOR,
64 sfConeOuterGain = AL_CONE_OUTER_GAIN,
65 sfSecOffset = AL_SEC_OFFSET,
66 sfSampleOffset = AL_SAMPLE_OFFSET,
67 sfByteOffset = AL_BYTE_OFFSET,
68 sfConeInnerAngle = AL_CONE_INNER_ANGLE,
69 sfConeOuterAngle = AL_CONE_OUTER_ANGLE,
70 sfRefDistance = AL_REFERENCE_DISTANCE,
72 sfPosition = AL_POSITION,
73 sfVelocity = AL_VELOCITY,
74 sfDirection = AL_DIRECTION,
76 sfSourceRelative = AL_SOURCE_RELATIVE,
77 sfLooping = AL_LOOPING,
78 sfBuffer = AL_BUFFER,
79 sfSourceState = AL_SOURCE_STATE,
80 sfBuffersQueued = AL_BUFFERS_QUEUED,
81 sfBuffersProcessed = AL_BUFFERS_PROCESSED,
82 sfSourceType = AL_SOURCE_TYPE,
84 /* ALC_EXT_EFX */
85 sfConeOuterGainHF = AL_CONE_OUTER_GAINHF,
86 sfAirAbsorptionFactor = AL_AIR_ABSORPTION_FACTOR,
87 sfRoomRolloffFactor = AL_ROOM_ROLLOFF_FACTOR,
88 sfDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO,
89 sfAuxSendFilterGainAuto = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,
90 sfAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO,
92 /* AL_SOFT_direct_channels */
93 sfDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT,
95 /* AL_EXT_source_distance_model */
96 sfDistanceModel = AL_DISTANCE_MODEL,
98 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
99 sfSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT,
100 sfByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT,
102 /* AL_SOFT_source_latency */
103 sfSecOffsetLatencySOFT = AL_SEC_OFFSET_LATENCY_SOFT,
104 } SrcFloatProp;
106 typedef enum SrcIntProp {
107 siMaxDistance = AL_MAX_DISTANCE,
108 siRolloffFactor = AL_ROLLOFF_FACTOR,
109 siRefDistance = AL_REFERENCE_DISTANCE,
110 siSourceRelative = AL_SOURCE_RELATIVE,
111 siConeInnerAngle = AL_CONE_INNER_ANGLE,
112 siConeOuterAngle = AL_CONE_OUTER_ANGLE,
113 siLooping = AL_LOOPING,
114 siBuffer = AL_BUFFER,
115 siSourceState = AL_SOURCE_STATE,
116 siBuffersQueued = AL_BUFFERS_QUEUED,
117 siBuffersProcessed = AL_BUFFERS_PROCESSED,
118 siSourceType = AL_SOURCE_TYPE,
119 siSecOffset = AL_SEC_OFFSET,
120 siSampleOffset = AL_SAMPLE_OFFSET,
121 siByteOffset = AL_BYTE_OFFSET,
122 siDopplerFactor = AL_DOPPLER_FACTOR,
123 siPosition = AL_POSITION,
124 siVelocity = AL_VELOCITY,
125 siDirection = AL_DIRECTION,
127 /* ALC_EXT_EFX */
128 siDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO,
129 siAuxSendFilterGainAutio = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,
130 siAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO,
131 siDirectFilter = AL_DIRECT_FILTER,
132 siAuxSendFilter = AL_AUXILIARY_SEND_FILTER,
134 /* AL_SOFT_direct_channels */
135 siDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT,
137 /* AL_EXT_source_distance_model */
138 siDistanceModel = AL_DISTANCE_MODEL,
140 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
141 siSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT,
142 siByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT,
144 /* AL_SOFT_source_latency */
145 siSampleOffsetLatencySOFT = 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 sfSampleRWOffsetsSOFT:
333 case sfByteRWOffsetsSOFT:
334 RETERR(AL_INVALID_OPERATION);
337 case sfSourceRelative:
338 case sfLooping:
339 case sfSourceState:
340 case sfSourceType:
341 case sfDistanceModel:
342 case sfDirectFilterGainHFAuto:
343 case sfAuxSendFilterGainAuto:
344 case sfAuxSendFilterGainHFAuto:
345 case sfDirectChannelsSOFT:
346 ival = (ALint)values[0];
347 return SetSourceiv(Source, Context, prop, &ival);
349 case sfBuffer:
350 case sfBuffersQueued:
351 case sfBuffersProcessed:
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 siSourceState:
445 case siSourceType:
446 case siBuffersQueued:
447 case siBuffersProcessed:
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 siSampleRWOffsetsSOFT:
474 case siByteRWOffsetsSOFT:
475 case siSampleOffsetLatencySOFT:
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 siDopplerFactor:
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 siSampleRWOffsetsSOFT:
602 case siByteRWOffsetsSOFT:
603 case siSampleOffsetLatencySOFT:
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 siSourceType:
615 case siBuffersQueued:
616 case siBuffersProcessed:
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 siDopplerFactor:
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 siSampleOffsetLatencySOFT:
924 /* i64 only */
925 break;
927 case siDirectFilter:
928 case siAuxSendFilter:
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 case siDirectFilter:
998 case siAuxSendFilter:
999 if((err=GetSourceiv(Source, Context, (int)prop, ivals)) == AL_NO_ERROR)
1000 *values = ivals[0];
1001 return err;
1004 ERR("Unexpected property: 0x%04x\n", prop);
1005 RETERR(AL_INVALID_ENUM);
1008 #undef RETERR
1011 AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
1013 ALCcontext *Context;
1014 ALsizei cur = 0;
1016 Context = GetContextRef();
1017 if(!Context) return;
1019 al_try
1021 ALenum err;
1023 CHECK_VALUE(Context, n >= 0);
1024 for(cur = 0;cur < n;cur++)
1026 ALsource *source = al_calloc(16, sizeof(ALsource));
1027 if(!source)
1028 al_throwerr(Context, AL_OUT_OF_MEMORY);
1029 InitSourceParams(source);
1031 err = NewThunkEntry(&source->id);
1032 if(err == AL_NO_ERROR)
1033 err = InsertUIntMapEntry(&Context->SourceMap, source->id, source);
1034 if(err != AL_NO_ERROR)
1036 FreeThunkEntry(source->id);
1037 memset(source, 0, sizeof(ALsource));
1038 al_free(source);
1040 al_throwerr(Context, err);
1043 sources[cur] = source->id;
1046 al_catchany()
1048 if(cur > 0)
1049 alDeleteSources(cur, sources);
1051 al_endtry;
1053 ALCcontext_DecRef(Context);
1057 AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
1059 ALCcontext *Context;
1061 Context = GetContextRef();
1062 if(!Context) return;
1064 al_try
1066 ALbufferlistitem *BufferList;
1067 ALsource *Source;
1068 ALsizei i, j;
1070 CHECK_VALUE(Context, n >= 0);
1072 /* Check that all Sources are valid */
1073 for(i = 0;i < n;i++)
1075 if(LookupSource(Context, sources[i]) == NULL)
1076 al_throwerr(Context, AL_INVALID_NAME);
1079 for(i = 0;i < n;i++)
1081 ALsource **srclist, **srclistend;
1083 if((Source=RemoveSource(Context, sources[i])) == NULL)
1084 continue;
1085 FreeThunkEntry(Source->id);
1087 LockContext(Context);
1088 srclist = Context->ActiveSources;
1089 srclistend = srclist + Context->ActiveSourceCount;
1090 while(srclist != srclistend)
1092 if(*srclist == Source)
1094 Context->ActiveSourceCount--;
1095 *srclist = *(--srclistend);
1096 break;
1098 srclist++;
1100 UnlockContext(Context);
1102 while(Source->queue != NULL)
1104 BufferList = Source->queue;
1105 Source->queue = BufferList->next;
1107 if(BufferList->buffer != NULL)
1108 DecrementRef(&BufferList->buffer->ref);
1109 free(BufferList);
1112 for(j = 0;j < MAX_SENDS;++j)
1114 if(Source->Send[j].Slot)
1115 DecrementRef(&Source->Send[j].Slot->ref);
1116 Source->Send[j].Slot = NULL;
1119 memset(Source, 0, sizeof(*Source));
1120 al_free(Source);
1123 al_endtry;
1125 ALCcontext_DecRef(Context);
1129 AL_API ALboolean AL_APIENTRY alIsSource(ALuint source)
1131 ALCcontext *Context;
1132 ALboolean result;
1134 Context = GetContextRef();
1135 if(!Context) return AL_FALSE;
1137 result = (LookupSource(Context, source) ? AL_TRUE : AL_FALSE);
1139 ALCcontext_DecRef(Context);
1141 return result;
1145 AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value)
1147 ALCcontext *Context;
1148 ALsource *Source;
1150 Context = GetContextRef();
1151 if(!Context) return;
1153 if((Source=LookupSource(Context, source)) == NULL)
1154 alSetError(Context, AL_INVALID_NAME);
1155 else switch(param)
1157 case AL_PITCH:
1158 case AL_CONE_INNER_ANGLE:
1159 case AL_CONE_OUTER_ANGLE:
1160 case AL_GAIN:
1161 case AL_MAX_DISTANCE:
1162 case AL_ROLLOFF_FACTOR:
1163 case AL_REFERENCE_DISTANCE:
1164 case AL_MIN_GAIN:
1165 case AL_MAX_GAIN:
1166 case AL_CONE_OUTER_GAIN:
1167 case AL_CONE_OUTER_GAINHF:
1168 case AL_AIR_ABSORPTION_FACTOR:
1169 case AL_ROOM_ROLLOFF_FACTOR:
1170 case AL_DOPPLER_FACTOR:
1171 case AL_SEC_OFFSET:
1172 case AL_SAMPLE_OFFSET:
1173 case AL_BYTE_OFFSET:
1174 SetSourcefv(Source, Context, param, &value);
1175 break;
1177 default:
1178 alSetError(Context, AL_INVALID_ENUM);
1181 ALCcontext_DecRef(Context);
1184 AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
1186 ALCcontext *Context;
1187 ALsource *Source;
1188 ALfloat fvals[3];
1190 Context = GetContextRef();
1191 if(!Context) return;
1193 if((Source=LookupSource(Context, source)) == NULL)
1194 alSetError(Context, AL_INVALID_NAME);
1195 else switch(param)
1197 case AL_POSITION:
1198 case AL_VELOCITY:
1199 case AL_DIRECTION:
1200 fvals[0] = value1;
1201 fvals[1] = value2;
1202 fvals[2] = value3;
1203 SetSourcefv(Source, Context, param, fvals);
1204 break;
1206 default:
1207 alSetError(Context, AL_INVALID_ENUM);
1210 ALCcontext_DecRef(Context);
1213 AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values)
1215 ALCcontext *Context;
1216 ALsource *Source;
1218 Context = GetContextRef();
1219 if(!Context) return;
1221 if((Source=LookupSource(Context, source)) == NULL)
1222 alSetError(Context, AL_INVALID_NAME);
1223 else if(!values)
1224 alSetError(Context, AL_INVALID_VALUE);
1225 else switch(param)
1227 case AL_PITCH:
1228 case AL_CONE_INNER_ANGLE:
1229 case AL_CONE_OUTER_ANGLE:
1230 case AL_GAIN:
1231 case AL_MAX_DISTANCE:
1232 case AL_ROLLOFF_FACTOR:
1233 case AL_REFERENCE_DISTANCE:
1234 case AL_MIN_GAIN:
1235 case AL_MAX_GAIN:
1236 case AL_CONE_OUTER_GAIN:
1237 case AL_CONE_OUTER_GAINHF:
1238 case AL_SEC_OFFSET:
1239 case AL_SAMPLE_OFFSET:
1240 case AL_BYTE_OFFSET:
1241 case AL_AIR_ABSORPTION_FACTOR:
1242 case AL_ROOM_ROLLOFF_FACTOR:
1244 case AL_POSITION:
1245 case AL_VELOCITY:
1246 case AL_DIRECTION:
1247 SetSourcefv(Source, Context, param, values);
1248 break;
1250 default:
1251 alSetError(Context, AL_INVALID_ENUM);
1254 ALCcontext_DecRef(Context);
1258 AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value)
1260 ALCcontext *Context;
1261 ALsource *Source;
1262 ALfloat fval;
1264 Context = GetContextRef();
1265 if(!Context) return;
1267 if((Source=LookupSource(Context, source)) == NULL)
1268 alSetError(Context, AL_INVALID_NAME);
1269 else switch(param)
1271 case AL_PITCH:
1272 case AL_CONE_INNER_ANGLE:
1273 case AL_CONE_OUTER_ANGLE:
1274 case AL_GAIN:
1275 case AL_MAX_DISTANCE:
1276 case AL_ROLLOFF_FACTOR:
1277 case AL_REFERENCE_DISTANCE:
1278 case AL_MIN_GAIN:
1279 case AL_MAX_GAIN:
1280 case AL_CONE_OUTER_GAIN:
1281 case AL_CONE_OUTER_GAINHF:
1282 case AL_AIR_ABSORPTION_FACTOR:
1283 case AL_ROOM_ROLLOFF_FACTOR:
1284 case AL_DOPPLER_FACTOR:
1285 case AL_SEC_OFFSET:
1286 case AL_SAMPLE_OFFSET:
1287 case AL_BYTE_OFFSET:
1288 fval = (ALfloat)value;
1289 SetSourcefv(Source, Context, param, &fval);
1290 break;
1292 default:
1293 alSetError(Context, AL_INVALID_ENUM);
1296 ALCcontext_DecRef(Context);
1299 AL_API ALvoid AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3)
1301 ALCcontext *Context;
1302 ALsource *Source;
1303 ALfloat fvals[3];
1305 Context = GetContextRef();
1306 if(!Context) return;
1308 if((Source=LookupSource(Context, source)) == NULL)
1309 alSetError(Context, AL_INVALID_NAME);
1310 else switch(param)
1312 case AL_POSITION:
1313 case AL_VELOCITY:
1314 case AL_DIRECTION:
1315 fvals[0] = (ALfloat)value1;
1316 fvals[1] = (ALfloat)value2;
1317 fvals[2] = (ALfloat)value3;
1318 SetSourcefv(Source, Context, param, fvals);
1319 break;
1321 default:
1322 alSetError(Context, AL_INVALID_ENUM);
1325 ALCcontext_DecRef(Context);
1328 AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values)
1330 ALCcontext *Context;
1331 ALsource *Source;
1332 ALfloat fvals[3];
1334 Context = GetContextRef();
1335 if(!Context) return;
1337 if((Source=LookupSource(Context, source)) == NULL)
1338 alSetError(Context, AL_INVALID_NAME);
1339 else if(!values)
1340 alSetError(Context, AL_INVALID_VALUE);
1341 else switch(param)
1343 case AL_PITCH:
1344 case AL_CONE_INNER_ANGLE:
1345 case AL_CONE_OUTER_ANGLE:
1346 case AL_GAIN:
1347 case AL_MAX_DISTANCE:
1348 case AL_ROLLOFF_FACTOR:
1349 case AL_REFERENCE_DISTANCE:
1350 case AL_MIN_GAIN:
1351 case AL_MAX_GAIN:
1352 case AL_CONE_OUTER_GAIN:
1353 case AL_CONE_OUTER_GAINHF:
1354 case AL_SEC_OFFSET:
1355 case AL_SAMPLE_OFFSET:
1356 case AL_BYTE_OFFSET:
1357 case AL_AIR_ABSORPTION_FACTOR:
1358 case AL_ROOM_ROLLOFF_FACTOR:
1359 fvals[0] = (ALfloat)values[0];
1360 SetSourcefv(Source, Context, param, fvals);
1361 break;
1363 case AL_SEC_OFFSET_LATENCY_SOFT:
1364 fvals[0] = (ALfloat)values[0];
1365 fvals[1] = (ALfloat)values[1];
1366 SetSourcefv(Source, Context, param, fvals);
1367 break;
1369 case AL_POSITION:
1370 case AL_VELOCITY:
1371 case AL_DIRECTION:
1372 fvals[0] = (ALfloat)values[0];
1373 fvals[1] = (ALfloat)values[1];
1374 fvals[2] = (ALfloat)values[2];
1375 SetSourcefv(Source, Context, param, fvals);
1376 break;
1378 default:
1379 alSetError(Context, AL_INVALID_ENUM);
1382 ALCcontext_DecRef(Context);
1386 AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value)
1388 ALCcontext *Context;
1389 ALsource *Source;
1391 Context = GetContextRef();
1392 if(!Context) return;
1394 if((Source=LookupSource(Context, source)) == NULL)
1395 alSetError(Context, AL_INVALID_NAME);
1396 else switch(param)
1398 case AL_MAX_DISTANCE:
1399 case AL_ROLLOFF_FACTOR:
1400 case AL_CONE_INNER_ANGLE:
1401 case AL_CONE_OUTER_ANGLE:
1402 case AL_REFERENCE_DISTANCE:
1403 case AL_SOURCE_RELATIVE:
1404 case AL_LOOPING:
1405 case AL_BUFFER:
1406 case AL_SOURCE_STATE:
1407 case AL_SEC_OFFSET:
1408 case AL_SAMPLE_OFFSET:
1409 case AL_BYTE_OFFSET:
1410 case AL_DIRECT_FILTER:
1411 case AL_DIRECT_FILTER_GAINHF_AUTO:
1412 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1413 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1414 case AL_DIRECT_CHANNELS_SOFT:
1415 case AL_DISTANCE_MODEL:
1416 SetSourceiv(Source, Context, param, &value);
1417 break;
1419 default:
1420 alSetError(Context, AL_INVALID_ENUM);
1423 ALCcontext_DecRef(Context);
1426 AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3)
1428 ALCcontext *Context;
1429 ALsource *Source;
1430 ALint ivals[3];
1432 Context = GetContextRef();
1433 if(!Context) return;
1435 if((Source=LookupSource(Context, source)) == NULL)
1436 alSetError(Context, AL_INVALID_NAME);
1437 else switch(param)
1439 case AL_POSITION:
1440 case AL_VELOCITY:
1441 case AL_DIRECTION:
1442 case AL_AUXILIARY_SEND_FILTER:
1443 ivals[0] = value1;
1444 ivals[1] = value2;
1445 ivals[2] = value3;
1446 SetSourceiv(Source, Context, param, ivals);
1447 break;
1449 default:
1450 alSetError(Context, AL_INVALID_ENUM);
1453 ALCcontext_DecRef(Context);
1456 AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values)
1458 ALCcontext *Context;
1459 ALsource *Source;
1461 Context = GetContextRef();
1462 if(!Context) return;
1464 if((Source=LookupSource(Context, source)) == NULL)
1465 alSetError(Context, AL_INVALID_NAME);
1466 else if(!values)
1467 alSetError(Context, AL_INVALID_VALUE);
1468 else switch(param)
1470 case AL_SOURCE_RELATIVE:
1471 case AL_CONE_INNER_ANGLE:
1472 case AL_CONE_OUTER_ANGLE:
1473 case AL_LOOPING:
1474 case AL_BUFFER:
1475 case AL_SOURCE_STATE:
1476 case AL_SEC_OFFSET:
1477 case AL_SAMPLE_OFFSET:
1478 case AL_BYTE_OFFSET:
1479 case AL_MAX_DISTANCE:
1480 case AL_ROLLOFF_FACTOR:
1481 case AL_REFERENCE_DISTANCE:
1482 case AL_DIRECT_FILTER:
1483 case AL_DIRECT_FILTER_GAINHF_AUTO:
1484 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1485 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1486 case AL_DISTANCE_MODEL:
1487 case AL_DIRECT_CHANNELS_SOFT:
1489 case AL_POSITION:
1490 case AL_VELOCITY:
1491 case AL_DIRECTION:
1492 case AL_AUXILIARY_SEND_FILTER:
1493 SetSourceiv(Source, Context, param, values);
1494 break;
1496 default:
1497 alSetError(Context, AL_INVALID_ENUM);
1500 ALCcontext_DecRef(Context);
1504 AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value)
1506 ALCcontext *Context;
1507 ALsource *Source;
1509 Context = GetContextRef();
1510 if(!Context) return;
1512 if((Source=LookupSource(Context, source)) == NULL)
1513 alSetError(Context, AL_INVALID_NAME);
1514 else switch(param)
1516 case AL_MAX_DISTANCE:
1517 case AL_ROLLOFF_FACTOR:
1518 case AL_CONE_INNER_ANGLE:
1519 case AL_CONE_OUTER_ANGLE:
1520 case AL_REFERENCE_DISTANCE:
1521 case AL_SOURCE_RELATIVE:
1522 case AL_LOOPING:
1523 case AL_SOURCE_STATE:
1524 case AL_SEC_OFFSET:
1525 case AL_SAMPLE_OFFSET:
1526 case AL_BYTE_OFFSET:
1527 case AL_DIRECT_FILTER_GAINHF_AUTO:
1528 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1529 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1530 case AL_DIRECT_CHANNELS_SOFT:
1531 case AL_DISTANCE_MODEL:
1532 case AL_BUFFER:
1533 case AL_DIRECT_FILTER:
1534 SetSourcei64v(Source, Context, param, &value);
1535 break;
1537 default:
1538 alSetError(Context, AL_INVALID_ENUM);
1541 ALCcontext_DecRef(Context);
1544 AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3)
1546 ALCcontext *Context;
1547 ALsource *Source;
1548 ALint64SOFT i64vals[3];
1550 Context = GetContextRef();
1551 if(!Context) return;
1553 if((Source=LookupSource(Context, source)) == NULL)
1554 alSetError(Context, AL_INVALID_NAME);
1555 else switch(param)
1557 case AL_POSITION:
1558 case AL_VELOCITY:
1559 case AL_DIRECTION:
1560 case AL_AUXILIARY_SEND_FILTER:
1561 i64vals[0] = value1;
1562 i64vals[1] = value2;
1563 i64vals[2] = value3;
1564 SetSourcei64v(Source, Context, param, i64vals);
1565 break;
1567 default:
1568 alSetError(Context, AL_INVALID_ENUM);
1571 ALCcontext_DecRef(Context);
1574 AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values)
1576 ALCcontext *Context;
1577 ALsource *Source;
1579 Context = GetContextRef();
1580 if(!Context) return;
1582 if((Source=LookupSource(Context, source)) == NULL)
1583 alSetError(Context, AL_INVALID_NAME);
1584 else if(!values)
1585 alSetError(Context, AL_INVALID_VALUE);
1586 else switch(param)
1588 case AL_SOURCE_RELATIVE:
1589 case AL_CONE_INNER_ANGLE:
1590 case AL_CONE_OUTER_ANGLE:
1591 case AL_LOOPING:
1592 case AL_SOURCE_STATE:
1593 case AL_SEC_OFFSET:
1594 case AL_SAMPLE_OFFSET:
1595 case AL_BYTE_OFFSET:
1596 case AL_MAX_DISTANCE:
1597 case AL_ROLLOFF_FACTOR:
1598 case AL_REFERENCE_DISTANCE:
1599 case AL_DIRECT_FILTER_GAINHF_AUTO:
1600 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1601 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1602 case AL_DISTANCE_MODEL:
1603 case AL_DIRECT_CHANNELS_SOFT:
1604 case AL_BUFFER:
1605 case AL_DIRECT_FILTER:
1607 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
1609 case AL_POSITION:
1610 case AL_VELOCITY:
1611 case AL_DIRECTION:
1612 case AL_AUXILIARY_SEND_FILTER:
1613 SetSourcei64v(Source, Context, param, values);
1614 break;
1616 default:
1617 alSetError(Context, AL_INVALID_ENUM);
1620 ALCcontext_DecRef(Context);
1624 AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value)
1626 ALCcontext *Context;
1627 ALsource *Source;
1628 ALdouble dval;
1630 Context = GetContextRef();
1631 if(!Context) return;
1633 if((Source=LookupSource(Context, source)) == NULL)
1634 alSetError(Context, AL_INVALID_NAME);
1635 else if(!value)
1636 alSetError(Context, AL_INVALID_VALUE);
1637 else switch(param)
1639 case AL_PITCH:
1640 case AL_GAIN:
1641 case AL_MIN_GAIN:
1642 case AL_MAX_GAIN:
1643 case AL_MAX_DISTANCE:
1644 case AL_ROLLOFF_FACTOR:
1645 case AL_CONE_OUTER_GAIN:
1646 case AL_CONE_OUTER_GAINHF:
1647 case AL_SEC_OFFSET:
1648 case AL_SAMPLE_OFFSET:
1649 case AL_BYTE_OFFSET:
1650 case AL_CONE_INNER_ANGLE:
1651 case AL_CONE_OUTER_ANGLE:
1652 case AL_REFERENCE_DISTANCE:
1653 case AL_AIR_ABSORPTION_FACTOR:
1654 case AL_ROOM_ROLLOFF_FACTOR:
1655 case AL_DOPPLER_FACTOR:
1656 if(GetSourcedv(Source, Context, param, &dval) == AL_NO_ERROR)
1657 *value = (ALfloat)dval;
1658 break;
1660 default:
1661 alSetError(Context, AL_INVALID_ENUM);
1664 ALCcontext_DecRef(Context);
1668 AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
1670 ALCcontext *Context;
1671 ALsource *Source;
1672 ALdouble dvals[3];
1674 Context = GetContextRef();
1675 if(!Context) return;
1677 if((Source=LookupSource(Context, source)) == NULL)
1678 alSetError(Context, AL_INVALID_NAME);
1679 else if(!(value1 && value2 && value3))
1680 alSetError(Context, AL_INVALID_VALUE);
1681 else switch(param)
1683 case AL_POSITION:
1684 case AL_VELOCITY:
1685 case AL_DIRECTION:
1686 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1688 *value1 = (ALfloat)dvals[0];
1689 *value2 = (ALfloat)dvals[1];
1690 *value3 = (ALfloat)dvals[2];
1692 break;
1694 default:
1695 alSetError(Context, AL_INVALID_ENUM);
1698 ALCcontext_DecRef(Context);
1702 AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values)
1704 ALCcontext *Context;
1705 ALsource *Source;
1706 ALdouble dvals[2];
1708 switch(param)
1710 case AL_PITCH:
1711 case AL_GAIN:
1712 case AL_MIN_GAIN:
1713 case AL_MAX_GAIN:
1714 case AL_MAX_DISTANCE:
1715 case AL_ROLLOFF_FACTOR:
1716 case AL_DOPPLER_FACTOR:
1717 case AL_CONE_OUTER_GAIN:
1718 case AL_SEC_OFFSET:
1719 case AL_SAMPLE_OFFSET:
1720 case AL_BYTE_OFFSET:
1721 case AL_CONE_INNER_ANGLE:
1722 case AL_CONE_OUTER_ANGLE:
1723 case AL_REFERENCE_DISTANCE:
1724 case AL_CONE_OUTER_GAINHF:
1725 case AL_AIR_ABSORPTION_FACTOR:
1726 case AL_ROOM_ROLLOFF_FACTOR:
1727 alGetSourcef(source, param, values);
1728 return;
1730 case AL_POSITION:
1731 case AL_VELOCITY:
1732 case AL_DIRECTION:
1733 alGetSource3f(source, param, values+0, values+1, values+2);
1734 return;
1737 Context = GetContextRef();
1738 if(!Context) return;
1740 if((Source=LookupSource(Context, source)) == NULL)
1741 alSetError(Context, AL_INVALID_NAME);
1742 else if(!values)
1743 alSetError(Context, AL_INVALID_VALUE);
1744 else switch(param)
1746 case AL_SAMPLE_RW_OFFSETS_SOFT:
1747 case AL_BYTE_RW_OFFSETS_SOFT:
1748 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1750 values[0] = (ALfloat)dvals[0];
1751 values[1] = (ALfloat)dvals[1];
1753 break;
1755 default:
1756 alSetError(Context, AL_INVALID_ENUM);
1759 ALCcontext_DecRef(Context);
1763 AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value)
1765 ALCcontext *Context;
1766 ALsource *Source;
1768 Context = GetContextRef();
1769 if(!Context) return;
1771 if((Source=LookupSource(Context, source)) == NULL)
1772 alSetError(Context, AL_INVALID_NAME);
1773 else if(!value)
1774 alSetError(Context, AL_INVALID_VALUE);
1775 else switch(param)
1777 case AL_PITCH:
1778 case AL_GAIN:
1779 case AL_MIN_GAIN:
1780 case AL_MAX_GAIN:
1781 case AL_MAX_DISTANCE:
1782 case AL_ROLLOFF_FACTOR:
1783 case AL_CONE_OUTER_GAIN:
1784 case AL_CONE_OUTER_GAINHF:
1785 case AL_SEC_OFFSET:
1786 case AL_SAMPLE_OFFSET:
1787 case AL_BYTE_OFFSET:
1788 case AL_CONE_INNER_ANGLE:
1789 case AL_CONE_OUTER_ANGLE:
1790 case AL_REFERENCE_DISTANCE:
1791 case AL_AIR_ABSORPTION_FACTOR:
1792 case AL_ROOM_ROLLOFF_FACTOR:
1793 case AL_DOPPLER_FACTOR:
1794 GetSourcedv(Source, Context, param, value);
1795 break;
1797 default:
1798 alSetError(Context, AL_INVALID_ENUM);
1801 ALCcontext_DecRef(Context);
1804 AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3)
1806 ALCcontext *Context;
1807 ALsource *Source;
1808 ALdouble dvals[3];
1810 Context = GetContextRef();
1811 if(!Context) return;
1813 if((Source=LookupSource(Context, source)) == NULL)
1814 alSetError(Context, AL_INVALID_NAME);
1815 else if(!(value1 && value2 && value3))
1816 alSetError(Context, AL_INVALID_VALUE);
1817 else switch(param)
1819 case AL_POSITION:
1820 case AL_VELOCITY:
1821 case AL_DIRECTION:
1822 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1824 *value1 = dvals[0];
1825 *value2 = dvals[1];
1826 *value3 = dvals[2];
1828 break;
1830 default:
1831 alSetError(Context, AL_INVALID_ENUM);
1834 ALCcontext_DecRef(Context);
1837 AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values)
1839 ALCcontext *Context;
1840 ALsource *Source;
1842 Context = GetContextRef();
1843 if(!Context) return;
1845 if((Source=LookupSource(Context, source)) == NULL)
1846 alSetError(Context, AL_INVALID_NAME);
1847 else if(!values)
1848 alSetError(Context, AL_INVALID_VALUE);
1849 else switch(param)
1851 case AL_PITCH:
1852 case AL_GAIN:
1853 case AL_MIN_GAIN:
1854 case AL_MAX_GAIN:
1855 case AL_MAX_DISTANCE:
1856 case AL_ROLLOFF_FACTOR:
1857 case AL_DOPPLER_FACTOR:
1858 case AL_CONE_OUTER_GAIN:
1859 case AL_SEC_OFFSET:
1860 case AL_SAMPLE_OFFSET:
1861 case AL_BYTE_OFFSET:
1862 case AL_CONE_INNER_ANGLE:
1863 case AL_CONE_OUTER_ANGLE:
1864 case AL_REFERENCE_DISTANCE:
1865 case AL_CONE_OUTER_GAINHF:
1866 case AL_AIR_ABSORPTION_FACTOR:
1867 case AL_ROOM_ROLLOFF_FACTOR:
1869 case AL_SAMPLE_RW_OFFSETS_SOFT:
1870 case AL_BYTE_RW_OFFSETS_SOFT:
1871 case AL_SEC_OFFSET_LATENCY_SOFT:
1873 case AL_POSITION:
1874 case AL_VELOCITY:
1875 case AL_DIRECTION:
1876 GetSourcedv(Source, Context, param, values);
1877 break;
1879 default:
1880 alSetError(Context, AL_INVALID_ENUM);
1883 ALCcontext_DecRef(Context);
1887 AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value)
1889 ALCcontext *Context;
1890 ALsource *Source;
1892 Context = GetContextRef();
1893 if(!Context) return;
1895 if((Source=LookupSource(Context, source)) == NULL)
1896 alSetError(Context, AL_INVALID_NAME);
1897 else if(!value)
1898 alSetError(Context, AL_INVALID_VALUE);
1899 else switch(param)
1901 case AL_MAX_DISTANCE:
1902 case AL_ROLLOFF_FACTOR:
1903 case AL_REFERENCE_DISTANCE:
1904 case AL_SOURCE_RELATIVE:
1905 case AL_CONE_INNER_ANGLE:
1906 case AL_CONE_OUTER_ANGLE:
1907 case AL_LOOPING:
1908 case AL_BUFFER:
1909 case AL_SOURCE_STATE:
1910 case AL_BUFFERS_QUEUED:
1911 case AL_BUFFERS_PROCESSED:
1912 case AL_SOURCE_TYPE:
1913 case AL_SEC_OFFSET:
1914 case AL_SAMPLE_OFFSET:
1915 case AL_BYTE_OFFSET:
1916 case AL_DIRECT_FILTER_GAINHF_AUTO:
1917 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1918 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1919 case AL_DOPPLER_FACTOR:
1920 case AL_DIRECT_CHANNELS_SOFT:
1921 case AL_DISTANCE_MODEL:
1922 GetSourceiv(Source, Context, param, value);
1923 break;
1925 default:
1926 alSetError(Context, AL_INVALID_ENUM);
1929 ALCcontext_DecRef(Context);
1933 AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3)
1935 ALCcontext *Context;
1936 ALsource *Source;
1937 ALint ivals[3];
1939 Context = GetContextRef();
1940 if(!Context) return;
1942 if((Source=LookupSource(Context, source)) == NULL)
1943 alSetError(Context, AL_INVALID_NAME);
1944 else if(!(value1 && value2 && value3))
1945 alSetError(Context, AL_INVALID_VALUE);
1946 else switch(param)
1948 case AL_POSITION:
1949 case AL_VELOCITY:
1950 case AL_DIRECTION:
1951 if(GetSourceiv(Source, Context, param, ivals) == AL_NO_ERROR)
1953 *value1 = ivals[0];
1954 *value2 = ivals[1];
1955 *value3 = ivals[2];
1957 break;
1959 default:
1960 alSetError(Context, AL_INVALID_ENUM);
1963 ALCcontext_DecRef(Context);
1967 AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values)
1969 ALCcontext *Context;
1970 ALsource *Source;
1972 Context = GetContextRef();
1973 if(!Context) return;
1975 if((Source=LookupSource(Context, source)) == NULL)
1976 alSetError(Context, AL_INVALID_NAME);
1977 else if(!values)
1978 alSetError(Context, AL_INVALID_VALUE);
1979 else switch(param)
1981 case AL_SOURCE_RELATIVE:
1982 case AL_CONE_INNER_ANGLE:
1983 case AL_CONE_OUTER_ANGLE:
1984 case AL_LOOPING:
1985 case AL_BUFFER:
1986 case AL_SOURCE_STATE:
1987 case AL_BUFFERS_QUEUED:
1988 case AL_BUFFERS_PROCESSED:
1989 case AL_SEC_OFFSET:
1990 case AL_SAMPLE_OFFSET:
1991 case AL_BYTE_OFFSET:
1992 case AL_MAX_DISTANCE:
1993 case AL_ROLLOFF_FACTOR:
1994 case AL_DOPPLER_FACTOR:
1995 case AL_REFERENCE_DISTANCE:
1996 case AL_SOURCE_TYPE:
1997 case AL_DIRECT_FILTER:
1998 case AL_DIRECT_FILTER_GAINHF_AUTO:
1999 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
2000 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
2001 case AL_DISTANCE_MODEL:
2002 case AL_DIRECT_CHANNELS_SOFT:
2004 case AL_SAMPLE_RW_OFFSETS_SOFT:
2005 case AL_BYTE_RW_OFFSETS_SOFT:
2007 case AL_POSITION:
2008 case AL_VELOCITY:
2009 case AL_DIRECTION:
2010 GetSourceiv(Source, Context, param, values);
2011 break;
2013 default:
2014 alSetError(Context, AL_INVALID_ENUM);
2017 ALCcontext_DecRef(Context);
2021 AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value)
2023 ALCcontext *Context;
2024 ALsource *Source;
2026 Context = GetContextRef();
2027 if(!Context) return;
2029 if((Source=LookupSource(Context, source)) == NULL)
2030 alSetError(Context, AL_INVALID_NAME);
2031 else if(!value)
2032 alSetError(Context, AL_INVALID_VALUE);
2033 else switch(param)
2035 case AL_MAX_DISTANCE:
2036 case AL_ROLLOFF_FACTOR:
2037 case AL_REFERENCE_DISTANCE:
2038 case AL_SOURCE_RELATIVE:
2039 case AL_CONE_INNER_ANGLE:
2040 case AL_CONE_OUTER_ANGLE:
2041 case AL_LOOPING:
2042 case AL_BUFFER:
2043 case AL_SOURCE_STATE:
2044 case AL_BUFFERS_QUEUED:
2045 case AL_BUFFERS_PROCESSED:
2046 case AL_SOURCE_TYPE:
2047 case AL_SEC_OFFSET:
2048 case AL_SAMPLE_OFFSET:
2049 case AL_BYTE_OFFSET:
2050 case AL_DIRECT_FILTER_GAINHF_AUTO:
2051 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
2052 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
2053 case AL_DOPPLER_FACTOR:
2054 case AL_DIRECT_CHANNELS_SOFT:
2055 case AL_DISTANCE_MODEL:
2056 GetSourcei64v(Source, Context, param, value);
2057 break;
2059 default:
2060 alSetError(Context, AL_INVALID_ENUM);
2063 ALCcontext_DecRef(Context);
2066 AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3)
2068 ALCcontext *Context;
2069 ALsource *Source;
2070 ALint64 i64vals[3];
2072 Context = GetContextRef();
2073 if(!Context) return;
2075 if((Source=LookupSource(Context, source)) == NULL)
2076 alSetError(Context, AL_INVALID_NAME);
2077 else if(!(value1 && value2 && value3))
2078 alSetError(Context, AL_INVALID_VALUE);
2079 else switch(param)
2081 case AL_POSITION:
2082 case AL_VELOCITY:
2083 case AL_DIRECTION:
2084 if(GetSourcei64v(Source, Context, param, i64vals) == AL_NO_ERROR)
2086 *value1 = i64vals[0];
2087 *value2 = i64vals[1];
2088 *value3 = i64vals[2];
2090 break;
2092 default:
2093 alSetError(Context, AL_INVALID_ENUM);
2096 ALCcontext_DecRef(Context);
2099 AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values)
2101 ALCcontext *Context;
2102 ALsource *Source;
2104 Context = GetContextRef();
2105 if(!Context) return;
2107 if((Source=LookupSource(Context, source)) == NULL)
2108 alSetError(Context, AL_INVALID_NAME);
2109 else if(!values)
2110 alSetError(Context, AL_INVALID_VALUE);
2111 else switch(param)
2113 case AL_MAX_DISTANCE:
2114 case AL_ROLLOFF_FACTOR:
2115 case AL_REFERENCE_DISTANCE:
2116 case AL_SOURCE_RELATIVE:
2117 case AL_CONE_INNER_ANGLE:
2118 case AL_CONE_OUTER_ANGLE:
2119 case AL_LOOPING:
2120 case AL_BUFFER:
2121 case AL_SOURCE_STATE:
2122 case AL_BUFFERS_QUEUED:
2123 case AL_BUFFERS_PROCESSED:
2124 case AL_SOURCE_TYPE:
2125 case AL_SEC_OFFSET:
2126 case AL_SAMPLE_OFFSET:
2127 case AL_BYTE_OFFSET:
2128 case AL_DIRECT_FILTER_GAINHF_AUTO:
2129 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
2130 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
2131 case AL_DOPPLER_FACTOR:
2132 case AL_DIRECT_CHANNELS_SOFT:
2133 case AL_DISTANCE_MODEL:
2135 case AL_SAMPLE_RW_OFFSETS_SOFT:
2136 case AL_BYTE_RW_OFFSETS_SOFT:
2137 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
2139 case AL_POSITION:
2140 case AL_VELOCITY:
2141 case AL_DIRECTION:
2142 GetSourcei64v(Source, Context, param, values);
2143 break;
2145 default:
2146 alSetError(Context, AL_INVALID_ENUM);
2149 ALCcontext_DecRef(Context);
2153 AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint source)
2155 alSourcePlayv(1, &source);
2157 AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
2159 ALCcontext *Context;
2160 ALsource *Source;
2161 ALsizei i;
2163 Context = GetContextRef();
2164 if(!Context) return;
2166 al_try
2168 CHECK_VALUE(Context, n >= 0);
2169 for(i = 0;i < n;i++)
2171 if(!LookupSource(Context, sources[i]))
2172 al_throwerr(Context, AL_INVALID_NAME);
2175 LockContext(Context);
2176 while(Context->MaxActiveSources-Context->ActiveSourceCount < n)
2178 void *temp = NULL;
2179 ALsizei newcount;
2181 newcount = Context->MaxActiveSources << 1;
2182 if(newcount > 0)
2183 temp = realloc(Context->ActiveSources,
2184 sizeof(*Context->ActiveSources) * newcount);
2185 if(!temp)
2187 UnlockContext(Context);
2188 al_throwerr(Context, AL_OUT_OF_MEMORY);
2191 Context->ActiveSources = temp;
2192 Context->MaxActiveSources = newcount;
2195 for(i = 0;i < n;i++)
2197 Source = LookupSource(Context, sources[i]);
2198 if(Context->DeferUpdates) Source->new_state = AL_PLAYING;
2199 else SetSourceState(Source, Context, AL_PLAYING);
2201 UnlockContext(Context);
2203 al_endtry;
2205 ALCcontext_DecRef(Context);
2208 AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source)
2210 alSourcePausev(1, &source);
2212 AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
2214 ALCcontext *Context;
2215 ALsource *Source;
2216 ALsizei i;
2218 Context = GetContextRef();
2219 if(!Context) return;
2221 al_try
2223 CHECK_VALUE(Context, n >= 0);
2224 for(i = 0;i < n;i++)
2226 if(!LookupSource(Context, sources[i]))
2227 al_throwerr(Context, AL_INVALID_NAME);
2230 LockContext(Context);
2231 for(i = 0;i < n;i++)
2233 Source = LookupSource(Context, sources[i]);
2234 if(Context->DeferUpdates) Source->new_state = AL_PAUSED;
2235 else SetSourceState(Source, Context, AL_PAUSED);
2237 UnlockContext(Context);
2239 al_endtry;
2241 ALCcontext_DecRef(Context);
2244 AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source)
2246 alSourceStopv(1, &source);
2248 AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
2250 ALCcontext *Context;
2251 ALsource *Source;
2252 ALsizei i;
2254 Context = GetContextRef();
2255 if(!Context) return;
2257 al_try
2259 CHECK_VALUE(Context, n >= 0);
2260 for(i = 0;i < n;i++)
2262 if(!LookupSource(Context, sources[i]))
2263 al_throwerr(Context, AL_INVALID_NAME);
2266 LockContext(Context);
2267 for(i = 0;i < n;i++)
2269 Source = LookupSource(Context, sources[i]);
2270 Source->new_state = AL_NONE;
2271 SetSourceState(Source, Context, AL_STOPPED);
2273 UnlockContext(Context);
2275 al_endtry;
2277 ALCcontext_DecRef(Context);
2280 AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source)
2282 alSourceRewindv(1, &source);
2284 AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
2286 ALCcontext *Context;
2287 ALsource *Source;
2288 ALsizei i;
2290 Context = GetContextRef();
2291 if(!Context) return;
2293 al_try
2295 CHECK_VALUE(Context, n >= 0);
2296 for(i = 0;i < n;i++)
2298 if(!LookupSource(Context, sources[i]))
2299 al_throwerr(Context, AL_INVALID_NAME);
2302 LockContext(Context);
2303 for(i = 0;i < n;i++)
2305 Source = LookupSource(Context, sources[i]);
2306 Source->new_state = AL_NONE;
2307 SetSourceState(Source, Context, AL_INITIAL);
2309 UnlockContext(Context);
2311 al_endtry;
2313 ALCcontext_DecRef(Context);
2317 AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers)
2319 ALCcontext *Context;
2320 ALsource *Source;
2321 ALsizei i;
2322 ALbufferlistitem *BufferListStart = NULL;
2323 ALbufferlistitem *BufferList;
2324 ALbuffer *BufferFmt;
2326 if(nb == 0)
2327 return;
2329 Context = GetContextRef();
2330 if(!Context) return;
2332 al_try
2334 ALCdevice *device = Context->Device;
2336 CHECK_VALUE(Context, nb >= 0);
2338 if((Source=LookupSource(Context, source)) == NULL)
2339 al_throwerr(Context, AL_INVALID_NAME);
2341 LockContext(Context);
2342 if(Source->SourceType == AL_STATIC)
2344 UnlockContext(Context);
2345 /* Can't queue on a Static Source */
2346 al_throwerr(Context, AL_INVALID_OPERATION);
2349 BufferFmt = NULL;
2351 /* Check for a valid Buffer, for its frequency and format */
2352 BufferList = Source->queue;
2353 while(BufferList)
2355 if(BufferList->buffer)
2357 BufferFmt = BufferList->buffer;
2358 break;
2360 BufferList = BufferList->next;
2363 for(i = 0;i < nb;i++)
2365 ALbuffer *buffer = NULL;
2366 if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
2368 UnlockContext(Context);
2369 al_throwerr(Context, AL_INVALID_NAME);
2372 if(!BufferListStart)
2374 BufferListStart = malloc(sizeof(ALbufferlistitem));
2375 BufferListStart->buffer = buffer;
2376 BufferListStart->next = NULL;
2377 BufferListStart->prev = NULL;
2378 BufferList = BufferListStart;
2380 else
2382 BufferList->next = malloc(sizeof(ALbufferlistitem));
2383 BufferList->next->buffer = buffer;
2384 BufferList->next->next = NULL;
2385 BufferList->next->prev = BufferList;
2386 BufferList = BufferList->next;
2388 if(!buffer) continue;
2389 IncrementRef(&buffer->ref);
2391 ReadLock(&buffer->lock);
2392 if(BufferFmt == NULL)
2394 BufferFmt = buffer;
2396 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
2397 Source->SampleSize = BytesFromFmt(buffer->FmtType);
2398 if(buffer->FmtChannels == FmtMono)
2399 Source->Update = CalcSourceParams;
2400 else
2401 Source->Update = CalcNonAttnSourceParams;
2403 Source->NeedsUpdate = AL_TRUE;
2405 else if(BufferFmt->Frequency != buffer->Frequency ||
2406 BufferFmt->OriginalChannels != buffer->OriginalChannels ||
2407 BufferFmt->OriginalType != buffer->OriginalType)
2409 ReadUnlock(&buffer->lock);
2410 UnlockContext(Context);
2411 al_throwerr(Context, AL_INVALID_OPERATION);
2413 ReadUnlock(&buffer->lock);
2416 /* Source is now streaming */
2417 Source->SourceType = AL_STREAMING;
2419 if(Source->queue == NULL)
2420 Source->queue = BufferListStart;
2421 else
2423 /* Append to the end of the queue */
2424 BufferList = Source->queue;
2425 while(BufferList->next != NULL)
2426 BufferList = BufferList->next;
2428 BufferListStart->prev = BufferList;
2429 BufferList->next = BufferListStart;
2432 Source->BuffersInQueue += nb;
2434 UnlockContext(Context);
2436 al_catchany()
2438 while(BufferListStart)
2440 BufferList = BufferListStart;
2441 BufferListStart = BufferList->next;
2443 if(BufferList->buffer)
2444 DecrementRef(&BufferList->buffer->ref);
2445 free(BufferList);
2448 al_endtry;
2450 ALCcontext_DecRef(Context);
2453 AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers)
2455 ALCcontext *Context;
2456 ALsource *Source;
2457 ALsizei i;
2458 ALbufferlistitem *BufferList;
2460 if(nb == 0)
2461 return;
2463 Context = GetContextRef();
2464 if(!Context) return;
2466 al_try
2468 CHECK_VALUE(Context, nb >= 0);
2470 if((Source=LookupSource(Context, source)) == NULL)
2471 al_throwerr(Context, AL_INVALID_NAME);
2473 LockContext(Context);
2474 if(Source->Looping || Source->SourceType != AL_STREAMING ||
2475 (ALuint)nb > Source->BuffersPlayed)
2477 UnlockContext(Context);
2478 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2479 al_throwerr(Context, AL_INVALID_VALUE);
2482 for(i = 0;i < nb;i++)
2484 BufferList = Source->queue;
2485 Source->queue = BufferList->next;
2486 Source->BuffersInQueue--;
2487 Source->BuffersPlayed--;
2489 if(BufferList->buffer)
2491 buffers[i] = BufferList->buffer->id;
2492 DecrementRef(&BufferList->buffer->ref);
2494 else
2495 buffers[i] = 0;
2497 free(BufferList);
2499 if(Source->queue)
2500 Source->queue->prev = NULL;
2501 UnlockContext(Context);
2503 al_endtry;
2505 ALCcontext_DecRef(Context);
2509 static ALvoid InitSourceParams(ALsource *Source)
2511 ALuint i;
2513 Source->InnerAngle = 360.0f;
2514 Source->OuterAngle = 360.0f;
2515 Source->Pitch = 1.0f;
2516 Source->Position[0] = 0.0f;
2517 Source->Position[1] = 0.0f;
2518 Source->Position[2] = 0.0f;
2519 Source->Orientation[0] = 0.0f;
2520 Source->Orientation[1] = 0.0f;
2521 Source->Orientation[2] = 0.0f;
2522 Source->Velocity[0] = 0.0f;
2523 Source->Velocity[1] = 0.0f;
2524 Source->Velocity[2] = 0.0f;
2525 Source->RefDistance = 1.0f;
2526 Source->MaxDistance = FLT_MAX;
2527 Source->RollOffFactor = 1.0f;
2528 Source->Looping = AL_FALSE;
2529 Source->Gain = 1.0f;
2530 Source->MinGain = 0.0f;
2531 Source->MaxGain = 1.0f;
2532 Source->OuterGain = 0.0f;
2533 Source->OuterGainHF = 1.0f;
2535 Source->DryGainHFAuto = AL_TRUE;
2536 Source->WetGainAuto = AL_TRUE;
2537 Source->WetGainHFAuto = AL_TRUE;
2538 Source->AirAbsorptionFactor = 0.0f;
2539 Source->RoomRolloffFactor = 0.0f;
2540 Source->DopplerFactor = 1.0f;
2541 Source->DirectChannels = AL_FALSE;
2543 Source->DistanceModel = DefaultDistanceModel;
2545 Source->Resampler = DefaultResampler;
2547 Source->state = AL_INITIAL;
2548 Source->new_state = AL_NONE;
2549 Source->SourceType = AL_UNDETERMINED;
2550 Source->Offset = -1.0;
2552 Source->DirectGain = 1.0f;
2553 Source->DirectGainHF = 1.0f;
2554 for(i = 0;i < MAX_SENDS;i++)
2556 Source->Send[i].Gain = 1.0f;
2557 Source->Send[i].GainHF = 1.0f;
2560 Source->NeedsUpdate = AL_TRUE;
2562 Source->Hrtf.Moving = AL_FALSE;
2563 Source->Hrtf.Counter = 0;
2567 /* SetSourceState
2569 * Sets the source's new play state given its current state.
2571 ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
2573 if(state == AL_PLAYING)
2575 ALbufferlistitem *BufferList;
2576 ALsizei j, k;
2578 /* Check that there is a queue containing at least one valid, non zero
2579 * length Buffer. */
2580 BufferList = Source->queue;
2581 while(BufferList)
2583 if(BufferList->buffer != NULL && BufferList->buffer->SampleLen)
2584 break;
2585 BufferList = BufferList->next;
2588 if(Source->state != AL_PLAYING)
2590 for(j = 0;j < MaxChannels;j++)
2592 for(k = 0;k < SRC_HISTORY_LENGTH;k++)
2593 Source->Hrtf.History[j][k] = 0.0f;
2594 for(k = 0;k < HRIR_LENGTH;k++)
2596 Source->Hrtf.Values[j][k][0] = 0.0f;
2597 Source->Hrtf.Values[j][k][1] = 0.0f;
2602 if(Source->state != AL_PAUSED)
2604 Source->state = AL_PLAYING;
2605 Source->position = 0;
2606 Source->position_fraction = 0;
2607 Source->BuffersPlayed = 0;
2609 else
2610 Source->state = AL_PLAYING;
2612 // Check if an Offset has been set
2613 if(Source->Offset >= 0.0)
2614 ApplyOffset(Source);
2616 /* If there's nothing to play, or device is disconnected, go right to
2617 * stopped */
2618 if(!BufferList || !Context->Device->Connected)
2620 SetSourceState(Source, Context, AL_STOPPED);
2621 return;
2624 for(j = 0;j < Context->ActiveSourceCount;j++)
2626 if(Context->ActiveSources[j] == Source)
2627 break;
2629 if(j == Context->ActiveSourceCount)
2630 Context->ActiveSources[Context->ActiveSourceCount++] = Source;
2632 else if(state == AL_PAUSED)
2634 if(Source->state == AL_PLAYING)
2636 Source->state = AL_PAUSED;
2637 Source->Hrtf.Moving = AL_FALSE;
2638 Source->Hrtf.Counter = 0;
2641 else if(state == AL_STOPPED)
2643 if(Source->state != AL_INITIAL)
2645 Source->state = AL_STOPPED;
2646 Source->BuffersPlayed = Source->BuffersInQueue;
2647 Source->Hrtf.Moving = AL_FALSE;
2648 Source->Hrtf.Counter = 0;
2650 Source->Offset = -1.0;
2652 else if(state == AL_INITIAL)
2654 if(Source->state != AL_INITIAL)
2656 Source->state = AL_INITIAL;
2657 Source->position = 0;
2658 Source->position_fraction = 0;
2659 Source->BuffersPlayed = 0;
2660 Source->Hrtf.Moving = AL_FALSE;
2661 Source->Hrtf.Counter = 0;
2663 Source->Offset = -1.0;
2667 /* GetSourceOffset
2669 * Gets the current read offset for the given Source, in 32.32 fixed-point
2670 * samples. The offset is relative to the start of the queue (not the start of
2671 * the current buffer).
2673 static ALint64 GetSourceOffset(const ALsource *Source)
2675 const ALbufferlistitem *BufferList;
2676 ALuint64 readPos;
2677 ALuint i;
2679 if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
2680 return 0;
2682 /* NOTE: This is the offset into the *current* buffer, so add the length of
2683 * any played buffers */
2684 readPos = (ALuint64)Source->position << 32;
2685 readPos |= (ALuint64)Source->position_fraction << (32-FRACTIONBITS);
2686 BufferList = Source->queue;
2687 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2689 if(BufferList->buffer)
2690 readPos += (ALuint64)BufferList->buffer->SampleLen << 32;
2691 BufferList = BufferList->next;
2694 return (ALint64)minu64(readPos, MAKEU64(0x7fffffff,0xffffffff));
2697 /* GetSourceSecOffset
2699 * Gets the current read offset for the given Source, in seconds. The offset is
2700 * relative to the start of the queue (not the start of the current buffer).
2702 static ALdouble GetSourceSecOffset(const ALsource *Source)
2704 const ALbufferlistitem *BufferList;
2705 const ALbuffer *Buffer = NULL;
2706 ALuint64 readPos;
2707 ALuint i;
2709 BufferList = Source->queue;
2710 while(BufferList)
2712 if(BufferList->buffer)
2714 Buffer = BufferList->buffer;
2715 break;
2717 BufferList = BufferList->next;
2720 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2721 return 0.0;
2723 /* NOTE: This is the offset into the *current* buffer, so add the length of
2724 * any played buffers */
2725 readPos = (ALuint64)Source->position << FRACTIONBITS;
2726 readPos |= (ALuint64)Source->position_fraction;
2727 BufferList = Source->queue;
2728 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2730 if(BufferList->buffer)
2731 readPos += (ALuint64)BufferList->buffer->SampleLen << FRACTIONBITS;
2732 BufferList = BufferList->next;
2735 return (ALdouble)readPos / (ALdouble)FRACTIONONE / (ALdouble)Buffer->Frequency;
2738 /* GetSourceOffsets
2740 * Gets the current read and write offsets for the given Source, in the
2741 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2742 * the start of the queue (not the start of the current buffer).
2744 static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen)
2746 const ALbufferlistitem *BufferList;
2747 const ALbuffer *Buffer = NULL;
2748 ALuint readPos, writePos;
2749 ALuint totalBufferLen;
2750 ALuint i;
2752 // Find the first valid Buffer in the Queue
2753 BufferList = Source->queue;
2754 while(BufferList)
2756 if(BufferList->buffer)
2758 Buffer = BufferList->buffer;
2759 break;
2761 BufferList = BufferList->next;
2764 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2766 offset[0] = 0.0;
2767 offset[1] = 0.0;
2768 return;
2771 if(updateLen > 0.0 && updateLen < 0.015)
2772 updateLen = 0.015;
2774 /* NOTE: This is the offset into the *current* buffer, so add the length of
2775 * any played buffers */
2776 readPos = Source->position;
2777 totalBufferLen = 0;
2778 BufferList = Source->queue;
2779 for(i = 0;BufferList;i++)
2781 if(BufferList->buffer)
2783 if(i < Source->BuffersPlayed)
2784 readPos += BufferList->buffer->SampleLen;
2785 totalBufferLen += BufferList->buffer->SampleLen;
2787 BufferList = BufferList->next;
2789 if(Source->state == AL_PLAYING)
2790 writePos = readPos + (ALuint)(updateLen*Buffer->Frequency);
2791 else
2792 writePos = readPos;
2794 if(Source->Looping)
2796 readPos %= totalBufferLen;
2797 writePos %= totalBufferLen;
2799 else
2801 /* Wrap positions back to 0 */
2802 if(readPos >= totalBufferLen)
2803 readPos = 0;
2804 if(writePos >= totalBufferLen)
2805 writePos = 0;
2808 switch(name)
2810 case AL_SEC_OFFSET:
2811 offset[0] = (ALdouble)readPos / Buffer->Frequency;
2812 offset[1] = (ALdouble)writePos / Buffer->Frequency;
2813 break;
2815 case AL_SAMPLE_OFFSET:
2816 case AL_SAMPLE_RW_OFFSETS_SOFT:
2817 offset[0] = (ALdouble)readPos;
2818 offset[1] = (ALdouble)writePos;
2819 break;
2821 case AL_BYTE_OFFSET:
2822 case AL_BYTE_RW_OFFSETS_SOFT:
2823 if(Buffer->OriginalType == UserFmtIMA4)
2825 ALuint BlockSize = 36 * ChannelsFromFmt(Buffer->FmtChannels);
2826 ALuint FrameBlockSize = 65;
2828 /* Round down to nearest ADPCM block */
2829 offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
2830 if(Source->state != AL_PLAYING)
2831 offset[1] = offset[0];
2832 else
2834 /* Round up to nearest ADPCM block */
2835 offset[1] = (ALdouble)((writePos+FrameBlockSize-1) /
2836 FrameBlockSize * BlockSize);
2839 else
2841 ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2842 offset[0] = (ALdouble)(readPos * FrameSize);
2843 offset[1] = (ALdouble)(writePos * FrameSize);
2845 break;
2850 /* ApplyOffset
2852 * Apply the stored playback offset to the Source. This function will update
2853 * the number of buffers "played" given the stored offset.
2855 ALboolean ApplyOffset(ALsource *Source)
2857 const ALbufferlistitem *BufferList;
2858 const ALbuffer *Buffer;
2859 ALint bufferLen, totalBufferLen;
2860 ALint buffersPlayed;
2861 ALint offset;
2863 /* Get sample frame offset */
2864 offset = GetSampleOffset(Source);
2865 if(offset == -1)
2866 return AL_FALSE;
2868 buffersPlayed = 0;
2869 totalBufferLen = 0;
2871 BufferList = Source->queue;
2872 while(BufferList)
2874 Buffer = BufferList->buffer;
2875 bufferLen = Buffer ? Buffer->SampleLen : 0;
2877 if(bufferLen <= offset-totalBufferLen)
2879 /* Offset is past this buffer so increment to the next buffer */
2880 buffersPlayed++;
2882 else if(totalBufferLen <= offset)
2884 /* Offset is in this buffer */
2885 Source->BuffersPlayed = buffersPlayed;
2887 Source->position = offset - totalBufferLen;
2888 Source->position_fraction = 0;
2889 return AL_TRUE;
2892 totalBufferLen += bufferLen;
2894 BufferList = BufferList->next;
2897 /* Offset is out of range of the queue */
2898 return AL_FALSE;
2902 /* GetSampleOffset
2904 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2905 * Second offset supplied by the application). This takes into account the fact
2906 * that the buffer format may have been modifed since.
2908 static ALint GetSampleOffset(ALsource *Source)
2910 const ALbuffer *Buffer = NULL;
2911 const ALbufferlistitem *BufferList;
2912 ALint Offset = -1;
2914 /* Find the first valid Buffer in the Queue */
2915 BufferList = Source->queue;
2916 while(BufferList)
2918 if(BufferList->buffer)
2920 Buffer = BufferList->buffer;
2921 break;
2923 BufferList = BufferList->next;
2926 if(!Buffer)
2928 Source->Offset = -1.0;
2929 return -1;
2932 switch(Source->OffsetType)
2934 case AL_BYTE_OFFSET:
2935 /* Determine the ByteOffset (and ensure it is block aligned) */
2936 Offset = (ALint)Source->Offset;
2937 if(Buffer->OriginalType == UserFmtIMA4)
2939 Offset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels);
2940 Offset *= 65;
2942 else
2943 Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2944 break;
2946 case AL_SAMPLE_OFFSET:
2947 Offset = (ALint)Source->Offset;
2948 break;
2950 case AL_SEC_OFFSET:
2951 Offset = (ALint)(Source->Offset * Buffer->Frequency);
2952 break;
2954 Source->Offset = -1.0;
2956 return Offset;
2960 /* ReleaseALSources
2962 * Destroys all sources in the source map.
2964 ALvoid ReleaseALSources(ALCcontext *Context)
2966 ALsizei pos;
2967 ALuint j;
2968 for(pos = 0;pos < Context->SourceMap.size;pos++)
2970 ALsource *temp = Context->SourceMap.array[pos].value;
2971 Context->SourceMap.array[pos].value = NULL;
2973 while(temp->queue != NULL)
2975 ALbufferlistitem *BufferList = temp->queue;
2976 temp->queue = BufferList->next;
2978 if(BufferList->buffer != NULL)
2979 DecrementRef(&BufferList->buffer->ref);
2980 free(BufferList);
2983 for(j = 0;j < MAX_SENDS;++j)
2985 if(temp->Send[j].Slot)
2986 DecrementRef(&temp->Send[j].Slot->ref);
2987 temp->Send[j].Slot = NULL;
2990 FreeThunkEntry(temp->id);
2991 memset(temp, 0, sizeof(*temp));
2992 al_free(temp);