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.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
34 #include "alAuxEffectSlot.h"
39 enum Resampler DefaultResampler
= LinearResampler
;
40 const ALsizei ResamplerPadding
[ResamplerMax
] = {
45 const ALsizei ResamplerPrePadding
[ResamplerMax
] = {
52 extern inline struct ALsource
*LookupSource(ALCcontext
*context
, ALuint id
);
53 extern inline struct ALsource
*RemoveSource(ALCcontext
*context
, ALuint id
);
55 static ALvoid
InitSourceParams(ALsource
*Source
);
56 static ALint64
GetSourceOffset(const ALsource
*Source
);
57 static ALdouble
GetSourceSecOffset(const ALsource
*Source
);
58 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offsets
, ALdouble updateLen
);
59 static ALint
GetSampleOffset(ALsource
*Source
);
61 typedef enum SrcFloatProp
{
64 sfMinGain
= AL_MIN_GAIN
,
65 sfMaxGain
= AL_MAX_GAIN
,
66 sfMaxDistance
= AL_MAX_DISTANCE
,
67 sfRolloffFactor
= AL_ROLLOFF_FACTOR
,
68 sfDopplerFactor
= AL_DOPPLER_FACTOR
,
69 sfConeOuterGain
= AL_CONE_OUTER_GAIN
,
70 sfSecOffset
= AL_SEC_OFFSET
,
71 sfSampleOffset
= AL_SAMPLE_OFFSET
,
72 sfByteOffset
= AL_BYTE_OFFSET
,
73 sfConeInnerAngle
= AL_CONE_INNER_ANGLE
,
74 sfConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
75 sfRefDistance
= AL_REFERENCE_DISTANCE
,
77 sfPosition
= AL_POSITION
,
78 sfVelocity
= AL_VELOCITY
,
79 sfDirection
= AL_DIRECTION
,
81 sfSourceRelative
= AL_SOURCE_RELATIVE
,
82 sfLooping
= AL_LOOPING
,
84 sfSourceState
= AL_SOURCE_STATE
,
85 sfBuffersQueued
= AL_BUFFERS_QUEUED
,
86 sfBuffersProcessed
= AL_BUFFERS_PROCESSED
,
87 sfSourceType
= AL_SOURCE_TYPE
,
90 sfConeOuterGainHF
= AL_CONE_OUTER_GAINHF
,
91 sfAirAbsorptionFactor
= AL_AIR_ABSORPTION_FACTOR
,
92 sfRoomRolloffFactor
= AL_ROOM_ROLLOFF_FACTOR
,
93 sfDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
94 sfAuxSendFilterGainAuto
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
95 sfAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
97 /* AL_SOFT_direct_channels */
98 sfDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
100 /* AL_EXT_source_distance_model */
101 sfDistanceModel
= AL_DISTANCE_MODEL
,
103 sfSecLength
= AL_SEC_LENGTH_SOFT
,
105 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
106 sfSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
107 sfByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
109 /* AL_SOFT_source_latency */
110 sfSecOffsetLatencySOFT
= AL_SEC_OFFSET_LATENCY_SOFT
,
113 sfOrientation
= AL_ORIENTATION
,
116 typedef enum SrcIntProp
{
117 siMaxDistance
= AL_MAX_DISTANCE
,
118 siRolloffFactor
= AL_ROLLOFF_FACTOR
,
119 siRefDistance
= AL_REFERENCE_DISTANCE
,
120 siSourceRelative
= AL_SOURCE_RELATIVE
,
121 siConeInnerAngle
= AL_CONE_INNER_ANGLE
,
122 siConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
123 siLooping
= AL_LOOPING
,
124 siBuffer
= AL_BUFFER
,
125 siSourceState
= AL_SOURCE_STATE
,
126 siBuffersQueued
= AL_BUFFERS_QUEUED
,
127 siBuffersProcessed
= AL_BUFFERS_PROCESSED
,
128 siSourceType
= AL_SOURCE_TYPE
,
129 siSecOffset
= AL_SEC_OFFSET
,
130 siSampleOffset
= AL_SAMPLE_OFFSET
,
131 siByteOffset
= AL_BYTE_OFFSET
,
132 siDopplerFactor
= AL_DOPPLER_FACTOR
,
133 siPosition
= AL_POSITION
,
134 siVelocity
= AL_VELOCITY
,
135 siDirection
= AL_DIRECTION
,
138 siDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
139 siAuxSendFilterGainAutio
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
140 siAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
141 siDirectFilter
= AL_DIRECT_FILTER
,
142 siAuxSendFilter
= AL_AUXILIARY_SEND_FILTER
,
144 /* AL_SOFT_direct_channels */
145 siDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
147 /* AL_EXT_source_distance_model */
148 siDistanceModel
= AL_DISTANCE_MODEL
,
150 siByteLength
= AL_BYTE_LENGTH_SOFT
,
151 siSampleLength
= AL_SAMPLE_LENGTH_SOFT
,
153 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
154 siSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
155 siByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
157 /* AL_SOFT_source_latency */
158 siSampleOffsetLatencySOFT
= AL_SAMPLE_OFFSET_LATENCY_SOFT
,
161 siOrientation
= AL_ORIENTATION
,
164 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
);
165 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
);
166 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
);
168 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
);
169 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
);
170 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
);
172 static ALint
FloatValsByProp(ALenum prop
)
174 if(prop
!= (ALenum
)((SrcFloatProp
)prop
))
176 switch((SrcFloatProp
)prop
)
183 case sfRolloffFactor
:
184 case sfDopplerFactor
:
185 case sfConeOuterGain
:
189 case sfConeInnerAngle
:
190 case sfConeOuterAngle
:
192 case sfConeOuterGainHF
:
193 case sfAirAbsorptionFactor
:
194 case sfRoomRolloffFactor
:
195 case sfDirectFilterGainHFAuto
:
196 case sfAuxSendFilterGainAuto
:
197 case sfAuxSendFilterGainHFAuto
:
198 case sfDirectChannelsSOFT
:
199 case sfDistanceModel
:
200 case sfSourceRelative
:
204 case sfBuffersQueued
:
205 case sfBuffersProcessed
:
210 case sfSampleRWOffsetsSOFT
:
211 case sfByteRWOffsetsSOFT
:
222 case sfSecOffsetLatencySOFT
:
223 break; /* Double only */
227 static ALint
DoubleValsByProp(ALenum prop
)
229 if(prop
!= (ALenum
)((SrcFloatProp
)prop
))
231 switch((SrcFloatProp
)prop
)
238 case sfRolloffFactor
:
239 case sfDopplerFactor
:
240 case sfConeOuterGain
:
244 case sfConeInnerAngle
:
245 case sfConeOuterAngle
:
247 case sfConeOuterGainHF
:
248 case sfAirAbsorptionFactor
:
249 case sfRoomRolloffFactor
:
250 case sfDirectFilterGainHFAuto
:
251 case sfAuxSendFilterGainAuto
:
252 case sfAuxSendFilterGainHFAuto
:
253 case sfDirectChannelsSOFT
:
254 case sfDistanceModel
:
255 case sfSourceRelative
:
259 case sfBuffersQueued
:
260 case sfBuffersProcessed
:
265 case sfSampleRWOffsetsSOFT
:
266 case sfByteRWOffsetsSOFT
:
267 case sfSecOffsetLatencySOFT
:
281 static ALint
IntValsByProp(ALenum prop
)
283 if(prop
!= (ALenum
)((SrcIntProp
)prop
))
285 switch((SrcIntProp
)prop
)
288 case siRolloffFactor
:
290 case siSourceRelative
:
291 case siConeInnerAngle
:
292 case siConeOuterAngle
:
296 case siBuffersQueued
:
297 case siBuffersProcessed
:
302 case siDopplerFactor
:
303 case siDirectFilterGainHFAuto
:
304 case siAuxSendFilterGainAutio
:
305 case siAuxSendFilterGainHFAuto
:
307 case siDirectChannelsSOFT
:
308 case siDistanceModel
:
313 case siSampleRWOffsetsSOFT
:
314 case siByteRWOffsetsSOFT
:
320 case siAuxSendFilter
:
326 case siSampleOffsetLatencySOFT
:
327 break; /* i64 only */
331 static ALint
Int64ValsByProp(ALenum prop
)
333 if(prop
!= (ALenum
)((SrcIntProp
)prop
))
335 switch((SrcIntProp
)prop
)
338 case siRolloffFactor
:
340 case siSourceRelative
:
341 case siConeInnerAngle
:
342 case siConeOuterAngle
:
346 case siBuffersQueued
:
347 case siBuffersProcessed
:
352 case siDopplerFactor
:
353 case siDirectFilterGainHFAuto
:
354 case siAuxSendFilterGainAutio
:
355 case siAuxSendFilterGainHFAuto
:
357 case siDirectChannelsSOFT
:
358 case siDistanceModel
:
363 case siSampleRWOffsetsSOFT
:
364 case siByteRWOffsetsSOFT
:
365 case siSampleOffsetLatencySOFT
:
371 case siAuxSendFilter
:
381 #define CHECKVAL(x) do { \
383 SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); \
386 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
)
393 CHECKVAL(*values
>= 0.0f
);
395 Source
->Pitch
= *values
;
396 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
399 case AL_CONE_INNER_ANGLE
:
400 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
402 Source
->InnerAngle
= *values
;
403 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
406 case AL_CONE_OUTER_ANGLE
:
407 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
409 Source
->OuterAngle
= *values
;
410 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
414 CHECKVAL(*values
>= 0.0f
);
416 Source
->Gain
= *values
;
417 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
420 case AL_MAX_DISTANCE
:
421 CHECKVAL(*values
>= 0.0f
);
423 Source
->MaxDistance
= *values
;
424 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
427 case AL_ROLLOFF_FACTOR
:
428 CHECKVAL(*values
>= 0.0f
);
430 Source
->RollOffFactor
= *values
;
431 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
434 case AL_REFERENCE_DISTANCE
:
435 CHECKVAL(*values
>= 0.0f
);
437 Source
->RefDistance
= *values
;
438 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
442 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
444 Source
->MinGain
= *values
;
445 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
449 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
451 Source
->MaxGain
= *values
;
452 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
455 case AL_CONE_OUTER_GAIN
:
456 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
458 Source
->OuterGain
= *values
;
459 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
462 case AL_CONE_OUTER_GAINHF
:
463 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
465 Source
->OuterGainHF
= *values
;
466 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
469 case AL_AIR_ABSORPTION_FACTOR
:
470 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
472 Source
->AirAbsorptionFactor
= *values
;
473 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
476 case AL_ROOM_ROLLOFF_FACTOR
:
477 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
479 Source
->RoomRolloffFactor
= *values
;
480 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
483 case AL_DOPPLER_FACTOR
:
484 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
486 Source
->DopplerFactor
= *values
;
487 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
491 case AL_SAMPLE_OFFSET
:
493 CHECKVAL(*values
>= 0.0f
);
495 LockContext(Context
);
496 Source
->OffsetType
= prop
;
497 Source
->Offset
= *values
;
499 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
500 !Context
->DeferUpdates
)
502 if(ApplyOffset(Source
) == AL_FALSE
)
504 UnlockContext(Context
);
505 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
508 UnlockContext(Context
);
513 case AL_SEC_OFFSET_LATENCY_SOFT
:
515 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
519 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
521 LockContext(Context
);
522 Source
->Position
[0] = values
[0];
523 Source
->Position
[1] = values
[1];
524 Source
->Position
[2] = values
[2];
525 UnlockContext(Context
);
526 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
530 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
532 LockContext(Context
);
533 Source
->Velocity
[0] = values
[0];
534 Source
->Velocity
[1] = values
[1];
535 Source
->Velocity
[2] = values
[2];
536 UnlockContext(Context
);
537 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
541 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
543 LockContext(Context
);
544 Source
->Direction
[0] = values
[0];
545 Source
->Direction
[1] = values
[1];
546 Source
->Direction
[2] = values
[2];
547 UnlockContext(Context
);
548 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
552 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]) &&
553 isfinite(values
[3]) && isfinite(values
[4]) && isfinite(values
[5]));
555 LockContext(Context
);
556 Source
->Orientation
[0][0] = values
[0];
557 Source
->Orientation
[0][1] = values
[1];
558 Source
->Orientation
[0][2] = values
[2];
559 Source
->Orientation
[1][0] = values
[3];
560 Source
->Orientation
[1][1] = values
[4];
561 Source
->Orientation
[1][2] = values
[5];
562 UnlockContext(Context
);
563 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
566 case sfSampleRWOffsetsSOFT
:
567 case sfByteRWOffsetsSOFT
:
568 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
571 case sfSourceRelative
:
575 case sfDistanceModel
:
576 case sfDirectFilterGainHFAuto
:
577 case sfAuxSendFilterGainAuto
:
578 case sfAuxSendFilterGainHFAuto
:
579 case sfDirectChannelsSOFT
:
580 ival
= (ALint
)values
[0];
581 return SetSourceiv(Source
, Context
, (SrcIntProp
)prop
, &ival
);
584 case sfBuffersQueued
:
585 case sfBuffersProcessed
:
586 ival
= (ALint
)((ALuint
)values
[0]);
587 return SetSourceiv(Source
, Context
, (SrcIntProp
)prop
, &ival
);
590 ERR("Unexpected property: 0x%04x\n", prop
);
591 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
594 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
)
596 ALCdevice
*device
= Context
->Device
;
597 ALbuffer
*buffer
= NULL
;
598 ALfilter
*filter
= NULL
;
599 ALeffectslot
*slot
= NULL
;
600 ALbufferlistitem
*oldlist
;
601 ALbufferlistitem
*newlist
;
606 case AL_SOURCE_RELATIVE
:
607 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
609 Source
->HeadRelative
= (ALboolean
)*values
;
610 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
614 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
616 Source
->Looping
= (ALboolean
)*values
;
620 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
622 WriteLock(&Source
->queue_lock
);
623 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
625 WriteUnlock(&Source
->queue_lock
);
626 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
631 /* Add the selected buffer to a one-item queue */
632 newlist
= malloc(sizeof(ALbufferlistitem
));
633 newlist
->buffer
= buffer
;
634 newlist
->next
= NULL
;
635 newlist
->prev
= NULL
;
636 IncrementRef(&buffer
->ref
);
638 /* Source is now Static */
639 Source
->SourceType
= AL_STATIC
;
641 ReadLock(&buffer
->lock
);
642 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
643 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
644 ReadUnlock(&buffer
->lock
);
648 /* Source is now Undetermined */
649 Source
->SourceType
= AL_UNDETERMINED
;
652 oldlist
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, newlist
);
653 ATOMIC_STORE(&Source
->current_buffer
, newlist
);
654 WriteUnlock(&Source
->queue_lock
);
656 /* Delete all elements in the previous queue */
657 while(oldlist
!= NULL
)
659 ALbufferlistitem
*temp
= oldlist
;
660 oldlist
= temp
->next
;
663 DecrementRef(&temp
->buffer
->ref
);
670 case siBuffersQueued
:
671 case siBuffersProcessed
:
673 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
676 case AL_SAMPLE_OFFSET
:
678 CHECKVAL(*values
>= 0);
680 LockContext(Context
);
681 Source
->OffsetType
= prop
;
682 Source
->Offset
= *values
;
684 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
685 !Context
->DeferUpdates
)
687 if(ApplyOffset(Source
) == AL_FALSE
)
689 UnlockContext(Context
);
690 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
693 UnlockContext(Context
);
699 case siSampleRWOffsetsSOFT
:
700 case siByteRWOffsetsSOFT
:
702 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
705 case AL_DIRECT_FILTER
:
706 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
708 LockContext(Context
);
711 Source
->Direct
.Gain
= 1.0f
;
712 Source
->Direct
.GainHF
= 1.0f
;
713 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
714 Source
->Direct
.GainLF
= 1.0f
;
715 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
719 Source
->Direct
.Gain
= filter
->Gain
;
720 Source
->Direct
.GainHF
= filter
->GainHF
;
721 Source
->Direct
.HFReference
= filter
->HFReference
;
722 Source
->Direct
.GainLF
= filter
->GainLF
;
723 Source
->Direct
.LFReference
= filter
->LFReference
;
725 UnlockContext(Context
);
726 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
729 case AL_DIRECT_FILTER_GAINHF_AUTO
:
730 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
732 Source
->DryGainHFAuto
= *values
;
733 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
736 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
737 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
739 Source
->WetGainAuto
= *values
;
740 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
743 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
744 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
746 Source
->WetGainHFAuto
= *values
;
747 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
750 case AL_DIRECT_CHANNELS_SOFT
:
751 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
753 Source
->DirectChannels
= *values
;
754 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
757 case AL_DISTANCE_MODEL
:
758 CHECKVAL(*values
== AL_NONE
||
759 *values
== AL_INVERSE_DISTANCE
||
760 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
761 *values
== AL_LINEAR_DISTANCE
||
762 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
763 *values
== AL_EXPONENT_DISTANCE
||
764 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
766 Source
->DistanceModel
= *values
;
767 if(Context
->SourceDistanceModel
)
768 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
772 case AL_AUXILIARY_SEND_FILTER
:
773 LockContext(Context
);
774 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
775 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
776 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
778 UnlockContext(Context
);
779 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
782 /* Add refcount on the new slot, and release the previous slot */
783 if(slot
) IncrementRef(&slot
->ref
);
784 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
785 if(slot
) DecrementRef(&slot
->ref
);
790 Source
->Send
[values
[1]].Gain
= 1.0f
;
791 Source
->Send
[values
[1]].GainHF
= 1.0f
;
792 Source
->Send
[values
[1]].HFReference
= LOWPASSFREQREF
;
793 Source
->Send
[values
[1]].GainLF
= 1.0f
;
794 Source
->Send
[values
[1]].LFReference
= HIGHPASSFREQREF
;
798 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
799 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
800 Source
->Send
[values
[1]].HFReference
= filter
->HFReference
;
801 Source
->Send
[values
[1]].GainLF
= filter
->GainLF
;
802 Source
->Send
[values
[1]].LFReference
= filter
->LFReference
;
804 UnlockContext(Context
);
805 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
809 case AL_MAX_DISTANCE
:
810 case AL_ROLLOFF_FACTOR
:
811 case AL_CONE_INNER_ANGLE
:
812 case AL_CONE_OUTER_ANGLE
:
813 case AL_REFERENCE_DISTANCE
:
814 case siDopplerFactor
:
815 fvals
[0] = (ALfloat
)*values
;
816 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
821 fvals
[0] = (ALfloat
)values
[0];
822 fvals
[1] = (ALfloat
)values
[1];
823 fvals
[2] = (ALfloat
)values
[2];
824 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
827 fvals
[0] = (ALfloat
)values
[0];
828 fvals
[1] = (ALfloat
)values
[1];
829 fvals
[2] = (ALfloat
)values
[2];
830 fvals
[3] = (ALfloat
)values
[3];
831 fvals
[4] = (ALfloat
)values
[4];
832 fvals
[5] = (ALfloat
)values
[5];
833 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
835 case siSampleOffsetLatencySOFT
:
840 ERR("Unexpected property: 0x%04x\n", prop
);
841 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
844 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
)
851 case siSampleRWOffsetsSOFT
:
852 case siByteRWOffsetsSOFT
:
853 case siSampleOffsetLatencySOFT
:
855 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
859 case AL_SOURCE_RELATIVE
:
861 case AL_SOURCE_STATE
:
863 case AL_SAMPLE_OFFSET
:
867 case siBuffersQueued
:
868 case siBuffersProcessed
:
869 case AL_DIRECT_FILTER_GAINHF_AUTO
:
870 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
871 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
872 case AL_DIRECT_CHANNELS_SOFT
:
873 case AL_DISTANCE_MODEL
:
874 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
876 ivals
[0] = (ALint
)*values
;
877 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
881 case AL_DIRECT_FILTER
:
882 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
884 ivals
[0] = (ALuint
)*values
;
885 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
888 case AL_AUXILIARY_SEND_FILTER
:
889 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
890 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
891 values
[2] <= UINT_MAX
&& values
[2] >= 0);
893 ivals
[0] = (ALuint
)values
[0];
894 ivals
[1] = (ALuint
)values
[1];
895 ivals
[2] = (ALuint
)values
[2];
896 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
899 case AL_MAX_DISTANCE
:
900 case AL_ROLLOFF_FACTOR
:
901 case AL_CONE_INNER_ANGLE
:
902 case AL_CONE_OUTER_ANGLE
:
903 case AL_REFERENCE_DISTANCE
:
905 case siDopplerFactor
:
906 fvals
[0] = (ALfloat
)*values
;
907 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
913 fvals
[0] = (ALfloat
)values
[0];
914 fvals
[1] = (ALfloat
)values
[1];
915 fvals
[2] = (ALfloat
)values
[2];
916 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
920 fvals
[0] = (ALfloat
)values
[0];
921 fvals
[1] = (ALfloat
)values
[1];
922 fvals
[2] = (ALfloat
)values
[2];
923 fvals
[3] = (ALfloat
)values
[3];
924 fvals
[4] = (ALfloat
)values
[4];
925 fvals
[5] = (ALfloat
)values
[5];
926 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
929 ERR("Unexpected property: 0x%04x\n", prop
);
930 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
936 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
)
938 ALbufferlistitem
*BufferList
;
947 *values
= Source
->Gain
;
951 *values
= Source
->Pitch
;
954 case AL_MAX_DISTANCE
:
955 *values
= Source
->MaxDistance
;
958 case AL_ROLLOFF_FACTOR
:
959 *values
= Source
->RollOffFactor
;
962 case AL_REFERENCE_DISTANCE
:
963 *values
= Source
->RefDistance
;
966 case AL_CONE_INNER_ANGLE
:
967 *values
= Source
->InnerAngle
;
970 case AL_CONE_OUTER_ANGLE
:
971 *values
= Source
->OuterAngle
;
975 *values
= Source
->MinGain
;
979 *values
= Source
->MaxGain
;
982 case AL_CONE_OUTER_GAIN
:
983 *values
= Source
->OuterGain
;
987 case AL_SAMPLE_OFFSET
:
989 LockContext(Context
);
990 ReadLock(&Source
->queue_lock
);
991 GetSourceOffsets(Source
, prop
, offsets
, 0.0);
992 ReadUnlock(&Source
->queue_lock
);
993 UnlockContext(Context
);
994 *values
= offsets
[0];
997 case AL_CONE_OUTER_GAINHF
:
998 *values
= Source
->OuterGainHF
;
1001 case AL_AIR_ABSORPTION_FACTOR
:
1002 *values
= Source
->AirAbsorptionFactor
;
1005 case AL_ROOM_ROLLOFF_FACTOR
:
1006 *values
= Source
->RoomRolloffFactor
;
1009 case AL_DOPPLER_FACTOR
:
1010 *values
= Source
->DopplerFactor
;
1014 ReadLock(&Source
->queue_lock
);
1015 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1022 ALbuffer
*buffer
= BufferList
->buffer
;
1023 if(buffer
&& buffer
->SampleLen
> 0)
1025 freq
= buffer
->Frequency
;
1026 length
+= buffer
->SampleLen
;
1028 } while((BufferList
=BufferList
->next
) != NULL
);
1029 *values
= (ALdouble
)length
/ (ALdouble
)freq
;
1031 ReadUnlock(&Source
->queue_lock
);
1034 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1035 case AL_BYTE_RW_OFFSETS_SOFT
:
1036 LockContext(Context
);
1037 ReadLock(&Source
->queue_lock
);
1038 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
1039 Context
->Device
->Frequency
;
1040 GetSourceOffsets(Source
, prop
, values
, updateLen
);
1041 ReadUnlock(&Source
->queue_lock
);
1042 UnlockContext(Context
);
1045 case AL_SEC_OFFSET_LATENCY_SOFT
:
1046 LockContext(Context
);
1047 ReadLock(&Source
->queue_lock
);
1048 values
[0] = GetSourceSecOffset(Source
);
1049 ReadUnlock(&Source
->queue_lock
);
1050 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
1052 UnlockContext(Context
);
1056 LockContext(Context
);
1057 values
[0] = Source
->Position
[0];
1058 values
[1] = Source
->Position
[1];
1059 values
[2] = Source
->Position
[2];
1060 UnlockContext(Context
);
1064 LockContext(Context
);
1065 values
[0] = Source
->Velocity
[0];
1066 values
[1] = Source
->Velocity
[1];
1067 values
[2] = Source
->Velocity
[2];
1068 UnlockContext(Context
);
1072 LockContext(Context
);
1073 values
[0] = Source
->Direction
[0];
1074 values
[1] = Source
->Direction
[1];
1075 values
[2] = Source
->Direction
[2];
1076 UnlockContext(Context
);
1079 case AL_ORIENTATION
:
1080 LockContext(Context
);
1081 values
[0] = Source
->Orientation
[0][0];
1082 values
[1] = Source
->Orientation
[0][1];
1083 values
[2] = Source
->Orientation
[0][2];
1084 values
[3] = Source
->Orientation
[1][0];
1085 values
[4] = Source
->Orientation
[1][1];
1086 values
[5] = Source
->Orientation
[1][2];
1087 UnlockContext(Context
);
1090 case AL_SOURCE_RELATIVE
:
1093 case AL_SOURCE_STATE
:
1094 case AL_BUFFERS_QUEUED
:
1095 case AL_BUFFERS_PROCESSED
:
1096 case AL_SOURCE_TYPE
:
1097 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1098 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1099 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1100 case AL_DIRECT_CHANNELS_SOFT
:
1101 case AL_DISTANCE_MODEL
:
1102 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1103 *values
= (ALdouble
)ivals
[0];
1107 ERR("Unexpected property: 0x%04x\n", prop
);
1108 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1111 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
)
1113 ALbufferlistitem
*BufferList
;
1119 case AL_SOURCE_RELATIVE
:
1120 *values
= Source
->HeadRelative
;
1124 *values
= Source
->Looping
;
1128 ReadLock(&Source
->queue_lock
);
1129 BufferList
= (Source
->SourceType
== AL_STATIC
) ? ATOMIC_LOAD(&Source
->queue
) :
1130 ATOMIC_LOAD(&Source
->current_buffer
);
1131 *values
= (BufferList
&& BufferList
->buffer
) ? BufferList
->buffer
->id
: 0;
1132 ReadUnlock(&Source
->queue_lock
);
1135 case AL_SOURCE_STATE
:
1136 *values
= Source
->state
;
1140 ReadLock(&Source
->queue_lock
);
1141 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1147 ALbuffer
*buffer
= BufferList
->buffer
;
1148 if(buffer
&& buffer
->SampleLen
> 0)
1150 ALuint byte_align
, sample_align
;
1151 if(buffer
->OriginalType
== UserFmtIMA4
)
1153 ALsizei align
= (buffer
->OriginalAlign
-1)/2 + 4;
1154 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1155 sample_align
= buffer
->OriginalAlign
;
1157 else if(buffer
->OriginalType
== UserFmtMSADPCM
)
1159 ALsizei align
= (buffer
->OriginalAlign
-2)/2 + 7;
1160 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1161 sample_align
= buffer
->OriginalAlign
;
1165 ALsizei align
= buffer
->OriginalAlign
;
1166 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1167 sample_align
= buffer
->OriginalAlign
;
1170 length
+= buffer
->SampleLen
/ sample_align
* byte_align
;
1172 } while((BufferList
=BufferList
->next
) != NULL
);
1175 ReadUnlock(&Source
->queue_lock
);
1178 case siSampleLength
:
1179 ReadLock(&Source
->queue_lock
);
1180 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1186 ALbuffer
*buffer
= BufferList
->buffer
;
1187 if(buffer
) length
+= buffer
->SampleLen
;
1188 } while((BufferList
=BufferList
->next
) != NULL
);
1191 ReadUnlock(&Source
->queue_lock
);
1194 case AL_BUFFERS_QUEUED
:
1195 ReadLock(&Source
->queue_lock
);
1196 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1203 } while((BufferList
=BufferList
->next
) != NULL
);
1206 ReadUnlock(&Source
->queue_lock
);
1209 case AL_BUFFERS_PROCESSED
:
1210 ReadLock(&Source
->queue_lock
);
1211 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
1213 /* Buffers on a looping source are in a perpetual state of
1214 * PENDING, so don't report any as PROCESSED */
1219 const ALbufferlistitem
*BufferList
= ATOMIC_LOAD(&Source
->queue
);
1220 const ALbufferlistitem
*Current
= ATOMIC_LOAD(&Source
->current_buffer
);
1222 while(BufferList
&& BufferList
!= Current
)
1225 BufferList
= BufferList
->next
;
1229 ReadUnlock(&Source
->queue_lock
);
1232 case AL_SOURCE_TYPE
:
1233 *values
= Source
->SourceType
;
1236 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1237 *values
= Source
->DryGainHFAuto
;
1240 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1241 *values
= Source
->WetGainAuto
;
1244 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1245 *values
= Source
->WetGainHFAuto
;
1248 case AL_DIRECT_CHANNELS_SOFT
:
1249 *values
= Source
->DirectChannels
;
1252 case AL_DISTANCE_MODEL
:
1253 *values
= Source
->DistanceModel
;
1256 case AL_MAX_DISTANCE
:
1257 case AL_ROLLOFF_FACTOR
:
1258 case AL_REFERENCE_DISTANCE
:
1259 case AL_CONE_INNER_ANGLE
:
1260 case AL_CONE_OUTER_ANGLE
:
1262 case AL_SAMPLE_OFFSET
:
1263 case AL_BYTE_OFFSET
:
1264 case AL_DOPPLER_FACTOR
:
1265 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1266 *values
= (ALint
)dvals
[0];
1269 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1270 case AL_BYTE_RW_OFFSETS_SOFT
:
1271 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1273 values
[0] = (ALint
)dvals
[0];
1274 values
[1] = (ALint
)dvals
[1];
1281 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1283 values
[0] = (ALint
)dvals
[0];
1284 values
[1] = (ALint
)dvals
[1];
1285 values
[2] = (ALint
)dvals
[2];
1289 case AL_ORIENTATION
:
1290 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1292 values
[0] = (ALint
)dvals
[0];
1293 values
[1] = (ALint
)dvals
[1];
1294 values
[2] = (ALint
)dvals
[2];
1295 values
[3] = (ALint
)dvals
[3];
1296 values
[4] = (ALint
)dvals
[4];
1297 values
[5] = (ALint
)dvals
[5];
1301 case siSampleOffsetLatencySOFT
:
1305 case siDirectFilter
:
1306 case siAuxSendFilter
:
1311 ERR("Unexpected property: 0x%04x\n", prop
);
1312 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1315 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
)
1323 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1324 LockContext(Context
);
1325 ReadLock(&Source
->queue_lock
);
1326 values
[0] = GetSourceOffset(Source
);
1327 ReadUnlock(&Source
->queue_lock
);
1328 values
[1] = ALCdevice_GetLatency(Context
->Device
);
1329 UnlockContext(Context
);
1332 case AL_MAX_DISTANCE
:
1333 case AL_ROLLOFF_FACTOR
:
1334 case AL_REFERENCE_DISTANCE
:
1335 case AL_CONE_INNER_ANGLE
:
1336 case AL_CONE_OUTER_ANGLE
:
1338 case AL_SAMPLE_OFFSET
:
1339 case AL_BYTE_OFFSET
:
1340 case AL_DOPPLER_FACTOR
:
1341 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1342 *values
= (ALint64
)dvals
[0];
1345 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1346 case AL_BYTE_RW_OFFSETS_SOFT
:
1347 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1349 values
[0] = (ALint64
)dvals
[0];
1350 values
[1] = (ALint64
)dvals
[1];
1357 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1359 values
[0] = (ALint64
)dvals
[0];
1360 values
[1] = (ALint64
)dvals
[1];
1361 values
[2] = (ALint64
)dvals
[2];
1365 case AL_ORIENTATION
:
1366 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1368 values
[0] = (ALint64
)dvals
[0];
1369 values
[1] = (ALint64
)dvals
[1];
1370 values
[2] = (ALint64
)dvals
[2];
1371 values
[3] = (ALint64
)dvals
[3];
1372 values
[4] = (ALint64
)dvals
[4];
1373 values
[5] = (ALint64
)dvals
[5];
1377 case AL_SOURCE_RELATIVE
:
1379 case AL_SOURCE_STATE
:
1380 case AL_BUFFERS_QUEUED
:
1381 case AL_BUFFERS_PROCESSED
:
1383 case siSampleLength
:
1384 case AL_SOURCE_TYPE
:
1385 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1386 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1387 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1388 case AL_DIRECT_CHANNELS_SOFT
:
1389 case AL_DISTANCE_MODEL
:
1390 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1395 case siDirectFilter
:
1396 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1397 *values
= (ALuint
)ivals
[0];
1400 case siAuxSendFilter
:
1401 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1403 values
[0] = (ALuint
)ivals
[0];
1404 values
[1] = (ALuint
)ivals
[1];
1405 values
[2] = (ALuint
)ivals
[2];
1410 ERR("Unexpected property: 0x%04x\n", prop
);
1411 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1415 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
1417 ALCcontext
*context
;
1421 context
= GetContextRef();
1422 if(!context
) return;
1425 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1426 for(cur
= 0;cur
< n
;cur
++)
1428 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
1431 alDeleteSources(cur
, sources
);
1432 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
1434 InitSourceParams(source
);
1436 err
= NewThunkEntry(&source
->id
);
1437 if(err
== AL_NO_ERROR
)
1438 err
= InsertUIntMapEntry(&context
->SourceMap
, source
->id
, source
);
1439 if(err
!= AL_NO_ERROR
)
1441 FreeThunkEntry(source
->id
);
1442 memset(source
, 0, sizeof(ALsource
));
1445 alDeleteSources(cur
, sources
);
1446 SET_ERROR_AND_GOTO(context
, err
, done
);
1449 sources
[cur
] = source
->id
;
1453 ALCcontext_DecRef(context
);
1457 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
1459 ALCcontext
*context
;
1460 ALbufferlistitem
*BufferList
;
1464 context
= GetContextRef();
1465 if(!context
) return;
1468 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1470 /* Check that all Sources are valid */
1471 for(i
= 0;i
< n
;i
++)
1473 if(LookupSource(context
, sources
[i
]) == NULL
)
1474 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
1476 for(i
= 0;i
< n
;i
++)
1478 ALvoice
*voice
, *voice_end
;
1480 if((Source
=RemoveSource(context
, sources
[i
])) == NULL
)
1482 FreeThunkEntry(Source
->id
);
1484 LockContext(context
);
1485 voice
= context
->Voices
;
1486 voice_end
= voice
+ context
->VoiceCount
;
1487 while(voice
!= voice_end
)
1489 ALsource
*old
= Source
;
1490 if(COMPARE_EXCHANGE(&voice
->Source
, &old
, NULL
))
1494 UnlockContext(context
);
1496 BufferList
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, NULL
);
1497 while(BufferList
!= NULL
)
1499 ALbufferlistitem
*next
= BufferList
->next
;
1500 if(BufferList
->buffer
!= NULL
)
1501 DecrementRef(&BufferList
->buffer
->ref
);
1506 for(j
= 0;j
< MAX_SENDS
;++j
)
1508 if(Source
->Send
[j
].Slot
)
1509 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1510 Source
->Send
[j
].Slot
= NULL
;
1513 memset(Source
, 0, sizeof(*Source
));
1518 ALCcontext_DecRef(context
);
1522 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1524 ALCcontext
*context
;
1527 context
= GetContextRef();
1528 if(!context
) return AL_FALSE
;
1530 ret
= (LookupSource(context
, source
) ? AL_TRUE
: AL_FALSE
);
1532 ALCcontext_DecRef(context
);
1538 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1540 ALCcontext
*Context
;
1543 Context
= GetContextRef();
1544 if(!Context
) return;
1546 if((Source
=LookupSource(Context
, source
)) == NULL
)
1547 alSetError(Context
, AL_INVALID_NAME
);
1548 else if(!(FloatValsByProp(param
) == 1))
1549 alSetError(Context
, AL_INVALID_ENUM
);
1551 SetSourcefv(Source
, Context
, param
, &value
);
1553 ALCcontext_DecRef(Context
);
1556 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1558 ALCcontext
*Context
;
1561 Context
= GetContextRef();
1562 if(!Context
) return;
1564 if((Source
=LookupSource(Context
, source
)) == NULL
)
1565 alSetError(Context
, AL_INVALID_NAME
);
1566 else if(!(FloatValsByProp(param
) == 3))
1567 alSetError(Context
, AL_INVALID_ENUM
);
1570 ALfloat fvals
[3] = { value1
, value2
, value3
};
1571 SetSourcefv(Source
, Context
, param
, fvals
);
1574 ALCcontext_DecRef(Context
);
1577 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1579 ALCcontext
*Context
;
1582 Context
= GetContextRef();
1583 if(!Context
) return;
1585 if((Source
=LookupSource(Context
, source
)) == NULL
)
1586 alSetError(Context
, AL_INVALID_NAME
);
1588 alSetError(Context
, AL_INVALID_VALUE
);
1589 else if(!(FloatValsByProp(param
) > 0))
1590 alSetError(Context
, AL_INVALID_ENUM
);
1592 SetSourcefv(Source
, Context
, param
, values
);
1594 ALCcontext_DecRef(Context
);
1598 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1600 ALCcontext
*Context
;
1603 Context
= GetContextRef();
1604 if(!Context
) return;
1606 if((Source
=LookupSource(Context
, source
)) == NULL
)
1607 alSetError(Context
, AL_INVALID_NAME
);
1608 else if(!(DoubleValsByProp(param
) == 1))
1609 alSetError(Context
, AL_INVALID_ENUM
);
1612 ALfloat fval
= (ALfloat
)value
;
1613 SetSourcefv(Source
, Context
, param
, &fval
);
1616 ALCcontext_DecRef(Context
);
1619 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1621 ALCcontext
*Context
;
1624 Context
= GetContextRef();
1625 if(!Context
) return;
1627 if((Source
=LookupSource(Context
, source
)) == NULL
)
1628 alSetError(Context
, AL_INVALID_NAME
);
1629 else if(!(DoubleValsByProp(param
) == 3))
1630 alSetError(Context
, AL_INVALID_ENUM
);
1633 ALfloat fvals
[3] = { (ALfloat
)value1
, (ALfloat
)value2
, (ALfloat
)value3
};
1634 SetSourcefv(Source
, Context
, param
, fvals
);
1637 ALCcontext_DecRef(Context
);
1640 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1642 ALCcontext
*Context
;
1646 Context
= GetContextRef();
1647 if(!Context
) return;
1649 if((Source
=LookupSource(Context
, source
)) == NULL
)
1650 alSetError(Context
, AL_INVALID_NAME
);
1652 alSetError(Context
, AL_INVALID_VALUE
);
1653 else if(!((count
=DoubleValsByProp(param
)) > 0 && count
<= 3))
1654 alSetError(Context
, AL_INVALID_ENUM
);
1660 for(i
= 0;i
< count
;i
++)
1661 fvals
[i
] = (ALfloat
)values
[i
];
1662 SetSourcefv(Source
, Context
, param
, fvals
);
1665 ALCcontext_DecRef(Context
);
1669 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1671 ALCcontext
*Context
;
1674 Context
= GetContextRef();
1675 if(!Context
) return;
1677 if((Source
=LookupSource(Context
, source
)) == NULL
)
1678 alSetError(Context
, AL_INVALID_NAME
);
1679 else if(!(IntValsByProp(param
) == 1))
1680 alSetError(Context
, AL_INVALID_ENUM
);
1682 SetSourceiv(Source
, Context
, param
, &value
);
1684 ALCcontext_DecRef(Context
);
1687 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1689 ALCcontext
*Context
;
1692 Context
= GetContextRef();
1693 if(!Context
) return;
1695 if((Source
=LookupSource(Context
, source
)) == NULL
)
1696 alSetError(Context
, AL_INVALID_NAME
);
1697 else if(!(IntValsByProp(param
) == 3))
1698 alSetError(Context
, AL_INVALID_ENUM
);
1701 ALint ivals
[3] = { value1
, value2
, value3
};
1702 SetSourceiv(Source
, Context
, param
, ivals
);
1705 ALCcontext_DecRef(Context
);
1708 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1710 ALCcontext
*Context
;
1713 Context
= GetContextRef();
1714 if(!Context
) return;
1716 if((Source
=LookupSource(Context
, source
)) == NULL
)
1717 alSetError(Context
, AL_INVALID_NAME
);
1719 alSetError(Context
, AL_INVALID_VALUE
);
1720 else if(!(IntValsByProp(param
) > 0))
1721 alSetError(Context
, AL_INVALID_ENUM
);
1723 SetSourceiv(Source
, Context
, param
, values
);
1725 ALCcontext_DecRef(Context
);
1729 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1731 ALCcontext
*Context
;
1734 Context
= GetContextRef();
1735 if(!Context
) return;
1737 if((Source
=LookupSource(Context
, source
)) == NULL
)
1738 alSetError(Context
, AL_INVALID_NAME
);
1739 else if(!(Int64ValsByProp(param
) == 1))
1740 alSetError(Context
, AL_INVALID_ENUM
);
1742 SetSourcei64v(Source
, Context
, param
, &value
);
1744 ALCcontext_DecRef(Context
);
1747 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1749 ALCcontext
*Context
;
1752 Context
= GetContextRef();
1753 if(!Context
) return;
1755 if((Source
=LookupSource(Context
, source
)) == NULL
)
1756 alSetError(Context
, AL_INVALID_NAME
);
1757 else if(!(Int64ValsByProp(param
) == 3))
1758 alSetError(Context
, AL_INVALID_ENUM
);
1761 ALint64SOFT i64vals
[3] = { value1
, value2
, value3
};
1762 SetSourcei64v(Source
, Context
, param
, i64vals
);
1765 ALCcontext_DecRef(Context
);
1768 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1770 ALCcontext
*Context
;
1773 Context
= GetContextRef();
1774 if(!Context
) return;
1776 if((Source
=LookupSource(Context
, source
)) == NULL
)
1777 alSetError(Context
, AL_INVALID_NAME
);
1779 alSetError(Context
, AL_INVALID_VALUE
);
1780 else if(!(Int64ValsByProp(param
) > 0))
1781 alSetError(Context
, AL_INVALID_ENUM
);
1783 SetSourcei64v(Source
, Context
, param
, values
);
1785 ALCcontext_DecRef(Context
);
1789 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1791 ALCcontext
*Context
;
1794 Context
= GetContextRef();
1795 if(!Context
) return;
1797 if((Source
=LookupSource(Context
, source
)) == NULL
)
1798 alSetError(Context
, AL_INVALID_NAME
);
1800 alSetError(Context
, AL_INVALID_VALUE
);
1801 else if(!(FloatValsByProp(param
) == 1))
1802 alSetError(Context
, AL_INVALID_ENUM
);
1806 if(GetSourcedv(Source
, Context
, param
, &dval
))
1807 *value
= (ALfloat
)dval
;
1810 ALCcontext_DecRef(Context
);
1814 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1816 ALCcontext
*Context
;
1819 Context
= GetContextRef();
1820 if(!Context
) return;
1822 if((Source
=LookupSource(Context
, source
)) == NULL
)
1823 alSetError(Context
, AL_INVALID_NAME
);
1824 else if(!(value1
&& value2
&& value3
))
1825 alSetError(Context
, AL_INVALID_VALUE
);
1826 else if(!(FloatValsByProp(param
) == 3))
1827 alSetError(Context
, AL_INVALID_ENUM
);
1831 if(GetSourcedv(Source
, Context
, param
, dvals
))
1833 *value1
= (ALfloat
)dvals
[0];
1834 *value2
= (ALfloat
)dvals
[1];
1835 *value3
= (ALfloat
)dvals
[2];
1839 ALCcontext_DecRef(Context
);
1843 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1845 ALCcontext
*Context
;
1849 Context
= GetContextRef();
1850 if(!Context
) return;
1852 if((Source
=LookupSource(Context
, source
)) == NULL
)
1853 alSetError(Context
, AL_INVALID_NAME
);
1855 alSetError(Context
, AL_INVALID_VALUE
);
1856 else if(!((count
=FloatValsByProp(param
)) > 0 && count
<= 3))
1857 alSetError(Context
, AL_INVALID_ENUM
);
1861 if(GetSourcedv(Source
, Context
, param
, dvals
))
1864 for(i
= 0;i
< count
;i
++)
1865 values
[i
] = (ALfloat
)dvals
[i
];
1869 ALCcontext_DecRef(Context
);
1873 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1875 ALCcontext
*Context
;
1878 Context
= GetContextRef();
1879 if(!Context
) return;
1881 if((Source
=LookupSource(Context
, source
)) == NULL
)
1882 alSetError(Context
, AL_INVALID_NAME
);
1884 alSetError(Context
, AL_INVALID_VALUE
);
1885 else if(!(DoubleValsByProp(param
) == 1))
1886 alSetError(Context
, AL_INVALID_ENUM
);
1888 GetSourcedv(Source
, Context
, param
, value
);
1890 ALCcontext_DecRef(Context
);
1893 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1895 ALCcontext
*Context
;
1898 Context
= GetContextRef();
1899 if(!Context
) return;
1901 if((Source
=LookupSource(Context
, source
)) == NULL
)
1902 alSetError(Context
, AL_INVALID_NAME
);
1903 else if(!(value1
&& value2
&& value3
))
1904 alSetError(Context
, AL_INVALID_VALUE
);
1905 else if(!(DoubleValsByProp(param
) == 3))
1906 alSetError(Context
, AL_INVALID_ENUM
);
1910 if(GetSourcedv(Source
, Context
, param
, dvals
))
1918 ALCcontext_DecRef(Context
);
1921 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1923 ALCcontext
*Context
;
1926 Context
= GetContextRef();
1927 if(!Context
) return;
1929 if((Source
=LookupSource(Context
, source
)) == NULL
)
1930 alSetError(Context
, AL_INVALID_NAME
);
1932 alSetError(Context
, AL_INVALID_VALUE
);
1933 else if(!(DoubleValsByProp(param
) > 0))
1934 alSetError(Context
, AL_INVALID_ENUM
);
1936 GetSourcedv(Source
, Context
, param
, values
);
1938 ALCcontext_DecRef(Context
);
1942 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1944 ALCcontext
*Context
;
1947 Context
= GetContextRef();
1948 if(!Context
) return;
1950 if((Source
=LookupSource(Context
, source
)) == NULL
)
1951 alSetError(Context
, AL_INVALID_NAME
);
1953 alSetError(Context
, AL_INVALID_VALUE
);
1954 else if(!(IntValsByProp(param
) == 1))
1955 alSetError(Context
, AL_INVALID_ENUM
);
1957 GetSourceiv(Source
, Context
, param
, value
);
1959 ALCcontext_DecRef(Context
);
1963 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1965 ALCcontext
*Context
;
1968 Context
= GetContextRef();
1969 if(!Context
) return;
1971 if((Source
=LookupSource(Context
, source
)) == NULL
)
1972 alSetError(Context
, AL_INVALID_NAME
);
1973 else if(!(value1
&& value2
&& value3
))
1974 alSetError(Context
, AL_INVALID_VALUE
);
1975 else if(!(IntValsByProp(param
) == 3))
1976 alSetError(Context
, AL_INVALID_ENUM
);
1980 if(GetSourceiv(Source
, Context
, param
, ivals
))
1988 ALCcontext_DecRef(Context
);
1992 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1994 ALCcontext
*Context
;
1997 Context
= GetContextRef();
1998 if(!Context
) return;
2000 if((Source
=LookupSource(Context
, source
)) == NULL
)
2001 alSetError(Context
, AL_INVALID_NAME
);
2003 alSetError(Context
, AL_INVALID_VALUE
);
2004 else if(!(IntValsByProp(param
) > 0))
2005 alSetError(Context
, AL_INVALID_ENUM
);
2007 GetSourceiv(Source
, Context
, param
, values
);
2009 ALCcontext_DecRef(Context
);
2013 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
2015 ALCcontext
*Context
;
2018 Context
= GetContextRef();
2019 if(!Context
) return;
2021 if((Source
=LookupSource(Context
, source
)) == NULL
)
2022 alSetError(Context
, AL_INVALID_NAME
);
2024 alSetError(Context
, AL_INVALID_VALUE
);
2025 else if(!(Int64ValsByProp(param
) == 1))
2026 alSetError(Context
, AL_INVALID_ENUM
);
2028 GetSourcei64v(Source
, Context
, param
, value
);
2030 ALCcontext_DecRef(Context
);
2033 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
2035 ALCcontext
*Context
;
2038 Context
= GetContextRef();
2039 if(!Context
) return;
2041 if((Source
=LookupSource(Context
, source
)) == NULL
)
2042 alSetError(Context
, AL_INVALID_NAME
);
2043 else if(!(value1
&& value2
&& value3
))
2044 alSetError(Context
, AL_INVALID_VALUE
);
2045 else if(!(Int64ValsByProp(param
) == 3))
2046 alSetError(Context
, AL_INVALID_ENUM
);
2050 if(GetSourcei64v(Source
, Context
, param
, i64vals
))
2052 *value1
= i64vals
[0];
2053 *value2
= i64vals
[1];
2054 *value3
= i64vals
[2];
2058 ALCcontext_DecRef(Context
);
2061 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
2063 ALCcontext
*Context
;
2066 Context
= GetContextRef();
2067 if(!Context
) return;
2069 if((Source
=LookupSource(Context
, source
)) == NULL
)
2070 alSetError(Context
, AL_INVALID_NAME
);
2072 alSetError(Context
, AL_INVALID_VALUE
);
2073 else if(!(Int64ValsByProp(param
) > 0))
2074 alSetError(Context
, AL_INVALID_ENUM
);
2076 GetSourcei64v(Source
, Context
, param
, values
);
2078 ALCcontext_DecRef(Context
);
2082 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2084 alSourcePlayv(1, &source
);
2086 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2088 ALCcontext
*context
;
2092 context
= GetContextRef();
2093 if(!context
) return;
2096 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2097 for(i
= 0;i
< n
;i
++)
2099 if(!LookupSource(context
, sources
[i
]))
2100 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2103 LockContext(context
);
2104 while(n
> context
->MaxVoices
-context
->VoiceCount
)
2106 ALvoice
*temp
= NULL
;
2109 newcount
= context
->MaxVoices
<< 1;
2111 temp
= realloc(context
->Voices
, newcount
* sizeof(context
->Voices
[0]));
2114 UnlockContext(context
);
2115 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
2117 memset(&temp
[context
->MaxVoices
], 0, (newcount
-context
->MaxVoices
) * sizeof(temp
[0]));
2119 context
->Voices
= temp
;
2120 context
->MaxVoices
= newcount
;
2123 for(i
= 0;i
< n
;i
++)
2125 source
= LookupSource(context
, sources
[i
]);
2126 if(context
->DeferUpdates
) source
->new_state
= AL_PLAYING
;
2127 else SetSourceState(source
, context
, AL_PLAYING
);
2129 UnlockContext(context
);
2132 ALCcontext_DecRef(context
);
2135 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2137 alSourcePausev(1, &source
);
2139 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2141 ALCcontext
*context
;
2145 context
= GetContextRef();
2146 if(!context
) return;
2149 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2150 for(i
= 0;i
< n
;i
++)
2152 if(!LookupSource(context
, sources
[i
]))
2153 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2156 LockContext(context
);
2157 for(i
= 0;i
< n
;i
++)
2159 source
= LookupSource(context
, sources
[i
]);
2160 if(context
->DeferUpdates
) source
->new_state
= AL_PAUSED
;
2161 else SetSourceState(source
, context
, AL_PAUSED
);
2163 UnlockContext(context
);
2166 ALCcontext_DecRef(context
);
2169 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2171 alSourceStopv(1, &source
);
2173 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2175 ALCcontext
*context
;
2179 context
= GetContextRef();
2180 if(!context
) return;
2183 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2184 for(i
= 0;i
< n
;i
++)
2186 if(!LookupSource(context
, sources
[i
]))
2187 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2190 LockContext(context
);
2191 for(i
= 0;i
< n
;i
++)
2193 source
= LookupSource(context
, sources
[i
]);
2194 source
->new_state
= AL_NONE
;
2195 SetSourceState(source
, context
, AL_STOPPED
);
2197 UnlockContext(context
);
2200 ALCcontext_DecRef(context
);
2203 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2205 alSourceRewindv(1, &source
);
2207 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2209 ALCcontext
*context
;
2213 context
= GetContextRef();
2214 if(!context
) return;
2217 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2218 for(i
= 0;i
< n
;i
++)
2220 if(!LookupSource(context
, sources
[i
]))
2221 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2224 LockContext(context
);
2225 for(i
= 0;i
< n
;i
++)
2227 source
= LookupSource(context
, sources
[i
]);
2228 source
->new_state
= AL_NONE
;
2229 SetSourceState(source
, context
, AL_INITIAL
);
2231 UnlockContext(context
);
2234 ALCcontext_DecRef(context
);
2238 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint src
, ALsizei nb
, const ALuint
*buffers
)
2241 ALCcontext
*context
;
2244 ALbufferlistitem
*BufferListStart
;
2245 ALbufferlistitem
*BufferList
;
2246 ALbuffer
*BufferFmt
= NULL
;
2251 context
= GetContextRef();
2252 if(!context
) return;
2254 device
= context
->Device
;
2257 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2258 if((source
=LookupSource(context
, src
)) == NULL
)
2259 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2261 WriteLock(&source
->queue_lock
);
2262 if(source
->SourceType
== AL_STATIC
)
2264 WriteUnlock(&source
->queue_lock
);
2265 /* Can't queue on a Static Source */
2266 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
2269 /* Check for a valid Buffer, for its frequency and format */
2270 BufferList
= ATOMIC_LOAD(&source
->queue
);
2273 if(BufferList
->buffer
)
2275 BufferFmt
= BufferList
->buffer
;
2278 BufferList
= BufferList
->next
;
2281 BufferListStart
= NULL
;
2283 for(i
= 0;i
< nb
;i
++)
2285 ALbuffer
*buffer
= NULL
;
2286 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2288 WriteUnlock(&source
->queue_lock
);
2289 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, buffer_error
);
2292 if(!BufferListStart
)
2294 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2295 BufferListStart
->buffer
= buffer
;
2296 BufferListStart
->next
= NULL
;
2297 BufferListStart
->prev
= NULL
;
2298 BufferList
= BufferListStart
;
2302 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2303 BufferList
->next
->buffer
= buffer
;
2304 BufferList
->next
->next
= NULL
;
2305 BufferList
->next
->prev
= BufferList
;
2306 BufferList
= BufferList
->next
;
2308 if(!buffer
) continue;
2310 /* Hold a read lock on each buffer being queued while checking all
2311 * provided buffers. This is done so other threads don't see an extra
2312 * reference on some buffers if this operation ends up failing. */
2313 ReadLock(&buffer
->lock
);
2314 IncrementRef(&buffer
->ref
);
2316 if(BufferFmt
== NULL
)
2320 source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2321 source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2323 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2324 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2325 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2327 WriteUnlock(&source
->queue_lock
);
2328 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, buffer_error
);
2331 /* A buffer failed (invalid ID or format), so unlock and release
2332 * each buffer we had. */
2333 while(BufferList
!= NULL
)
2335 ALbufferlistitem
*prev
= BufferList
->prev
;
2336 if((buffer
=BufferList
->buffer
) != NULL
)
2338 DecrementRef(&buffer
->ref
);
2339 ReadUnlock(&buffer
->lock
);
2347 /* All buffers good, unlock them now. */
2348 while(BufferList
!= NULL
)
2350 ALbuffer
*buffer
= BufferList
->buffer
;
2351 if(buffer
) ReadUnlock(&buffer
->lock
);
2352 BufferList
= BufferList
->prev
;
2355 /* Source is now streaming */
2356 source
->SourceType
= AL_STREAMING
;
2359 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->queue
, &BufferList
, BufferListStart
))
2361 /* Queue head is not NULL, append to the end of the queue */
2362 while(BufferList
->next
!= NULL
)
2363 BufferList
= BufferList
->next
;
2365 BufferListStart
->prev
= BufferList
;
2366 BufferList
->next
= BufferListStart
;
2369 ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->current_buffer
, &BufferList
, BufferListStart
);
2370 WriteUnlock(&source
->queue_lock
);
2373 ALCcontext_DecRef(context
);
2376 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint src
, ALsizei nb
, ALuint
*buffers
)
2378 ALCcontext
*context
;
2380 ALbufferlistitem
*NewHead
;
2381 ALbufferlistitem
*OldHead
;
2382 ALbufferlistitem
*Current
;
2388 context
= GetContextRef();
2389 if(!context
) return;
2392 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2394 if((source
=LookupSource(context
, src
)) == NULL
)
2395 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2397 WriteLock(&source
->queue_lock
);
2398 /* Find the new buffer queue head */
2399 NewHead
= ATOMIC_LOAD(&source
->queue
);
2400 Current
= ATOMIC_LOAD(&source
->current_buffer
);
2401 for(i
= 0;i
< nb
&& NewHead
;i
++)
2403 if(NewHead
== Current
)
2405 NewHead
= NewHead
->next
;
2407 if(source
->Looping
|| source
->SourceType
!= AL_STREAMING
|| i
!= nb
)
2409 WriteUnlock(&source
->queue_lock
);
2410 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2411 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2414 /* Swap it, and cut the new head from the old. */
2415 OldHead
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &source
->queue
, NewHead
);
2418 ALCdevice
*device
= context
->Device
;
2419 ALbufferlistitem
*OldTail
= NewHead
->prev
;
2422 /* Cut the new head's link back to the old body. The mixer is robust
2423 * enough to handle the link back going away. Once the active mix (if
2424 * any) is complete, it's safe to finish cutting the old tail from the
2426 NewHead
->prev
= NULL
;
2427 if(((count
=ReadRef(&device
->MixCount
))&1) != 0)
2429 while(count
== ReadRef(&device
->MixCount
))
2432 OldTail
->next
= NULL
;
2434 WriteUnlock(&source
->queue_lock
);
2436 while(OldHead
!= NULL
)
2438 ALbufferlistitem
*next
= OldHead
->next
;
2439 ALbuffer
*buffer
= OldHead
->buffer
;
2445 *(buffers
++) = buffer
->id
;
2446 DecrementRef(&buffer
->ref
);
2454 ALCcontext_DecRef(context
);
2458 static ALvoid
InitSourceParams(ALsource
*Source
)
2462 RWLockInit(&Source
->queue_lock
);
2464 Source
->InnerAngle
= 360.0f
;
2465 Source
->OuterAngle
= 360.0f
;
2466 Source
->Pitch
= 1.0f
;
2467 Source
->Position
[0] = 0.0f
;
2468 Source
->Position
[1] = 0.0f
;
2469 Source
->Position
[2] = 0.0f
;
2470 Source
->Velocity
[0] = 0.0f
;
2471 Source
->Velocity
[1] = 0.0f
;
2472 Source
->Velocity
[2] = 0.0f
;
2473 Source
->Direction
[0] = 0.0f
;
2474 Source
->Direction
[1] = 0.0f
;
2475 Source
->Direction
[2] = 0.0f
;
2476 Source
->Orientation
[0][0] = 0.0f
;
2477 Source
->Orientation
[0][1] = 0.0f
;
2478 Source
->Orientation
[0][2] = -1.0f
;
2479 Source
->Orientation
[1][0] = 0.0f
;
2480 Source
->Orientation
[1][1] = 1.0f
;
2481 Source
->Orientation
[1][2] = 0.0f
;
2482 Source
->RefDistance
= 1.0f
;
2483 Source
->MaxDistance
= FLT_MAX
;
2484 Source
->RollOffFactor
= 1.0f
;
2485 Source
->Looping
= AL_FALSE
;
2486 Source
->Gain
= 1.0f
;
2487 Source
->MinGain
= 0.0f
;
2488 Source
->MaxGain
= 1.0f
;
2489 Source
->OuterGain
= 0.0f
;
2490 Source
->OuterGainHF
= 1.0f
;
2492 Source
->DryGainHFAuto
= AL_TRUE
;
2493 Source
->WetGainAuto
= AL_TRUE
;
2494 Source
->WetGainHFAuto
= AL_TRUE
;
2495 Source
->AirAbsorptionFactor
= 0.0f
;
2496 Source
->RoomRolloffFactor
= 0.0f
;
2497 Source
->DopplerFactor
= 1.0f
;
2498 Source
->DirectChannels
= AL_FALSE
;
2500 Source
->Radius
= 0.0f
;
2502 Source
->DistanceModel
= DefaultDistanceModel
;
2504 Source
->Resampler
= DefaultResampler
;
2506 Source
->state
= AL_INITIAL
;
2507 Source
->new_state
= AL_NONE
;
2508 Source
->SourceType
= AL_UNDETERMINED
;
2509 Source
->Offset
= -1.0;
2511 ATOMIC_INIT(&Source
->queue
, NULL
);
2512 ATOMIC_INIT(&Source
->current_buffer
, NULL
);
2514 Source
->Direct
.Gain
= 1.0f
;
2515 Source
->Direct
.GainHF
= 1.0f
;
2516 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
2517 Source
->Direct
.GainLF
= 1.0f
;
2518 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
2519 for(i
= 0;i
< MAX_SENDS
;i
++)
2521 Source
->Send
[i
].Gain
= 1.0f
;
2522 Source
->Send
[i
].GainHF
= 1.0f
;
2523 Source
->Send
[i
].HFReference
= LOWPASSFREQREF
;
2524 Source
->Send
[i
].GainLF
= 1.0f
;
2525 Source
->Send
[i
].LFReference
= HIGHPASSFREQREF
;
2528 ATOMIC_INIT(&Source
->NeedsUpdate
, AL_TRUE
);
2534 * Sets the source's new play state given its current state.
2536 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2538 ReadLock(&Source
->queue_lock
);
2539 if(state
== AL_PLAYING
)
2541 ALCdevice
*device
= Context
->Device
;
2542 ALbufferlistitem
*BufferList
;
2543 ALvoice
*voice
= NULL
;
2546 /* Check that there is a queue containing at least one valid, non zero
2548 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2552 if((buffer
=BufferList
->buffer
) != NULL
&& buffer
->SampleLen
> 0)
2554 BufferList
= BufferList
->next
;
2557 if(Source
->state
!= AL_PAUSED
)
2559 Source
->state
= AL_PLAYING
;
2560 Source
->position
= 0;
2561 Source
->position_fraction
= 0;
2562 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2565 Source
->state
= AL_PLAYING
;
2567 // Check if an Offset has been set
2568 if(Source
->Offset
>= 0.0)
2569 ApplyOffset(Source
);
2571 /* If there's nothing to play, or device is disconnected, go right to
2573 if(!BufferList
|| !device
->Connected
)
2576 /* Make sure this source isn't already active, while looking for an
2577 * unused active source slot to put it in. */
2578 for(i
= 0;i
< Context
->VoiceCount
;i
++)
2580 ALsource
*old
= Source
;
2581 if(COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, NULL
))
2585 voice
= &Context
->Voices
[i
];
2586 voice
->Source
= Source
;
2591 if(voice
== NULL
&& COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, Source
))
2592 voice
= &Context
->Voices
[i
];
2596 voice
= &Context
->Voices
[Context
->VoiceCount
++];
2597 voice
->Source
= Source
;
2600 voice
->Direct
.Moving
= AL_FALSE
;
2601 voice
->Direct
.Counter
= 0;
2602 for(i
= 0;i
< MAX_INPUT_CHANNELS
;i
++)
2605 for(j
= 0;j
< HRTF_HISTORY_LENGTH
;j
++)
2606 voice
->Direct
.Hrtf
.State
[i
].History
[j
] = 0.0f
;
2607 for(j
= 0;j
< HRIR_LENGTH
;j
++)
2609 voice
->Direct
.Hrtf
.State
[i
].Values
[j
][0] = 0.0f
;
2610 voice
->Direct
.Hrtf
.State
[i
].Values
[j
][1] = 0.0f
;
2613 for(i
= 0;i
< (ALsizei
)device
->NumAuxSends
;i
++)
2615 voice
->Send
[i
].Moving
= AL_FALSE
;
2616 voice
->Send
[i
].Counter
= 0;
2619 if(BufferList
->buffer
->FmtChannels
== FmtMono
)
2620 voice
->Update
= CalcSourceParams
;
2622 voice
->Update
= CalcNonAttnSourceParams
;
2624 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
2626 else if(state
== AL_PAUSED
)
2628 if(Source
->state
== AL_PLAYING
)
2629 Source
->state
= AL_PAUSED
;
2631 else if(state
== AL_STOPPED
)
2634 if(Source
->state
!= AL_INITIAL
)
2636 Source
->state
= AL_STOPPED
;
2637 ATOMIC_STORE(&Source
->current_buffer
, NULL
);
2639 Source
->Offset
= -1.0;
2641 else if(state
== AL_INITIAL
)
2643 if(Source
->state
!= AL_INITIAL
)
2645 Source
->state
= AL_INITIAL
;
2646 Source
->position
= 0;
2647 Source
->position_fraction
= 0;
2648 ATOMIC_STORE(&Source
->current_buffer
, ATOMIC_LOAD(&Source
->queue
));
2650 Source
->Offset
= -1.0;
2652 ReadUnlock(&Source
->queue_lock
);
2657 * Gets the current read offset for the given Source, in 32.32 fixed-point
2658 * samples. The offset is relative to the start of the queue (not the start of
2659 * the current buffer).
2661 static ALint64
GetSourceOffset(const ALsource
*Source
)
2663 const ALbufferlistitem
*BufferList
;
2664 const ALbufferlistitem
*Current
;
2667 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2670 /* NOTE: This is the offset into the *current* buffer, so add the length of
2671 * any played buffers */
2672 readPos
= (ALuint64
)Source
->position
<< 32;
2673 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2674 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2675 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2676 while(BufferList
&& BufferList
!= Current
)
2678 if(BufferList
->buffer
)
2679 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2680 BufferList
= BufferList
->next
;
2683 return (ALint64
)minu64(readPos
, U64(0x7fffffffffffffff));
2686 /* GetSourceSecOffset
2688 * Gets the current read offset for the given Source, in seconds. The offset is
2689 * relative to the start of the queue (not the start of the current buffer).
2691 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2693 const ALbufferlistitem
*BufferList
;
2694 const ALbufferlistitem
*Current
;
2695 const ALbuffer
*Buffer
= NULL
;
2698 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2701 /* NOTE: This is the offset into the *current* buffer, so add the length of
2702 * any played buffers */
2703 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2704 readPos
|= (ALuint64
)Source
->position_fraction
;
2705 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2706 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2707 while(BufferList
&& BufferList
!= Current
)
2709 const ALbuffer
*buffer
= BufferList
->buffer
;
2712 if(!Buffer
) Buffer
= buffer
;
2713 readPos
+= (ALuint64
)buffer
->SampleLen
<< FRACTIONBITS
;
2715 BufferList
= BufferList
->next
;
2718 while(BufferList
&& !Buffer
)
2720 Buffer
= BufferList
->buffer
;
2721 BufferList
= BufferList
->next
;
2723 assert(Buffer
!= NULL
);
2725 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2730 * Gets the current read and write offsets for the given Source, in the
2731 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2732 * the start of the queue (not the start of the current buffer).
2734 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2736 const ALbufferlistitem
*BufferList
;
2737 const ALbufferlistitem
*Current
;
2738 const ALbuffer
*Buffer
= NULL
;
2739 ALboolean readFin
= AL_FALSE
;
2740 ALuint readPos
, writePos
;
2741 ALuint totalBufferLen
;
2743 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2750 if(updateLen
> 0.0 && updateLen
< 0.015)
2753 /* NOTE: This is the offset into the *current* buffer, so add the length of
2754 * any played buffers */
2756 readPos
= Source
->position
;
2757 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2758 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2759 while(BufferList
!= NULL
)
2761 const ALbuffer
*buffer
;
2762 readFin
= readFin
|| (BufferList
== Current
);
2763 if((buffer
=BufferList
->buffer
) != NULL
)
2765 if(!Buffer
) Buffer
= buffer
;
2766 totalBufferLen
+= buffer
->SampleLen
;
2767 if(!readFin
) readPos
+= buffer
->SampleLen
;
2769 BufferList
= BufferList
->next
;
2771 assert(Buffer
!= NULL
);
2773 if(Source
->state
== AL_PLAYING
)
2774 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2780 readPos
%= totalBufferLen
;
2781 writePos
%= totalBufferLen
;
2785 /* Wrap positions back to 0 */
2786 if(readPos
>= totalBufferLen
)
2788 if(writePos
>= totalBufferLen
)
2795 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2796 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2799 case AL_SAMPLE_OFFSET
:
2800 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2801 offset
[0] = (ALdouble
)readPos
;
2802 offset
[1] = (ALdouble
)writePos
;
2805 case AL_BYTE_OFFSET
:
2806 case AL_BYTE_RW_OFFSETS_SOFT
:
2807 if(Buffer
->OriginalType
== UserFmtIMA4
)
2809 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2810 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2811 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2813 /* Round down to nearest ADPCM block */
2814 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2815 if(Source
->state
!= AL_PLAYING
)
2816 offset
[1] = offset
[0];
2819 /* Round up to nearest ADPCM block */
2820 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2821 FrameBlockSize
* BlockSize
);
2824 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2826 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2827 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2828 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2830 /* Round down to nearest ADPCM block */
2831 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2832 if(Source
->state
!= AL_PLAYING
)
2833 offset
[1] = offset
[0];
2836 /* Round up to nearest ADPCM block */
2837 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2838 FrameBlockSize
* BlockSize
);
2843 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2844 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2845 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2854 * Apply the stored playback offset to the Source. This function will update
2855 * the number of buffers "played" given the stored offset.
2857 ALboolean
ApplyOffset(ALsource
*Source
)
2859 ALbufferlistitem
*BufferList
;
2860 const ALbuffer
*Buffer
;
2861 ALint bufferLen
, totalBufferLen
;
2864 /* Get sample frame offset */
2865 offset
= GetSampleOffset(Source
);
2870 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2871 while(BufferList
&& totalBufferLen
<= offset
)
2873 Buffer
= BufferList
->buffer
;
2874 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2876 if(bufferLen
> offset
-totalBufferLen
)
2878 /* Offset is in this buffer */
2879 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2881 Source
->position
= offset
- totalBufferLen
;
2882 Source
->position_fraction
= 0;
2886 totalBufferLen
+= bufferLen
;
2888 BufferList
= BufferList
->next
;
2891 /* Offset is out of range of the queue */
2898 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2899 * Second offset supplied by the application). This takes into account the fact
2900 * that the buffer format may have been modifed since.
2902 static ALint
GetSampleOffset(ALsource
*Source
)
2904 const ALbuffer
*Buffer
= NULL
;
2905 const ALbufferlistitem
*BufferList
;
2908 /* Find the first valid Buffer in the Queue */
2909 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2912 if(BufferList
->buffer
)
2914 Buffer
= BufferList
->buffer
;
2917 BufferList
= BufferList
->next
;
2922 Source
->Offset
= -1.0;
2926 switch(Source
->OffsetType
)
2928 case AL_BYTE_OFFSET
:
2929 /* Determine the ByteOffset (and ensure it is block aligned) */
2930 Offset
= (ALint
)Source
->Offset
;
2931 if(Buffer
->OriginalType
== UserFmtIMA4
)
2933 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2934 Offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2935 Offset
*= Buffer
->OriginalAlign
;
2937 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2939 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2940 Offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2941 Offset
*= Buffer
->OriginalAlign
;
2944 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2947 case AL_SAMPLE_OFFSET
:
2948 Offset
= (ALint
)Source
->Offset
;
2952 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2955 Source
->Offset
= -1.0;
2963 * Destroys all sources in the source map.
2965 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2967 ALbufferlistitem
*item
;
2970 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2972 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2973 Context
->SourceMap
.array
[pos
].value
= NULL
;
2975 item
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &temp
->queue
, NULL
);
2978 ALbufferlistitem
*next
= item
->next
;
2979 if(item
->buffer
!= NULL
)
2980 DecrementRef(&item
->buffer
->ref
);
2985 for(j
= 0;j
< MAX_SENDS
;++j
)
2987 if(temp
->Send
[j
].Slot
)
2988 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2989 temp
->Send
[j
].Slot
= NULL
;
2992 FreeThunkEntry(temp
->id
);
2993 memset(temp
, 0, sizeof(*temp
));